mirror of
https://github.com/ansible/awx.git
synced 2026-01-11 01:57:35 -03:30
Replace pytz with standard library timezone (#16197)
Refactored code to use Python's built-in datetime.timezone and zoneinfo instead of pytz for timezone handling. This modernizes the codebase and removes the dependency on pytz, aligning with current best practices for timezone-aware datetime objects.
This commit is contained in:
parent
dbe979b425
commit
fee71b8917
@ -50,7 +50,7 @@ from rest_framework_yaml.renderers import YAMLRenderer
|
||||
# ansi2html
|
||||
from ansi2html import Ansi2HTMLConverter
|
||||
|
||||
import pytz
|
||||
from datetime import timezone as dt_timezone
|
||||
from wsgiref.util import FileWrapper
|
||||
|
||||
# django-ansible-base
|
||||
@ -648,7 +648,7 @@ class SchedulePreview(GenericAPIView):
|
||||
continue
|
||||
schedule.append(event)
|
||||
|
||||
return Response({'local': schedule, 'utc': [s.astimezone(pytz.utc) for s in schedule]})
|
||||
return Response({'local': schedule, 'utc': [s.astimezone(dt_timezone.utc) for s in schedule]})
|
||||
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
|
||||
|
||||
@ -4,7 +4,6 @@
|
||||
# Python
|
||||
import datetime
|
||||
import logging
|
||||
import pytz
|
||||
import re
|
||||
|
||||
|
||||
@ -43,7 +42,7 @@ def partition_name_dt(part_name):
|
||||
if not m:
|
||||
return m
|
||||
dt_str = f"{m.group(3)}_{m.group(4)}"
|
||||
dt = datetime.datetime.strptime(dt_str, '%Y%m%d_%H').replace(tzinfo=pytz.UTC)
|
||||
dt = datetime.datetime.strptime(dt_str, '%Y%m%d_%H').replace(tzinfo=datetime.timezone.utc)
|
||||
return dt
|
||||
|
||||
|
||||
|
||||
@ -24,8 +24,6 @@ from awx.main.models.jobs import LaunchTimeConfig
|
||||
from awx.main.utils import ignore_inventory_computed_fields
|
||||
from awx.main.consumers import emit_channel_notification
|
||||
|
||||
import pytz
|
||||
|
||||
|
||||
logger = logging.getLogger('awx.main.models.schedule')
|
||||
|
||||
@ -255,7 +253,7 @@ class Schedule(PrimordialModel, LaunchTimeConfig):
|
||||
|
||||
# Coerce the datetime to UTC and format it as a string w/ Zulu format
|
||||
# utc_until = UNTIL=20200601T220000Z
|
||||
utc_until = 'UNTIL=' + localized_until.astimezone(pytz.utc).strftime('%Y%m%dT%H%M%SZ')
|
||||
utc_until = 'UNTIL=' + localized_until.astimezone(datetime.timezone.utc).strftime('%Y%m%dT%H%M%SZ')
|
||||
|
||||
# rule was: DTSTART;TZID=America/New_York:20200601T120000 RRULE:...;UNTIL=20200601T170000
|
||||
# rule is now: DTSTART;TZID=America/New_York:20200601T120000 RRULE:...;UNTIL=20200601T220000Z
|
||||
@ -310,7 +308,7 @@ class Schedule(PrimordialModel, LaunchTimeConfig):
|
||||
# If we made it this far we should have an end date and can ask the ruleset what the last date is
|
||||
# However, if the until/count is before dtstart we will get an IndexError when trying to get [-1]
|
||||
try:
|
||||
return ruleset[-1].astimezone(pytz.utc)
|
||||
return ruleset[-1].astimezone(datetime.timezone.utc)
|
||||
except IndexError:
|
||||
return None
|
||||
|
||||
@ -328,14 +326,14 @@ class Schedule(PrimordialModel, LaunchTimeConfig):
|
||||
if not datetime_exists(next_run_actual):
|
||||
# skip imaginary dates, like 2:30 on DST boundaries
|
||||
next_run_actual = future_rs.after(next_run_actual)
|
||||
next_run_actual = next_run_actual.astimezone(pytz.utc)
|
||||
next_run_actual = next_run_actual.astimezone(datetime.timezone.utc)
|
||||
else:
|
||||
next_run_actual = None
|
||||
|
||||
self.next_run = next_run_actual
|
||||
if not self.dtstart:
|
||||
try:
|
||||
self.dtstart = future_rs[0].astimezone(pytz.utc)
|
||||
self.dtstart = future_rs[0].astimezone(datetime.timezone.utc)
|
||||
except IndexError:
|
||||
self.dtstart = None
|
||||
self.dtend = Schedule.get_end_date(future_rs)
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import datetime, timedelta, timezone
|
||||
from contextlib import contextmanager
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
from django.utils.timezone import now
|
||||
from django.db.utils import IntegrityError
|
||||
from unittest import mock
|
||||
import pytest
|
||||
import pytz
|
||||
|
||||
from awx.main.models import JobTemplate, Schedule, ActivityStream
|
||||
|
||||
@ -76,7 +76,7 @@ class TestComputedFields:
|
||||
with self.assert_no_unwanted_stuff(s):
|
||||
# force update of next_run, as if schedule re-calculation had not happened
|
||||
# since this time
|
||||
old_next_run = datetime(2009, 3, 13, tzinfo=pytz.utc)
|
||||
old_next_run = datetime(2009, 3, 13, tzinfo=timezone.utc)
|
||||
Schedule.objects.filter(pk=s.pk).update(next_run=old_next_run)
|
||||
s.next_run = old_next_run
|
||||
prior_modified = s.modified
|
||||
@ -259,7 +259,7 @@ def test_utc_until_in_the_past(job_template):
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@mock.patch('awx.main.models.schedules.now', lambda: datetime(2030, 3, 5, tzinfo=pytz.utc))
|
||||
@mock.patch('awx.main.models.schedules.now', lambda: datetime(2030, 3, 5, tzinfo=timezone.utc))
|
||||
def test_dst_phantom_hour(job_template):
|
||||
# The DST period in the United States begins at 02:00 (2 am) local time, so
|
||||
# the hour from 2:00:00 to 2:59:59 does not exist in the night of the
|
||||
@ -456,15 +456,15 @@ def test_skip_sundays():
|
||||
RRULE:INTERVAL=1;FREQ=DAILY
|
||||
EXRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=SU
|
||||
'''
|
||||
timezone = pytz.timezone("America/New_York")
|
||||
friday_apr_29th = datetime(2022, 4, 29, 0, 0, 0, 0, timezone)
|
||||
monday_may_2nd = datetime(2022, 5, 2, 23, 59, 59, 999, timezone)
|
||||
tz = ZoneInfo("America/New_York")
|
||||
friday_apr_29th = datetime(2022, 4, 29, 0, 0, 0, 0, tz)
|
||||
monday_may_2nd = datetime(2022, 5, 2, 23, 59, 59, 999, tz)
|
||||
ruleset = Schedule.rrulestr(rrule)
|
||||
gen = ruleset.between(friday_apr_29th, monday_may_2nd, True)
|
||||
# We should only get Fri, Sat and Mon (skipping Sunday)
|
||||
assert len(list(gen)) == 3
|
||||
saturday_night = datetime(2022, 4, 30, 23, 59, 59, 9999, timezone)
|
||||
monday_morning = datetime(2022, 5, 2, 0, 0, 0, 0, timezone)
|
||||
saturday_night = datetime(2022, 4, 30, 23, 59, 59, 9999, tz)
|
||||
monday_morning = datetime(2022, 5, 2, 0, 0, 0, 0, tz)
|
||||
gen = ruleset.between(saturday_night, monday_morning, True)
|
||||
assert len(list(gen)) == 0
|
||||
|
||||
@ -476,17 +476,17 @@ def test_skip_sundays():
|
||||
[
|
||||
pytest.param(
|
||||
'DTSTART;TZID=America/New_York:20210310T150000 RRULE:INTERVAL=1;FREQ=DAILY;UNTIL=20210430T150000Z EXRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=SU;COUNT=5',
|
||||
datetime(2021, 4, 29, 19, 0, 0, tzinfo=pytz.utc),
|
||||
datetime(2021, 4, 29, 19, 0, 0, tzinfo=timezone.utc),
|
||||
id="Single rule in rule set with UTC TZ aware until",
|
||||
),
|
||||
pytest.param(
|
||||
'DTSTART;TZID=America/New_York:20220310T150000 RRULE:INTERVAL=1;FREQ=DAILY;UNTIL=20220430T150000 EXRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=SU;COUNT=5',
|
||||
datetime(2022, 4, 30, 19, 0, tzinfo=pytz.utc),
|
||||
datetime(2022, 4, 30, 19, 0, tzinfo=timezone.utc),
|
||||
id="Single rule in ruleset with naive until",
|
||||
),
|
||||
pytest.param(
|
||||
'DTSTART;TZID=America/New_York:20220310T150000 RRULE:INTERVAL=1;FREQ=DAILY;COUNT=4 EXRULE:FREQ=WEEKLY;INTERVAL=1;BYDAY=SU;COUNT=5',
|
||||
datetime(2022, 3, 12, 20, 0, tzinfo=pytz.utc),
|
||||
datetime(2022, 3, 12, 20, 0, tzinfo=timezone.utc),
|
||||
id="Single rule in ruleset with count",
|
||||
),
|
||||
pytest.param(
|
||||
@ -501,12 +501,12 @@ def test_skip_sundays():
|
||||
),
|
||||
pytest.param(
|
||||
'DTSTART;TZID=America/New_York:20220310T150000 RRULE:INTERVAL=1;FREQ=DAILY;UNTIL=20220430T150000Z',
|
||||
datetime(2022, 4, 29, 19, 0, tzinfo=pytz.utc),
|
||||
datetime(2022, 4, 29, 19, 0, tzinfo=timezone.utc),
|
||||
id="Single rule in rule with UTZ TZ aware until",
|
||||
),
|
||||
pytest.param(
|
||||
'DTSTART;TZID=America/New_York:20220310T150000 RRULE:INTERVAL=1;FREQ=DAILY;UNTIL=20220430T150000',
|
||||
datetime(2022, 4, 30, 19, 0, tzinfo=pytz.utc),
|
||||
datetime(2022, 4, 30, 19, 0, tzinfo=timezone.utc),
|
||||
id="Single rule in rule with naive until",
|
||||
),
|
||||
pytest.param(
|
||||
@ -521,12 +521,12 @@ def test_skip_sundays():
|
||||
),
|
||||
pytest.param(
|
||||
'DTSTART;TZID=America/New_York:20220310T150000 RRULE:INTERVAL=1;FREQ=DAILY;BYDAY=SU;UNTIL=20220430T1500Z RRULE:INTERVAL=1;FREQ=DAILY;BYDAY=MO;COUNT=4',
|
||||
datetime(2022, 4, 24, 19, 0, tzinfo=pytz.utc),
|
||||
datetime(2022, 4, 24, 19, 0, tzinfo=timezone.utc),
|
||||
id="Multi rule one with until and one with an count",
|
||||
),
|
||||
pytest.param(
|
||||
'DTSTART;TZID=America/New_York:20010430T1500 RRULE:INTERVAL=1;FREQ=DAILY;BYDAY=SU;COUNT=1',
|
||||
datetime(2001, 5, 6, 19, 0, tzinfo=pytz.utc),
|
||||
datetime(2001, 5, 6, 19, 0, tzinfo=timezone.utc),
|
||||
id="Rule with count but ends in the past",
|
||||
),
|
||||
pytest.param(
|
||||
|
||||
@ -22,10 +22,6 @@ filterwarnings =
|
||||
once:datetime.datetime.utcfromtimestamp\(\) is deprecated and scheduled for removal in a future version. Use timezone-aware objects to represent datetimes in UTC:DeprecationWarning
|
||||
|
||||
# NOTE: the following are present using python 3.11
|
||||
# FIXME: Set `USE_TZ` to `True`.
|
||||
# Note: RemovedInDjango50Warning may not exist in newer Django versions
|
||||
ignore:The default value of USE_TZ will change from False to True in Django 5.0. Set USE_TZ to False in your project settings if you want to keep the current default behavior.
|
||||
|
||||
# FIXME: Delete this entry once `pyparsing` is updated.
|
||||
once:module 'sre_constants' is deprecated:DeprecationWarning:_pytest.assertion.rewrite
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user