fix: 포트 충돌 회피 — note_bridge 8098, intent_service 8099
Jellyfin(8096), OrbStack(8097) 포트 충돌으로 변경. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,145 @@
|
||||
import re
|
||||
|
||||
import pytest
|
||||
|
||||
from icalendar import Calendar, Event, Parameters, vCalAddress
|
||||
|
||||
|
||||
@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"'),
|
||||
("Арамис д'Аламеда", '"Арамис д\'Аламеда"'),
|
||||
# Before, double quote is replaced with single quote
|
||||
# Since RFC 6868, we replace this with ^'
|
||||
('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))
|
||||
Reference in New Issue
Block a user