Refactor calendar tests for use with pytest

pull/602/head
Nicco Kunzmann 2024-03-18 15:28:03 +00:00
rodzic dec17302c5
commit a59ce3c7b7
4 zmienionych plików z 340 dodań i 277 usunięć

Wyświetl plik

@ -0,0 +1,21 @@
BEGIN:VCALENDAR
PRODID:-//Google Inc//Google Calendar 70.9054//EN
VERSION:2.0
CALSCALE:GREGORIAN
METHOD:PUBLISH
BEGIN:VEVENT
DESCRIPTION:Perfectly OK event
DTSTART;VALUE=DATE:20080303
DTEND;VALUE=DATE:20080304
RRULE:FREQ=DAILY;UNTIL=20080323T235959Z
EXDATE;VALUE=DATE:20080311
END:VEVENT
BEGIN:VEVENT
DESCRIPTION:Wrong event
DTSTART;VALUE=DATE:20080303
DTEND;VALUE=DATE:20080304
RRULE:FREQ=DAILY;UNTIL=20080323T235959Z
EXDATE;VALUE=DATE:20080311
EXDATE;VALUE=DATE:
END:VEVENT
END:VCALENDAR

Wyświetl plik

@ -0,0 +1,11 @@
BEGIN:VCALENDAR
BEGIN:VTIMEZONE
TZID:Europe/Prague
BEGIN:STANDARD
DTSTART:18500101T000000
TZNAME:PMT
TZOFFSETFROM:+5744
TZOFFSETTO:+5744
END:STANDARD
END:VTIMEZONE
END:VCALENDAR

Wyświetl plik

@ -8,6 +8,8 @@ try:
import zoneinfo import zoneinfo
except ModuleNotFoundError: except ModuleNotFoundError:
from backports import zoneinfo from backports import zoneinfo
from icalendar.cal import Component, Calendar, Event, ComponentFactory
class DataSource: class DataSource:
'''A collection of parsed ICS elements (e.g calendars, timezones, events)''' '''A collection of parsed ICS elements (e.g calendars, timezones, events)'''
@ -118,3 +120,44 @@ def vUTCOffset_ignore_exceptions():
icalendar.vUTCOffset.ignore_exceptions = True icalendar.vUTCOffset.ignore_exceptions = True
yield yield
icalendar.vUTCOffset.ignore_exceptions = False icalendar.vUTCOffset.ignore_exceptions = False
@pytest.fixture()
def event_component():
"""Return an event component."""
c = Component()
c.name = 'VEVENT'
return c
@pytest.fixture()
def c():
"""Return an empty component."""
c = Component()
return c
comp = c
@pytest.fixture()
def calendar_component():
"""Return an empty component."""
c = Component()
c.name = 'VCALENDAR'
return c
@pytest.fixture()
def filled_event_component(c, calendar_component):
"""Return an event with some values and add it to calendar_component."""
e = Component(summary='A brief history of time')
e.name = 'VEVENT'
e.add('dtend', '20000102T000000', encode=0)
e.add('dtstart', '20000101T000000', encode=0)
calendar_component.add_component(e)
return e
@pytest.fixture()
def calendar_with_resources():
c = Calendar()
c['resources'] = 'Chair, Table, "Room: 42"'
return c

Wyświetl plik

@ -12,58 +12,46 @@ from icalendar.cal import Component, Calendar, Event, ComponentFactory
from icalendar import prop, cal from icalendar import prop, cal
def test_cal_Component(calendar_component):
"""A component is like a dictionary with extra methods and attributes."""
assert calendar_component
assert calendar_component.is_empty()
class TestCalComponent(unittest.TestCase):
def test_cal_Component(self): def test_nonempty_calendar_component(calendar_component):
"""Every key defines a property.A property can consist of either a
# A component is like a dictionary with extra methods and attributes. single item. This can be set with a single value...
c = Component() """
c.name = 'VCALENDAR' calendar_component['prodid'] = '-//max m//icalendar.mxm.dk/'
assert not calendar_component.is_empty()
self.assertTrue(c) assert calendar_component == Calendar({'PRODID': '-//max m//icalendar.mxm.dk/'})
self.assertTrue(c.is_empty())
# 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.assertFalse(c.is_empty())
self.assertEqual(
c,
Calendar({'PRODID': '-//max m//icalendar.mxm.dk/'})
)
# or with a list # or with a list
c['ATTENDEE'] = ['Max M', 'Rasmussen'] calendar_component['ATTENDEE'] = ['Max M', 'Rasmussen']
self.assertEqual( assert calendar_component == Calendar(
c, {'ATTENDEE': ['Max M', 'Rasmussen'],
Calendar({'ATTENDEE': ['Max M', 'Rasmussen'],
'PRODID': '-//max m//icalendar.mxm.dk/'}) '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 def test_add_multiple_values(event_component):
# a list or not. """add multiple values to a property.
c = Component()
c.name = 'VEVENT'
If you use the add method you don't have to considder if a value is
a list or not.
"""
# add multiple values at once # add multiple values at once
c.add('attendee', event_component.add('attendee',
['test@test.com', 'test2@test.com']) ['test@test.com', 'test2@test.com'])
# or add one per line # or add one per line
c.add('attendee', 'maxm@mxm.dk') event_component.add('attendee', 'maxm@mxm.dk')
c.add('attendee', 'test@example.dk') event_component.add('attendee', 'test@example.dk')
# add again multiple values at once to very concatenaton of lists # add again multiple values at once to very concatenaton of lists
c.add('attendee', event_component.add('attendee',
['test3@test.com', 'test4@test.com']) ['test3@test.com', 'test4@test.com'])
self.assertEqual( assert event_component == Event({'ATTENDEE': [
c,
Event({'ATTENDEE': [
prop.vCalAddress('test@test.com'), prop.vCalAddress('test@test.com'),
prop.vCalAddress('test2@test.com'), prop.vCalAddress('test2@test.com'),
prop.vCalAddress('maxm@mxm.dk'), prop.vCalAddress('maxm@mxm.dk'),
@ -71,157 +59,150 @@ class TestCalComponent(unittest.TestCase):
prop.vCalAddress('test3@test.com'), prop.vCalAddress('test3@test.com'),
prop.vCalAddress('test4@test.com') prop.vCalAddress('test4@test.com')
]}) ]})
)
###
# You can get the values back directly ... def test_get_content_directly(c):
"""You can get the values back directly ..."""
c.add('prodid', '-//my product//') c.add('prodid', '-//my product//')
self.assertEqual(c['prodid'], prop.vText('-//my product//')) assert c['prodid'] == prop.vText('-//my product//')
# ... or decoded to a python type # ... or decoded to a python type
self.assertEqual(c.decoded('prodid'), b'-//my product//') assert c.decoded('prodid') == b'-//my product//'
# With default values for non existing properties
self.assertEqual(c.decoded('version', 'No Version'), 'No Version')
def test_get_default_value(c):
"""With default values for non existing properties"""
assert c.decoded('version', 'No Version') == 'No Version'
def test_default_list_example(c):
c.add('rdate', [datetime(2013, 3, 28), datetime(2013, 3, 27)]) c.add('rdate', [datetime(2013, 3, 28), datetime(2013, 3, 27)])
self.assertTrue(isinstance(c.decoded('rdate'), prop.vDDDLists)) assert 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 subcomponent. Eg a calendar def test_render_component(calendar_component):
# holds events. """The component can render itself in the RFC 2445 format."""
e = Component(summary='A brief history of time') calendar_component.add('attendee', 'Max M')
e.name = 'VEVENT' assert calendar_component.to_ical() == b'BEGIN:VCALENDAR\r\nATTENDEE:Max M\r\nEND:VCALENDAR\r\n'
e.add('dtend', '20000102T000000', encode=0)
e.add('dtstart', '20000101T000000', encode=0)
self.assertEqual( def test_nested_component_event_ics(filled_event_component):
e.to_ical(), """Check the ical string of the event component."""
assert filled_event_component.to_ical() == (
b'BEGIN:VEVENT\r\nDTEND:20000102T000000\r\n' b'BEGIN:VEVENT\r\nDTEND:20000102T000000\r\n'
+ b'DTSTART:20000101T000000\r\nSUMMARY:A brief history of time\r' + b'DTSTART:20000101T000000\r\nSUMMARY:A brief history of time\r'
+ b'\nEND:VEVENT\r\n' + b'\nEND:VEVENT\r\n'
) )
c.add_component(e)
def test_nested_components(calendar_component, filled_event_component):
"""Components can be nested, so You can add a subcomponent. Eg a calendar
holds events."""
self.assertEqual( self.assertEqual(
c.subcomponents, calendar_component.subcomponents,
[Event({'DTEND': '20000102T000000', 'DTSTART': '20000101T000000', [Event({'DTEND': '20000102T000000', 'DTSTART': '20000101T000000',
'SUMMARY': 'A brief history of time'})] '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 def test_walk_filled_calendar_component(calendar_component, filled_event_component):
# them on their name. """We can walk over nested componentes with the walk method."""
self.assertEqual([i.name for i in c.walk('VEVENT')], ['VEVENT']) assert [i.name for i in calendar_component.walk()] == ['VCALENDAR', 'VEVENT']
self.assertEqual(
[i['dtstart'] for i in c.walk('VEVENT')],
['20000101T000000']
)
# We can enumerate property items recursively with the property_items def test_filter_walk(calendar_component, filled_event_component):
# method. """We can also just walk over specific component types, by filtering
self.assertEqual( them on their name."""
c.property_items(), assert [i.name for i in calendar_component.walk('VEVENT')] == ['VEVENT']
[('BEGIN', b'VCALENDAR'), ('ATTENDEE', prop.vCalAddress('Max M')), assert [i['dtstart'] for i in calendar_component.walk('VEVENT')] == ['20000101T000000']
def test_recursive_property_items(calendar_component, filled_event_component):
"""We can enumerate property items recursively with the property_items
method."""
calendar_component.add('attendee', 'Max M')
assert calendar_component.property_items() == [
('BEGIN', b'VCALENDAR'), ('ATTENDEE', prop.vCalAddress('Max M')),
('BEGIN', b'VEVENT'), ('DTEND', '20000102T000000'), ('BEGIN', b'VEVENT'), ('DTEND', '20000102T000000'),
('DTSTART', '20000101T000000'), ('DTSTART', '20000101T000000'),
('SUMMARY', 'A brief history of time'), ('END', b'VEVENT'), ('SUMMARY', 'A brief history of time'), ('END', b'VEVENT'),
('END', b'VCALENDAR')] ('END', b'VCALENDAR')]
)
# We can also enumerate property items just under the component.
self.assertEqual( def test_flat_property_items(calendar_component, filled_event_component):
c.property_items(recursive=False), """We can also enumerate property items just under the component."""
[('BEGIN', b'VCALENDAR'), assert calendar_component.property_items(recursive=False) == [
('BEGIN', b'VCALENDAR'),
('ATTENDEE', prop.vCalAddress('Max M')), ('ATTENDEE', prop.vCalAddress('Max M')),
('END', b'VCALENDAR')] ('END', b'VCALENDAR')]
)
sc = c.subcomponents[0]
self.assertEqual( def test_flat_property_items(filled_event_component):
sc.property_items(recursive=False), """Flat enumeration on the event."""
[('BEGIN', b'VEVENT'), ('DTEND', '20000102T000000'), assert filled_event_component.property_items(recursive=False) == [
('BEGIN', b'VEVENT'), ('DTEND', '20000102T000000'),
('DTSTART', '20000101T000000'), ('DTSTART', '20000101T000000'),
('SUMMARY', 'A brief history of time'), ('END', b'VEVENT')] ('SUMMARY', 'A brief history of time'), ('END', b'VEVENT')]
)
# Text fields which span multiple mulitple lines require proper
# indenting def test_indent():
"""Text fields which span multiple mulitple lines require proper indenting"""
c = Calendar() c = Calendar()
c['description'] = 'Paragraph one\n\nParagraph two' c['description'] = 'Paragraph one\n\nParagraph two'
self.assertEqual( assert c.to_ical() == (
c.to_ical(),
b'BEGIN:VCALENDAR\r\nDESCRIPTION:Paragraph one\\n\\nParagraph two' b'BEGIN:VCALENDAR\r\nDESCRIPTION:Paragraph one\\n\\nParagraph two'
+ b'\r\nEND:VCALENDAR\r\n' + 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( def test_INLINE_properties(calendar_with_resources):
c.to_ical(), """INLINE properties have their values on one property line. Note the
double quoting of the value with a colon in it.
"""
assert calendar_with_resources == Calendar({'RESOURCES': 'Chair, Table, "Room: 42"'})
assert calendar_with_resources.to_ical() == (
b'BEGIN:VCALENDAR\r\nRESOURCES:Chair\\, Table\\, "Room: 42"\r\n' b'BEGIN:VCALENDAR\r\nRESOURCES:Chair\\, Table\\, "Room: 42"\r\n'
+ b'END:VCALENDAR\r\n' + b'END:VCALENDAR\r\n'
) )
# The inline values must be handled by the get_inline() and
# set_inline() methods. def test_get_inline(calendar_with_resources):
self.assertEqual( """The inline values must be handled by the get_inline() and
c.get_inline('resources', decode=0), set_inline() methods.
"""
assert calendar_with_resources.get_inline('resources', decode=0) == \
['Chair', 'Table', 'Room: 42'] ['Chair', 'Table', 'Room: 42']
)
# These can also be decoded
self.assertEqual( def test_get_inline_decoded(calendar_with_resources):
c.get_inline('resources', decode=1), """These can also be decoded"""
assert calendar_with_resources.get_inline('resources', decode=1) == \
[b'Chair', b'Table', b'Room: 42'] [b'Chair', b'Table', b'Room: 42']
)
# You can set them directly ...
c.set_inline('resources', ['A', 'List', 'of', 'some, recources'], def test_set_inline(calendar_with_resources):
"""You can set them directly ..."""
calendar_with_resources.set_inline('resources', ['A', 'List', 'of', 'some, recources'],
encode=1) encode=1)
self.assertEqual(c['resources'], 'A,List,of,"some, recources"') assert calendar_with_resources['resources'] == 'A,List,of,"some, recources"'
assert calendar_with_resources.get_inline('resources', decode=0) == ['A', 'List', 'of', 'some, recources']
# ... and back again
self.assertEqual(
c.get_inline('resources', decode=0),
['A', 'List', 'of', 'some, recources']
)
def test_inline_free_busy_inline(c):
c['freebusy'] = '19970308T160000Z/PT3H,19970308T200000Z/PT1H,'\ c['freebusy'] = '19970308T160000Z/PT3H,19970308T200000Z/PT1H,'\
+ '19970308T230000Z/19970309T000000Z' + '19970308T230000Z/19970309T000000Z'
self.assertEqual( assert c.get_inline('freebusy', decode=0) == \
c.get_inline('freebusy', decode=0),
['19970308T160000Z/PT3H', '19970308T200000Z/PT1H', ['19970308T160000Z/PT3H', '19970308T200000Z/PT1H',
'19970308T230000Z/19970309T000000Z'] '19970308T230000Z/19970309T000000Z']
)
freebusy = c.get_inline('freebusy', decode=1) freebusy = c.get_inline('freebusy', decode=1)
self.assertTrue(isinstance(freebusy[0][0], datetime)) assert isinstance(freebusy[0][0], datetime)
self.assertTrue(isinstance(freebusy[0][1], timedelta)) assert isinstance(freebusy[0][1], timedelta)
def test_cal_Component_add(self):
# Test the for timezone correctness: dtstart should preserve it's def test_cal_Component_add(comp):
# timezone, created, dtstamp and last-modified must be in UTC. """Test the for timezone correctness: dtstart should preserve it's
Component = icalendar.cal.Component timezone, created, dtstamp and last-modified must be in UTC.
comp = Component() """
vienna = pytz.timezone("Europe/Vienna") vienna = pytz.timezone("Europe/Vienna")
comp.add('dtstart', vienna.localize(datetime(2010, 10, 10, 10, 0, 0))) comp.add('dtstart', vienna.localize(datetime(2010, 10, 10, 10, 0, 0)))
comp.add('created', datetime(2010, 10, 10, 12, 0, 0)) comp.add('created', datetime(2010, 10, 10, 12, 0, 0))
@ -230,59 +211,65 @@ class TestCalComponent(unittest.TestCase):
datetime(2010, 10, 10, 16, 0, 0))) datetime(2010, 10, 10, 16, 0, 0)))
lines = comp.to_ical().splitlines() lines = comp.to_ical().splitlines()
self.assertTrue( assert b"DTSTART;TZID=Europe/Vienna:20101010T100000" in lines
b"DTSTART;TZID=Europe/Vienna:20101010T100000" assert b"CREATED:20101010T120000Z" in lines
in lines) assert b"DTSTAMP:20101010T120000Z" in lines
self.assertTrue(b"CREATED:20101010T120000Z" in lines) assert b"LAST-MODIFIED:20101010T160000Z" in lines
self.assertTrue(b"DTSTAMP:20101010T120000Z" in lines)
self.assertTrue(
b"LAST-MODIFIED:20101010T160000Z" in lines
)
def test_cal_Component_add_no_reencode(self):
def test_cal_Component_add_no_reencode(comp):
"""Already encoded values should not be re-encoded. """Already encoded values should not be re-encoded.
""" """
comp = cal.Component()
comp.add('ATTACH', 'me') comp.add('ATTACH', 'me')
comp.add('ATTACH', 'you', encode=False) comp.add('ATTACH', 'you', encode=False)
binary = prop.vBinary('us') binary = prop.vBinary('us')
comp.add('ATTACH', binary) comp.add('ATTACH', binary)
self.assertEqual(comp['ATTACH'], ['me', 'you', binary]) assert comp['ATTACH'] == ['me', 'you', binary]
def test_cal_Component_add_property_parameter(self):
# Test the for timezone correctness: dtstart should preserve it's def test_cal_Component_add_property_parameter(comp):
# timezone, crated, dtstamp and last-modified must be in UTC. """Test the for timezone correctness: dtstart should preserve it's
comp = Component() timezone, crated, dtstamp and last-modified must be in UTC.
"""
comp.add('X-TEST-PROP', 'tryout.', comp.add('X-TEST-PROP', 'tryout.',
parameters={'prop1': 'val1', 'prop2': 'val2'}) parameters={'prop1': 'val1', 'prop2': 'val2'})
lines = comp.to_ical().splitlines() lines = comp.to_ical().splitlines()
self.assertTrue(b"X-TEST-PROP;PROP1=val1;PROP2=val2:tryout." in lines) assert b"X-TEST-PROP;PROP1=val1;PROP2=val2:tryout." in lines
def test_cal_Component_from_ical(self):
# Check for proper handling of TZID parameter of datetime properties comp_prop = pytest.mark.parametrize(
for component_name, property_name in ( "component_name, property_name",
[
('VEVENT', 'DTSTART'), ('VEVENT', 'DTSTART'),
('VEVENT', 'DTEND'), ('VEVENT', 'DTEND'),
('VEVENT', 'RECURRENCE-ID'), ('VEVENT', 'RECURRENCE-ID'),
('VTODO', 'DUE') ('VTODO', 'DUE')
): ]
)
@comp_prop
def test_cal_Component_from_ical(component_name, property_name):
"""Check for proper handling of TZID parameter of datetime properties"""
component_str = 'BEGIN:' + component_name + '\n' component_str = 'BEGIN:' + component_name + '\n'
component_str += property_name + ';TZID=America/Denver:' component_str += property_name + ';TZID=America/Denver:'
component_str += '20120404T073000\nEND:' + component_name component_str += '20120404T073000\nEND:' + component_name
component = Component.from_ical(component_str) component = Component.from_ical(component_str)
self.assertEqual(str(component[property_name].dt.tzinfo.zone), assert str(component[property_name].dt.tzinfo.zone) == "America/Denver"
"America/Denver")
@comp_prop
def test_cal_Component_from_ical_2(component_name, property_name):
"""Check for proper handling of TZID parameter of datetime properties"""
component_str = 'BEGIN:' + component_name + '\n' component_str = 'BEGIN:' + component_name + '\n'
component_str += property_name + ':' component_str += property_name + ':'
component_str += '20120404T073000\nEND:' + component_name component_str += '20120404T073000\nEND:' + component_name
component = Component.from_ical(component_str) component = Component.from_ical(component_str)
self.assertEqual(component[property_name].dt.tzinfo, assert component[property_name].dt.tzinfo == None
None)
def test_cal_Component_to_ical_property_order(self):
def test_cal_Component_to_ical_property_order():
component_str = [b'BEGIN:VEVENT', component_str = [b'BEGIN:VEVENT',
b'DTSTART:19970714T170000Z', b'DTSTART:19970714T170000Z',
b'DTEND:19970715T035959Z', b'DTEND:19970715T035959Z',
@ -297,7 +284,8 @@ class TestCalComponent(unittest.TestCase):
preserved_str = component.to_ical(sorted=False).splitlines() preserved_str = component.to_ical(sorted=False).splitlines()
assert preserved_str == component_str assert preserved_str == component_str
def test_cal_Component_to_ical_parameter_order(self):
def test_cal_Component_to_ical_parameter_order():
component_str = [b'BEGIN:VEVENT', component_str = [b'BEGIN:VEVENT',
b'X-FOOBAR;C=one;A=two;B=three:helloworld.', b'X-FOOBAR;C=one;A=two;B=three:helloworld.',
b'END:VEVENT'] b'END:VEVENT']
@ -311,44 +299,44 @@ class TestCalComponent(unittest.TestCase):
preserved_str = component.to_ical(sorted=False).splitlines() preserved_str = component.to_ical(sorted=False).splitlines()
assert preserved_str == component_str assert preserved_str == component_str
def test_repr(self):
"""Test correct class representation. @pytest.fixture()
""" def repr_example(c):
component = Component() class ReprExample:
component = c
component['key1'] = 'value1' component['key1'] = 'value1'
self.assertTrue(
re.match(r"Component\({u?'KEY1': u?'value1'}\)", str(component))
)
calendar = Calendar() calendar = Calendar()
calendar['key1'] = 'value1' calendar['key1'] = 'value1'
self.assertTrue(
re.match(r"VCALENDAR\({u?'KEY1': u?'value1'}\)", str(calendar))
)
event = Event() event = Event()
event['key1'] = 'value1' event['key1'] = 'value1'
self.assertTrue(
re.match(r"VEVENT\({u?'KEY1': u?'value1'}\)", str(event))
)
# Representation of nested Components
nested = Component(key1='VALUE1') nested = Component(key1='VALUE1')
nested.add_component(component) nested.add_component(component)
calendar.add_component(event)
nested.add_component(calendar) nested.add_component(calendar)
return ReprExample
self.assertTrue( def test_repr_component(repr_example):
re.match( """Test correct class representation.
"""
assert re.match(r"Component\({u?'KEY1': u?'value1'}\)", str(repr_example.component))
def test_repr_calendar(repr_example):
assert re.match(r"VCALENDAR\({u?'KEY1': u?'value1'}\)", str(repr_example.calendar))
def test_repr_event(repr_example):
assert re.match(r"VEVENT\({u?'KEY1': u?'value1'}\)", str(repr_example.event))
def test_nested_components(repr_example):
"""Representation of nested Components"""
repr_example.calendar.add_component(repr_example.event)
print(repr_example.nested)
assert re.match(
r"Component\({u?'KEY1': u?'VALUE1'}, " r"Component\({u?'KEY1': u?'VALUE1'}, "
r"Component\({u?'KEY1': u?'value1'}\), " r"Component\({u?'KEY1': u?'value1'}\), "
r"VCALENDAR\({u?'KEY1': u?'value1'}, " r"VCALENDAR\({u?'KEY1': u?'value1'}, "
r"VEVENT\({u?'KEY1': u?'value1'}\)\)\)", r"VEVENT\({u?'KEY1': u?'value1'}\)\)\)",
str(nested) str(repr_example.nested)
)
) )