Fix compatibility with Python 3.8

We removed compatibility with Python 3.8 once but it was added back to
tested runtimes for 2023.2. Thus we have to make sure the code works
with Python 3.8, which was broken by [1].

Note that pytz is added back to requirmenets.txt and is now required
regardless of the python version. This is a short term solution until
we figure out the way to fix the requirement-check job (or we again
remove python 3.8 support).

[1] a326ec5eea

Change-Id: I3b222bb59260dff7a06a5ed48720df3dc8c74ea7
This commit is contained in:
Hervé Beraud 2023-05-15 10:57:53 +02:00
parent d4c988ab9c
commit 61c460f3f2
4 changed files with 46 additions and 17 deletions

View File

@ -33,9 +33,16 @@ import functools
import itertools import itertools
import uuid import uuid
from xmlrpc import client as xmlrpclib from xmlrpc import client as xmlrpclib
import zoneinfo
import msgpack import msgpack
try:
import zoneinfo
except ImportError:
# zoneinfo is available in Python >= 3.9
from pytz import timezone
zoneinfo = None
from oslo_utils import importutils from oslo_utils import importutils
netaddr = importutils.try_import("netaddr") netaddr = importutils.try_import("netaddr")
@ -236,7 +243,10 @@ class DateTimeHandler(object):
'microsecond': dt.microsecond, 'microsecond': dt.microsecond,
} }
if dt.tzinfo: if dt.tzinfo:
tz = str(dt.tzinfo) if zoneinfo:
tz = str(dt.tzinfo)
else:
tz = dt.tzinfo.tzname(None)
dct['tz'] = tz dct['tz'] = tz
return dumps(dct, registry=self._registry) return dumps(dct, registry=self._registry)
@ -264,8 +274,12 @@ class DateTimeHandler(object):
second=dct['second'], second=dct['second'],
microsecond=dct['microsecond']) microsecond=dct['microsecond'])
if 'tz' in dct and dct['tz']: if 'tz' in dct and dct['tz']:
tzinfo = zoneinfo.ZoneInfo(dct['tz']) if zoneinfo:
dt = dt.replace(tzinfo=tzinfo) tzinfo = zoneinfo.ZoneInfo(dct['tz'])
dt = dt.replace(tzinfo=tzinfo)
else:
tzinfo = timezone(dct['tz'])
dt = tzinfo.localize(dt)
return dt return dt

View File

@ -15,11 +15,17 @@
import datetime import datetime
import itertools import itertools
from xmlrpc import client as xmlrpclib from xmlrpc import client as xmlrpclib
import zoneinfo
import netaddr import netaddr
from oslotest import base as test_base from oslotest import base as test_base
try:
import zoneinfo
except ImportError:
# zoneinfo is available in Python >= 3.9
from pytz import timezone
zoneinfo = None
from oslo_serialization import msgpackutils from oslo_serialization import msgpackutils
from oslo_utils import uuidutils from oslo_utils import uuidutils
@ -145,22 +151,31 @@ class MsgPackUtilsTest(test_base.BaseTestCase):
self.assertEqual(today, _dumps_loads(today)) self.assertEqual(today, _dumps_loads(today))
def test_datetime_tz_clone(self): def test_datetime_tz_clone(self):
eastern = zoneinfo.ZoneInfo('US/Eastern')
now = datetime.datetime.now() now = datetime.datetime.now()
e_dt = now.replace(tzinfo=eastern) if zoneinfo:
eastern = zoneinfo.ZoneInfo('US/Eastern')
e_dt = now.replace(tzinfo=eastern)
else:
eastern = timezone('US/Eastern')
e_dt = eastern.localize(now)
e_dt2 = _dumps_loads(e_dt) e_dt2 = _dumps_loads(e_dt)
self.assertEqual(e_dt, e_dt2) self.assertEqual(e_dt, e_dt2)
self.assertEqual(e_dt.strftime(_TZ_FMT), e_dt2.strftime(_TZ_FMT)) self.assertEqual(e_dt.strftime(_TZ_FMT), e_dt2.strftime(_TZ_FMT))
def test_datetime_tz_different(self): def test_datetime_tz_different(self):
eastern = zoneinfo.ZoneInfo('US/Eastern')
pacific = zoneinfo.ZoneInfo('US/Pacific')
now = datetime.datetime.now() now = datetime.datetime.now()
if zoneinfo:
now = now.replace(tzinfo=eastern) eastern = zoneinfo.ZoneInfo('US/Eastern')
e_dt = now pacific = zoneinfo.ZoneInfo('US/Pacific')
now = now.replace(tzinfo=pacific) now = now.replace(tzinfo=eastern)
p_dt = now e_dt = now
now = now.replace(tzinfo=pacific)
p_dt = now
else:
eastern = timezone('US/Eastern')
pacific = timezone('US/Pacific')
e_dt = eastern.localize(now)
p_dt = pacific.localize(now)
self.assertNotEqual(e_dt, p_dt) self.assertNotEqual(e_dt, p_dt)
self.assertNotEqual(e_dt.strftime(_TZ_FMT), p_dt.strftime(_TZ_FMT)) self.assertNotEqual(e_dt.strftime(_TZ_FMT), p_dt.strftime(_TZ_FMT))

View File

@ -1,6 +1,5 @@
--- ---
other: other:
- | - |
Implement zoneinfo to allow us to remove pytz's dependency. zoneinfo Implement zoneinfo to allow us to remove pytz's dependency for Python 3.9
was introduced by python 3.9, and the series 2023.2 (bobcat) set py39 and 3.10
as the minimal supported runtime, so we are able to remove pytz.

View File

@ -10,4 +10,5 @@
pbr!=2.1.0,>=2.0.0 # Apache-2.0 pbr!=2.1.0,>=2.0.0 # Apache-2.0
msgpack>=0.5.2 # Apache-2.0 msgpack>=0.5.2 # Apache-2.0
oslo.utils>=3.33.0 # Apache-2.0 oslo.utils>=3.33.0 # Apache-2.0
pytz>=2013.6 # MIT
tzdata>=2022.4 # MIT tzdata>=2022.4 # MIT