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:
358
.venv/lib/python3.9/site-packages/icalendar/tests/conftest.py
Normal file
358
.venv/lib/python3.9/site-packages/icalendar/tests/conftest.py
Normal file
@@ -0,0 +1,358 @@
|
||||
try:
|
||||
from backports import zoneinfo # type: ignore # noqa: PGH003
|
||||
except ImportError:
|
||||
import zoneinfo
|
||||
from typing import Generator
|
||||
|
||||
import pytest
|
||||
|
||||
import icalendar
|
||||
|
||||
from . import timezone_ids
|
||||
|
||||
try:
|
||||
import pytz
|
||||
except ImportError:
|
||||
pytz = None
|
||||
import itertools
|
||||
import sys
|
||||
import uuid
|
||||
from pathlib import Path
|
||||
|
||||
from dateutil import tz
|
||||
|
||||
from icalendar.cal import Calendar, Component
|
||||
from icalendar.timezone import TZP
|
||||
from icalendar.timezone import tzp as _tzp
|
||||
|
||||
HAS_PYTZ = pytz is not None
|
||||
if HAS_PYTZ:
|
||||
PYTZ_UTC = [
|
||||
pytz.utc,
|
||||
pytz.timezone("UTC"),
|
||||
]
|
||||
PYTZ_IN_TIMEZONE = [
|
||||
lambda dt, tzname: pytz.timezone(tzname).localize(dt),
|
||||
]
|
||||
PYTZ_TZP = ["pytz"]
|
||||
else:
|
||||
PYTZ_UTC = []
|
||||
PYTZ_IN_TIMEZONE = []
|
||||
PYTZ_TZP = []
|
||||
|
||||
|
||||
class DataSource:
|
||||
"""A collection of parsed ICS elements (e.g calendars, timezones, events)"""
|
||||
|
||||
def __init__(self, data_source_folder: Path, parser):
|
||||
self._parser = parser
|
||||
self._data_source_folder = data_source_folder
|
||||
|
||||
def keys(self):
|
||||
"""Return all the files that could be used."""
|
||||
return [
|
||||
p.stem
|
||||
for p in self._data_source_folder.iterdir()
|
||||
if p.suffix.lower() == ".ics"
|
||||
]
|
||||
|
||||
def __getitem__(self, attribute):
|
||||
"""Parse a file and return the result stored in the attribute."""
|
||||
if attribute.endswith(".ics"):
|
||||
source_file = attribute
|
||||
attribute = attribute[:-4]
|
||||
else:
|
||||
source_file = attribute + ".ics"
|
||||
source_path = self._data_source_folder / source_file
|
||||
if not source_path.is_file():
|
||||
raise AttributeError(f"{source_path} does not exist.")
|
||||
with source_path.open("rb") as f:
|
||||
raw_ics = f.read()
|
||||
source = self._parser(raw_ics)
|
||||
if not isinstance(source, list):
|
||||
source.raw_ics = raw_ics
|
||||
source.source_file = source_file
|
||||
self.__dict__[attribute] = source
|
||||
return source
|
||||
|
||||
def __contains__(self, key):
|
||||
"""key in self.keys()"""
|
||||
if key.endswith(".ics"):
|
||||
key = key[:-4]
|
||||
return key in self.keys()
|
||||
|
||||
def __getattr__(self, key):
|
||||
return self[key]
|
||||
|
||||
def __repr__(self):
|
||||
return repr(self.__dict__)
|
||||
|
||||
@property
|
||||
def multiple(self):
|
||||
"""Return a list of all components parsed."""
|
||||
return self.__class__(
|
||||
self._data_source_folder, lambda data: self._parser(data, multiple=True)
|
||||
)
|
||||
|
||||
|
||||
HERE = Path(__file__).parent
|
||||
CALENDARS_FOLDER = HERE / "calendars"
|
||||
TIMEZONES_FOLDER = HERE / "timezones"
|
||||
EVENTS_FOLDER = HERE / "events"
|
||||
ALARMS_FOLDER = HERE / "alarms"
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def calendars(tzp):
|
||||
return DataSource(CALENDARS_FOLDER, icalendar.Calendar.from_ical)
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def timezones(tzp):
|
||||
return DataSource(TIMEZONES_FOLDER, icalendar.Timezone.from_ical)
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def events(tzp):
|
||||
return DataSource(EVENTS_FOLDER, icalendar.Event.from_ical)
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def alarms(tzp):
|
||||
return DataSource(ALARMS_FOLDER, icalendar.Alarm.from_ical)
|
||||
|
||||
|
||||
@pytest.fixture(params=PYTZ_UTC + [zoneinfo.ZoneInfo("UTC"), tz.UTC, tz.gettz("UTC")])
|
||||
def utc(request, tzp):
|
||||
return request.param
|
||||
|
||||
|
||||
@pytest.fixture(
|
||||
params=PYTZ_IN_TIMEZONE
|
||||
+ [
|
||||
lambda dt, tzname: dt.replace(tzinfo=tz.gettz(tzname)),
|
||||
lambda dt, tzname: dt.replace(tzinfo=zoneinfo.ZoneInfo(tzname)),
|
||||
]
|
||||
)
|
||||
def in_timezone(request, tzp):
|
||||
return request.param
|
||||
|
||||
|
||||
# exclude broken calendars here
|
||||
ICS_FILES_EXCLUDE = (
|
||||
"big_bad_calendar.ics",
|
||||
"issue_104_broken_calendar.ics",
|
||||
"small_bad_calendar.ics",
|
||||
"multiple_calendar_components.ics",
|
||||
"pr_480_summary_with_colon.ics",
|
||||
"parsing_error_in_UTC_offset.ics",
|
||||
"parsing_error.ics",
|
||||
)
|
||||
ICS_FILES = [
|
||||
file.name
|
||||
for file in itertools.chain(
|
||||
CALENDARS_FOLDER.iterdir(), TIMEZONES_FOLDER.iterdir(), EVENTS_FOLDER.iterdir()
|
||||
)
|
||||
if file.name not in ICS_FILES_EXCLUDE
|
||||
]
|
||||
|
||||
|
||||
@pytest.fixture(params=ICS_FILES)
|
||||
def ics_file(tzp, calendars, timezones, events, request):
|
||||
"""An example ICS file."""
|
||||
ics_file = request.param
|
||||
print("example file:", ics_file)
|
||||
for data in calendars, timezones, events:
|
||||
if ics_file in data:
|
||||
return data[ics_file]
|
||||
raise ValueError(f"Could not find file {ics_file}.")
|
||||
|
||||
|
||||
FUZZ_V1 = [key for key in CALENDARS_FOLDER.iterdir() if "fuzz-testcase" in str(key)]
|
||||
|
||||
|
||||
@pytest.fixture(params=FUZZ_V1)
|
||||
def fuzz_v1_calendar(request):
|
||||
"""Clusterfuzz calendars."""
|
||||
return request.param
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def x_sometime():
|
||||
"""Map x_sometime to time"""
|
||||
icalendar.cal.types_factory.types_map["X-SOMETIME"] = "time"
|
||||
yield
|
||||
icalendar.cal.types_factory.types_map.pop("X-SOMETIME")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def factory():
|
||||
"""Return a new component factory."""
|
||||
return icalendar.ComponentFactory()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def vUTCOffset_ignore_exceptions():
|
||||
icalendar.vUTCOffset.ignore_exceptions = True
|
||||
yield
|
||||
icalendar.vUTCOffset.ignore_exceptions = False
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def event_component(tzp):
|
||||
"""Return an event component."""
|
||||
c = Component()
|
||||
c.name = "VEVENT"
|
||||
return c
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def c(tzp):
|
||||
"""Return an empty component."""
|
||||
c = Component()
|
||||
return c
|
||||
|
||||
|
||||
comp = c
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def calendar_component(tzp):
|
||||
"""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(tzp):
|
||||
c = Calendar()
|
||||
c["resources"] = 'Chair, Table, "Room: 42"'
|
||||
return c
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def tzp(tzp_name) -> Generator[TZP, None, None]:
|
||||
"""The timezone provider."""
|
||||
_tzp.use(tzp_name)
|
||||
yield _tzp
|
||||
_tzp.use_default()
|
||||
|
||||
|
||||
@pytest.fixture(params=PYTZ_TZP + ["zoneinfo"])
|
||||
def other_tzp(request, tzp):
|
||||
"""This is annother timezone provider.
|
||||
|
||||
The purpose here is to cross test: pytz <-> zoneinfo.
|
||||
tzp as parameter makes sure we test the cross product.
|
||||
"""
|
||||
return TZP(request.param)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def pytz_only(tzp, tzp_name) -> str:
|
||||
"""Skip tests that are not running under pytz."""
|
||||
assert tzp.uses_pytz()
|
||||
return tzp_name
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def zoneinfo_only(tzp, request, tzp_name) -> str:
|
||||
"""Skip tests that are not running under zoneinfo."""
|
||||
assert tzp.uses_zoneinfo()
|
||||
return tzp_name
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def no_pytz(tzp_name) -> str:
|
||||
"""Do not run tests with pytz."""
|
||||
assert tzp_name != "pytz"
|
||||
return tzp_name
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def no_zoneinfo(tzp_name) -> str:
|
||||
"""Do not run tests with zoneinfo."""
|
||||
assert tzp_name != "zoneinfo"
|
||||
return tzp_name
|
||||
|
||||
|
||||
def pytest_generate_tests(metafunc):
|
||||
"""Parametrize without skipping:
|
||||
|
||||
tzp_name will be parametrized according to the use of
|
||||
- pytz_only
|
||||
- zoneinfo_only
|
||||
- no_pytz
|
||||
- no_zoneinfo
|
||||
|
||||
See https://docs.pytest.org/en/6.2.x/example/parametrize.html#deferring-the-setup-of-parametrized-resources
|
||||
"""
|
||||
if "tzp_name" in metafunc.fixturenames:
|
||||
tzp_names = PYTZ_TZP + ["zoneinfo"]
|
||||
if "zoneinfo_only" in metafunc.fixturenames:
|
||||
tzp_names = ["zoneinfo"]
|
||||
if "pytz_only" in metafunc.fixturenames:
|
||||
tzp_names = PYTZ_TZP
|
||||
assert not (
|
||||
"zoneinfo_only" in metafunc.fixturenames
|
||||
and "pytz_only" in metafunc.fixturenames
|
||||
), "Use pytz_only or zoneinfo_only but not both!"
|
||||
for name in ["pytz", "zoneinfo"]:
|
||||
if f"no_{name}" in metafunc.fixturenames and name in tzp_names:
|
||||
tzp_names.remove(name)
|
||||
metafunc.parametrize("tzp_name", tzp_names, scope="module")
|
||||
|
||||
|
||||
class DoctestZoneInfo(zoneinfo.ZoneInfo):
|
||||
"""Constent ZoneInfo representation for tests."""
|
||||
|
||||
def __repr__(self):
|
||||
return f"ZoneInfo(key={self.key!r})"
|
||||
|
||||
|
||||
def doctest_print(obj):
|
||||
"""doctest print"""
|
||||
if isinstance(obj, bytes):
|
||||
obj = obj.decode("UTF-8")
|
||||
print(str(obj).strip().replace("\r\n", "\n").replace("\r", "\n"))
|
||||
|
||||
|
||||
def doctest_import(name, *args, **kw):
|
||||
"""Replace the import mechanism to skip the whole doctest if we import pytz."""
|
||||
if name == "pytz":
|
||||
return pytz
|
||||
return __import__(name, *args, **kw)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def env_for_doctest(monkeypatch):
|
||||
"""Modify the environment to make doctests run."""
|
||||
monkeypatch.setitem(sys.modules, "zoneinfo", zoneinfo)
|
||||
monkeypatch.setattr(zoneinfo, "ZoneInfo", DoctestZoneInfo)
|
||||
from icalendar.timezone.zoneinfo import ZONEINFO
|
||||
uid = uuid.UUID("d755cef5-2311-46ed-a0e1-6733c9e15c63", version=4)
|
||||
monkeypatch.setattr(uuid, "uuid4", lambda: uid)
|
||||
|
||||
monkeypatch.setattr(ZONEINFO, "utc", zoneinfo.ZoneInfo("UTC"))
|
||||
return {"print": doctest_print}
|
||||
|
||||
|
||||
@pytest.fixture(params=timezone_ids.TZIDS)
|
||||
def tzid(request: pytest.FixtureRequest) -> str:
|
||||
"""Return a timezone id to be used with pytz or zoneinfo.
|
||||
|
||||
This goes through all the different timezones possible.
|
||||
"""
|
||||
return request.param
|
||||
Reference in New Issue
Block a user