Skip to content

Commit

Permalink
Support for adding alarms (without having to manually create the ical…
Browse files Browse the repository at this point in the history
…endar data) to events. Partial fix for #132
  • Loading branch information
tobixen committed Nov 30, 2022
1 parent cd92b62 commit b6d3e03
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 6 deletions.
23 changes: 21 additions & 2 deletions caldav/lib/vcal.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

import icalendar
from caldav.lib.python_utilities import to_normal_str
from caldav.lib.python_utilities import to_local
from caldav.lib.python_utilities import to_wire

## Fixups to the icalendar data to work around compatbility issues.

Expand Down Expand Up @@ -81,8 +83,12 @@ def fix(event):

## sorry for being english-language-euro-centric ... fits rather perfectly as default language for me :-)
def create_ical(ical_fragment=None, objtype=None, language="en_DK", **props):
"""
I somehow feel this fits more into the icalendar library than here
"""Creates some icalendar based on properties given as parameters.
It basically creates an icalendar object with all the boilerplate,
some sensible defaults, the properties given and returns it as a
string.
TODO: timezones not supported so far
"""
ical_fragment = to_normal_str(ical_fragment)
if not ical_fragment or not re.search("^BEGIN:V", ical_fragment, re.MULTILINE):
Expand All @@ -105,18 +111,31 @@ def create_ical(ical_fragment=None, objtype=None, language="en_DK", **props):
my_instance = icalendar.Calendar.from_ical(ical_fragment)
component = my_instance.subcomponents[0]
ical_fragment = None
alarm = {}
for prop in props:
if props[prop] is not None:
if prop in ("child", "parent"):
for value in props[prop]:
component.add(
"related-to", props[prop], parameters={"rel-type": prop.upper()}
)
elif prop.startswith("alarm_"):
alarm[prop[6:]] = props[prop]
else:
component.add(prop, props[prop])
if alarm:
add_alarm(my_instance, alarm)
ret = to_normal_str(my_instance.to_ical())
if ical_fragment and ical_fragment.strip():
ret = re.sub(
"^END:V", ical_fragment.strip() + "\nEND:V", ret, flags=re.MULTILINE
)
return ret


def add_alarm(ical, alarm):
ia = icalendar.Alarm()
for prop in alarm:
ia.add(prop, alarm[prop])
ical.subcomponents[0].add_component(ia)
return ical
9 changes: 5 additions & 4 deletions caldav/objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -704,7 +704,8 @@ def save_event(self, ical=None, no_overwrite=False, no_create=False, **ical_data
* ical - ical object (text)
* no_overwrite - existing calendar objects should not be overwritten
* no_create - don't create a new object, existing calendar objects should be updated
* ical_data - passed to lib.vcal.create_ical
* dt_start, dt_end, summary, etc - properties to be inserted into the icalendar object
* alarm_trigger, alarm_action, alarm_attach, etc - when given, one alarm will be added
"""
e = Event(
self.client,
Expand Down Expand Up @@ -1906,7 +1907,7 @@ def copy(self, keep_uid=False, new_parent=None):
id=self.id if keep_uid else str(uuid.uuid1()),
)
if new_parent or not keep_uid:
obj.url = obj.generate_url()
obj.url = obj._generate_url()
else:
obj.url = self.url
return obj
Expand Down Expand Up @@ -1963,7 +1964,7 @@ def _find_id_path(self, id=None, path=None):
error.assert_(x.get("UID", None) == self.id)

if path is None:
path = self.generate_url()
path = self._generate_url()
else:
path = self.parent.url.join(path)

Expand Down Expand Up @@ -1992,7 +1993,7 @@ def _create(self, id=None, path=None, retry_on_failure=True):
self._find_id_path(id=id, path=path)
self._put()

def generate_url(self):
def _generate_url(self):
## See https://github.com/python-caldav/caldav/issues/143 for the rationale behind double-quoting slashes
## TODO: should try to wrap my head around issues that arises when id contains weird characters. maybe it's
## better to generate a new uuid here, particularly if id is in some unexpected format.
Expand Down
12 changes: 12 additions & 0 deletions tests/test_caldav.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from collections import namedtuple
from datetime import date
from datetime import datetime
from datetime import timedelta

import pytest
import requests
Expand Down Expand Up @@ -766,6 +767,17 @@ def testCreateEvent(self):
events = c.events()
assert len(events) == len(existing_events) + 2

def testCreateAlarm(self):
c = self._fixCalendar()
ev = c.save_event(
dtstart=datetime(2015, 10, 10, 8, 7, 6),
summary="This is a test event",
dtend=datetime(2016, 10, 10, 9, 8, 7),
alarm_trigger=timedelta(minutes=-15),
alarm_action="AUDIO",
)
pass

def testCalendarByFullURL(self):
"""
ref private email, passing a full URL as cal_id works in 0.5.0 but
Expand Down

0 comments on commit b6d3e03

Please sign in to comment.