cctool

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

commit
93d3f4c4c5777d60e3e6701878b4e869c08cc5cf
parent
82cf4c9b5edebcb4326466af97e3c6687ae1ede1
Author
Tobias Bengfort <tobias.bengfort@gmx.net>
Date
2015-05-08 11:54
switch from vobject to icalendar for ical support

vobject seems to be unmaintained

Diffstat

M cctool.py 50 +++++++++++++++++++++++++++++++++-----------------
M setup.py 2 +-
M tests.py 4 ++--
M tox.ini 1 +

4 files changed, 37 insertions, 20 deletions


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

@@ -52,9 +52,9 @@ except ImportError as err:
   52    52 	ldif = err
   53    53 
   54    54 try:
   55    -1 	import vobject
   -1    55 	import icalendar
   56    56 except ImportError as err:
   57    -1 	vobject = err
   -1    57 	icalendar = err
   58    58 
   59    59 
   60    60 NOTSET = object()
@@ -72,7 +72,7 @@ def formats():
   72    72 		'json': JSON,
   73    73 		'pickle': Pickle,
   74    74 	}
   75    -1 	if not isinstance(vobject, Exception):
   -1    75 	if not isinstance(icalendar, Exception):
   76    76 		informats['ics'] = ICal
   77    77 		outformats['ics'] = ICal
   78    78 	if not isinstance(ldif, Exception):
@@ -199,30 +199,46 @@ class ICal(Format):
  199   199 		'created', 'dtstamp', 'last-modified', 'sequence']
  200   200 
  201   201 	@classmethod
   -1   202 	def _iter_events(cls, component):
   -1   203 		if isinstance(component, icalendar.Event):
   -1   204 			yield component
   -1   205 		elif hasattr(component, 'subcomponents'):
   -1   206 			for c in component.subcomponents:
   -1   207 				for event in cls._iter_events(c):
   -1   208 					yield event
   -1   209 
   -1   210 	@classmethod
  202   211 	def load(cls, fh):
  203    -1 		if isinstance(vobject, Exception):
  204    -1 			raise vobject
   -1   212 		if isinstance(icalendar, Exception):
   -1   213 			raise icalendar
  205   214 
  206    -1 		for calendar in vobject.readComponents(fh):
  207    -1 			for event in calendar.vevent_list:
  208    -1 				d = MultiDict()
  209    -1 				for key, value in event.contents.iteritems():
  210    -1 					d[key] = [i.value for i in value]
  211    -1 				yield d
   -1   215 		calendar = icalendar.Calendar.from_ical(fh.read())
   -1   216 
   -1   217 		for event in cls._iter_events(calendar):
   -1   218 			d = MultiDict()
   -1   219 			for key, value in event.items():
   -1   220 				if key.lower() in cls.fields:
   -1   221 					d[key.lower()] = [value.from_ical(value)]
   -1   222 			yield d
  212   223 
  213   224 	@classmethod
  214   225 	def dump(cls, data, fh):
  215    -1 		if isinstance(vobject, Exception):
  216    -1 			raise vobject
   -1   226 		if isinstance(icalendar, Exception):
   -1   227 			raise icalendar
   -1   228 
   -1   229 		calendar = icalendar.Calendar()
   -1   230 		calendar.add('prodid', '-//XI//NONSGML CCTOOL//')
   -1   231 		calendar.add('version', '2.0')
  217   232 
  218    -1 		ical = vobject.iCalendar()
  219   233 		for event in data:
  220    -1 			vevent = ical.add('vevent')
   -1   234 			vevent = icalendar.Event()
  221   235 			for key in event:
  222   236 				if key in cls.fields:
  223   237 					for value in event[key]:
  224    -1 						vevent.add(key).value = value
  225    -1 		ical.serialize(fh)
   -1   238 						vevent.add(key.upper(), value)
   -1   239 			calendar.add_component(vevent)
   -1   240 
   -1   241 		fh.write(calendar.to_ical())
  226   242 
  227   243 
  228   244 class ABook(Format):

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

@@ -12,7 +12,7 @@ setup(
   12    12     py_modules=['cctool'],
   13    13     extras_require={
   14    14         'ldif': ['python-ldap'],
   15    -1         'ical': ['vobject'],
   -1    15         'ical': ['icaledar'],
   16    16     },
   17    17     license='GPLv3+',
   18    18     entry_points={'console_scripts': 'cctool=cctool:main'},

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

@@ -90,12 +90,12 @@ class TestBSDCal(_TestFormat):
   90    90 		pass
   91    91 
   92    92 
   93    -1 @unittest.skipIf(isinstance(cctool.vobject, Exception), 'vobject not available')
   -1    93 @unittest.skipIf(isinstance(cctool.icalendar, Exception), 'icalendar not available')
   94    94 class TestICal(_TestFormat):
   95    95 	def setUp(self):
   96    96 		self.format = cctool.ICal()
   97    97 		self.data = [cctool.MultiDict({u'uid': [u'20140519T210153Z-13022@tobias-eee']})]
   98    -1 		self.text = 'BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//PYVOBJECT//NONSGML Version 1//EN\r\nBEGIN:VEVENT\r\nUID:20140519T210153Z-13022@tobias-eee\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n'
   -1    98 		self.text = 'BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//XI//NONSGML CCTOOL//\r\nBEGIN:VEVENT\r\nUID:20140519T210153Z-13022@tobias-eee\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n'
   99    99 
  100   100 
  101   101 class TestABook(_TestFormat):

diff --git a/tox.ini b/tox.ini

@@ -14,3 +14,4 @@ deps =
   14    14     nose
   15    15     coverage
   16    16     flake8
   -1    17     icalendar