- commit
- 8379fca760e9d3a1b53976b59541580f2df27b5d
- parent
- 5e1ad6dd5e2c5fd9e76c4ee8fb5b90e618d14cc0
- Author
- Tobias Bengfort <tobias.bengfort@gmx.net>
- Date
- 2015-05-08 21:47
add more tests
Diffstat
| M | cctool.py | 42 | +++++++++++++++++++++--------------------- |
| M | tests.py | 266 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- |
2 files changed, 283 insertions, 25 deletions
diff --git a/cctool.py b/cctool.py
@@ -49,19 +49,19 @@ import pickle 49 49 import re 50 50 import sys 51 5152 -1 try:-1 52 try: # pragma: nocover 53 53 from ConfigParser import RawConfigParser as ConfigParser54 -1 except ImportError:-1 54 except ImportError: # pragma: nocover 55 55 from configparser import RawConfigParser as ConfigParser 56 5657 -1 try:-1 57 try: # pragma: nocover 58 58 import icalendar59 -1 except ImportError as err:-1 59 except ImportError as err: # pragma: nocover 60 60 icalendar = err 61 6162 -1 try:-1 62 try: # pragma: nocover 63 63 import yaml64 -1 except ImportError as err:-1 64 except ImportError as err: # pragma: nocover 65 65 yaml = err 66 66 67 67 @@ -70,14 +70,14 @@ PERSON = ['abook', 'ldif'] 70 70 EVENT = ['bsdcal', 'ics'] 71 71 72 7273 -1 def _str(x):-1 73 def _str(x): # pragma: nocover 74 74 try: 75 75 return unicode(x) 76 76 except NameError: 77 77 return str(x) 78 78 79 7980 -1 def formats():-1 80 def formats(): # pragma: nocover 81 81 informats = { 82 82 'bsdcal': BSDCal, 83 83 'abook': ABook, @@ -91,10 +91,10 @@ def formats(): 91 91 'json': JSON, 92 92 'pickle': Pickle, 93 93 }94 -1 if not isinstance(icalendar, Exception):-1 94 if not isinstance(icalendar, Exception): # pragma: nocover 95 95 informats['ics'] = ICal 96 96 outformats['ics'] = ICal97 -1 if not isinstance(yaml, Exception):-1 97 if not isinstance(yaml, Exception): # pragma: nocover 98 98 informats['yml'] = YAML 99 99 outformats['yml'] = YAML 100 100 return informats, outformats @@ -194,7 +194,7 @@ class Format(object): 194 194 """ 195 195 196 196 @classmethod197 -1 def load(cls, fh):-1 197 def load(cls, fh): # pragma: nocover 198 198 raise NotImplementedError 199 199 200 200 @classmethod @@ -202,7 +202,7 @@ class Format(object): 202 202 return cls.load(BytesIO(s)) 203 203 204 204 @classmethod205 -1 def dump(cls, data, fh):-1 205 def dump(cls, data, fh): # pragma: nocover 206 206 raise NotImplementedError 207 207 208 208 @classmethod @@ -281,15 +281,13 @@ class ICal(Format): 281 281 282 282 @classmethod 283 283 def load(cls, fh):284 -1 if isinstance(icalendar, Exception):-1 284 if isinstance(icalendar, Exception): # pragma: nocover 285 285 raise icalendar 286 286 287 287 calendar = icalendar.Calendar.from_ical(fh.read()) 288 288 289 289 for event in cls._iter_events(calendar): 290 290 d = MultiDict()291 -1 if 'RRULE' in event:292 -1 d['freq'] = [s.lower() for s in event['RRULE']['FREQ']]293 291 for key, value in event.items(): 294 292 if key.lower() in cls.fields: 295 293 try: @@ -299,11 +297,13 @@ class ICal(Format): 299 297 except ValueError: 300 298 break 301 299 else: -1 300 if 'RRULE' in event: -1 301 d['freq'] = [s.lower() for s in event['RRULE']['FREQ']] 302 302 yield map_keys(d, cls.fields) 303 303 304 304 @classmethod 305 305 def dump(cls, data, fh):306 -1 if isinstance(icalendar, Exception):-1 306 if isinstance(icalendar, Exception): # pragma: nocover 307 307 raise icalendar 308 308 309 309 calendar = icalendar.Calendar() @@ -353,10 +353,10 @@ class ABook(Format): 353 353 def dump(cls, data, fh): 354 354 cp = ConfigParser() 355 355356 -1 if isinstance(cp.__module__, bytes):-1 356 if isinstance(cp.__module__, bytes): # pragma: nocover 357 357 _fh = fh 358 358 encode = lambda x: x.encode('utf8')359 -1 else:-1 359 else: # pragma: nocover 360 360 _fh = codecs.getwriter('utf8')(fh) 361 361 encode = lambda x: x 362 362 @@ -441,14 +441,14 @@ class JSON(Format): 441 441 class YAML(Format): 442 442 @classmethod 443 443 def load(cls, fh):444 -1 if isinstance(yaml, Exception):-1 444 if isinstance(yaml, Exception): # pragma: nocover 445 445 raise yaml 446 446 447 447 return [MultiDict(d) for d in yaml.load(fh.read())] 448 448 449 449 @classmethod 450 450 def dump(cls, data, fh):451 -1 if isinstance(yaml, Exception):-1 451 if isinstance(yaml, Exception): # pragma: nocover 452 452 raise yaml 453 453 454 454 _fh = codecs.getwriter('utf8')(fh) @@ -511,7 +511,7 @@ def get_informat(filename): 511 511 sys.exit(1) 512 512 513 513514 -1 def main():-1 514 def main(): # pragma: nocover 515 515 informats, outformats = formats() 516 516 args = parse_args() 517 517
diff --git a/tests.py b/tests.py
@@ -2,6 +2,7 @@ from __future__ import unicode_literals 2 2 3 3 import unittest 4 4 from datetime import datetime -1 5 from io import BytesIO 5 6 6 7 import cctool 7 8 @@ -12,6 +13,26 @@ class TestMultiDict(unittest.TestCase): 12 13 def setUp(self): 13 14 self.d = cctool.MultiDict() 14 15 -1 16 def test_construct_list(self): -1 17 d = cctool.MultiDict([ -1 18 ('foo', [1, 2]), -1 19 ('bar', [3, 4]), -1 20 ]) -1 21 -1 22 self.assertEqual(list(d.keys()), ['foo', 'bar']) -1 23 self.assertEqual(d['foo'], [1, 2]) -1 24 self.assertEqual(d['bar'], [3, 4]) -1 25 -1 26 def test_construct_dict(self): -1 27 d = cctool.MultiDict({ -1 28 'foo': [1, 2], -1 29 'bar': [3, 4], -1 30 }) -1 31 -1 32 self.assertEqual(set(d.keys()), set(['foo', 'bar'])) -1 33 self.assertEqual(d['foo'], [1, 2]) -1 34 self.assertEqual(d['bar'], [3, 4]) -1 35 15 36 def test_containes(self): 16 37 self.assertFalse('foo' in self.d) 17 38 self.d['foo'] = [1, 2, 3] @@ -35,6 +56,10 @@ class TestMultiDict(unittest.TestCase): 35 56 self.assertEqual(self.d.join('foo'), '1,2,3') 36 57 self.assertEqual(self.d.join('bar', default='baz'), 'baz') 37 58 -1 59 def test_join_missing_key(self): -1 60 with self.assertRaises(KeyError): -1 61 self.d.join('foo', default=None) -1 62 38 63 def test_update(self): 39 64 self.d['foo'] = [1] 40 65 self.d['bar'] = [1, 2] @@ -69,6 +94,169 @@ class TestMerged(unittest.TestCase): 69 94 self.assertIn(item, expected) 70 95 71 96 -1 97 class TestMapKeys(unittest.TestCase): -1 98 def test_simple(self): -1 99 d = cctool.MultiDict([ -1 100 ('foo', [1, 2]), -1 101 ('bar', [3, 4]), -1 102 ]) -1 103 -1 104 d2 = cctool.map_keys(d, { -1 105 'foo': 'baz' -1 106 }) -1 107 -1 108 self.assertEqual(list(d2.keys()), ['baz']) -1 109 self.assertEqual(d2['baz'], [1, 2]) -1 110 -1 111 def test_keep_order(self): -1 112 d = cctool.MultiDict([ -1 113 ('foo', [1, 2]), -1 114 ('bar', [3, 4]), -1 115 ('baz', [4, 5]), -1 116 ]) -1 117 -1 118 d2 = cctool.map_keys(d, { -1 119 'foo': 'bar', -1 120 'bar': 'baz', -1 121 'baz': 'foo', -1 122 }) -1 123 -1 124 self.assertEqual(list(d2.keys()), ['bar', 'baz', 'foo']) -1 125 self.assertEqual(d2['bar'], [1, 2]) -1 126 self.assertEqual(d2['baz'], [3, 4]) -1 127 self.assertEqual(d2['foo'], [4, 5]) -1 128 -1 129 def test_reverse(self): -1 130 d = cctool.MultiDict([ -1 131 ('foo', [1, 2]), -1 132 ('bar', [3, 4]), -1 133 ('baz', [4, 5]), -1 134 ]) -1 135 -1 136 d2 = cctool.map_keys(d, { -1 137 'foo': 'bar', -1 138 'bar': 'baz', -1 139 'baz': 'foo', -1 140 }, reverse=True) -1 141 -1 142 self.assertEqual(list(d2.keys()), ['baz', 'foo', 'bar']) -1 143 self.assertEqual(d2['baz'], [1, 2]) -1 144 self.assertEqual(d2['foo'], [3, 4]) -1 145 self.assertEqual(d2['bar'], [4, 5]) -1 146 -1 147 def test_non_exclusive(self): -1 148 d = cctool.MultiDict([ -1 149 ('foo', [1, 2]), -1 150 ('bar', [3, 4]), -1 151 ]) -1 152 -1 153 d2 = cctool.map_keys(d, { -1 154 'foo': 'baz' -1 155 }, exclusive=False) -1 156 -1 157 self.assertEqual(list(d2.keys()), ['baz', 'bar']) -1 158 self.assertEqual(d2['baz'], [1, 2]) -1 159 self.assertEqual(d2['bar'], [3, 4]) -1 160 -1 161 def test_join(self): -1 162 d = cctool.MultiDict([ -1 163 ('foo', [1, 2]), -1 164 ('bar', [3, 4]), -1 165 ('baz', [4, 5]), -1 166 ]) -1 167 -1 168 d2 = cctool.map_keys(d, { -1 169 'foo': 'foo', -1 170 'bar': 'foo', -1 171 'baz': 'baz', -1 172 }) -1 173 -1 174 self.assertEqual(list(d2.keys()), ['foo', 'baz']) -1 175 self.assertEqual(d2['foo'], [1, 2, 3, 4]) -1 176 self.assertEqual(d2['baz'], [4, 5]) -1 177 -1 178 @unittest.skip # non deterministic -1 179 def test_join_reverse(self): -1 180 d = cctool.MultiDict([ -1 181 ('foo', [1, 2]), -1 182 ('bar', [3, 4]), -1 183 ('baz', [4, 5]), -1 184 ]) -1 185 -1 186 d2 = cctool.map_keys(d, { -1 187 'foo': 'foo', -1 188 'bar': 'foo', -1 189 'baz': 'baz', -1 190 }, reverse=True) -1 191 -1 192 self.assertEqual(list(d2.keys()), ['bar', 'baz']) -1 193 self.assertEqual(d2['bar'], [1, 2]) -1 194 self.assertEqual(d2['baz'], [4, 5]) -1 195 -1 196 def test_non_destructive(self): -1 197 d = cctool.MultiDict([ -1 198 ('foo', [1, 2]), -1 199 ('bar', [3, 4]), -1 200 ('baz', [4, 5]), -1 201 ]) -1 202 -1 203 d2 = cctool.map_keys(d, { -1 204 'foo': 'bar', -1 205 'bar': 'baz', -1 206 'baz': 'foo', -1 207 }) -1 208 -1 209 self.assertEqual(list(d.keys()), ['foo', 'bar', 'baz']) -1 210 self.assertEqual(d['foo'], [1, 2]) -1 211 self.assertEqual(d['bar'], [3, 4]) -1 212 self.assertEqual(d['baz'], [4, 5]) -1 213 -1 214 -1 215 class TestEvent2Person(unittest.TestCase): -1 216 def test_event2person(self): -1 217 items = list(cctool.event2person([cctool.MultiDict([ -1 218 ('summary', ['some summary']), -1 219 ('dtstart', [dt]), -1 220 ('tag', ['tag1', 'tag2']), -1 221 ])])) -1 222 -1 223 self.assertEqual(list(items[0].keys()), ['name', 'bday', 'tag']) -1 224 self.assertEqual(items[0]['name'], ['some summary']) -1 225 self.assertEqual(items[0]['bday'], [dt]) -1 226 self.assertEqual(items[0]['tag'], ['tag1', 'tag2']) -1 227 -1 228 def test_person2event(self): -1 229 items = list(cctool.event2person([cctool.MultiDict([ -1 230 ('name', ['some name']), -1 231 ('bday', [dt]), -1 232 ('tag', ['tag1', 'tag2']), -1 233 ])], reverse=True)) -1 234 -1 235 self.assertEqual(list(items[0].keys()), ['summary', 'dtstart', 'tag', 'freq']) -1 236 self.assertEqual(items[0]['summary'], ['some name']) -1 237 self.assertEqual(items[0]['dtstart'], [dt]) -1 238 self.assertEqual(items[0]['tag'], ['tag1', 'tag2']) -1 239 self.assertEqual(items[0]['freq'], ['yearly']) -1 240 -1 241 def test_event2person_wo_dtstart(self): -1 242 items = list(cctool.event2person([cctool.MultiDict([ -1 243 ('summary', ['some summary']), -1 244 ('tag', ['tag1', 'tag2']), -1 245 ])])) -1 246 -1 247 self.assertEqual(list(items[0].keys()), ['name', 'tag']) -1 248 self.assertEqual(items[0]['name'], ['some summary']) -1 249 self.assertEqual(items[0]['tag'], ['tag1', 'tag2']) -1 250 -1 251 def test_person2event_wo_dtstart(self): -1 252 items = list(cctool.event2person([cctool.MultiDict([ -1 253 ('name', ['some name']), -1 254 ('tag', ['tag1', 'tag2']), -1 255 ])], reverse=True)) -1 256 -1 257 self.assertEqual(len(items), 0) -1 258 -1 259 72 260 class _TestFormat(unittest.TestCase): 73 261 data = [cctool.MultiDict({'name': ['foo']})] 74 262 @@ -85,11 +273,11 @@ class TestBSDCal(_TestFormat): 85 273 self.data = [ 86 274 cctool.MultiDict([ 87 275 ('dtstart', [dt]),88 -1 ('summary', [u'foo']),-1 276 ('summary', ['foo']), 89 277 ]), 90 278 cctool.MultiDict([ 91 279 ('dtstart', [dt]),92 -1 ('summary', [u'bar']),-1 280 ('summary', ['bar']), 93 281 ('freq', ['yearly']), 94 282 ]), 95 283 ] @@ -100,8 +288,18 @@ class TestBSDCal(_TestFormat): 100 288 class TestICal(_TestFormat): 101 289 def setUp(self): 102 290 self.format = cctool.ICal()103 -1 self.data = [cctool.MultiDict({u'summary': [u'lorem ipsum']})]104 -1 self.text = b'BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//XI//NONSGML CCTOOL//\r\nBEGIN:VEVENT\r\nSUMMARY:lorem ipsum\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n'-1 291 self.data = [ -1 292 cctool.MultiDict([ -1 293 ('summary', ['lorem ipsum']), -1 294 ('dtstart', [dt]), -1 295 ('freq', ['daily']), -1 296 ]), -1 297 cctool.MultiDict([ -1 298 ('summary', ['lorem ipsum2', 'lorem ipsum3']), -1 299 ('dtstart', [dt.date()]), -1 300 ]), -1 301 ] -1 302 self.text = b'BEGIN:VCALENDAR\r\nVERSION:2.0\r\nPRODID:-//XI//NONSGML CCTOOL//\r\nBEGIN:VEVENT\r\nSUMMARY:lorem ipsum\r\nDTSTART;VALUE=DATE-TIME:20150101T000000\r\nRRULE:FREQ=DAILY\r\nEND:VEVENT\r\nBEGIN:VEVENT\r\nSUMMARY:lorem ipsum2\r\nSUMMARY:lorem ipsum3\r\nDTSTART;VALUE=DATE:20150101\r\nEND:VEVENT\r\nEND:VCALENDAR\r\n' 105 303 106 304 107 305 class TestABook(_TestFormat): @@ -126,6 +324,24 @@ class TestLDIF(_TestFormat): 126 324 def test_dump(self): 127 325 pass 128 326 -1 327 def test_get_blocks(self): -1 328 fh = BytesIO(b'foo: bar\n baz\n zz\n# second block\nencoded:: aHVodQ==\n\nfoo: bar') -1 329 blocks = list(self.format.get_blocks(fh)) -1 330 -1 331 self.assertEqual(blocks, [ -1 332 [b'foo: bar bazzz', b'encoded:: aHVodQ=='], -1 333 [b'foo: bar'], -1 334 ]) -1 335 -1 336 def test_get_blocks_w_trailing(self): -1 337 fh = BytesIO(b'foo: bar\n baz\n zz\n# second block\nencoded:: aHVodQ==\n\nfoo: bar\n\n') -1 338 blocks = list(self.format.get_blocks(fh)) -1 339 -1 340 self.assertEqual(blocks, [ -1 341 [b'foo: bar bazzz', b'encoded:: aHVodQ=='], -1 342 [b'foo: bar'], -1 343 ]) -1 344 129 345 130 346 class TestJSON(_TestFormat): 131 347 def setUp(self): @@ -165,5 +381,47 @@ class TestArgs(unittest.TestCase): 165 381 self.assertEqual(args.outformat, 'bsdcal') 166 382 167 383 -1 384 class ArgsMock(object): -1 385 outformat = None -1 386 output = None -1 387 -1 388 -1 389 class TestGetOutformat(unittest.TestCase): -1 390 def test_arg(self): -1 391 args = ArgsMock() -1 392 args.outformat = 'json' -1 393 -1 394 self.assertEqual(cctool.get_outformat(args), 'json') -1 395 -1 396 def test_extension(self): -1 397 args = ArgsMock() -1 398 args.output = 'foo.json' -1 399 -1 400 self.assertEqual(cctool.get_outformat(args), 'json') -1 401 -1 402 -1 403 class TestGetInformat(unittest.TestCase): -1 404 def test_extension(self): -1 405 filename = 'foo.json' -1 406 e, fn = cctool.get_informat(filename) -1 407 -1 408 self.assertEqual(e, 'json') -1 409 self.assertEqual(fn, filename) -1 410 -1 411 def test_colon(self): -1 412 filename = 'foo:json' -1 413 e, fn = cctool.get_informat(filename) -1 414 -1 415 self.assertEqual(e, 'json') -1 416 self.assertEqual(fn, 'foo') -1 417 -1 418 def test_both(self): -1 419 filename = 'foo.json:json' -1 420 e, fn = cctool.get_informat(filename) -1 421 -1 422 self.assertEqual(e, 'json') -1 423 self.assertEqual(fn, 'foo.json') -1 424 -1 425 168 426 if __name__ == '__main__': 169 427 unittest.main()