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_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 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_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(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(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))