def __init__(self, collection, conf, date_list, location=None, repeat=None): try: event = aux.construct_event( date_list, location=location, repeat=repeat, **conf['locale']) except FatalError: sys.exit(1) event = Event(event, collection.default_calendar_name, locale=conf['locale'], ) try: collection.new(event) except ReadOnlyCalendarError: logger.fatal('ERROR: Cannot modify calendar "{}" as it is ' 'read-only'.format(collection.default_calendar_name)) sys.exit(1) if conf['default']['print_new'] == 'event': echo(event.long()) elif conf['default']['print_new'] == 'path': path = collection._calnames[event.calendar].path + event.href echo(path.encode(conf['locale']['encoding']))
def test_raw_dt(self): event = Event(event_dt, **event_kwargs) assert event.raw.split('\r\n') == cal_dt assert event.compact(datetime.date(2014, 4, 9)) == u'09:30-10:30: An Event' event = Event(event_dt, unicode_symbols=False, **event_kwargs) assert event.compact(datetime.date(2014, 4, 9)) == u'09:30-10:30: An Event' assert event.recur is False
def test_update_simple(): event = Event.fromString(_get_text('event_dt_simple'), **EVENT_KWARGS) event_updated = Event.fromString(_get_text('event_dt_simple_updated'), **EVENT_KWARGS) event.update_summary('A not so simple Event') event.update_description('Everything has changed') event.update_location('anywhere') assert normalize_component(event.raw) == normalize_component(event_updated.raw)
def test_dt_two_tz(): event = Event(event_dt_two_tz, **event_kwargs) assert normalize_component(cal_dt_two_tz) == normalize_component(event.raw) # local (Berlin) time! assert event.compact(datetime.date(2014, 4, 9)) == u'09:30-16:30: An Event' assert event.long() == u'09:30-16:30 09.04.2014: An Event'
def test_event_rr(self): event = Event(event_dt_rr, **event_kwargs) assert event.recur is True assert event.compact(datetime.date(2014, 4, 9)) == u'09:30-10:30: An Event ⟳' event = Event(event_d_rr, **event_kwargs) assert event.recur is True assert event.compact(datetime.date(2014, 4, 9)) == u'Another Event ⟳'
def test_cancelled_instance(): orig_event_str = _get_text('event_rrule_recuid_cancelled') event = Event.fromString(orig_event_str, ref='1405314000', **EVENT_KWARGS) assert event.format(SEARCH_FORMAT, dt.date(2014, 7, 14)) == \ 'CANCELLED 14.07.2014 07:00-12:00 Arbeit ⟳\x1b[0m' event = Event.fromString(orig_event_str, ref='PROTO', **EVENT_KWARGS) assert event.format(SEARCH_FORMAT, dt.date(2014, 7, 14)) == \ '30.06.2014 07:00-12:00 Arbeit ⟳\x1b[0m'
def test_event_no_dst(): """test the creation of a corect VTIMEZONE for timezones with no dst""" bogota_locale = locale.copy() bogota_locale['local_timezone'] = bogota bogota_locale['default_timezone'] = bogota event = Event(event_no_dst, calendar='foobar', locale=bogota_locale) assert event.raw.split('\r\n') == cal_no_dst assert event.long() == u'09:30-10:30 09.04.2014: An Event'
def test_raw_dt(): event = Event(event_dt, **event_kwargs) assert normalize_component(event.raw) == normalize_component(cal_dt) assert event.compact(datetime.date(2014, 4, 9)) == u'09:30-10:30: An Event' event = Event(event_dt, unicode_symbols=False, **event_kwargs) assert event.compact(datetime.date(2014, 4, 9)) == u'09:30-10:30: An Event' assert event.long() == u'09:30-10:30 09.04.2014: An Event' assert event.recur is False
def test_list(self, coll_vdirs): coll, vdirs = coll_vdirs event = Event.fromString(event_d, calendar=cal1, locale=aux.locale) coll.new(event) event = Event.fromString(event_today, calendar=cal1, locale=aux.locale) coll.new(event) hrefs = sorted(href for href, uid in coll._backend.list(cal1)) assert set(str(coll._backend.get(href, calendar=cal1).uid) for href in hrefs) == set(( '*****@*****.**', 'V042MJ8B3SJNFXQOJL6P53OFMHJE8Z3VZWOU', ))
def test_list(self, cal_vdir): cal, vdir = cal_vdir event = Event.fromString(event_d, calendar=cal.name, locale=aux.locale) cal.new(event) event = Event.fromString(event_today, calendar=cal.name, locale=aux.locale) cal.new(event) hrefs = sorted(href for href, uid in cal._dbtool.list()) assert set(str(cal._dbtool.get(href).uid) for href in hrefs) == set(( '*****@*****.**', 'V042MJ8B3SJNFXQOJL6P53OFMHJE8Z3VZWOU', ))
def test_list(self, cal_vdir): cal, vdir = cal_vdir event = Event.fromString(event_d, calendar=cal.name, locale=locale) cal.new(event) event = Event.fromString(event_today, calendar=cal.name, locale=locale) cal.new(event) hrefs = sorted(href for href, uid in cal._dbtool.list()) assert hrefs == [ 'V042MJ8B3SJNFXQOJL6P53OFMHJE8Z3VZWOU.ics', '*****@*****.**' ] assert cal._dbtool.get('*****@*****.**').uid == '*****@*****.**'
def test_event_dt_tz_missing(): """localized event DTSTART;TZID=foo, but VTIMEZONE components missing""" event_str = _get_text('event_dt_local_missing_tz') event = Event.fromString(event_str, **EVENT_KWARGS) assert event.start == BERLIN.localize(datetime(2014, 4, 9, 9, 30)) assert event.end == BERLIN.localize(datetime(2014, 4, 9, 10, 30)) assert event.start_local == BERLIN.localize(datetime(2014, 4, 9, 9, 30)) assert event.end_local == BERLIN.localize(datetime(2014, 4, 9, 10, 30)) event = Event.fromString(event_str, calendar='foobar', locale=MIXED_LOCALE) assert event.start == BERLIN.localize(datetime(2014, 4, 9, 9, 30)) assert event.end == BERLIN.localize(datetime(2014, 4, 9, 10, 30)) assert event.start_local == BOGOTA.localize(datetime(2014, 4, 9, 2, 30)) assert event.end_local == BOGOTA.localize(datetime(2014, 4, 9, 3, 30))
def test_event_dt_tz_missing(): """localized event DTSTART;TZID=foo, but VTIMEZONE components missing""" event_str = _get_text('event_dt_local_missing_tz') event = Event.fromString(event_str, **EVENT_KWARGS) assert event.start == BERLIN.localize(dt.datetime(2014, 4, 9, 9, 30)) assert event.end == BERLIN.localize(dt.datetime(2014, 4, 9, 10, 30)) assert event.start_local == BERLIN.localize(dt.datetime(2014, 4, 9, 9, 30)) assert event.end_local == BERLIN.localize(dt.datetime(2014, 4, 9, 10, 30)) assert event.format('{duration}', relative_to=dt.date.today()) == '1h\x1b[0m' event = Event.fromString(event_str, calendar='foobar', locale=LOCALE_MIXED) assert event.start == BERLIN.localize(dt.datetime(2014, 4, 9, 9, 30)) assert event.end == BERLIN.localize(dt.datetime(2014, 4, 9, 10, 30)) assert event.start_local == BOGOTA.localize(dt.datetime(2014, 4, 9, 2, 30)) assert event.end_local == BOGOTA.localize(dt.datetime(2014, 4, 9, 3, 30))
def test_transform_event(): """test if transformation between different event types works""" event_d = _get_text('event_d') event = Event.fromString(event_d, **EVENT_KWARGS) assert isinstance(event, AllDayEvent) start = BERLIN.localize(datetime(2014, 4, 9, 9, 30)) end = BERLIN.localize(datetime(2014, 4, 9, 10, 30)) event.update_start_end(start, end) assert isinstance(event, LocalizedEvent) assert event.event_description == '09:30-10:30 09.04.2014: An Event' analog_event = Event.fromString(_get_text('event_dt_simple'), **EVENT_KWARGS) assert normalize_component(event.raw) == normalize_component(analog_event.raw) with pytest.raises(ValueError): event.update_start_end(start, date(2014, 4, 9))
def test_event_d_rr(): event_d_rr = _get_text('event_d_rr') event = Event.fromString(event_d_rr, **EVENT_KWARGS) assert event.recurring is True desc = 'Another Event ⟳' assert event.relative_to(date(2014, 4, 9)) == desc assert event.event_description == '09.04.2014: Another Event\nRepeat: FREQ=DAILY;COUNT=10' start = date(2014, 4, 10) end = date(2014, 4, 11) event = Event.fromString(event_d_rr, start=start, end=end, **EVENT_KWARGS) assert event.recurring is True desc = 'Another Event ⟳' assert event.relative_to(date(2014, 4, 10)) == desc assert event.event_description == '10.04.2014: Another Event\nRepeat: FREQ=DAILY;COUNT=10'
def new_from_args(collection, calendar_name, conf, dtstart=None, dtend=None, summary=None, description=None, allday=None, location=None, categories=None, repeat=None, until=None, alarms=None, timezone=None, format=None, env=None): try: event = aux.new_event(locale=conf['locale'], location=location, categories=categories, repeat=repeat, until=until, alarms=alarms, dtstart=dtstart, dtend=dtend, summary=summary, description=description, timezone=timezone) except ValueError as e: logger.fatal('ERROR: '+str(e)) sys.exit(1) except FatalError: sys.exit(1) event = Event.fromVEvents( [event], calendar=calendar_name, locale=conf['locale']) try: collection.new(event) except ReadOnlyCalendarError: logger.fatal('ERROR: Cannot modify calendar "{}" as it is ' 'read-only'.format(calendar_name)) sys.exit(1) if conf['default']['print_new'] == 'event': if format is None: format = conf['view']['event_format'] echo(event.format(format, datetime.now(), env=env)) elif conf['default']['print_new'] == 'path': path = collection._calnames[event.calendar].path + event.href echo(path) return event
def test_no_end(): """reading an event with neither DTEND nor DURATION""" event = Event.fromString(_get_text('event_dt_no_end'), **EVENT_KWARGS) # TODO make sure the event also gets converted to an all day event, as we # usually do assert event.format(SEARCH_FORMAT, dt.date(2014, 4, 12)) == \ '16.01.2016 08:00-17.01.2016 08:00 Test\x1b[0m'
def test_remove_instance_from_two_rdate(): """removing an instance from a recurring event which has two RDATE props""" event = Event.fromString(_get_text('event_dt_two_rd'), **EVENT_KWARGS) assert event.raw.count('RDATE') == 2 event.delete_instance(datetime(2014, 4, 10, 9, 30)) assert event.raw.count('RDATE') == 1 assert 'RDATE:20140411T093000,20140412T093000' in event.raw.split('\r\n')
def new_from_string(collection, calendar_name, conf, date_list, location=None, repeat=None, until=None): """construct a new event from a string and add it""" try: event = aux.construct_event( date_list, location=location, repeat=repeat, until=until, locale=conf['locale']) except FatalError: sys.exit(1) event = Event.fromVEvents( [event], calendar=calendar_name, locale=conf['locale']) try: collection.new(event) except ReadOnlyCalendarError: logger.fatal('ERROR: Cannot modify calendar "{}" as it is ' 'read-only'.format(calendar_name)) sys.exit(1) if conf['default']['print_new'] == 'event': echo(event.event_description) elif conf['default']['print_new'] == 'path': path = collection._calnames[event.calendar].path + event.href echo(path.encode(conf['locale']['encoding']))
def test_search(self, coll_vdirs): coll, vdirs = coll_vdirs assert len(list(coll.search('Event'))) == 0 event = Event.fromString( _get_text('event_dt_simple'), calendar=cal1, locale=aux.locale) coll.new(event, cal1) assert len(list(coll.search('Event'))) == 1
def test_event_no_dst(): """test the creation of a corect VTIMEZONE for timezones with no dst""" event_no_dst = _get_text('event_no_dst') cal_no_dst = _get_text('cal_no_dst') event = Event.fromString(event_no_dst, calendar='foobar', locale=BOGOTA_LOCALE) assert normalize_component(event.raw) == normalize_component(cal_no_dst) assert event.event_description == '09:30-10:30 09.04.2014: An Event'
def test_remove_instance_from_rrule(): """removing an instance from a recurring event""" event = Event.fromString(_get_text('event_dt_rr'), **EVENT_KWARGS) event.delete_instance(datetime(2014, 4, 10, 9, 30)) assert 'EXDATE:20140410T093000' in event.raw.split('\r\n') event.delete_instance(datetime(2014, 4, 12, 9, 30)) assert 'EXDATE:20140410T093000,20140412T093000' in event.raw.split('\r\n')
def test_update_event_d(): event_d = _get_text('event_d') event = Event.fromString(event_d, **EVENT_KWARGS) event.update_start_end(date(2014, 4, 20), date(2014, 4, 22)) assert event.event_description == '20.04. - 22.04.2014: An Event' assert 'DTSTART;VALUE=DATE:20140420' in event.raw.split('\r\n') assert 'DTEND;VALUE=DATE:20140423' in event.raw.split('\r\n')
def test_multi_uid(): """test for support for events with consist of several sub events with the same uid""" orig_event_str = _get_text('event_rrule_recuid') event = Event.fromString(orig_event_str, **EVENT_KWARGS) for line in orig_event_str.split('\n'): assert line in event.raw.split('\r\n')
def test_event_d_rr(): event_d_rr = _get_text('event_d_rr') event = Event.fromString(event_d_rr, **EVENT_KWARGS) assert event.recurring is True assert event.format(LIST_FORMAT, date(2014, 4, 9)) == ' Another Event ⟳\x1b[0m' assert event.format(SEARCH_FORMAT, date(2014, 4, 9)) == \ '09.04.2014 Another Event ⟳\x1b[0m' assert event.format('{repeat-pattern}', date(2014, 4, 9)) == 'FREQ=DAILY;COUNT=10\x1b[0m' start = date(2014, 4, 10) end = date(2014, 4, 11) event = Event.fromString(event_d_rr, start=start, end=end, **EVENT_KWARGS) assert event.recurring is True assert event.format(LIST_FORMAT, date(2014, 4, 10)) == ' Another Event ⟳\x1b[0m' assert event.format(SEARCH_FORMAT, date(2014, 4, 10)) == \ '10.04.2014 Another Event ⟳\x1b[0m'
def test_event_dt_duration(): """event has no end, but duration""" event_dt_duration = _get_text('event_dt_duration') event = Event.fromString(event_dt_duration, **EVENT_KWARGS) assert event.relative_to(date(2014, 4, 9)) == u'09:30-10:30: An Event' assert event.end == BERLIN.localize(datetime(2014, 4, 9, 10, 30)) assert event.event_description == u'09:30-10:30 09.04.2014: An Event'
def test_event_no_dst(): """test the creation of a corect VTIMEZONE for timezones with no dst""" event_no_dst = _get_text('event_no_dst') cal_no_dst = _get_text('cal_no_dst') event = Event.fromString(event_no_dst, calendar='foobar', locale=BOGOTA_LOCALE) assert normalize_component(event.raw) == normalize_component(cal_no_dst) assert event.format(SEARCH_FORMAT, date(2014, 4, 10)) == \ '09.04.2014 09:30-10:30 An Event \x1b[0m'
def test_raw_dt(): event_dt = _get_text('event_dt_simple') start = BERLIN.localize(datetime(2014, 4, 9, 9, 30)) end = BERLIN.localize(datetime(2014, 4, 9, 10, 30)) event = Event.fromString(event_dt, start=start, end=end, **EVENT_KWARGS) with freeze_time('2016-1-1'): assert normalize_component(event.raw) == \ normalize_component(_get_text('event_dt_simple_inkl_vtimezone')) event = Event.fromString(event_dt, **EVENT_KWARGS) assert event.format(LIST_FORMAT, date(2014, 4, 9)) == '09:30-10:30 An Event \x1b[0m' assert event.format(SEARCH_FORMAT, date(2014, 4, 9)) == \ '09.04.2014 09:30-10:30 An Event \x1b[0m' assert event.recurring is False assert event.duration == timedelta(hours=1) assert event.uid == 'V042MJ8B3SJNFXQOJL6P53OFMHJE8Z3VZWOU' assert event.organizer == ''
def test_event_dt_long(): event_dt_long = _get_text('event_dt_long') event = Event.fromString(event_dt_long, **EVENT_KWARGS) assert event.relative_to(date(2014, 4, 9)) == '09:30→ : An Event' # FIXME ugly! replace with one arrow assert event.relative_to(date(2014, 4, 10)) == '→ → : An Event' assert event.relative_to(date(2014, 4, 12)) == '→ 10:30: An Event' assert event.event_description == '09.04.2014 09:30 - 12.04.2014 10:30: An Event'
def test_remove_instance_from_recuid(): """remove an istance from an event which is specified via an additional VEVENT with the same UID (which we call `recuid` here""" event = Event.fromString(_get_text('event_rrule_recuid'), **EVENT_KWARGS) assert event.raw.split('\r\n').count('UID:event_rrule_recurrence_id') == 2 event.delete_instance(BERLIN.localize(datetime(2014, 7, 7, 7, 0))) assert event.raw.split('\r\n').count('UID:event_rrule_recurrence_id') == 1 assert 'EXDATE;TZID=Europe/Berlin:20140707T070000' in event.raw.split('\r\n')
def import_event(vevent, collection, locale, batch, format=None, env=None): """import one event into collection, let user choose the collection :type vevent: list of vevents, which can be more than one VEVENT, i.e., the same UID, i.e., one "master" event and (optionally) 1+ RECURRENCE-ID events :type vevent: list(str) """ # print all sub-events if not batch: for item in cal_from_ics(vevent).walk(): if item.name == 'VEVENT': event = Event.fromVEvents( [item], calendar=collection.default_calendar_name, locale=locale) echo(event.format(format, dt.datetime.now(), env=env)) # get the calendar to insert into if not collection.writable_names: raise ConfigurationError( 'No writable calendars found, aborting import.') if len(collection.writable_names) == 1: calendar_name = collection.writable_names[0] elif batch: calendar_name = collection.default_calendar_name else: calendar_names = sorted(collection.writable_names) choices = ', '.join([ '{}({})'.format(name, num) for num, name in enumerate(calendar_names) ]) while True: value = prompt( "Which calendar do you want to import to? (unique prefixes are fine)\n" "{}".format(choices), default=collection.default_calendar_name, ) try: calendar_name = calendar_names[int(value)] break except (ValueError, IndexError): matches = [ x for x in collection.writable_names if x.startswith(value) ] if len(matches) == 1: calendar_name = matches[0] break echo('invalid choice') assert calendar_name in collection.writable_names if batch or confirm("Do you want to import this event into `{}`?".format( calendar_name)): try: collection.new(Item(vevent), collection=calendar_name) except DuplicateUid: if batch or confirm( "An event with the same UID already exists. Do you want to update it?" ): collection.force_update(Item(vevent), collection=calendar_name) else: logger.warning("Not importing event with UID `{}`".format( event.uid))
def test_raw_d(self): assert Event(event_d, **event_kwargs).raw.split('\r\n') == cal_d