cctool

A tool for managing contacts and calendars.
git clone https://git.ce9e.org/cctool.git

commit
100ef7e9d211e7b8189cdbab43980087a61dc0c5
parent
25721f10154408cd14f3516ebab210548f3e57f7
Author
Tobias Bengfort <tobias.bengfort@gmx.net>
Date
2015-05-22 09:48
Revert "implement own ldif parser"

This reverts commit b329a7613a15efa3cbe9c6f8538b639e801ea889.

Conflicts:
	cctool.py

Diffstat

M cctool.py 58 ++++++++++++++++++++++++++++------------------------------
M setup.py 1 +
M tests.py 19 +------------------

3 files changed, 30 insertions, 48 deletions


diff --git a/cctool.py b/cctool.py

@@ -41,9 +41,9 @@ from datetime import date
   41    41 from datetime import datetime
   42    42 from io import BytesIO
   43    43 import argparse
   44    -1 import base64
   45    44 import codecs
   46    45 import json
   -1    46 import logging as log
   47    47 import os
   48    48 import pickle
   49    49 import re
@@ -55,6 +55,11 @@ except ImportError:  # pragma: nocover
   55    55 	from configparser import RawConfigParser as ConfigParser
   56    56 
   57    57 try:  # pragma: nocover
   -1    58 	import ldif
   -1    59 except ImportError as err:  # pragma: nocover
   -1    60 	ldif = err
   -1    61 
   -1    62 try:  # pragma: nocover
   58    63 	import icalendar
   59    64 except ImportError as err:  # pragma: nocover
   60    65 	icalendar = err
@@ -83,7 +88,6 @@ def formats():  # pragma: nocover
   83    88 		'abook': ABook,
   84    89 		'json': JSON,
   85    90 		'pickle': Pickle,
   86    -1 		'ldif': LDIF,
   87    91 	}
   88    92 	outformats = {
   89    93 		'bsdcal': BSDCal,
@@ -94,6 +98,8 @@ def formats():  # pragma: nocover
   94    98 	if not isinstance(icalendar, Exception):  # pragma: nocover
   95    99 		informats['ics'] = ICal
   96   100 		outformats['ics'] = ICal
   -1   101 	if not isinstance(ldif, Exception):  # pragma: nocover
   -1   102 		informats['ldif'] = LDIF
   97   103 	if not isinstance(yaml, Exception):  # pragma: nocover
   98   104 		informats['yml'] = YAML
   99   105 		outformats['yml'] = YAML
@@ -380,6 +386,16 @@ class ABook(Format):
  380   386 		cp.write(_fh)
  381   387 
  382   388 
   -1   389 if not isinstance(ldif, Exception):
   -1   390 	class LDIFParser(ldif.LDIFParser):
   -1   391 		def __init__(self, fh):
   -1   392 			ldif.LDIFParser.__init__(self, fh)
   -1   393 			self.entries = {}
   -1   394 
   -1   395 		def handle(self, dn, entry):
   -1   396 			self.entries[dn] = entry
   -1   397 
   -1   398 
  383   399 class LDIF(Format):
  384   400 	fields = {
  385   401 		'cn': 'name',
@@ -387,35 +403,17 @@ class LDIF(Format):
  387   403 	}
  388   404 
  389   405 	@classmethod
  390    -1 	def get_blocks(cls, fh):
  391    -1 		block = []
  392    -1 		for _line in fh:
  393    -1 			line = _line.rstrip()
  394    -1 			if not line:
  395    -1 				yield block
  396    -1 				block = []
  397    -1 			elif line.startswith(b'#'):
  398    -1 				continue
  399    -1 			elif line.startswith(b' '):
  400    -1 				block[-1] += line[1:]
  401    -1 			else:
  402    -1 				block.append(line)
  403    -1 		if block:
  404    -1 			yield block
  405    -1 
  406    -1 	@classmethod
  407   406 	def load(cls, fh):
  408    -1 		for block in cls.get_blocks(fh):
  409    -1 			item = MultiDict()
  410    -1 			for line in block:
  411    -1 				m = re.match(b'([^:]*):(:?) *(.*)', line)
  412    -1 				if m:
  413    -1 					key, b64, value = m.groups()
  414    -1 					if b64 == b':':
  415    -1 						value = base64.decodestring(value)
  416    -1 					item.append(key.decode('utf8'), [value.decode('utf8')])
  417    -1 			if item:
  418    -1 				yield map_keys(item, cls.fields)
   -1   407 		if isinstance(ldif, Exception):
   -1   408 			raise ldif
   -1   409 		parser = LDIFParser(fh)
   -1   410 		try:
   -1   411 			parser.parse()
   -1   412 		except ValueError as err:
   -1   413 			log.warning("ValueError after reading %i records: %s",
   -1   414 				parser.records_read, err)
   -1   415 		for entry in parser.entries.values():
   -1   416 			yield map_keys(MultiDict(entry), cls.fields)
  419   417 
  420   418 
  421   419 class DateTimeJSONEncoder(json.JSONEncoder):

diff --git a/setup.py b/setup.py

@@ -11,6 +11,7 @@ setup(
   11    11     platforms='any',
   12    12     py_modules=['cctool'],
   13    13     extras_require={
   -1    14         'ldif': ['python-ldap'],
   14    15         'ical': ['icaledar'],
   15    16         'yaml': ['PyYAML'],
   16    17     },

diff --git a/tests.py b/tests.py

@@ -312,6 +312,7 @@ class TestABook(_TestFormat):
  312   312 		self.text = b'[0]\nname = foo\nbday = 1970-01-01\n\n'
  313   313 
  314   314 
   -1   315 @unittest.skipIf(isinstance(cctool.ldif, Exception), 'ldif not available')
  315   316 class TestLDIF(_TestFormat):
  316   317 	def setUp(self):
  317   318 		self.format = cctool.LDIF()
@@ -324,24 +325,6 @@ class TestLDIF(_TestFormat):
  324   325 	def test_dump(self):
  325   326 		pass
  326   327 
  327    -1 	def test_get_blocks(self):
  328    -1 		fh = BytesIO(b'foo: bar\n  baz\n zz\n# second block\nencoded:: aHVodQ==\n\nfoo: bar')
  329    -1 		blocks = list(self.format.get_blocks(fh))
  330    -1 
  331    -1 		self.assertEqual(blocks, [
  332    -1 			[b'foo: bar bazzz', b'encoded:: aHVodQ=='],
  333    -1 			[b'foo: bar'],
  334    -1 		])
  335    -1 
  336    -1 	def test_get_blocks_w_trailing(self):
  337    -1 		fh = BytesIO(b'foo: bar\n  baz\n zz\n# second block\nencoded:: aHVodQ==\n\nfoo: bar\n\n')
  338    -1 		blocks = list(self.format.get_blocks(fh))
  339    -1 
  340    -1 		self.assertEqual(blocks, [
  341    -1 			[b'foo: bar bazzz', b'encoded:: aHVodQ=='],
  342    -1 			[b'foo: bar'],
  343    -1 		])
  344    -1 
  345   328 
  346   329 class TestJSON(_TestFormat):
  347   330 	def setUp(self):