split_collection: Allow multiple wrappers

Fix #78
This commit is contained in:
Markus Unterwaditzer 2014-06-14 13:06:07 +02:00
parent 783d2b56b3
commit 11adeaff86
3 changed files with 53 additions and 30 deletions

View file

@ -12,25 +12,42 @@ import vdirsyncer.utils.vobject as vobject
from .. import normalize_item, VCARD_TEMPLATE, BARE_EVENT_TEMPLATE, \
EVENT_TEMPLATE
_simple_joined = u'\r\n'.join((
u'BEGIN:VADDRESSBOOK',
VCARD_TEMPLATE.format(r=123),
VCARD_TEMPLATE.format(r=345),
VCARD_TEMPLATE.format(r=678),
u'END:VADDRESSBOOK\r\n'
))
_simple_split = [
VCARD_TEMPLATE.format(r=123),
VCARD_TEMPLATE.format(r=345),
VCARD_TEMPLATE.format(r=678)
]
_simple_joined = u'\r\n'.join(
[u'BEGIN:VADDRESSBOOK'] +
_simple_split +
[u'END:VADDRESSBOOK\r\n']
)
def test_split_collection_simple():
given = list(vobject.split_collection(_simple_joined))
assert [normalize_item(item) for item in given] == \
[normalize_item(item) for item in _simple_split]
if vobject.ICALENDAR_ORIGINAL_ORDER_SUPPORT:
assert [x.splitlines() for x in given] == \
[x.splitlines() for x in _simple_split]
def test_split_collection_multiple_wrappers():
joined = u'\r\n'.join(
u'BEGIN:VADDRESSBOOK\r\n' +
x +
u'\r\nEND:VADDRESSBOOK\r\n'
for x in _simple_split
)
given = list(vobject.split_collection(joined))
assert [normalize_item(item) for item in given] == \
[normalize_item(item) for item in _simple_split]
if vobject.ICALENDAR_ORIGINAL_ORDER_SUPPORT:
assert [x.splitlines() for x in given] == \
[x.splitlines() for x in _simple_split]

View file

@ -11,7 +11,7 @@ import os
import requests
from .. import log, exceptions
from .compat import urlparse, get_raw_input
from .compat import urlparse, get_raw_input, iteritems
logger = log.get(__name__)
@ -35,13 +35,19 @@ def expand_path(p):
def split_dict(d, f):
'''Puts key into first dict if f(key), otherwise in second dict'''
a = {}
b = {}
for k, v in d.items():
if f(k):
a[k] = v
a, b = split_sequence(iteritems(d), lambda item: f(item[0]))
return dict(a), dict(b)
def split_sequence(s, f):
'''Puts item into first list if f(item), else in second list'''
a = []
b = []
for item in s:
if f(item):
a.append(item)
else:
b[k] = v
b.append(item)
return a, b

View file

@ -12,7 +12,7 @@ import icalendar.cal
import icalendar.parser
import icalendar.caselessdict
from . import cached_property
from . import cached_property, split_sequence
from .compat import text_type, itervalues
@ -128,25 +128,25 @@ def split_collection(text, inline=(u'VTIMEZONE',),
wrap_items_with=(u'VCALENDAR',)):
'''Emits items in the order they occur in the text.'''
assert isinstance(text, text_type)
collection = icalendar.cal.Component.from_ical(text)
items = collection.subcomponents
collections = icalendar.cal.Component.from_ical(text, multiple=True)
assert collections
if collection.name in wrap_items_with:
start = u'BEGIN:{}'.format(collection.name)
end = u'END:{}'.format(collection.name)
else:
start = end = u''
for collection in collections:
items = collection.subcomponents
inlined_items = {}
for item in items:
if item.name in inline:
inlined_items[item.name] = item
if collection.name in wrap_items_with:
start = u'BEGIN:{}'.format(collection.name)
end = u'END:{}'.format(collection.name)
else:
start = end = u''
for item in items:
if item.name not in inline:
inlined_items, normal_items = \
split_sequence(items, lambda item: item.name in inline)
for item in normal_items:
lines = []
lines.append(start)
for inlined_item in itervalues(inlined_items):
for inlined_item in inlined_items:
lines.extend(to_unicode_lines(inlined_item))
lines.extend(to_unicode_lines(item))