diff --git a/heat/engine/constraint/common_constraints.py b/heat/engine/constraint/common_constraints.py index cef2571414..0e91995183 100644 --- a/heat/engine/constraint/common_constraints.py +++ b/heat/engine/constraint/common_constraints.py @@ -14,7 +14,13 @@ import croniter import eventlet import netaddr -import pytz + +try: + import zoneinfo +except ImportError: + # zoneinfo is available in Python >= 3.9 + import pytz + zoneinfo = None from neutron_lib.api import validators from oslo_utils import timeutils @@ -167,7 +173,10 @@ class TimezoneConstraint(constraints.BaseCustomConstraint): if not value: return True try: - pytz.timezone(value) + if zoneinfo: + zoneinfo.ZoneInfo(value) + else: + pytz.timezone(value) return True except Exception as ex: self._error_message = _( diff --git a/heat/tests/clients/test_swift_client.py b/heat/tests/clients/test_swift_client.py index ae04ae42c9..8ad43f7ad1 100644 --- a/heat/tests/clients/test_swift_client.py +++ b/heat/tests/clients/test_swift_client.py @@ -14,7 +14,13 @@ import datetime from unittest import mock -import pytz +try: + import zoneinfo +except ImportError: + # zoneinfo is available in Python >= 3.9 + import pytz + zoneinfo = None + from testtools import matchers from heat.engine.clients.os import swift @@ -126,8 +132,12 @@ class SwiftUtilsTest(SwiftClientPluginTestCase): def test_parse_last_modified(self): self.assertIsNone(self.swift_plugin.parse_last_modified(None)) + if zoneinfo: + tz = zoneinfo.ZoneInfo('GMT') + else: + tz = pytz.timezone('GMT') now = datetime.datetime( - 2015, 2, 5, 1, 4, 40, 0, pytz.timezone('GMT')) + 2015, 2, 5, 1, 4, 40, 0, tz) now_naive = datetime.datetime( 2015, 2, 5, 1, 4, 40, 0) last_modified = now.strftime('%a, %d %b %Y %H:%M:%S %Z') diff --git a/heat/tests/constraints/test_common_constraints.py b/heat/tests/constraints/test_common_constraints.py index c466b06054..03399bf691 100644 --- a/heat/tests/constraints/test_common_constraints.py +++ b/heat/tests/constraints/test_common_constraints.py @@ -13,6 +13,12 @@ from unittest import mock +try: + import zoneinfo +except ImportError: + # zoneinfo is available in Python >= 3.9 + zoneinfo = None + from heat.engine.constraint import common_constraints as cc from heat.tests import common from heat.tests import utils @@ -279,7 +285,10 @@ class TimezoneConstraintTest(common.HeatTestCase): def test_validation_error(self): timezone = "wrong_timezone" - expected = "Invalid timezone: '%s'" % timezone + err = timezone + if zoneinfo: + err = "No time zone found with key %s" % timezone + expected = "Invalid timezone: '%s'" % err self.assertFalse(self.constraint.validate(timezone, self.ctx)) self.assertEqual( diff --git a/heat/tests/openstack/aodh/test_alarm.py b/heat/tests/openstack/aodh/test_alarm.py index 48b756fddb..609cc9dc26 100644 --- a/heat/tests/openstack/aodh/test_alarm.py +++ b/heat/tests/openstack/aodh/test_alarm.py @@ -16,6 +16,12 @@ import copy import json from unittest import mock +try: + import zoneinfo +except ImportError: + # zoneinfo is available in Python >= 3.9 + zoneinfo = None + from heat.common import exception from heat.common import template_format from heat.engine.clients.os import aodh @@ -579,11 +585,14 @@ class AodhAlarmTest(common.HeatTestCase): exception.ResourceFailure, scheduler.TaskRunner(rsrc.update, snippet) ) + err = timezone + if zoneinfo: + err = "No time zone found with key %s" % timezone self.assertEqual( "StackValidationFailed: resources.MEMAlarmHigh: Property error: " "Properties.time_constraints[0].timezone: Error " "validating value '%s': Invalid timezone: '%s'" - % (timezone, timezone), + % (timezone, err), error.message) def test_alarm_live_state(self): diff --git a/requirements.txt b/requirements.txt index 04ebf4e9e9..f25280dcc9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -51,10 +51,11 @@ python-troveclient>=2.2.0 # Apache-2.0 python-vitrageclient>=2.7.0 # Apache-2.0 python-zaqarclient>=1.3.0 # Apache-2.0 python-zunclient>=3.4.0 # Apache-2.0 -pytz>=2013.6 # MIT +pytz>=2013.6;python_version<"3.9" # MIT PyYAML>=5.1 # MIT requests>=2.23.0 # Apache-2.0 tenacity>=6.1.0 # Apache-2.0 +tzdata>=2022.4;python_version>="3.9" # MIT Routes>=2.3.1 # MIT SQLAlchemy>=1.4.0 # MIT stevedore>=3.1.0 # Apache-2.0