diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 88c7228..546c461 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -57,7 +57,7 @@ build_debian: Section: web Priority: optional Architecture: all - Depends: python3 (>= 3.7), python3-jinja2, python3-bottle, python3-dateutil, python3-icalendar, python3-isodate, python3-tz + Depends: python3 (>= 3.7), python3-jinja2, python3-bottle, python3-dateutil, python3-icalendar, python3-isodate Description: Scrape iCalendar endpoints and present their data in a timeseries format. A small service that scrapes iCalendar files served over HTTP, parses their contents and returns a timeseries diff --git a/CHANGELOG.md b/CHANGELOG.md index 689f8c9..9dedff8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,19 @@ # iCalendar Timeseries Server Changelog + +## Version 0.3.3 + +### Changes + + +- Fix type confusion bug in recurring events +- Remove pytz dependency in favor of dateutil.tz + + + + + ## Version 0.3.2 diff --git a/README.md b/README.md index 41bb59c..c762283 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,6 @@ The server would transform this into the following API response: - `icalendar`: Parse iCalendar - `isodate`: Parse ISO-8601 time periods - `jinja2`: Template value replacements -- `pytz`: Work with timezones ## Configuration diff --git a/icalendar_timeseries_server/__init__.py b/icalendar_timeseries_server/__init__.py index 8299a60..2fd20b5 100644 --- a/icalendar_timeseries_server/__init__.py +++ b/icalendar_timeseries_server/__init__.py @@ -1,2 +1,2 @@ -__version__ = '0.3.2' +__version__ = '0.3.3' diff --git a/icalendar_timeseries_server/cal.py b/icalendar_timeseries_server/cal.py index 8db89b5..e4e479a 100644 --- a/icalendar_timeseries_server/cal.py +++ b/icalendar_timeseries_server/cal.py @@ -26,6 +26,8 @@ def _parse_recurring(event: cal.Event, start: datetime, end: datetime, duration: occurences: List[datetime] = [] evstart = event.get('dtstart').dt + if isinstance(evstart, date) and not isinstance(evstart, datetime): + evstart = datetime(evstart.year, evstart.month, evstart.day, tzinfo=start.tzinfo) # First occurence lies in the future; no need to process further if evstart >= end: return occurences diff --git a/icalendar_timeseries_server/config.py b/icalendar_timeseries_server/config.py index c3d18df..b763527 100644 --- a/icalendar_timeseries_server/config.py +++ b/icalendar_timeseries_server/config.py @@ -8,9 +8,10 @@ import urllib.request import sys import logging -import pytz import jinja2 from isodate import Duration, parse_duration +from dateutil import tz +from datetime import tzinfo from icalendar_timeseries_server import __version__ @@ -93,7 +94,7 @@ class Config: config = dict() self._addr: str = _keycheck('addr', config, str, '', default_value='127.0.0.1') self._port: int = _keycheck('port', config, int, '', default_value=8090) - self._tz: pytz.tzinfo = _parse_timezone('tz', config, '', default_value='UTC') + self._tz: tzinfo = _parse_timezone('tz', config, '', default_value='UTC') self._start_delta: Duration = _parse_timedelta('start_delta', config, '', default_value='PT') self._end_delta: Duration = _parse_timedelta('end_delta', config, '', default_value='P30D') self._calendars: Dict[str, CalendarConfig] = self._parse_calendars_config('calendars', config, '') @@ -120,7 +121,7 @@ class Config: return self._port @property - def tz(self) -> pytz.tzinfo: + def tz(self) -> tzinfo: return self._tz @property @@ -185,7 +186,10 @@ def _parse_timezone(key: str, path: str, default_value: Any = None) -> Any: zonename: str = _keycheck(key, config, str, path, default_value=default_value) - return pytz.timezone(zonename) + zone: zoneinfo = tz.gettz(zonename) + if zone is None: + raise ValueError(f'Unknown timezone: {zonename}') + return zone def _parse_key_replace(key: str, diff --git a/icalendar_timeseries_server/test/test_config.py b/icalendar_timeseries_server/test/test_config.py index c0f7601..3d9be55 100644 --- a/icalendar_timeseries_server/test/test_config.py +++ b/icalendar_timeseries_server/test/test_config.py @@ -2,9 +2,9 @@ import unittest import json -import pytz -from datetime import timedelta +from datetime import timedelta, tzinfo +from dateutil import tz from isodate.duration import Duration from icalendar_timeseries_server.config import _keycheck, _parse_timedelta, _parse_timezone, Config @@ -113,10 +113,10 @@ class ConfigTest(unittest.TestCase): 'tz': 'Europe/Zurich', 'notz': 'North/Winterfell' } - self.assertEqual(_parse_timezone('tz', config, ''), pytz.timezone('Europe/Zurich')) + self.assertEqual(_parse_timezone('tz', config, ''), tz.gettz('Europe/Zurich')) self.assertEqual(_parse_timezone('def', config, '', default_value='Europe/Berlin'), - pytz.timezone('Europe/Berlin')) - with self.assertRaises(pytz.exceptions.UnknownTimeZoneError): + tz.gettz('Europe/Berlin')) + with self.assertRaises(ValueError): _parse_timezone('notz', config, '') def test_parse_full_config_valid(self): @@ -125,7 +125,7 @@ class ConfigTest(unittest.TestCase): self.assertEqual(config.port, 8090) self.assertEqual(config.start_delta, Duration(hours=-3)) self.assertEqual(config.end_delta, Duration(days=30)) - self.assertEqual(config.tz, pytz.timezone('Europe/Zurich')) + self.assertEqual(config.tz, tz.gettz('Europe/Zurich')) def test_parse_calendars(self): config = Config(json.loads(_CONFIG_VALID)) diff --git a/package/debian/icalendar-timeseries-server/DEBIAN/postinst b/package/debian/icalendar-timeseries-server/DEBIAN/postinst index b7586de..be22d72 100755 --- a/package/debian/icalendar-timeseries-server/DEBIAN/postinst +++ b/package/debian/icalendar-timeseries-server/DEBIAN/postinst @@ -17,4 +17,9 @@ if [[ "$1" == "configure" ]]; then systemctl daemon-reload || true + if [[ "$2" != "" ]]; then + # Restart after upgrading the package + systemctl restart icalendar-timeseries-server.service + fi + fi diff --git a/setup.py b/setup.py index e5aaae3..dfb999b 100755 --- a/setup.py +++ b/setup.py @@ -18,11 +18,10 @@ setup( python_requires='>=3.6', install_requires=[ 'bottle', - 'python-dateutil', + 'python-dateutil>=2.8', 'icalendar', 'isodate', - 'jinja2', - 'pytz' + 'jinja2' ], entry_points={ 'console_scripts': [