Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-tasklib for openSUSE:Factory checked in at 2022-12-06 14:23:08 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-tasklib (Old) and /work/SRC/openSUSE:Factory/.python-tasklib.new.1835 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-tasklib" Tue Dec 6 14:23:08 2022 rev:6 rq:1040393 version:2.5.1 Changes: -------- --- /work/SRC/openSUSE:Factory/python-tasklib/python-tasklib.changes 2022-10-12 18:28:31.438196070 +0200 +++ /work/SRC/openSUSE:Factory/.python-tasklib.new.1835/python-tasklib.changes 2022-12-06 14:23:15.269564975 +0100 @@ -1,0 +2,6 @@ +Mon Dec 5 13:39:38 UTC 2022 - Yogalakshmi Arunachalam <yarunacha...@suse.com> + +- Update to 2.5.1 + * Support for zoneinfo and comparison operators for TaskUUIDSets + +------------------------------------------------------------------- Old: ---- tasklib-2.4.3.tar.gz New: ---- tasklib-2.5.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-tasklib.spec ++++++ --- /var/tmp/diff_new_pack.lrKl30/_old 2022-12-06 14:23:16.721577355 +0100 +++ /var/tmp/diff_new_pack.lrKl30/_new 2022-12-06 14:23:16.729577423 +0100 @@ -19,7 +19,7 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} %define skip_python2 1 Name: python-tasklib -Version: 2.4.3 +Version: 2.5.1 Release: 0 Summary: Python Task Warrior library License: BSD-3-Clause ++++++ tasklib-2.4.3.tar.gz -> tasklib-2.5.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tasklib-2.4.3/AUTHORS new/tasklib-2.5.1/AUTHORS --- old/tasklib-2.4.3/AUTHORS 1970-01-01 01:00:00.000000000 +0100 +++ new/tasklib-2.5.1/AUTHORS 2021-09-19 20:02:50.000000000 +0200 @@ -0,0 +1,2 @@ +Rob Golding +Tomas Babej diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tasklib-2.4.3/PKG-INFO new/tasklib-2.5.1/PKG-INFO --- old/tasklib-2.4.3/PKG-INFO 2021-10-10 16:34:21.336986800 +0200 +++ new/tasklib-2.5.1/PKG-INFO 2022-11-17 03:42:05.877242600 +0100 @@ -1,67 +1,12 @@ -Metadata-Version: 1.1 +Metadata-Version: 2.1 Name: tasklib -Version: 2.4.3 +Version: 2.5.1 Summary: Official Taskwarrior library for Python Home-page: https://github.com/GothenburgBitFactory/tasklib +Download-URL: https://github.com/GothenburgBitFactory/tasklib/downloads Author: GothenburgBitFactory Author-email: supp...@gothenburgbitfactory.org License: BSD -Download-URL: https://github.com/GothenburgBitFactory/tasklib/downloads -Description: tasklib - ======= - - .. image:: https://travis-ci.org/robgolding/tasklib.png?branch=develop - :target: http://travis-ci.org/robgolding/tasklib - - .. image:: https://coveralls.io/repos/robgolding/tasklib/badge.png?branch=develop - :target: https://coveralls.io/r/robgolding/tasklib?branch=develop - - tasklib is a Python library for interacting with taskwarrior_ databases, using - a queryset API similar to that of Django's ORM. - - Requirements - ------------ - - * Python 3.5 or above - * taskwarrior_ v2.4.x or above. - - Older versions of taskwarrior are untested and may not work. - - Installation - ------------ - - Install via pip:: - - pip install tasklib - - Usage - ----- - - tasklib has a similar API to that of Django's ORM:: - - >>> from tasklib import TaskWarrior - - >>> tw = TaskWarrior('~/.task') - >>> tasks = tw.tasks.pending() - >>> tasks - ['Tidy the house', 'Learn German'] - >>> tasks.filter(tags__contain='chores') - ['Tidy the house'] - >>> type(tasks[0]) - <class 'tasklib.task.Task'> - >>> tasks[0].done() - >>> tasks = tw.tasks.pending() - >>> tasks - ['Learn German'] - >>> tasks[0]['tags'] = ['languages'] - >>> tasks[0].save() - - For more advanced usage, see the documentation_. - - .. _taskwarrior: http://taskwarrior.org - .. _documentation: http://tasklib.readthedocs.org/en/latest/ - -Platform: UNKNOWN Classifier: Development Status :: 6 - Mature Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3 @@ -77,3 +22,59 @@ Classifier: Intended Audience :: Information Technology Classifier: Intended Audience :: System Administrators Classifier: Operating System :: OS Independent +License-File: LICENSE +License-File: AUTHORS + +tasklib +======= + +.. image:: https://travis-ci.org/robgolding/tasklib.png?branch=develop + :target: http://travis-ci.org/robgolding/tasklib + +.. image:: https://coveralls.io/repos/robgolding/tasklib/badge.png?branch=develop + :target: https://coveralls.io/r/robgolding/tasklib?branch=develop + +tasklib is a Python library for interacting with taskwarrior_ databases, using +a queryset API similar to that of Django's ORM. + +Requirements +------------ + +* Python 3.5 or above +* taskwarrior_ v2.4.x or above. + +Older versions of taskwarrior are untested and may not work. + +Installation +------------ + +Install via pip:: + + pip install tasklib + +Usage +----- + +tasklib has a similar API to that of Django's ORM:: + + >>> from tasklib import TaskWarrior + + >>> tw = TaskWarrior('~/.task') + >>> tasks = tw.tasks.pending() + >>> tasks + ['Tidy the house', 'Learn German'] + >>> tasks.filter(tags__contain='chores') + ['Tidy the house'] + >>> type(tasks[0]) + <class 'tasklib.task.Task'> + >>> tasks[0].done() + >>> tasks = tw.tasks.pending() + >>> tasks + ['Learn German'] + >>> tasks[0]['tags'] = ['languages'] + >>> tasks[0].save() + +For more advanced usage, see the documentation_. + +.. _taskwarrior: http://taskwarrior.org +.. _documentation: http://tasklib.readthedocs.org/en/latest/ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tasklib-2.4.3/setup.py new/tasklib-2.5.1/setup.py --- old/tasklib-2.4.3/setup.py 2021-10-10 16:34:09.000000000 +0200 +++ new/tasklib-2.5.1/setup.py 2022-11-17 03:35:38.000000000 +0100 @@ -1,13 +1,6 @@ from setuptools import setup, find_packages -install_requirements = ['pytz', 'tzlocal'] - -version = '2.4.3' - -try: - import importlib -except ImportError: - install_requirements.append('importlib') +version = '2.5.1' setup( name='tasklib', @@ -22,7 +15,7 @@ packages=find_packages(), include_package_data=True, test_suite='tasklib.tests', - install_requires=install_requirements, + install_requires=['backports.zoneinfo;python_version<"3.9"'], classifiers=[ 'Development Status :: 6 - Mature', 'Programming Language :: Python', diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tasklib-2.4.3/tasklib/__init__.py new/tasklib-2.5.1/tasklib/__init__.py --- old/tasklib-2.4.3/tasklib/__init__.py 2021-10-10 16:34:09.000000000 +0200 +++ new/tasklib-2.5.1/tasklib/__init__.py 2022-11-17 03:35:38.000000000 +0100 @@ -1,5 +1,4 @@ from .backends import TaskWarrior from .task import Task -from .serializing import local_zone -__version__ = '2.4.3' +__version__ = '2.5.1' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tasklib-2.4.3/tasklib/backends.py new/tasklib-2.5.1/tasklib/backends.py --- old/tasklib-2.4.3/tasklib/backends.py 2021-10-10 16:34:03.000000000 +0200 +++ new/tasklib-2.5.1/tasklib/backends.py 2022-11-17 03:35:38.000000000 +0100 @@ -10,7 +10,6 @@ from .task import Task, TaskQuerySet, ReadOnlyDictView from .filters import TaskWarriorFilter -from .serializing import local_zone DATE_FORMAT_CALC = '%Y-%m-%dT%H:%M:%S' @@ -225,7 +224,7 @@ args = value.split() result = self.execute_command(['calc'] + args) naive = datetime.datetime.strptime(result[0], DATE_FORMAT_CALC) - localized = local_zone.localize(naive) + localized = naive.astimezone() return localized @property diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tasklib-2.4.3/tasklib/lazy.py new/tasklib-2.5.1/tasklib/lazy.py --- old/tasklib-2.4.3/tasklib/lazy.py 2021-09-19 20:02:50.000000000 +0200 +++ new/tasklib-2.5.1/tasklib/lazy.py 2022-10-04 15:16:18.000000000 +0200 @@ -165,11 +165,17 @@ def __ge__(self, other): return self.issuperset(other) + def __lt__(self, other): + return self._uuids < set(t['uuid'] for t in other) + + def __gt__(self, other): + return self._uuids > set(t['uuid'] for t in other) + def issubset(self, other): - return all([task in other for task in self]) + return self._uuids <= set(t['uuid'] for t in other) def issuperset(self, other): - return all([task in self for task in other]) + return self._uuids >= set(t['uuid'] for t in other) def union(self, other): return LazyUUIDTaskSet( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tasklib-2.4.3/tasklib/serializing.py new/tasklib-2.5.1/tasklib/serializing.py --- old/tasklib-2.4.3/tasklib/serializing.py 2021-10-10 16:34:03.000000000 +0200 +++ new/tasklib-2.5.1/tasklib/serializing.py 2022-11-17 03:35:38.000000000 +0100 @@ -1,14 +1,15 @@ import datetime import importlib import json -import pytz -import tzlocal +try: + from zoneinfo import ZoneInfo +except ImportError: + from backports.zoneinfo import ZoneInfo from .lazy import LazyUUIDTaskSet, LazyUUIDTask DATE_FORMAT = '%Y%m%dT%H%M%SZ' -local_zone = pytz.timezone(str(tzlocal.get_localzone())) class SerializingObject(object): @@ -73,7 +74,7 @@ # Any serialized timestamp should be localized, we need to # convert to UTC before converting to string (DATE_FORMAT uses UTC) - date = date.astimezone(pytz.utc) + date = date.astimezone(ZoneInfo('UTC')) return date.strftime(DATE_FORMAT) @@ -83,8 +84,8 @@ # Return timestamp localized in the local zone naive_timestamp = datetime.datetime.strptime(date_str, DATE_FORMAT) - localized_timestamp = pytz.utc.localize(naive_timestamp) - return localized_timestamp.astimezone(local_zone) + localized_timestamp = naive_timestamp.replace(tzinfo=ZoneInfo('UTC')) + return localized_timestamp.astimezone() def serialize_entry(self, value): return self.timestamp_serializer(value) @@ -226,11 +227,11 @@ ): # Convert to local midnight value_full = datetime.datetime.combine(value, datetime.time.min) - localized = local_zone.localize(value_full) + localized = value_full.astimezone() elif isinstance(value, datetime.datetime): if value.tzinfo is None: # Convert to localized datetime object - localized = local_zone.localize(value) + localized = value.astimezone() else: # If the value is already localized, there is no need to change # time zone at this point. Also None is a valid value too. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tasklib-2.4.3/tasklib/task.py new/tasklib-2.5.1/tasklib/task.py --- old/tasklib-2.4.3/tasklib/task.py 2021-10-10 16:34:09.000000000 +0200 +++ new/tasklib-2.5.1/tasklib/task.py 2022-11-17 03:35:38.000000000 +0100 @@ -7,7 +7,7 @@ import os import sys -from .serializing import SerializingObject, local_zone +from .serializing import SerializingObject DATE_FORMAT = '%Y%m%dT%H%M%SZ' REPR_OUTPUT_SIZE = 10 @@ -299,7 +299,7 @@ if not self['wait']: return False - return self['wait'] > local_zone.localize(datetime.datetime.now()) + return self['wait'] > datetime.datetime.now().astimezone() @property def pending(self): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tasklib-2.4.3/tasklib/tests.py new/tasklib-2.5.1/tasklib/tests.py --- old/tasklib-2.4.3/tasklib/tests.py 2021-10-10 16:34:09.000000000 +0200 +++ new/tasklib-2.5.1/tasklib/tests.py 2022-11-17 03:35:38.000000000 +0100 @@ -5,17 +5,20 @@ import itertools import json import os -import pytz import shutil import sys import tempfile import unittest from io import StringIO +try: + from zoneinfo import ZoneInfo +except ImportError: + from backports.zoneinfo import ZoneInfo from .backends import TaskWarrior from .task import Task, ReadOnlyDictView from .lazy import LazyUUIDTask, LazyUUIDTaskSet -from .serializing import DATE_FORMAT, local_zone +from .serializing import DATE_FORMAT # http://taskwarrior.org/docs/design/task.html , Section: The Attributes TASK_STANDARD_ATTRS = ( @@ -1110,8 +1113,7 @@ self.tw, description='test task', project='Home', - due=pytz.utc.localize( - datetime.datetime(2015, 1, 1, 23, 23, 23)), + due=datetime.datetime(2015, 1, 1, 23, 23, 23, tzinfo=ZoneInfo('UTC')), ) # Check that the output is a permutation of: @@ -1132,11 +1134,10 @@ def setUp(self): super(TimezoneAwareDatetimeTest, self).setUp() - self.zone = local_zone self.localdate_naive = datetime.datetime(2015, 2, 2) self.localtime_naive = datetime.datetime(2015, 2, 2, 0, 0, 0) - self.localtime_aware = self.zone.localize(self.localtime_naive) - self.utctime_aware = self.localtime_aware.astimezone(pytz.utc) + self.localtime_aware = self.localtime_naive.astimezone() + self.utctime_aware = self.localtime_aware.astimezone(ZoneInfo('UTC')) def test_timezone_naive_datetime_setitem(self): t = Task(self.tw, description='test task') @@ -1217,7 +1218,7 @@ return t = Task(self.tw, description='test task', due='now') - now = local_zone.localize(datetime.datetime.now()) + now = datetime.datetime.now().astimezone() # Assert that both times are not more than 5 seconds apart if sys.version_info < (2, 7): @@ -1237,24 +1238,24 @@ return t = Task(self.tw, description='test task', due='eoy') - now = local_zone.localize(datetime.datetime.now()) - eoy = local_zone.localize(datetime.datetime( + now = datetime.datetime.now().astimezone() + eoy = datetime.datetime( year=now.year, month=12, day=31, hour=23, minute=59, second=59, - )) + ).astimezone() if self.tw.version >= '2.5.2' and self.tw.version < '2.6.0': - eoy = local_zone.localize(datetime.datetime( + eoy = datetime.datetime( year=now.year+1, month=1, day=1, hour=0, minute=0, second=0, - )) + ).astimezone() self.assertEqual(eoy, t['due']) def test_complex_eoy_conversion(self): @@ -1267,28 +1268,24 @@ return t = Task(self.tw, description='test task', due='eoy - 4 months') - now = local_zone.localize(datetime.datetime.now()) - due_date = local_zone.localize( - datetime.datetime( - year=now.year, - month=12, - day=31, - hour=23, - minute=59, - second=59, - ) - ) - datetime.timedelta(0, 4 * 30 * 86400) + now = datetime.datetime.now().astimezone() + due_date = datetime.datetime( + year=now.year, + month=12, + day=31, + hour=23, + minute=59, + second=59, + ).astimezone() - datetime.timedelta(0, 4 * 30 * 86400) if self.tw.version >= '2.5.2' and self.tw.version < '2.6.0': - due_date = local_zone.localize( - datetime.datetime( - year=now.year+1, - month=1, - day=1, - hour=0, - minute=0, - second=0, - ) - ) - datetime.timedelta(0, 4 * 30 * 86400) + due_date = datetime.datetime( + year=now.year+1, + month=1, + day=1, + hour=0, + minute=0, + second=0, + ).astimezone() - datetime.timedelta(0, 4 * 30 * 86400) self.assertEqual(due_date, t['due']) def test_filtering_with_string_datetime(self): @@ -1656,6 +1653,70 @@ lazyset &= taskset assert lazyset == set([self.task2]) + def test_le(self): + lazyset = LazyUUIDTaskSet( + self.tw, + (self.task2['uuid'], self.task3['uuid']) + ) + empty_lazyset = LazyUUIDTaskSet( + self.tw, + [], + ) + + assert lazyset <= set([self.task1, self.task2, self.task3]) + assert self.lazy <= set([self.task1, self.task2, self.task3]) + assert not lazyset <= set([self.task1, self.task2]) + assert empty_lazyset <= set() + assert empty_lazyset <= set([self.task1]) + + def test_ge(self): + lazyset = LazyUUIDTaskSet( + self.tw, + (self.task2['uuid'], self.task3['uuid']) + ) + empty_lazyset = LazyUUIDTaskSet( + self.tw, + [], + ) + + assert self.lazy >= set([self.task1, self.task2]) + assert self.lazy >= set([self.task1, self.task2, self.task3]) + assert not lazyset >= set([self.task1, self.task2]) + assert empty_lazyset >= set() + assert not empty_lazyset >= set([self.task1]) + + def test_lt(self): + lazyset = LazyUUIDTaskSet( + self.tw, + (self.task2['uuid'], self.task3['uuid']) + ) + empty_lazyset = LazyUUIDTaskSet( + self.tw, + [], + ) + + assert lazyset < set([self.task1, self.task2, self.task3]) + assert not lazyset < set([self.task2, self.task3]) + assert not lazyset < set([self.task1, self.task2]) + assert empty_lazyset < set([self.task1]) + assert not empty_lazyset < set() + + def test_gt(self): + lazyset = LazyUUIDTaskSet( + self.tw, + (self.task2['uuid'], self.task3['uuid']) + ) + empty_lazyset = LazyUUIDTaskSet( + self.tw, + [], + ) + + assert lazyset > set([self.task2]) + assert not lazyset > set([self.task2, self.task3]) + assert not lazyset > set([self.task1, self.task2]) + assert not empty_lazyset > set([self.task1]) + assert not empty_lazyset > set() + class TaskWarriorBackendTest(TasklibTest): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tasklib-2.4.3/tasklib.egg-info/PKG-INFO new/tasklib-2.5.1/tasklib.egg-info/PKG-INFO --- old/tasklib-2.4.3/tasklib.egg-info/PKG-INFO 2021-10-10 16:34:21.000000000 +0200 +++ new/tasklib-2.5.1/tasklib.egg-info/PKG-INFO 2022-11-17 03:42:05.000000000 +0100 @@ -1,67 +1,12 @@ -Metadata-Version: 1.1 +Metadata-Version: 2.1 Name: tasklib -Version: 2.4.3 +Version: 2.5.1 Summary: Official Taskwarrior library for Python Home-page: https://github.com/GothenburgBitFactory/tasklib +Download-URL: https://github.com/GothenburgBitFactory/tasklib/downloads Author: GothenburgBitFactory Author-email: supp...@gothenburgbitfactory.org License: BSD -Download-URL: https://github.com/GothenburgBitFactory/tasklib/downloads -Description: tasklib - ======= - - .. image:: https://travis-ci.org/robgolding/tasklib.png?branch=develop - :target: http://travis-ci.org/robgolding/tasklib - - .. image:: https://coveralls.io/repos/robgolding/tasklib/badge.png?branch=develop - :target: https://coveralls.io/r/robgolding/tasklib?branch=develop - - tasklib is a Python library for interacting with taskwarrior_ databases, using - a queryset API similar to that of Django's ORM. - - Requirements - ------------ - - * Python 3.5 or above - * taskwarrior_ v2.4.x or above. - - Older versions of taskwarrior are untested and may not work. - - Installation - ------------ - - Install via pip:: - - pip install tasklib - - Usage - ----- - - tasklib has a similar API to that of Django's ORM:: - - >>> from tasklib import TaskWarrior - - >>> tw = TaskWarrior('~/.task') - >>> tasks = tw.tasks.pending() - >>> tasks - ['Tidy the house', 'Learn German'] - >>> tasks.filter(tags__contain='chores') - ['Tidy the house'] - >>> type(tasks[0]) - <class 'tasklib.task.Task'> - >>> tasks[0].done() - >>> tasks = tw.tasks.pending() - >>> tasks - ['Learn German'] - >>> tasks[0]['tags'] = ['languages'] - >>> tasks[0].save() - - For more advanced usage, see the documentation_. - - .. _taskwarrior: http://taskwarrior.org - .. _documentation: http://tasklib.readthedocs.org/en/latest/ - -Platform: UNKNOWN Classifier: Development Status :: 6 - Mature Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3 @@ -77,3 +22,59 @@ Classifier: Intended Audience :: Information Technology Classifier: Intended Audience :: System Administrators Classifier: Operating System :: OS Independent +License-File: LICENSE +License-File: AUTHORS + +tasklib +======= + +.. image:: https://travis-ci.org/robgolding/tasklib.png?branch=develop + :target: http://travis-ci.org/robgolding/tasklib + +.. image:: https://coveralls.io/repos/robgolding/tasklib/badge.png?branch=develop + :target: https://coveralls.io/r/robgolding/tasklib?branch=develop + +tasklib is a Python library for interacting with taskwarrior_ databases, using +a queryset API similar to that of Django's ORM. + +Requirements +------------ + +* Python 3.5 or above +* taskwarrior_ v2.4.x or above. + +Older versions of taskwarrior are untested and may not work. + +Installation +------------ + +Install via pip:: + + pip install tasklib + +Usage +----- + +tasklib has a similar API to that of Django's ORM:: + + >>> from tasklib import TaskWarrior + + >>> tw = TaskWarrior('~/.task') + >>> tasks = tw.tasks.pending() + >>> tasks + ['Tidy the house', 'Learn German'] + >>> tasks.filter(tags__contain='chores') + ['Tidy the house'] + >>> type(tasks[0]) + <class 'tasklib.task.Task'> + >>> tasks[0].done() + >>> tasks = tw.tasks.pending() + >>> tasks + ['Learn German'] + >>> tasks[0]['tags'] = ['languages'] + >>> tasks[0].save() + +For more advanced usage, see the documentation_. + +.. _taskwarrior: http://taskwarrior.org +.. _documentation: http://tasklib.readthedocs.org/en/latest/ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tasklib-2.4.3/tasklib.egg-info/SOURCES.txt new/tasklib-2.5.1/tasklib.egg-info/SOURCES.txt --- old/tasklib-2.4.3/tasklib.egg-info/SOURCES.txt 2021-10-10 16:34:21.000000000 +0200 +++ new/tasklib-2.5.1/tasklib.egg-info/SOURCES.txt 2022-11-17 03:42:05.000000000 +0100 @@ -1,3 +1,4 @@ +AUTHORS LICENSE MANIFEST.in README.rst diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tasklib-2.4.3/tasklib.egg-info/requires.txt new/tasklib-2.5.1/tasklib.egg-info/requires.txt --- old/tasklib-2.4.3/tasklib.egg-info/requires.txt 2021-10-10 16:34:21.000000000 +0200 +++ new/tasklib-2.5.1/tasklib.egg-info/requires.txt 2022-11-17 03:42:05.000000000 +0100 @@ -1,2 +1,3 @@ -pytz -tzlocal + +[:python_version < "3.9"] +backports.zoneinfo