kopia lustrzana https://github.com/collective/icalendar
Improve error message if wrong provider is used
rodzic
30472097f5
commit
914b204535
|
@ -99,7 +99,6 @@ def create_utc_property(name:str, docs:str):
|
|||
return None
|
||||
dt = self.get(name)
|
||||
value = getattr(dt, "dt", None)
|
||||
print(value)
|
||||
if value is None or not isinstance(value, date):
|
||||
raise InvalidCalendar(f"{name} must be a datetime in UTC, not {value}")
|
||||
return value
|
||||
|
@ -109,7 +108,7 @@ def create_utc_property(name:str, docs:str):
|
|||
if not isinstance(value, date):
|
||||
raise TypeError(f"{name} takes a datetime in UTC, not {value}")
|
||||
self.pop(name)
|
||||
self.add(name, tzp.localize_utc(to_datetime(value)))
|
||||
self.add(name, tzp.localize_utc(value))
|
||||
|
||||
|
||||
return property(p_get, p_set, doc=docs)
|
||||
|
|
|
@ -35,28 +35,25 @@ primitive Python datatype. So it should always be true that:
|
|||
These types are mainly used for parsing and file generation. But you can set
|
||||
them directly.
|
||||
"""
|
||||
from datetime import date
|
||||
from datetime import datetime
|
||||
from datetime import time
|
||||
from datetime import timedelta
|
||||
from datetime import tzinfo
|
||||
from icalendar.caselessdict import CaselessDict
|
||||
from icalendar.parser import Parameters
|
||||
from icalendar.parser import escape_char
|
||||
from icalendar.parser import unescape_char
|
||||
from icalendar.parser_tools import (
|
||||
DEFAULT_ENCODING, SEQUENCE_TYPES, to_unicode, from_unicode, ICAL_TYPE
|
||||
)
|
||||
|
||||
import base64
|
||||
import binascii
|
||||
from .timezone import tzp
|
||||
import re
|
||||
import time as _time
|
||||
|
||||
from typing import Optional, Union
|
||||
from datetime import date, datetime, time, timedelta, tzinfo
|
||||
from enum import Enum, auto
|
||||
from typing import Optional, Union
|
||||
|
||||
from icalendar.caselessdict import CaselessDict
|
||||
from icalendar.parser import Parameters, escape_char, unescape_char
|
||||
from icalendar.parser_tools import (
|
||||
DEFAULT_ENCODING,
|
||||
ICAL_TYPE,
|
||||
SEQUENCE_TYPES,
|
||||
from_unicode,
|
||||
to_unicode,
|
||||
)
|
||||
|
||||
from . import timezone as _timezone
|
||||
|
||||
DURATION_REGEX = re.compile(r'([-+]?)P(?:(\d+)W)?(?:(\d+)D)?'
|
||||
r'(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?)?$')
|
||||
|
@ -410,7 +407,7 @@ class vDatetime(TimeBase):
|
|||
def from_ical(ical, timezone=None):
|
||||
tzinfo = None
|
||||
if timezone:
|
||||
tzinfo = tzp.timezone(timezone)
|
||||
tzinfo = _timezone.tzp.timezone(timezone)
|
||||
|
||||
try:
|
||||
timetuple = (
|
||||
|
@ -422,11 +419,11 @@ class vDatetime(TimeBase):
|
|||
int(ical[13:15]), # second
|
||||
)
|
||||
if tzinfo:
|
||||
return tzp.localize(datetime(*timetuple), tzinfo)
|
||||
return _timezone.tzp.localize(datetime(*timetuple), tzinfo)
|
||||
elif not ical[15:]:
|
||||
return datetime(*timetuple)
|
||||
elif ical[15:16] == 'Z':
|
||||
return tzp.localize_utc(datetime(*timetuple))
|
||||
return _timezone.tzp.localize_utc(datetime(*timetuple))
|
||||
else:
|
||||
raise ValueError(ical)
|
||||
except Exception:
|
||||
|
|
|
@ -5,7 +5,7 @@ from datetime import date, datetime, timedelta
|
|||
import pytest
|
||||
|
||||
from icalendar import Event, FreeBusy, Journal, Todo, vDDDTypes
|
||||
from icalendar.cal import InvalidCalendar
|
||||
from icalendar.cal import Component, InvalidCalendar
|
||||
|
||||
|
||||
@pytest.fixture(params=[Event, Todo, Journal, FreeBusy])
|
||||
|
@ -19,6 +19,20 @@ def test_no_dtstamp(dtstamp_comp):
|
|||
assert dtstamp_comp.DTSTAMP is None
|
||||
|
||||
|
||||
def set_dtstamp_attribute(component:Component, value:date):
|
||||
"""Use the setter."""
|
||||
component.DTSTAMP = value
|
||||
|
||||
def set_dtstamp_item(component: Component, value:date):
|
||||
"""Use setitem."""
|
||||
component["DTSTAMP"] = vDDDTypes(value)
|
||||
|
||||
def set_dtstamp_add(component: Component, value:date):
|
||||
"""Use add."""
|
||||
component.add("DTSTAMP", value)
|
||||
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("value", "timezone", "expected"),
|
||||
[
|
||||
|
@ -28,10 +42,13 @@ def test_no_dtstamp(dtstamp_comp):
|
|||
(date(2024, 10, 10), None, datetime(2024, 10, 10)),
|
||||
]
|
||||
)
|
||||
def test_set_value_and_get_it(dtstamp_comp, value, timezone, expected, tzp):
|
||||
@pytest.mark.parametrize(
|
||||
"set_dtstamp", [set_dtstamp_add, set_dtstamp_attribute, set_dtstamp_item]
|
||||
)
|
||||
def test_set_value_and_get_it(dtstamp_comp, value, timezone, expected, tzp, set_dtstamp):
|
||||
"""Set and get the DTSTAMP value."""
|
||||
dtstamp = value if timezone is None else tzp.localize(value, timezone)
|
||||
dtstamp_comp.DTSTAMP = dtstamp
|
||||
set_dtstamp(dtstamp_comp, dtstamp)
|
||||
in_utc = tzp.localize_utc(expected)
|
||||
get_value = dtstamp_comp.get("DTSTAMP").dt
|
||||
assert in_utc == get_value
|
||||
|
|
|
@ -90,3 +90,15 @@ def test_cache_is_emptied_when_tzp_is_switched(tzp, timezones, new_tzp_name):
|
|||
tzp.cache_timezone_component(timezones.pacific_fiji)
|
||||
tz2 = tzp.timezone("custom_Pacific/Fiji")
|
||||
assert tz1 is not tz2
|
||||
|
||||
|
||||
def test_invalid_name(tzp):
|
||||
"""Check that the provider name is ok."""
|
||||
provider = "invalid_provider"
|
||||
with pytest.raises(ValueError) as e:
|
||||
tzp.use(provider)
|
||||
# f"Unknown provider {provider}. Use 'pytz' or 'zoneinfo'."
|
||||
message = e.value.args[0]
|
||||
assert f"Unknown provider {provider}." in message
|
||||
assert "zoneinfo" in message
|
||||
assert "pytz" in message
|
||||
|
|
|
@ -13,4 +13,4 @@ def use_zoneinfo():
|
|||
tzp.use_zoneinfo()
|
||||
|
||||
|
||||
__all__ = ["tzp", "use_pytz", "use_zoneinfo", "normalize_pytz"]
|
||||
__all__ = ["tzp", "use_pytz", "use_zoneinfo"]
|
||||
|
|
|
@ -1,12 +1,19 @@
|
|||
from __future__ import annotations
|
||||
import datetime
|
||||
from .. import cal
|
||||
from typing import Optional, Union
|
||||
from .windows_to_olson import WINDOWS_TO_OLSON
|
||||
from .provider import TZProvider
|
||||
from icalendar import prop
|
||||
from dateutil.rrule import rrule
|
||||
|
||||
from typing import TYPE_CHECKING, Optional, Union
|
||||
|
||||
from icalendar.tools import to_datetime
|
||||
|
||||
from .windows_to_olson import WINDOWS_TO_OLSON
|
||||
|
||||
if TYPE_CHECKING:
|
||||
import datetime
|
||||
|
||||
from dateutil.rrule import rrule
|
||||
|
||||
from icalendar import cal, prop
|
||||
|
||||
from .provider import TZProvider
|
||||
|
||||
DEFAULT_TIMEZONE_PROVIDER = "zoneinfo"
|
||||
|
||||
|
@ -41,10 +48,10 @@ class TZP:
|
|||
def use(self, provider:Union[str, TZProvider]):
|
||||
"""Switch to a different timezone provider."""
|
||||
if isinstance(provider, str):
|
||||
provider = getattr(self, f"use_{provider}", None)
|
||||
if provider is None:
|
||||
raise ValueError(f"Unknown provider {provider_name}. Use 'pytz' or 'zoneinfo'.")
|
||||
provider()
|
||||
use_provider = getattr(self, f"use_{provider}", None)
|
||||
if use_provider is None:
|
||||
raise ValueError(f"Unknown provider {provider}. Use 'pytz' or 'zoneinfo'.")
|
||||
use_provider()
|
||||
else:
|
||||
self._use(provider)
|
||||
|
||||
|
@ -52,12 +59,12 @@ class TZP:
|
|||
"""Use the default timezone provider."""
|
||||
self.use(DEFAULT_TIMEZONE_PROVIDER)
|
||||
|
||||
def localize_utc(self, dt: datetime.datetime) -> datetime.datetime:
|
||||
def localize_utc(self, dt: datetime.date) -> datetime.datetime:
|
||||
"""Return the datetime in UTC.
|
||||
|
||||
If the datetime has no timezone, set UTC as its timezone.
|
||||
"""
|
||||
return self.__provider.localize_utc(dt)
|
||||
return self.__provider.localize_utc(to_datetime(dt))
|
||||
|
||||
def localize(self, dt: datetime.datetime, tz: Union[datetime.tzinfo, str]) -> datetime.datetime:
|
||||
"""Localize a datetime to a timezone."""
|
||||
|
|
|
@ -4,7 +4,6 @@ from datetime import date, datetime, tzinfo
|
|||
from string import ascii_letters, digits
|
||||
|
||||
from icalendar.parser_tools import to_unicode
|
||||
from icalendar.prop import vDatetime, vText
|
||||
|
||||
|
||||
class UIDGenerator:
|
||||
|
@ -26,6 +25,7 @@ class UIDGenerator:
|
|||
Like:
|
||||
20050105T225746Z-HKtJMqUgdO0jDUwm@example.com
|
||||
"""
|
||||
from icalendar.prop import vDatetime, vText
|
||||
host_name = to_unicode(host_name)
|
||||
unique = unique or UIDGenerator.rnd_string()
|
||||
today = to_unicode(vDatetime(datetime.today()).to_ical())
|
||||
|
|
Ładowanie…
Reference in New Issue