def _extract_from_component( incomp: Component, outcomp: Component, requested) -> None: """Extract specific properties from a calendar event. Args: incomp: Incoming component outcomp: Outcoming component requested: Which components should be included """ for tag in requested: if tag.tag == ('{%s}comp' % NAMESPACE): for insub in incomp.subcomponents: if insub.name == tag.get('name'): outsub = component_factory[insub.name]() outcomp.add_component(outsub) _extract_from_component(insub, outsub, tag) elif tag.tag == ('{%s}prop' % NAMESPACE): outcomp[tag.get('name')] = incomp[tag.get('name')] elif tag.tag == ('{%s}allprop' % NAMESPACE): for propname in incomp: outcomp[propname] = incomp[propname] elif tag.tag == ('{%s}allcomp' % NAMESPACE): for insub in incomp.subcomponents: outsub = component_factory[insub.name]() outcomp.add_component(outsub) _extract_from_component(insub, outsub, tag) else: raise AssertionError('invalid element %r' % tag)
def test_format_event_real_html(self): component = Component() component.add('summary', 'Встреча ML-клуба') component.add('location', 'ул. Таубе, 5, Омск, Омская обл., Россия, 644037') component.add( 'description', '10 февраля в 11:00 пройдет 5-я встреча <a href="https://vk.com/mlomsk">ML клуба</a> в офисе <a href="https://vk.com/7bits">7bits</a>, Таубе 5. Регистрация на встречу: <a href="https://vk.com/away.php?to=http%3A%2F%2Fmlomsk.1der.link%2Fmeetup%2Fsignup&post=-141957789_74&cc_key=" target="_blank">mlomsk.1der.link/meetup/signup</a>.<br><br>В этот раз у нас будет 2 доклада:' ) timezone = pytz.timezone('Asia/Omsk') component.add( 'dtstart', datetime.datetime(2018, 2, 10, 11, 0, 0, tzinfo=timezone)) event = Event.from_vevent(component, timezone) user_config = UserConfig.new(Config('calbot.cfg.sample'), 'TEST') user_config.language = 'ru_RU.UTF-8' result = format_event(user_config, event) self.assertEqual( 'Встреча ML-клуба\nСуббота, 10 февраля 2018, 11:00 Asia/Omsk\nул. Таубе, 5, Омск, Омская обл., Россия, 644037\n10 февраля в 11:00 пройдет 5-я встреча ML клуба (https://vk.com/mlomsk) в офисе 7bits (https://vk.com/7bits), Таубе 5. Регистрация на встречу: mlomsk.1der.link/meetup/signup.\n\nВ этот раз у нас будет 2 доклада:', result)
def test_cal_Component_add_property_parameter(self): # Test the for timezone correctness: dtstart should preserve it's # timezone, crated, dtstamp and last-modified must be in UTC. Component = icalendar.cal.Component comp = Component() comp.add("X-TEST-PROP", "tryout.", parameters={"prop1": "val1", "prop2": "val2"}) lines = comp.to_ical().splitlines() self.assertTrue(b"X-TEST-PROP;PROP1=val1;PROP2=val2:tryout." in lines)
def test_cal_Component_add_property_parameter(self): # Test the for timezone correctness: dtstart should preserve it's # timezone, crated, dtstamp and last-modified must be in UTC. Component = icalendar.cal.Component comp = Component() comp.add('X-TEST-PROP', 'tryout.', parameters={'prop1': 'val1', 'prop2': 'val2'}) lines = comp.to_ical().splitlines() self.assertTrue(b"X-TEST-PROP;PROP1=val1;PROP2=val2:tryout." in lines)
def test_format_event_blanks(self): component = Component() component.add('dtstart', datetime.datetime(2018, 2, 3, 13, 3, 4, tzinfo=pytz.UTC)) event = Event.from_vevent(component, pytz.UTC) user_config = UserConfig.new(Config('calbot.cfg.sample'), 'TEST') user_config.language = 'ru_RU.UTF-8' result = format_event(user_config, event) self.assertEqual( 'None\nСуббота, 03 февраля 2018, 13:03 UTC\nNone\nNone', result)
def test_cal_Component_from_ical(self): # RecurrenceIDs may contain a TZID parameter, if so, they should create # a tz localized datetime, otherwise, create a naive datetime Component = icalendar.cal.Component componentStr = 'BEGIN:VEVENT\nRECURRENCE-ID;TZID=America/Denver:'\ + '20120404T073000\nEND:VEVENT' component = Component.from_ical(componentStr) self.assertEqual(str(component['RECURRENCE-ID'].dt.tzinfo.zone), "America/Denver") componentStr = 'BEGIN:VEVENT\nRECURRENCE-ID:20120404T073000\n'\ + 'END:VEVENT' component = Component.from_ical(componentStr) self.assertEqual(component['RECURRENCE-ID'].dt.tzinfo, None)
def cnode2ical(cnode): """Convert a tree of cnodes to an ical calendar cnode: typically from Erebus2ICSVisitor return: icalendar.Calendar """ comp = Component() comp.name = cnode.name.upper() for k,v in cnode.attr.iteritems(): # If an attribute is a CNode, say n, we must add all the # attributes of n as parameters to the iCalendar element. We # first encode the value to the corresponding iCalendar value # (with types_factory, like icalendar.Component does # internally), and then add the parameters. if v.__class__ == CNode: target_class = types_factory.for_property(k) val = target_class(v.content) val.params = Parameters() for p,pv in v.attr.iteritems(): val.params[p] = pv comp.add(k, val, encode=0) else: comp.add(k, v, encode=1) for c in cnode.children: comp.add_component(cnode2ical(c)) return comp
def test_cal_Component_from_ical(self): # RecurrenceIDs may contain a TZID parameter, if so, they should create # a tz localized datetime, otherwise, create a naive datetime Component = icalendar.cal.Component componentStr = 'BEGIN:VEVENT\nRECURRENCE-ID;TZID=America/Denver:'\ + '20120404T073000\nEND:VEVENT' component = Component.from_ical(componentStr) self.assertEqual( str(component['RECURRENCE-ID'].dt.tzinfo.zone), "America/Denver") componentStr = 'BEGIN:VEVENT\nRECURRENCE-ID:20120404T073000\n'\ + 'END:VEVENT' component = Component.from_ical(componentStr) self.assertEqual(component['RECURRENCE-ID'].dt.tzinfo, None)
def test_cal_Component_add(self): # Test the for timezone correctness: dtstart should preserve it's # timezone, crated, dtstamp and last-modified must be in UTC. Component = icalendar.cal.Component comp = Component() comp.add("dtstart", datetime(2010, 10, 10, 10, 0, 0, tzinfo=pytz.timezone("Europe/Vienna"))) comp.add("created", datetime(2010, 10, 10, 12, 0, 0)) comp.add("dtstamp", datetime(2010, 10, 10, 14, 0, 0, tzinfo=pytz.timezone("Europe/Vienna"))) comp.add("last-modified", datetime(2010, 10, 10, 16, 0, 0, tzinfo=pytz.utc)) lines = comp.to_ical().splitlines() self.assertTrue("DTSTART;TZID=Europe/Vienna;VALUE=DATE-TIME:20101010T100000" in lines) self.assertTrue("CREATED;VALUE=DATE-TIME:20101010T120000Z" in lines) self.assertTrue("DTSTAMP;VALUE=DATE-TIME:20101010T130000Z" in lines) self.assertTrue("LAST-MODIFIED;VALUE=DATE-TIME:20101010T160000Z" in lines)
def make_ical(self, csv_configs=None): # type: (Dict[str, int]) -> Calendar """ Make iCal entries """ csv_configs = self._generate_configs_from_default(csv_configs) self.cal = Calendar() self.cal.add('version', '2.0') self.cal.add('prodid', 'Custom Rapla to csv to ics converter') timezone = Timezone() timezone = Component.from_ical(vtimezone_str) self.cal.add_component(timezone) for row in self.csv_data: event = Event() event.add('summary', row[csv_configs['CSV_NAME']]) event.add('dtstart', row[csv_configs['CSV_START_DATE']]) event.add('dtend', row[csv_configs['CSV_END_DATE']]) event.add('description', row[csv_configs['CSV_DESCRIPTION']]) event.add('location', row[csv_configs['CSV_LOCATION']]) event.add( 'uid', b64encode(( row[csv_configs['CSV_START_DATE']].strftime( "%Y-%m-%d %H:%M") + row[csv_configs['CSV_END_DATE']].strftime("%Y-%m-%d %H:%M") + row[csv_configs['CSV_DESCRIPTION']] + '@' + uname()[1]).encode('utf-8'))) event.add('dtstamp', datetime.datetime.now()) self.cal.add_component(event) return self.cal
def test_format_event_html(self): component = Component() component.add('summary', '<b>summary</b>') component.add('location', '<i>location</i>') component.add( 'description', '<b>description</b><br><br> <a href="link.html">link</a>') component.add('dtstart', datetime.datetime(2018, 2, 3, 13, 3, 4, tzinfo=pytz.UTC)) event = Event.from_vevent(component, pytz.UTC) user_config = UserConfig.new(Config('calbot.cfg.sample'), 'TEST') user_config.language = 'ru_RU.UTF-8' result = format_event(user_config, event) self.assertEqual( 'summary\nСуббота, 03 февраля 2018, 13:03 UTC\nlocation\ndescription\n\n link (link.html)', result)
def test_repr(self): """Test correct class representation. """ from icalendar.cal import Component, Calendar, Event component = Component() component['key1'] = 'value1' self.assertTrue( re.match(r"Component\({u?'KEY1': 'value1'}\)", str(component))) calendar = Calendar() calendar['key1'] = 'value1' self.assertTrue( re.match(r"VCALENDAR\({u?'KEY1': 'value1'}\)", str(calendar))) event = Event() event['key1'] = 'value1' self.assertTrue(re.match(r"VEVENT\({u?'KEY1': 'value1'}\)", str(event))) # Representation of nested Components nested = Component(key1='VALUE1') nested.add_component(component) calendar.add_component(event) nested.add_component(calendar) self.assertTrue( re.match( r"Component\({u?'KEY1': 'VALUE1'}, Component\({u?'KEY1': 'value1'}\), VCALENDAR\({u?'KEY1': 'value1'}, VEVENT\({u?'KEY1': 'value1'}\)\)\)", # nopep8 str(nested)))
def __init__(self, name=u'Jリーグ'): cal = Calendar() cal['method'] = 'PUBLISH' cal['prodid'] = '-//J-League Calendar//S.Kitazaki//' cal['version'] = '2.0' cal.set('X-WR-CALNAME', name) cal['X-WR-TIMEZONE'] = 'Asia/Tokyo' tz = Timezone() tz['TZID'] = 'Asia/Tokyo' tz['X-LIC-LOCATION'] = 'Asia/Tokyo' c = Component() c.name = 'STANDARD' c['TZOFFSETFROM'] = '+0900' c['TZOFFSETTO'] = '+0900' c['TZNAME'] = 'JST' c['DTSTART'] = '19700101T000000' tz.add_component(c) cal.add_component(tz) self.cal = cal
def test_cal_Component_from_ical(self): # Check for proper handling of TZID parameter of datetime properties Component = icalendar.cal.Component for component_name, property_name in (('VEVENT', 'DTSTART'), ('VEVENT', 'DTEND'), ('VEVENT', 'RECURRENCE-ID'), ('VTODO', 'DUE')): component_str = 'BEGIN:' + component_name + '\n' component_str += property_name + ';TZID=America/Denver:' component_str += '20120404T073000\nEND:' + component_name component = Component.from_ical(component_str) self.assertEqual(str(component[property_name].dt.tzinfo.zone), "America/Denver") component_str = 'BEGIN:' + component_name + '\n' component_str += property_name + ':' component_str += '20120404T073000\nEND:' + component_name component = Component.from_ical(component_str) self.assertEqual(component[property_name].dt.tzinfo, None)
def test_cal_Component_from_ical(self): # Check for proper handling of TZID parameter of datetime properties Component = icalendar.cal.Component for component_name, property_name in ( ("VEVENT", "DTSTART"), ("VEVENT", "DTEND"), ("VEVENT", "RECURRENCE-ID"), ("VTODO", "DUE"), ): component_str = "BEGIN:" + component_name + "\n" component_str += property_name + ";TZID=America/Denver:" component_str += "20120404T073000\nEND:" + component_name component = Component.from_ical(component_str) self.assertEqual(str(component[property_name].dt.tzinfo.zone), "America/Denver") component_str = "BEGIN:" + component_name + "\n" component_str += property_name + ":" component_str += "20120404T073000\nEND:" + component_name component = Component.from_ical(component_str) self.assertEqual(component[property_name].dt.tzinfo, None)
def test_repr(self): """Test correct class representation. """ from icalendar.cal import Component, Calendar, Event component = Component() component['key1'] = 'value1' self.assertTrue( re.match(r"Component\({u?'KEY1': u?'value1'}\)", str(component)) ) calendar = Calendar() calendar['key1'] = 'value1' self.assertTrue( re.match(r"VCALENDAR\({u?'KEY1': u?'value1'}\)", str(calendar)) ) event = Event() event['key1'] = 'value1' self.assertTrue( re.match(r"VEVENT\({u?'KEY1': u?'value1'}\)", str(event)) ) # Representation of nested Components nested = Component(key1='VALUE1') nested.add_component(component) calendar.add_component(event) nested.add_component(calendar) self.assertTrue( re.match( r"Component\({u?'KEY1': u?'VALUE1'}, " r"Component\({u?'KEY1': u?'value1'}\), " r"VCALENDAR\({u?'KEY1': u?'value1'}, " r"VEVENT\({u?'KEY1': u?'value1'}\)\)\)", str(nested) ) )
def test_cal_Component_to_ical_parameter_order(self): Component = icalendar.cal.Component component_str = [b"BEGIN:VEVENT", b"X-FOOBAR;C=one;A=two;B=three:helloworld.", b"END:VEVENT"] component = Component.from_ical(b"\r\n".join(component_str)) sorted_str = component.to_ical().splitlines() assert sorted_str[0] == component_str[0] assert sorted_str[1] == b"X-FOOBAR;A=two;B=three;C=one:helloworld." assert sorted_str[2] == component_str[2] preserved_str = component.to_ical(sorted=False).splitlines() assert preserved_str == component_str
def test_cal_Component_from_ical(self): # Check for proper handling of TZID parameter of datetime properties Component = icalendar.cal.Component for component_name, property_name in ( ('VEVENT', 'DTSTART'), ('VEVENT', 'DTEND'), ('VEVENT', 'RECURRENCE-ID'), ('VTODO', 'DUE') ): component_str = 'BEGIN:' + component_name + '\n' component_str += property_name + ';TZID=America/Denver:' component_str += '20120404T073000\nEND:' + component_name component = Component.from_ical(component_str) self.assertEqual(str(component[property_name].dt.tzinfo.zone), "America/Denver") component_str = 'BEGIN:' + component_name + '\n' component_str += property_name + ':' component_str += '20120404T073000\nEND:' + component_name component = Component.from_ical(component_str) self.assertEqual(component[property_name].dt.tzinfo, None)
def test_cal_Component_to_ical_parameter_order(self): Component = icalendar.cal.Component component_str = [b'BEGIN:VEVENT', b'X-FOOBAR;C=one;A=two;B=three:helloworld.', b'END:VEVENT'] component = Component.from_ical(b'\r\n'.join(component_str)) sorted_str = component.to_ical().splitlines() assert sorted_str[0] == component_str[0] assert sorted_str[1] == b'X-FOOBAR;A=two;B=three;C=one:helloworld.' assert sorted_str[2] == component_str[2] preserved_str = component.to_ical(sorted=False).splitlines() assert preserved_str == component_str
def test_cal_Component_to_ical_property_order(self): Component = icalendar.cal.Component component_str = [b'BEGIN:VEVENT', b'DTSTART:19970714T170000Z', b'DTEND:19970715T035959Z', b'SUMMARY:Bastille Day Party', b'END:VEVENT'] component = Component.from_ical(b'\r\n'.join(component_str)) sorted_str = component.to_ical().splitlines() assert sorted_str != component_str assert set(sorted_str) == set(component_str) preserved_str = component.to_ical(sorted=False).splitlines() assert preserved_str == component_str
def test_cal_Component_to_ical_property_order(self): Component = icalendar.cal.Component component_str = [ b'BEGIN:VEVENT', b'DTSTART:19970714T170000Z', b'DTEND:19970715T035959Z', b'SUMMARY:Bastille Day Party', b'END:VEVENT' ] component = Component.from_ical(b'\r\n'.join(component_str)) sorted_str = component.to_ical().splitlines() assert sorted_str != component_str assert set(sorted_str) == set(component_str) preserved_str = component.to_ical(sorted=False).splitlines() assert preserved_str == component_str
def convert_from_calendar(dict_calendar): data = { 'format': dict_calendar['format'] } if dict_calendar["format"] == CALENDAR: pattern = dict_calendar["pattern"] calendar_event = Component.from_ical( CalendarUtil.decode_calendar_pattern(pattern) ) if isinstance(calendar_event, Event): calendar_event_rule = calendar_event['RRULE'] data['frequence'] = calendar_event_rule['FREQ'][0] if data['frequence'] == MONTHLY and not ( 'INTERVAL' in calendar_event['RRULE']): data['date'] = ' '.join( str(date) for date in calendar_event_rule['BYMONTHDAY']) if data['frequence'] == WEEKLY and not ( 'INTERVAL' in calendar_event['RRULE']): data['day'] = ' '.join( str(CALENDAR_DAY_MAPPING_DICT[day]) for day in calendar_event_rule['BYDAY']) if 'BYHOUR' in calendar_event['RRULE']: data['hour'] = ' '.join( str(hour) for hour in calendar_event_rule['BYHOUR']) if 'BYMINUTE' in calendar_event['RRULE']: data['minute'] = ' '.join( str(minute) for minute in calendar_event_rule['BYMINUTE']) if 'INTERVAL' in calendar_event['RRULE']: data['interval'] = ' '.join( str(interval) for interval in calendar_event_rule['INTERVAL']) return data
def test_cal_Component(self): from icalendar.cal import Component, Calendar, Event from icalendar import prop # A component is like a dictionary with extra methods and attributes. c = Component() c.name = 'VCALENDAR' # Every key defines a property.A property can consist of either a # single item. This can be set with a single value... c['prodid'] = '-//max m//icalendar.mxm.dk/' self.assertEqual( c, Calendar({'PRODID': '-//max m//icalendar.mxm.dk/'}) ) # or with a list c['ATTENDEE'] = ['Max M', 'Rasmussen'] self.assertEqual( c, Calendar({'ATTENDEE': ['Max M', 'Rasmussen'], 'PRODID': '-//max m//icalendar.mxm.dk/'}) ) ### ADD MULTIPLE VALUES TO A PROPERTY # if you use the add method you don't have to considder if a value is # a list or not. c = Component() c.name = 'VEVENT' # add multiple values at once c.add('attendee', ['*****@*****.**', '*****@*****.**']) # or add one per line c.add('attendee', '*****@*****.**') c.add('attendee', '*****@*****.**') # add again multiple values at once to very concatenaton of lists c.add('attendee', ['*****@*****.**', '*****@*****.**']) self.assertEqual( c, Event({'ATTENDEE': [ prop.vCalAddress('*****@*****.**'), prop.vCalAddress('*****@*****.**'), prop.vCalAddress('*****@*****.**'), prop.vCalAddress('*****@*****.**'), prop.vCalAddress('*****@*****.**'), prop.vCalAddress('*****@*****.**') ]}) ) ### # You can get the values back directly ... c.add('prodid', '-//my product//') self.assertEqual(c['prodid'], prop.vText(u'-//my product//')) # ... or decoded to a python type self.assertEqual(c.decoded('prodid'), b'-//my product//') # With default values for non existing properties self.assertEqual(c.decoded('version', 'No Version'), 'No Version') c.add('rdate', [datetime(2013, 3, 28), datetime(2013, 3, 27)]) self.assertTrue(isinstance(c.decoded('rdate'), prop.vDDDLists)) # The component can render itself in the RFC 2445 format. c = Component() c.name = 'VCALENDAR' c.add('attendee', 'Max M') self.assertEqual( c.to_ical(), b'BEGIN:VCALENDAR\r\nATTENDEE:Max M\r\nEND:VCALENDAR\r\n' ) # Components can be nested, so You can add a subcompont. Eg a calendar # holds events. e = Component(summary='A brief history of time') e.name = 'VEVENT' e.add('dtend', '20000102T000000', encode=0) e.add('dtstart', '20000101T000000', encode=0) self.assertEqual( e.to_ical(), b'BEGIN:VEVENT\r\nDTEND:20000102T000000\r\n' + b'DTSTART:20000101T000000\r\nSUMMARY:A brief history of time\r' + b'\nEND:VEVENT\r\n' ) c.add_component(e) self.assertEqual( c.subcomponents, [Event({'DTEND': '20000102T000000', 'DTSTART': '20000101T000000', 'SUMMARY': 'A brief history of time'})] ) # We can walk over nested componentes with the walk method. self.assertEqual([i.name for i in c.walk()], ['VCALENDAR', 'VEVENT']) # We can also just walk over specific component types, by filtering # them on their name. self.assertEqual([i.name for i in c.walk('VEVENT')], ['VEVENT']) self.assertEqual( [i['dtstart'] for i in c.walk('VEVENT')], ['20000101T000000'] ) # We can enumerate property items recursively with the property_items # method. self.assertEqual( c.property_items(), [('BEGIN', b'VCALENDAR'), ('ATTENDEE', prop.vCalAddress('Max M')), ('BEGIN', b'VEVENT'), ('DTEND', '20000102T000000'), ('DTSTART', '20000101T000000'), ('SUMMARY', 'A brief history of time'), ('END', b'VEVENT'), ('END', b'VCALENDAR')] ) # We can also enumerate property items just under the component. self.assertEqual( c.property_items(recursive=False), [('BEGIN', b'VCALENDAR'), ('ATTENDEE', prop.vCalAddress('Max M')), ('END', b'VCALENDAR')] ) sc = c.subcomponents[0] self.assertEqual( sc.property_items(recursive=False), [('BEGIN', b'VEVENT'), ('DTEND', '20000102T000000'), ('DTSTART', '20000101T000000'), ('SUMMARY', 'A brief history of time'), ('END', b'VEVENT')] ) # Text fields which span multiple mulitple lines require proper # indenting c = Calendar() c['description'] = u'Paragraph one\n\nParagraph two' self.assertEqual( c.to_ical(), b'BEGIN:VCALENDAR\r\nDESCRIPTION:Paragraph one\\n\\nParagraph two' + b'\r\nEND:VCALENDAR\r\n' ) # INLINE properties have their values on one property line. Note the # double quoting of the value with a colon in it. c = Calendar() c['resources'] = 'Chair, Table, "Room: 42"' self.assertEqual( c, Calendar({'RESOURCES': 'Chair, Table, "Room: 42"'}) ) self.assertEqual( c.to_ical(), b'BEGIN:VCALENDAR\r\nRESOURCES:Chair\\, Table\\, "Room: 42"\r\n' + b'END:VCALENDAR\r\n' ) # The inline values must be handled by the get_inline() and # set_inline() methods. self.assertEqual( c.get_inline('resources', decode=0), [u'Chair', u'Table', u'Room: 42'] ) # These can also be decoded self.assertEqual( c.get_inline('resources', decode=1), [b'Chair', b'Table', b'Room: 42'] ) # You can set them directly ... c.set_inline('resources', ['A', 'List', 'of', 'some, recources'], encode=1) self.assertEqual(c['resources'], 'A,List,of,"some, recources"') # ... and back again self.assertEqual( c.get_inline('resources', decode=0), ['A', 'List', 'of', 'some, recources'] ) c['freebusy'] = '19970308T160000Z/PT3H,19970308T200000Z/PT1H,'\ + '19970308T230000Z/19970309T000000Z' self.assertEqual( c.get_inline('freebusy', decode=0), ['19970308T160000Z/PT3H', '19970308T200000Z/PT1H', '19970308T230000Z/19970309T000000Z'] ) freebusy = c.get_inline('freebusy', decode=1) self.assertTrue(isinstance(freebusy[0][0], datetime)) self.assertTrue(isinstance(freebusy[0][1], timedelta))
def test_cal_Component(self): from icalendar.cal import Component, Calendar, Event from icalendar import prop # A component is like a dictionary with extra methods and attributes. c = Component() c.name = 'VCALENDAR' # Every key defines a property.A property can consist of either a # single item. This can be set with a single value... c['prodid'] = '-//max m//icalendar.mxm.dk/' self.assertEqual(c, Calendar({'PRODID': '-//max m//icalendar.mxm.dk/'})) # or with a list c['ATTENDEE'] = ['Max M', 'Rasmussen'] self.assertEqual( c, Calendar({ 'ATTENDEE': ['Max M', 'Rasmussen'], 'PRODID': '-//max m//icalendar.mxm.dk/' })) ### ADD MULTIPLE VALUES TO A PROPERTY # if you use the add method you don't have to considder if a value is # a list or not. c = Component() c.name = 'VEVENT' # add multiple values at once c.add('attendee', ['*****@*****.**', '*****@*****.**']) # or add one per line c.add('attendee', '*****@*****.**') c.add('attendee', '*****@*****.**') # add again multiple values at once to very concatenaton of lists c.add('attendee', ['*****@*****.**', '*****@*****.**']) self.assertEqual( c, Event({ 'ATTENDEE': [ prop.vCalAddress('*****@*****.**'), prop.vCalAddress('*****@*****.**'), prop.vCalAddress('*****@*****.**'), prop.vCalAddress('*****@*****.**'), prop.vCalAddress('*****@*****.**'), prop.vCalAddress('*****@*****.**') ] })) ### # You can get the values back directly ... c.add('prodid', '-//my product//') self.assertEqual(c['prodid'], prop.vText(u'-//my product//')) # ... or decoded to a python type self.assertEqual(c.decoded('prodid'), b'-//my product//') # With default values for non existing properties self.assertEqual(c.decoded('version', 'No Version'), 'No Version') c.add('rdate', [datetime(2013, 3, 28), datetime(2013, 3, 27)]) self.assertTrue(isinstance(c.decoded('rdate'), prop.vDDDLists)) # The component can render itself in the RFC 2445 format. c = Component() c.name = 'VCALENDAR' c.add('attendee', 'Max M') self.assertEqual( c.to_ical(), b'BEGIN:VCALENDAR\r\nATTENDEE:Max M\r\nEND:VCALENDAR\r\n') # Components can be nested, so You can add a subcompont. Eg a calendar # holds events. e = Component(summary='A brief history of time') e.name = 'VEVENT' e.add('dtend', '20000102T000000', encode=0) e.add('dtstart', '20000101T000000', encode=0) self.assertEqual( e.to_ical(), b'BEGIN:VEVENT\r\nDTEND:20000102T000000\r\n' + b'DTSTART:20000101T000000\r\nSUMMARY:A brief history of time\r' + b'\nEND:VEVENT\r\n') c.add_component(e) self.assertEqual(c.subcomponents, [ Event({ 'DTEND': '20000102T000000', 'DTSTART': '20000101T000000', 'SUMMARY': 'A brief history of time' }) ]) # We can walk over nested componentes with the walk method. self.assertEqual([i.name for i in c.walk()], ['VCALENDAR', 'VEVENT']) # We can also just walk over specific component types, by filtering # them on their name. self.assertEqual([i.name for i in c.walk('VEVENT')], ['VEVENT']) self.assertEqual([i['dtstart'] for i in c.walk('VEVENT')], ['20000101T000000']) # We can enumerate property items recursively with the property_items # method. self.assertEqual(c.property_items(), [('BEGIN', b'VCALENDAR'), ('ATTENDEE', prop.vCalAddress('Max M')), ('BEGIN', b'VEVENT'), ('DTEND', '20000102T000000'), ('DTSTART', '20000101T000000'), ('SUMMARY', 'A brief history of time'), ('END', b'VEVENT'), ('END', b'VCALENDAR')]) # We can also enumerate property items just under the component. self.assertEqual(c.property_items(recursive=False), [('BEGIN', b'VCALENDAR'), ('ATTENDEE', prop.vCalAddress('Max M')), ('END', b'VCALENDAR')]) sc = c.subcomponents[0] self.assertEqual(sc.property_items(recursive=False), [('BEGIN', b'VEVENT'), ('DTEND', '20000102T000000'), ('DTSTART', '20000101T000000'), ('SUMMARY', 'A brief history of time'), ('END', b'VEVENT')]) # Text fields which span multiple mulitple lines require proper # indenting c = Calendar() c['description'] = u'Paragraph one\n\nParagraph two' self.assertEqual( c.to_ical(), b'BEGIN:VCALENDAR\r\nDESCRIPTION:Paragraph one\\n\\nParagraph two' + b'\r\nEND:VCALENDAR\r\n') # INLINE properties have their values on one property line. Note the # double quoting of the value with a colon in it. c = Calendar() c['resources'] = 'Chair, Table, "Room: 42"' self.assertEqual(c, Calendar({'RESOURCES': 'Chair, Table, "Room: 42"'})) self.assertEqual( c.to_ical(), b'BEGIN:VCALENDAR\r\nRESOURCES:Chair\\, Table\\, "Room: 42"\r\n' + b'END:VCALENDAR\r\n') # The inline values must be handled by the get_inline() and # set_inline() methods. self.assertEqual(c.get_inline('resources', decode=0), [u'Chair', u'Table', u'Room: 42']) # These can also be decoded self.assertEqual(c.get_inline('resources', decode=1), [b'Chair', b'Table', b'Room: 42']) # You can set them directly ... c.set_inline('resources', ['A', 'List', 'of', 'some, recources'], encode=1) self.assertEqual(c['resources'], 'A,List,of,"some, recources"') # ... and back again self.assertEqual(c.get_inline('resources', decode=0), ['A', 'List', 'of', 'some, recources']) c['freebusy'] = '19970308T160000Z/PT3H,19970308T200000Z/PT1H,'\ + '19970308T230000Z/19970309T000000Z' self.assertEqual(c.get_inline('freebusy', decode=0), [ '19970308T160000Z/PT3H', '19970308T200000Z/PT1H', '19970308T230000Z/19970309T000000Z' ]) freebusy = c.get_inline('freebusy', decode=1) self.assertTrue(isinstance(freebusy[0][0], datetime)) self.assertTrue(isinstance(freebusy[0][1], timedelta))
def test_cal_Component_add(self): # Test the for timezone correctness: dtstart should preserve it's # timezone, created, dtstamp and last-modified must be in UTC. Component = icalendar.cal.Component comp = Component() vienna = pytz.timezone("Europe/Vienna") comp.add('dtstart', vienna.localize(datetime(2010, 10, 10, 10, 0, 0))) comp.add('created', datetime(2010, 10, 10, 12, 0, 0)) comp.add('dtstamp', vienna.localize(datetime(2010, 10, 10, 14, 0, 0))) comp.add('last-modified', pytz.utc.localize(datetime(2010, 10, 10, 16, 0, 0))) lines = comp.to_ical().splitlines() self.assertTrue( b"DTSTART;TZID=Europe/Vienna;VALUE=DATE-TIME:20101010T100000" in lines) self.assertTrue(b"CREATED;VALUE=DATE-TIME:20101010T120000Z" in lines) self.assertTrue(b"DTSTAMP;VALUE=DATE-TIME:20101010T120000Z" in lines) self.assertTrue( b"LAST-MODIFIED;VALUE=DATE-TIME:20101010T160000Z" in lines)
def test_cal_Component(self): from icalendar.cal import Component, Calendar, Event from icalendar import prop # A component is like a dictionary with extra methods and attributes. c = Component() c.name = "VCALENDAR" # Every key defines a property.A property can consist of either a # single item. This can be set with a single value... c["prodid"] = "-//max m//icalendar.mxm.dk/" self.assertEqual(c, Calendar({"PRODID": "-//max m//icalendar.mxm.dk/"})) # or with a list c["ATTENDEE"] = ["Max M", "Rasmussen"] self.assertEqual(c, Calendar({"ATTENDEE": ["Max M", "Rasmussen"], "PRODID": "-//max m//icalendar.mxm.dk/"})) ### ADD MULTIPLE VALUES TO A PROPERTY # if you use the add method you don't have to considder if a value is # a list or not. c = Component() c.name = "VEVENT" # add multiple values at once c.add("attendee", ["*****@*****.**", "*****@*****.**"]) # or add one per line c.add("attendee", "*****@*****.**") c.add("attendee", "*****@*****.**") # add again multiple values at once to very concatenaton of lists c.add("attendee", ["*****@*****.**", "*****@*****.**"]) self.assertEqual( c, Event( { "ATTENDEE": [ prop.vCalAddress("*****@*****.**"), prop.vCalAddress("*****@*****.**"), prop.vCalAddress("*****@*****.**"), prop.vCalAddress("*****@*****.**"), prop.vCalAddress("*****@*****.**"), prop.vCalAddress("*****@*****.**"), ] } ), ) ### # You can get the values back directly ... c.add("prodid", "-//my product//") self.assertEqual(c["prodid"], prop.vText(u"-//my product//")) # ... or decoded to a python type self.assertEqual(c.decoded("prodid"), b"-//my product//") # With default values for non existing properties self.assertEqual(c.decoded("version", "No Version"), "No Version") c.add("rdate", [datetime(2013, 3, 28), datetime(2013, 3, 27)]) self.assertTrue(isinstance(c.decoded("rdate"), prop.vDDDLists)) # The component can render itself in the RFC 2445 format. c = Component() c.name = "VCALENDAR" c.add("attendee", "Max M") self.assertEqual(c.to_ical(), b"BEGIN:VCALENDAR\r\nATTENDEE:Max M\r\nEND:VCALENDAR\r\n") # Components can be nested, so You can add a subcompont. Eg a calendar # holds events. e = Component(summary="A brief history of time") e.name = "VEVENT" e.add("dtend", "20000102T000000", encode=0) e.add("dtstart", "20000101T000000", encode=0) self.assertEqual( e.to_ical(), b"BEGIN:VEVENT\r\nDTEND:20000102T000000\r\n" + b"DTSTART:20000101T000000\r\nSUMMARY:A brief history of time\r" + b"\nEND:VEVENT\r\n", ) c.add_component(e) self.assertEqual( c.subcomponents, [Event({"DTEND": "20000102T000000", "DTSTART": "20000101T000000", "SUMMARY": "A brief history of time"})], ) # We can walk over nested componentes with the walk method. self.assertEqual([i.name for i in c.walk()], ["VCALENDAR", "VEVENT"]) # We can also just walk over specific component types, by filtering # them on their name. self.assertEqual([i.name for i in c.walk("VEVENT")], ["VEVENT"]) self.assertEqual([i["dtstart"] for i in c.walk("VEVENT")], ["20000101T000000"]) # We can enumerate property items recursively with the property_items # method. self.assertEqual( c.property_items(), [ ("BEGIN", b"VCALENDAR"), ("ATTENDEE", prop.vCalAddress("Max M")), ("BEGIN", b"VEVENT"), ("DTEND", "20000102T000000"), ("DTSTART", "20000101T000000"), ("SUMMARY", "A brief history of time"), ("END", b"VEVENT"), ("END", b"VCALENDAR"), ], ) # We can also enumerate property items just under the component. self.assertEqual( c.property_items(recursive=False), [("BEGIN", b"VCALENDAR"), ("ATTENDEE", prop.vCalAddress("Max M")), ("END", b"VCALENDAR")], ) sc = c.subcomponents[0] self.assertEqual( sc.property_items(recursive=False), [ ("BEGIN", b"VEVENT"), ("DTEND", "20000102T000000"), ("DTSTART", "20000101T000000"), ("SUMMARY", "A brief history of time"), ("END", b"VEVENT"), ], ) # Text fields which span multiple mulitple lines require proper # indenting c = Calendar() c["description"] = u"Paragraph one\n\nParagraph two" self.assertEqual( c.to_ical(), b"BEGIN:VCALENDAR\r\nDESCRIPTION:Paragraph one\\n\\nParagraph two" + b"\r\nEND:VCALENDAR\r\n" ) # INLINE properties have their values on one property line. Note the # double quoting of the value with a colon in it. c = Calendar() c["resources"] = 'Chair, Table, "Room: 42"' self.assertEqual(c, Calendar({"RESOURCES": 'Chair, Table, "Room: 42"'})) self.assertEqual( c.to_ical(), b'BEGIN:VCALENDAR\r\nRESOURCES:Chair\\, Table\\, "Room: 42"\r\n' + b"END:VCALENDAR\r\n" ) # The inline values must be handled by the get_inline() and # set_inline() methods. self.assertEqual(c.get_inline("resources", decode=0), [u"Chair", u"Table", u"Room: 42"]) # These can also be decoded self.assertEqual(c.get_inline("resources", decode=1), [b"Chair", b"Table", b"Room: 42"]) # You can set them directly ... c.set_inline("resources", ["A", "List", "of", "some, recources"], encode=1) self.assertEqual(c["resources"], 'A,List,of,"some, recources"') # ... and back again self.assertEqual(c.get_inline("resources", decode=0), ["A", "List", "of", "some, recources"]) c["freebusy"] = "19970308T160000Z/PT3H,19970308T200000Z/PT1H," + "19970308T230000Z/19970309T000000Z" self.assertEqual( c.get_inline("freebusy", decode=0), ["19970308T160000Z/PT3H", "19970308T200000Z/PT1H", "19970308T230000Z/19970309T000000Z"], ) freebusy = c.get_inline("freebusy", decode=1) self.assertTrue(isinstance(freebusy[0][0], datetime)) self.assertTrue(isinstance(freebusy[0][1], timedelta))
TZOFFSETFROM:-0800 TZOFFSETTO:-0700 TZNAME:PDT DTSTART:19700308T020000 RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU END:DAYLIGHT BEGIN:STANDARD TZOFFSETFROM:-0700 TZOFFSETTO:-0800 TZNAME:PST DTSTART:19701101T020000 RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU END:STANDARD END:VTIMEZONE""" timezone = Component.from_ical(vtimezone_str) weekday_abbrv_converter = { "U": "SU", "M": "MO", "T": "TU", "W": "WE", "R": "TH", "F": "FR", "S": "SA" } def make_calender(userdata_json): cal = Calendar() cal.add_component(timezone)
def _get_component(): component = Component() component.add('summary', 'summary') component.add('location', 'location') component.add('description', 'description') return component