|
| 1 | +"""Quoting the TZID parameter creates compatibility problems. |
| 2 | +
|
| 3 | +See https://github.com/collective/icalendar/issues/836 |
| 4 | +
|
| 5 | +:rfc:`5545`: |
| 6 | +
|
| 7 | +.. code-block:: text |
| 8 | +
|
| 9 | + param-value = paramtext / quoted-string |
| 10 | + paramtext = *SAFE-CHAR |
| 11 | + quoted-string = DQUOTE *QSAFE-CHAR DQUOTE |
| 12 | + SAFE-CHAR = WSP / %x21 / %x23-2B / %x2D-39 / %x3C-7E |
| 13 | + / NON-US-ASCII |
| 14 | + ; Any character except CONTROL, DQUOTE, ";", ":", "," |
| 15 | + NON-US-ASCII = UTF8-2 / UTF8-3 / UTF8-4 |
| 16 | + ; UTF8-2, UTF8-3, and UTF8-4 are defined in [RFC3629] |
| 17 | +
|
| 18 | +""" |
| 19 | +from datetime import datetime, time |
| 20 | +from icalendar import Event, Parameters, vDDDTypes, vDatetime, vPeriod, vTime |
| 21 | +import pytest |
| 22 | + |
| 23 | +from icalendar.prop import vDDDLists |
| 24 | + |
| 25 | +# All the controls except HTAB |
| 26 | +CONTROL = { |
| 27 | + i for i in range(256) if 0x00 <= i <= 0x08 or 0x0A <= i <= 0x1F or i == 0x7F |
| 28 | +} |
| 29 | + |
| 30 | +# Any character except CONTROL, DQUOTE, ";", ":", "," |
| 31 | +SAFE_CHAR = set(range(256)) - CONTROL - set(b'";:,') |
| 32 | + |
| 33 | +param_tzid = pytest.mark.parametrize( |
| 34 | + "tzid", |
| 35 | + [ |
| 36 | + "Europe/London", |
| 37 | + "Eastern Standard Time", |
| 38 | + ] |
| 39 | +) |
| 40 | + |
| 41 | +@param_tzid |
| 42 | +@pytest.mark.parametrize( |
| 43 | + "vdt", |
| 44 | + [ |
| 45 | + vDatetime(datetime(2024, 10, 11, 12, 0)), |
| 46 | + vTime(time(23, 59, 59)), |
| 47 | + vDDDTypes(datetime(2024, 10, 11, 12, 0)), |
| 48 | + vPeriod((datetime(2024, 10, 11, 12, 0), datetime(2024, 10, 11, 13, 0))), |
| 49 | + vDDDLists([datetime(2024, 10, 11, 12, 0)]), |
| 50 | + ] |
| 51 | +) |
| 52 | +def test_parameter_is_not_quoted_when_not_needed(tzid, vdt): |
| 53 | + """Check that serializing the value works without quoting.""" |
| 54 | + e = Event() |
| 55 | + vdt.params["TZID"] = tzid |
| 56 | + e["DTSTART"] = vdt |
| 57 | + ics = e.to_ical().decode() |
| 58 | + print(ics) |
| 59 | + assert tzid in ics |
| 60 | + assert f'"{tzid}' not in ics |
| 61 | + assert f'{tzid}"' not in ics |
| 62 | + |
| 63 | + |
| 64 | +@pytest.mark.parametrize( |
| 65 | + "safe_char", |
| 66 | + list(map(chr, sorted(SAFE_CHAR))) |
| 67 | +) |
| 68 | +def test_safe_char_is_not_escaped(safe_char): |
| 69 | + """Check that paramerter serialization is without quotes for safe chars.""" |
| 70 | + params = Parameters(tzid=safe_char) |
| 71 | + result = params.to_ical().decode() |
| 72 | + assert '"' not in result |
| 73 | + |
| 74 | + |
| 75 | +def test_get_calendar_and_serialize_it_wihtout_quotes(calendars): |
| 76 | + """The example calendar should not contain the timezone with quotes.""" |
| 77 | + ics = calendars.issue_836_do_not_quote_tzid.to_ical().decode() |
| 78 | + assert '"Eastern Standard' not in ics |
| 79 | + assert 'Standard Time"' not in ics |
| 80 | + assert "Eastern Standard Time" in ics |
0 commit comments