Replace pytz by built-in library

Python >= 3.9 provides the zoneinfo module to manipulate timezones.
Replace pytz by the built-in library to reduce external dependency.

Change-Id: I22707f966b692c056cedecaa83bf2cb0a29c09aa
This commit is contained in:
Takashi Kajinami 2024-06-10 18:11:32 +09:00
parent 116bd8ccdf
commit 85316931bd
8 changed files with 23 additions and 23 deletions

View File

@ -23,8 +23,6 @@ import datetime
import json import json
import logging import logging
import pytz
from django.conf import settings from django.conf import settings
from django.contrib.auth import REDIRECT_FIELD_NAME from django.contrib.auth import REDIRECT_FIELD_NAME
from django.contrib.auth.views import redirect_to_login from django.contrib.auth.views import redirect_to_login
@ -74,7 +72,7 @@ class HorizonMiddleware(object):
if settings.SESSION_REFRESH: if settings.SESSION_REFRESH:
timeout = settings.SESSION_TIMEOUT timeout = settings.SESSION_TIMEOUT
token_life = request.user.token.expires - datetime.datetime.now( token_life = request.user.token.expires - datetime.datetime.now(
pytz.utc) datetime.timezone.utc)
session_time = min(timeout, int(token_life.total_seconds())) session_time = min(timeout, int(token_life.total_seconds()))
request.session.set_expiry(session_time) request.session.set_expiry(session_time)

View File

@ -16,8 +16,6 @@
import datetime import datetime
from unittest import mock from unittest import mock
import pytz
from django.conf import settings from django.conf import settings
from django.http import HttpResponseRedirect from django.http import HttpResponseRedirect
from django import test as django_test from django import test as django_test
@ -95,7 +93,7 @@ class MiddlewareTests(django_test.TestCase):
request = self.factory.get(url) request = self.factory.get(url)
now = datetime.datetime.now(pytz.utc) now = datetime.datetime.now(datetime.timezone.utc)
token_expiry = now + datetime.timedelta(seconds=1800) token_expiry = now + datetime.timedelta(seconds=1800)
request.user.token = mock.Mock(expires=token_expiry) request.user.token = mock.Mock(expires=token_expiry)
session_expiry_before = now + datetime.timedelta(seconds=300) session_expiry_before = now + datetime.timedelta(seconds=300)
@ -117,7 +115,7 @@ class MiddlewareTests(django_test.TestCase):
request = self.factory.get(url) request = self.factory.get(url)
now = datetime.datetime.now(pytz.utc) now = datetime.datetime.now(datetime.timezone.utc)
token_expiry = now + datetime.timedelta(seconds=10) token_expiry = now + datetime.timedelta(seconds=10)
request.user.token = mock.Mock(expires=token_expiry) request.user.token = mock.Mock(expires=token_expiry)
@ -139,7 +137,7 @@ class MiddlewareTests(django_test.TestCase):
request = self.factory.get(url) request = self.factory.get(url)
now = datetime.datetime.now(pytz.utc) now = datetime.datetime.now(datetime.timezone.utc)
token_expiry = now + datetime.timedelta(seconds=1800) token_expiry = now + datetime.timedelta(seconds=1800)
request.user.token = mock.Mock(expires=token_expiry) request.user.token = mock.Mock(expires=token_expiry)
session_expiry_before = now + datetime.timedelta(seconds=300) session_expiry_before = now + datetime.timedelta(seconds=300)

View File

@ -16,8 +16,6 @@
import datetime import datetime
import logging import logging
import pytz
from django.conf import settings from django.conf import settings
from django.utils.module_loading import import_string from django.utils.module_loading import import_string
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
@ -210,7 +208,8 @@ class KeystoneBackend(object):
request.user = user request.user = user
timeout = settings.SESSION_TIMEOUT timeout = settings.SESSION_TIMEOUT
token_life = user.token.expires - datetime.datetime.now(pytz.utc) token_life = (user.token.expires -
datetime.datetime.now(datetime.timezone.utc))
session_time = min(timeout, int(token_life.total_seconds())) session_time = min(timeout, int(token_life.total_seconds()))
request.session.set_expiry(session_time) request.session.set_expiry(session_time)

View File

@ -14,12 +14,12 @@
# limitations under the License. # limitations under the License.
from datetime import datetime from datetime import datetime
import zoneinfo
from django.conf import settings from django.conf import settings
from django.http import JsonResponse from django.http import JsonResponse
import django.template as django_template import django.template as django_template
from django.views import generic from django.views import generic
import pytz
from openstack_dashboard import api from openstack_dashboard import api
from openstack_dashboard.api.rest import urls from openstack_dashboard.api.rest import urls
@ -92,6 +92,6 @@ class Timezones(generic.View):
@rest_utils.ajax() @rest_utils.ajax()
def get(self, request): def get(self, request):
zones = {tz: datetime.now(pytz.timezone(tz)).strftime('%z') zones = {tz: datetime.now(zoneinfo.ZoneInfo(tz)).strftime('%z')
for tz in pytz.common_timezones} for tz in zoneinfo.available_timezones()}
return JsonResponse({'timezone_dict': zones}) return JsonResponse({'timezone_dict': zones})

View File

@ -14,6 +14,7 @@
from datetime import datetime from datetime import datetime
import string import string
import zoneinfo
import babel import babel
import babel.dates import babel.dates
@ -22,7 +23,6 @@ from django import shortcuts
from django.utils import encoding from django.utils import encoding
from django.utils import translation from django.utils import translation
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
import pytz
from horizon import forms from horizon import forms
from horizon import messages from horizon import messages
@ -42,10 +42,9 @@ class UserSettingsForm(forms.SelfHandlingForm):
@staticmethod @staticmethod
def _sorted_zones(): def _sorted_zones():
today = datetime.today() zones = [(tz, datetime.now(zoneinfo.ZoneInfo(tz)).strftime('%z'))
d = datetime(today.year, today.month, today.day) for tz in zoneinfo.available_timezones()
zones = [(tz, pytz.timezone(tz).localize(d).strftime('%z')) if tz not in ('localtime', 'Factory')]
for tz in pytz.common_timezones]
zones.sort(key=lambda zone: int(zone[1])) zones.sort(key=lambda zone: int(zone[1]))
return zones return zones
@ -109,7 +108,7 @@ class UserSettingsForm(forms.SelfHandlingForm):
response = functions.save_config_value( response = functions.save_config_value(
request, response, 'django_timezone', request, response, 'django_timezone',
pytz.timezone(data['timezone']).zone) zoneinfo.ZoneInfo(data['timezone']).key)
response = functions.save_config_value( response = functions.save_config_value(
request, response, 'API_RESULT_PAGE_SIZE', data['pagesize']) request, response, 'API_RESULT_PAGE_SIZE', data['pagesize'])

View File

@ -0,0 +1,5 @@
---
upgrade:
- |
Python 3.8 support has been removed. Now the minimum supported python
version is 3.9.

View File

@ -29,10 +29,10 @@ python-keystoneclient>=3.22.0 # Apache-2.0
python-neutronclient>=8.1.0 # Apache-2.0 python-neutronclient>=8.1.0 # Apache-2.0
python-novaclient>=9.1.0 # Apache-2.0 python-novaclient>=9.1.0 # Apache-2.0
python-swiftclient>=3.2.0 # Apache-2.0 python-swiftclient>=3.2.0 # Apache-2.0
pytz>=2013.6 # MIT
PyYAML>=6.0 # MIT PyYAML>=6.0 # MIT
requests>=2.25.1 # Apache-2.0 requests>=2.25.1 # Apache-2.0
semantic-version>=2.3.1 # BSD semantic-version>=2.3.1 # BSD
tzdata>=2022.4
XStatic>=1.0.3 # MIT License XStatic>=1.0.3 # MIT License
XStatic-Angular>=1.8.2.2 # MIT License XStatic-Angular>=1.8.2.2 # MIT License
XStatic-Angular-Bootstrap>=2.2.0.0 # MIT License XStatic-Angular-Bootstrap>=2.2.0.0 # MIT License

View File

@ -6,7 +6,7 @@ description_file =
author = OpenStack author = OpenStack
author_email = openstack-discuss@lists.openstack.org author_email = openstack-discuss@lists.openstack.org
home_page = https://docs.openstack.org/horizon/latest/ home_page = https://docs.openstack.org/horizon/latest/
python_requires = >=3.8 python_requires = >=3.9
classifier = classifier =
Development Status :: 5 - Production/Stable Development Status :: 5 - Production/Stable
Environment :: OpenStack Environment :: OpenStack
@ -20,8 +20,9 @@ classifier =
Programming Language :: Python Programming Language :: Python
Programming Language :: Python :: 3 :: Only Programming Language :: Python :: 3 :: Only
Programming Language :: Python :: 3 Programming Language :: Python :: 3
Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.11
Topic :: Internet :: WWW/HTTP Topic :: Internet :: WWW/HTTP
[global] [global]