Kill it with fire.

This commit is contained in:
Markus Unterwaditzer 2014-05-03 20:53:06 +02:00
parent e7fdc87d70
commit d781ac1101
2 changed files with 55 additions and 21 deletions

View file

@ -49,14 +49,15 @@ def test_split_collection_timezones():
u'END:VTIMEZONE' u'END:VTIMEZONE'
) )
full = u'\n'.join( full = list(
(u'BEGIN:VCALENDAR',) + (u'BEGIN:VCALENDAR',) +
timezone + tuple(line for item in items for line in item) + timezone + tuple(line for item in items for line in item) +
(u'END:VCALENDAR',) (u'END:VCALENDAR',)
) )
given = [tuple(x.raw.splitlines()) for x in split_collection(full)] given = [tuple(x) for x in split_collection(full)]
expected = [item[:-1] + timezone + (item[-1],) for item in items] expected = [(u'BEGIN:VCALENDAR',) + timezone + item + (u'END:VCALENDAR',)
for item in items]
print(given) print(given)
print(expected) print(expected)
assert given == expected assert given == expected
@ -110,7 +111,8 @@ def test_list(monkeypatch):
assert etag2 == etag assert etag2 == etag
found_items[item.raw.strip()] = href found_items[item.raw.strip()] = href
assert set(found_items) == set(items) assert set(found_items) == set(u'BEGIN:VCALENDAR\n' + x + '\nEND:VCALENDAR'
for x in items)
for href, etag in s.list(): for href, etag in s.list():
item, etag2 = s.get(href) item, etag2 = s.get(href)

View file

@ -15,19 +15,11 @@ from ..utils import expand_path, get_password, request, text_type, urlparse
USERAGENT = 'vdirsyncer' USERAGENT = 'vdirsyncer'
def split_collection(text): def split_simple_collection(lines):
'''
This is a horrible "parser", but Python tooling isn't much better. The only
library which supports both calendars and addressbooks (VObject) is Python
2 only and doesn't seem maintained anymore, the other one (icalendar) only
handles calendars... which wouldn't eliminate this function anyway. Let's
just hope this handles all cases.
'''
item = [] item = []
collection_type = None collection_type = None
item_type = None item_type = None
timezone = None for line in lines:
for line in text.splitlines():
if u':' not in line: if u':' not in line:
item.append(line) item.append(line)
continue continue
@ -38,19 +30,14 @@ def split_collection(text):
elif item_type is None: elif item_type is None:
item_type = value item_type = value
item.append(line) item.append(line)
if item_type == u'VTIMEZONE':
timezone = item
else: else:
item.append(line) item.append(line)
elif key == u'END': elif key == u'END':
if value == collection_type: if value == collection_type:
break break
elif value == item_type: elif value == item_type:
if timezone is not None and item_type != u'VTIMEZONE':
item.extend(timezone)
item.append(line) item.append(line)
if item_type != u'VTIMEZONE': yield item
yield Item(u'\n'.join(item), needs_uid=False)
item = [] item = []
item_type = None item_type = None
else: else:
@ -60,6 +47,50 @@ def split_collection(text):
item.append(line) item.append(line)
def wrap_items(items, collection_type, exclude=(u'VTIMEZONE',)):
for item in items:
key, value = (x.strip() for x in item[0].split(u':'))
if value in exclude:
yield item
else:
yield ([u'BEGIN:' + collection_type] + item +
[u'END:' + collection_type])
def inline_timezones(items):
timezone = None
for item in items:
if u':' not in item[0]:
import pdb
pdb.set_trace()
key, value = (x.strip() for x in item[0].split(u':'))
if value == u'VTIMEZONE':
if timezone is not None:
raise ValueError('Multiple timezones.')
timezone = item
else:
if timezone is not None:
item = [item[0]] + timezone + item[1:]
yield item
def split_collection(lines):
collection_type = None
for line in lines:
key, value = (x.strip() for x in line.split(u':'))
if key == u'BEGIN':
collection_type = value
break
is_calendar = collection_type == u'VCALENDAR'
rv = split_simple_collection(lines)
if is_calendar:
rv = inline_timezones(wrap_items(rv, collection_type))
return rv
def prepare_auth(auth, username, password): def prepare_auth(auth, username, password):
if (username and password) or auth == 'basic': if (username and password) or auth == 'basic':
return (username, password) return (username, password)
@ -119,7 +150,8 @@ class HttpStorage(Storage):
r = request('GET', self.url, **self._settings) r = request('GET', self.url, **self._settings)
r.raise_for_status() r.raise_for_status()
self._items.clear() self._items.clear()
for i, item in enumerate(split_collection(r.text)): for i, item in enumerate(split_collection(r.text.splitlines())):
item = Item(u'\n'.join(item), needs_uid=False)
uid = item.uid if item.uid is not None else i uid = item.uid if item.uid is not None else i
self._items[uid] = item self._items[uid] = item