Merge branch 'main' into vgeo

pull/769/head
Nicco Kunzmann 2025-01-17 17:18:34 +01:00 zatwierdzone przez GitHub
commit 8146a2142d
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: B5690EEEBB952194
16 zmienionych plików z 50 dodań i 43 usunięć

Wyświetl plik

@ -10,6 +10,7 @@ Minor changes:
- Document :class:`icalendar.prop.vRecur` property. See `Issue 758 <https://github.com/collective/icalendar/issues/758>`_.
- Print failure of doctest to aid debugging.
- Improve documentation of :class:`icalendar.prop.vGeo`
- Fix tests, improve code readability, fix typing. See `Issue 766 <https://github.com/collective/icalendar/issues/766>`_ and `Issue 765 <https://github.com/collective/icalendar/issues/765>`_.
Breaking changes:

Wyświetl plik

@ -8,8 +8,9 @@ files.
----
:Homepage: https://icalendar.readthedocs.io
:Community Discussions: https://github.com/collective/icalendar/discussions
:Issue Tracker: https://github.com/collective/icalendar/issues
:Code: https://github.com/collective/icalendar
:Mailing list: https://github.com/collective/icalendar/issues
:Dependencies: `python-dateutil`_ and `tzdata`_.
:License: `BSD`_

Wyświetl plik

@ -129,7 +129,7 @@ if version is None and not options.accept_buildout_test_releases:
def _final_version(parsed_version):
for part in parsed_version:
if (part[:1] == '*') and (part not in _final_parts):
if (part.startswith('*')) and (part not in _final_parts):
return False
return True
index = setuptools.package_index.PackageIndex(

Wyświetl plik

@ -491,6 +491,7 @@ class Component(CaselessDict):
'Found no components where exactly one is required', st))
return comps[0]
@staticmethod
def _format_error(error_description, bad_input, elipsis='[...]'):
# there's three character more in the error, ie. ' ' x2 and a ':'
max_error_length = 100 - 3

Wyświetl plik

@ -1,4 +1,4 @@
from typing import Any, Union
from typing import List, Union
SEQUENCE_TYPES = (list, tuple)
DEFAULT_ENCODING = 'utf-8'
@ -13,13 +13,14 @@ def from_unicode(value: ICAL_TYPE, encoding='utf-8') -> bytes:
:return: The bytes representation of the value
"""
if isinstance(value, bytes):
value = value
return value
elif isinstance(value, str):
try:
value = value.encode(encoding)
return value.encode(encoding)
except UnicodeEncodeError:
value = value.encode('utf-8', 'replace')
return value
return value.encode('utf-8', 'replace')
else:
return value
def to_unicode(value: ICAL_TYPE, encoding='utf-8-sig') -> str:
@ -29,13 +30,16 @@ def to_unicode(value: ICAL_TYPE, encoding='utf-8-sig') -> str:
return value
elif isinstance(value, bytes):
try:
value = value.decode(encoding)
return value.decode(encoding)
except UnicodeDecodeError:
value = value.decode('utf-8-sig', 'replace')
return value
return value.decode('utf-8-sig', 'replace')
else:
return value
def data_encode(data: Union[ICAL_TYPE, dict, list], encoding=DEFAULT_ENCODING) -> bytes:
def data_encode(
data: Union[ICAL_TYPE, dict, list], encoding=DEFAULT_ENCODING
) -> Union[bytes, List[bytes], dict]:
"""Encode all datastructures to the given encoding.
Currently unicode strings, dicts and lists are supported.
"""

Wyświetl plik

@ -1042,7 +1042,7 @@ class vMonth(int):
month_index = int(month)
leap = False
else:
if not month[-1] == "L" and month[:-1].isdigit():
if month[-1] != "L" and month[:-1].isdigit():
raise ValueError(f"Invalid month: {month!r}")
month_index = int(month[:-1])
leap = True

Wyświetl plik

@ -19,7 +19,7 @@ def fuzz_calendar_v1(
cal = [cal]
for c in cal:
if should_walk:
for event in cal.walk("VEVENT"):
for event in c.walk("VEVENT"):
event.to_ical()
else:
cal.to_ical()
c.to_ical()

Wyświetl plik

@ -24,9 +24,9 @@ class TestProp(unittest.TestCase):
from icalendar.prop import vDDDLists
dt_list = vDDDLists.from_ical("19960402T010000Z")
self.assertTrue(isinstance(dt_list, list))
self.assertIsInstance(dt_list, list)
self.assertEqual(len(dt_list), 1)
self.assertTrue(isinstance(dt_list[0], datetime))
self.assertIsInstance(dt_list[0], datetime)
self.assertEqual(str(dt_list[0]), "1996-04-02 01:00:00+00:00")
p = "19960402T010000Z,19960403T010000Z,19960404T010000Z"
@ -45,7 +45,7 @@ class TestProp(unittest.TestCase):
self.assertEqual(dt_list.to_ical(), b"20000101T000000,20001111T000000")
instance = vDDDLists([])
self.assertFalse(instance == "value")
self.assertNotEqual(instance, "value")
def test_prop_vDate(self):
from icalendar.prop import vDate
@ -149,7 +149,7 @@ class TestProp(unittest.TestCase):
self.assertEqual(vRecur(r).to_ical(), b"FREQ=DAILY;COUNT=10;INTERVAL=2")
r = vRecur.from_ical(
"FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=-SU;" "BYHOUR=8,9;BYMINUTE=30"
"FREQ=YEARLY;INTERVAL=2;BYMONTH=1;BYDAY=-SU;BYHOUR=8,9;BYMINUTE=30"
)
self.assertEqual(
r,
@ -165,7 +165,7 @@ class TestProp(unittest.TestCase):
self.assertEqual(
vRecur(r).to_ical(),
b"FREQ=YEARLY;INTERVAL=2;BYMINUTE=30;BYHOUR=8,9;BYDAY=-SU;" b"BYMONTH=1",
b"FREQ=YEARLY;INTERVAL=2;BYMINUTE=30;BYHOUR=8,9;BYDAY=-SU;BYMONTH=1",
)
r = vRecur.from_ical("FREQ=WEEKLY;INTERVAL=1;BYWEEKDAY=TH")

Wyświetl plik

@ -12,7 +12,7 @@ def test_windows_timezone(tzp):
"""Test that the timezone is mapped correctly to olson."""
dt = vDatetime.from_ical("20170507T181920", "Eastern Standard Time")
expected = tzp.localize(datetime(2017, 5, 7, 18, 19, 20), "America/New_York")
assert dt.tzinfo == dt.tzinfo
assert dt.tzinfo == expected.tzinfo
assert dt == expected

Wyświetl plik

@ -40,7 +40,7 @@ class IcalendarTestCase(unittest.TestCase):
)
self.assertEqual(
Contentlines.from_ical(
"A faked\r\n long line\r\nAnd another " "lin\r\n\te that is folded\r\n"
"A faked\r\n long line\r\nAnd another lin\r\n\te that is folded\r\n"
),
["A faked long line", "And another line that is folded", ""],
)
@ -112,7 +112,7 @@ class IcalendarTestCase(unittest.TestCase):
)
c = Contentline(
"ATTENDEE;CN=Max Rasmussen;ROLE=REQ-PARTICIPANT:" "MAILTO:maxm@example.com"
"ATTENDEE;CN=Max Rasmussen;ROLE=REQ-PARTICIPANT:MAILTO:maxm@example.com"
)
self.assertEqual(
c.parts(),
@ -124,7 +124,7 @@ class IcalendarTestCase(unittest.TestCase):
)
self.assertEqual(
c.to_ical().decode("utf-8"),
"ATTENDEE;CN=Max Rasmussen;ROLE=REQ-PARTICIPANT:" "MAILTO:maxm@example.com",
"ATTENDEE;CN=Max Rasmussen;ROLE=REQ-PARTICIPANT:MAILTO:maxm@example.com",
)
# and back again

Wyświetl plik

@ -56,7 +56,7 @@ def test_conversion_converges(tzp, tzid):
tzinfo2 = generated1.to_tz()
generated2 = Timezone.from_tzinfo(tzinfo2, "test-generated")
tzinfo3 = generated2.to_tz()
generated3 = Timezone.from_tzinfo(tzinfo2, "test-generated")
generated3 = Timezone.from_tzinfo(tzinfo3, "test-generated")
# pprint(generated1.get_transitions())
# pprint(generated2.get_transitions())
assert_components_equal(generated1, generated2)

Wyświetl plik

@ -115,10 +115,10 @@ class TestCaselessdict(unittest.TestCase):
self.assertEqual(ncd.get("key1"), "val1")
self.assertEqual(ncd.get("key3", "NOT FOUND"), "val3")
self.assertEqual(ncd.get("key4", "NOT FOUND"), "NOT FOUND")
self.assertTrue("key4" in ncd)
self.assertIn("key4", ncd)
del ncd["key4"]
self.assertFalse("key4" in ncd)
self.assertNotIn("key4", ncd)
ncd.update({"key5": "val5", "KEY6": "val6", "KEY5": "val7"})
self.assertEqual(ncd["key6"], "val6")

Wyświetl plik

@ -12,7 +12,7 @@ class TestParserTools(unittest.TestCase):
self.assertEqual(to_unicode(b"\xc6\xb5"), "\u01b5")
self.assertEqual(to_unicode(b"\xc6\xb5", encoding="ascii"), "\u01b5")
self.assertEqual(to_unicode(1), 1)
self.assertEqual(to_unicode(None), None)
self.assertIsNone(to_unicode(None))
def test_parser_tools_from_unicode(self):
self.assertEqual(from_unicode("\u01b5", encoding="ascii"), b"\xc6\xb5")

Wyświetl plik

@ -13,20 +13,20 @@ class TestTools(unittest.TestCase):
txt = uid.to_ical()
length = 15 + 1 + 16 + 1 + 11
self.assertTrue(len(txt) == length)
self.assertTrue(b"@example.com" in txt)
self.assertEqual(len(txt), length)
self.assertIn(b"@example.com", txt)
# You should at least insert your own hostname to be more compliant
uid = g.uid("Example.ORG")
txt = uid.to_ical()
self.assertTrue(len(txt) == length)
self.assertTrue(b"@Example.ORG" in txt)
self.assertEqual(len(txt), length)
self.assertIn(b"@Example.ORG", txt)
# You can also insert a path or similar
uid = g.uid("Example.ORG", "/path/to/content")
txt = uid.to_ical()
self.assertTrue(len(txt) == length)
self.assertTrue(b"-/path/to/content@Example.ORG" in txt)
self.assertEqual(len(txt), length)
self.assertIn(b"-/path/to/content@Example.ORG", txt)
@pytest.mark.parametrize(

Wyświetl plik

@ -20,7 +20,7 @@ from multiprocessing import Pool, cpu_count
from pathlib import Path
from pprint import pprint
from time import time
from typing import Callable, NamedTuple, Optional
from typing import Callable, NamedTuple, Optional, Any, Tuple, List
from zoneinfo import ZoneInfo, available_timezones
@ -30,7 +30,7 @@ from pytz import AmbiguousTimeError, NonExistentTimeError
def check(dt, tz:tzinfo):
return (dt, tz.utcoffset(dt))
def checks(tz:tzinfo) -> tuple:
def checks(tz:tzinfo) -> List[Tuple[Any, Optional[timedelta]]]:
result = []
for dt in DTS:
try:
@ -123,7 +123,7 @@ def main(
with file.open("w") as f:
f.write(f"'''This file is automatically generated by {Path(__file__).name}'''\n")
f.write("import datetime\n\n")
f.write(f"\nlookup = ")
f.write("\nlookup = ")
pprint(lookup, stream=f)
f.write("\n\n__all__ = ['lookup']\n")

Wyświetl plik

@ -105,16 +105,16 @@ class TZP:
"""
return tzid.strip("/")
def timezone(self, id: str) -> Optional[datetime.tzinfo]:
def timezone(self, tz_id: str) -> Optional[datetime.tzinfo]:
"""Return a timezone with an id or None if we cannot find it."""
_unclean_id = id
id = self.clean_timezone_id(id)
tz = self.__provider.timezone(id)
_unclean_id = tz_id
tz_id = self.clean_timezone_id(tz_id)
tz = self.__provider.timezone(tz_id)
if tz is not None:
return tz
if id in WINDOWS_TO_OLSON:
tz = self.__provider.timezone(WINDOWS_TO_OLSON[id])
return tz or self.__provider.timezone(_unclean_id) or self.__tz_cache.get(id)
if tz_id in WINDOWS_TO_OLSON:
tz = self.__provider.timezone(WINDOWS_TO_OLSON[tz_id])
return tz or self.__provider.timezone(_unclean_id) or self.__tz_cache.get(tz_id)
def uses_pytz(self) -> bool:
"""Whether we use pytz at all."""