Skip to content

Commit c6c6b8d

Browse files
committed
WIP: uploading of modified events
Locally modified events don't get overwritten anymore and or uploaded. Might actually be working properly now, needs more testing Also: made _create_timezone take pytz.tzinfo
1 parent 3b9eb2d commit c6c6b8d

File tree

5 files changed

+64
-12
lines changed

5 files changed

+64
-12
lines changed

khal/backend.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,9 @@ def needs_update(self, account_name, href_etag_list):
217217
def update(self, vevent, account_name, href='', etag='', status=OK):
218218
"""insert a new or update an existing card in the db
219219
220+
This is mostly a wrapper around two SQL statements, doing some cleanup
221+
before.
222+
220223
:param vcard: vcard to be inserted or updated
221224
:type vcard: unicode
222225
:param href: href of the card on the server, if this href already
@@ -343,7 +346,7 @@ def update_href(self, oldhref, newhref, account_name, etag='', status=OK):
343346
self.sql_ex(sql_s, (newhref, oldhref))
344347

345348
def href_exists(self, href, account_name):
346-
"""returns True if href already exist in db
349+
"""returns True if href already exists in db
347350
348351
:param href: href
349352
:type href: str()
@@ -493,8 +496,11 @@ def get_vevent_from_db(self, href, account_name, start=None, end=None,
493496
"""returns the Event matching href, if start and end are given, a
494497
specific Event from a Recursion set is returned, the Event as saved in
495498
the db
499+
500+
All other parameters given to this function are handed over to the
501+
Event.
496502
"""
497-
sql_s = 'SELECT vevent, status FROM {0} WHERE href=(?)'.format(account_name)
503+
sql_s = 'SELECT vevent, status, etag FROM {0} WHERE href=(?)'.format(account_name)
498504
result = self.sql_ex(sql_s, (href, ))
499505
return Event(result[0][0],
500506
local_tz =self.conf.default.local_timezone,
@@ -506,10 +512,11 @@ def get_vevent_from_db(self, href, account_name, start=None, end=None,
506512
account=account_name,
507513
status=result[0][1],
508514
readonly=readonly,
515+
etag=result[0][2],
509516
unicode_symbols=unicode_symbols)
510517

511518
def get_changed(self, account_name):
512-
"""returns list of hrefs of locally edited vcards
519+
"""returns list of hrefs of locally edited vevents
513520
"""
514521
sql_s = 'SELECT href FROM {0} WHERE status == (?)'.format(account_name)
515522
result = self.sql_ex(sql_s, (CHANGED, ))

khal/caldav.py

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -349,20 +349,20 @@ def _create_calendar(self):
349349

350350
return calendar
351351

352-
353-
def _create_timezone(self,conf):
352+
def _create_timezone(self, tz):
354353
"""
355-
create the timezone information
354+
create an icalendar timezone from a pytz.tzinfo
356355
357-
:param conf: the configuration settings
358-
:type conf: Namespace()
356+
:param tz: the timezone
357+
:type conf: pytz.tzinfo
359358
:returns: timezone information set
360359
:rtype: icalendar.Timezone()
361360
"""
362361
timezone = icalendar.Timezone()
363-
tz = conf.default.default_timezone
364362
timezone.add('TZID', tz)
365-
daylight, standard = [(num, dt) for num,dt in enumerate(tz._utc_transition_times) if dt.year == datetime.datetime.today().year]
363+
364+
# FIXME should match year of the event, not this year
365+
daylight, standard = [(num, dt) for num, dt in enumerate(tz._utc_transition_times) if dt.year == datetime.datetime.today().year]
366366

367367
timezone_daylight = icalendar.TimezoneDaylight()
368368
timezone_daylight.add('TZNAME', tz._transition_info[daylight[0]][2])
@@ -395,7 +395,7 @@ def upload(self, conf, vevent):
395395
"""
396396
self._check_write_support()
397397
calendar = self._create_calendar()
398-
timezone = self._create_timezone(conf)
398+
timezone = self._create_timezone(conf.default.default_timezone) # FIXME
399399
calendar.add_component(timezone)
400400
calendar.add_component(vevent)
401401

@@ -420,3 +420,38 @@ def upload(self, conf, vevent):
420420

421421
return (parsed_url.path, etag)
422422
response.raise_for_status()
423+
424+
def update(self, vevent, href, etag):
425+
"""
426+
updates a modified event on the server
427+
428+
:param vevent: the event to upload
429+
:type vevent: icalendar.cal.Event
430+
:param href: the href of the event
431+
:type href: str
432+
:param etag: etag of the event
433+
:type etag: str
434+
:returns: new etag (if the server returns it)
435+
:rtype: str or None
436+
"""
437+
self._check_write_support()
438+
calendar = self._create_calendar()
439+
if (vevent['DTSTART'].dt, 'tzinfo'): # FIXME as most other timezone related stuff
440+
timezone = self._create_timezone(vevent['DTSTART'].dt.tzinfo)
441+
calendar.add_component(timezone)
442+
calendar.add_component(vevent)
443+
444+
remotepath = str(self.url.base + href)
445+
headers = self.headers
446+
headers['content-type'] = 'text/calendar'
447+
headers['If-Match'] = etag
448+
response = requests.put(remotepath,
449+
data=calendar.to_ical(),
450+
headers=headers,
451+
**self._settings)
452+
response.raise_for_status()
453+
454+
if 'etag' in response.headers.keys():
455+
return response.headers['etag']
456+
else:
457+
return None

khal/controllers.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,12 @@ def __init__(self, conf, sync_account_name):
137137
'you need to enable write support to use this feature'
138138
', see the documentation.')
139139

140+
# syncing locally modified events
141+
hrefs = self.dbtool.get_changed(sync_account.name)
142+
for href in hrefs:
143+
event = self.dbtool.get_vevent_from_db(href, sync_account.name)
144+
etag = self.syncer.update(event.vevent, event.href, event.etag)
145+
140146
# looking for events deleted on the server but still in the local db
141147
locale_hrefs = self.dbtool.hrefs_by_time_range(start_utc,
142148
end_utc,

khal/model.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
class Event(object):
3434
def __init__(self, ical, status=0, href=None, account=None, local_tz=None,
3535
default_tz=None, start=None, end=None, color=None,
36-
readonly=False, unicode_symbols=True, dbtool=None):
36+
readonly=False, unicode_symbols=True, dbtool=None, etag=None):
3737
self.vevent = icalendar.Event.from_ical(ical)
3838
if account is None:
3939
raise TypeError('account must not be None')
@@ -45,6 +45,7 @@ def __init__(self, ical, status=0, href=None, account=None, local_tz=None,
4545
self.readonly = readonly
4646
self.unicode_symbols = unicode_symbols
4747
self.dbtool = dbtool
48+
self.etag = etag
4849

4950
if unicode_symbols:
5051
self.recurstr = u' ⟳'
@@ -110,6 +111,8 @@ def compact(self, day, timeformat='%H:%M'):
110111
status = 'X '
111112
elif self.status == NEW:
112113
status = 'N '
114+
elif self.status == CHANGED:
115+
status = 'M '
113116
else:
114117
status = ''
115118
if self.allday:

khal/ui/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -804,6 +804,7 @@ def save(self, button):
804804
self.dbtool.update(self.event.vevent.to_ical(),
805805
self.event.account,
806806
self.event.href,
807+
etag=self.event.etag,
807808
status=status)
808809
self.cancel(refresh=True)
809810

0 commit comments

Comments
 (0)