import pytest from icalendar import Calendar, Event, Parameters, vCalAddress import unittest import icalendar import re @pytest.mark.parametrize('parameter, expected', [ # Simple parameter:value pair (Parameters(parameter1='Value1'), b'PARAMETER1=Value1'), # Parameter with list of values must be separated by comma (Parameters({'parameter1': ['Value1', 'Value2']}), b'PARAMETER1=Value1,Value2'), # Multiple parameters must be separated by a semicolon (Parameters({'RSVP': 'TRUE', 'ROLE': 'REQ-PARTICIPANT'}), b'ROLE=REQ-PARTICIPANT;RSVP=TRUE'), # Parameter values containing ',;:' must be double quoted (Parameters({'ALTREP': 'http://www.wiz.org'}), b'ALTREP="http://www.wiz.org"'), # list items must be quoted separately (Parameters({'MEMBER': ['MAILTO:projectA@host.com', 'MAILTO:projectB@host.com']}), b'MEMBER="MAILTO:projectA@host.com","MAILTO:projectB@host.com"'), (Parameters({'parameter1': 'Value1', 'parameter2': ['Value2', 'Value3'], 'ALTREP': ['http://www.wiz.org', 'value4']}), b'ALTREP="http://www.wiz.org",value4;PARAMETER1=Value1;PARAMETER2=Value2,Value3'), # Including empty strings (Parameters({'PARAM': ''}), b'PARAM='), # We can also parse parameter strings (Parameters({'MEMBER': ['MAILTO:projectA@host.com', 'MAILTO:projectB@host.com']}), b'MEMBER="MAILTO:projectA@host.com","MAILTO:projectB@host.com"'), # We can also parse parameter strings (Parameters({'PARAMETER1': 'Value1', 'ALTREP': ['http://www.wiz.org', 'value4'], 'PARAMETER2': ['Value2', 'Value3']}), b'ALTREP="http://www.wiz.org",value4;PARAMETER1=Value1;PARAMETER2=Value2,Value3'), ]) def test_parameter_to_ical_is_inverse_of_from_ical(parameter, expected): assert parameter.to_ical() == expected assert Parameters.from_ical(expected.decode('utf-8')) == parameter def test_parse_parameter_string_without_quotes(): assert Parameters.from_ical('PARAM1=Value 1;PARA2=Value 2') == Parameters({'PARAM1': 'Value 1', 'PARA2': 'Value 2'}) def test_parametr_is_case_insensitive(): parameter = Parameters(parameter1='Value1') assert parameter['parameter1'] == parameter['PARAMETER1'] == parameter['PaRaMeTer1'] def test_parameter_keys_are_uppercase(): parameter = Parameters(parameter1='Value1') assert list(parameter.keys()) == ['PARAMETER1'] @pytest.mark.parametrize('cn_param, cn_quoted', [ # not double-quoted ('Aramis', 'Aramis'), # if a space is present - enclose in double quotes ('Aramis Alameda', '"Aramis Alameda"'), # a single quote in parameter value - double quote the value ('Aramis d\'Alameda', '"Aramis d\'Alameda"'), ('Арамис д\'Аламеда', '"Арамис д\'Аламеда"'), # double quote is replaced with single quote ('Aramis d\"Alameda', '"Aramis d\'Alameda"'), ]) def test_quoting(cn_param, cn_quoted): event = Event() attendee = vCalAddress('test@example.com') attendee.params['CN'] = cn_param event.add('ATTENDEE', attendee) assert f'ATTENDEE;CN={cn_quoted}:test@example.com' in event.to_ical().decode('utf-8') def test_property_params(): """Property parameters with values containing a COLON character, a SEMICOLON character or a COMMA character MUST be placed in quoted text.""" cal_address = vCalAddress('mailto:john.doe@example.org') cal_address.params["CN"] = "Doe, John" ical = Calendar() ical.add('organizer', cal_address) ical_str = Calendar.to_ical(ical) exp_str = b"""BEGIN:VCALENDAR\r\nORGANIZER;CN="Doe, John":"""\ b"""mailto:john.doe@example.org\r\nEND:VCALENDAR\r\n""" assert ical_str == exp_str # other way around: ensure the property parameters can be restored from # an icalendar string. ical2 = Calendar.from_ical(ical_str) assert ical2.get('ORGANIZER').params.get('CN') == 'Doe, John' def test_parse_and_access_property_params(calendars): """Parse an ics string and access some property parameters then. This is a follow-up of a question received per email. """ event = calendars.property_params.walk("VEVENT")[0] attendee = event['attendee'][0] assert attendee.to_ical() == b'MAILTO:rembrand@xs4all.nl' assert attendee.params.to_ical() == b'CN=RembrandXS;PARTSTAT=NEEDS-ACTION;RSVP=TRUE' assert attendee.params['cn'] == 'RembrandXS' def test_repr(): """Test correct class representation. """ it = Parameters(parameter1='Value1') assert re.match(r"Parameters\({u?'PARAMETER1': u?'Value1'}\)", str(it))