You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airflow.apache.org by jh...@apache.org on 2021/08/09 22:52:33 UTC
[airflow] 35/39: Fix ``AttributeError``: ``datetime.timezone``
object has no attribute ``name`` (#16599)
This is an automated email from the ASF dual-hosted git repository.
jhtimmins pushed a commit to branch v2-1-test
in repository https://gitbox.apache.org/repos/asf/airflow.git
commit 88fd2db56175c770d2d76cc889d9cadd9022b120
Author: Ruben Laguna <ru...@gmail.com>
AuthorDate: Wed Jun 23 16:31:45 2021 +0200
Fix ``AttributeError``: ``datetime.timezone`` object has no attribute ``name`` (#16599)
closes: #16551
Previous implementation tried to force / coerce the provided timezone (from the dag's `start_date`) into a `pendulum.tz.timezone.*` that only worked if the provided timezone was already a pendulum's timezone and it specifically failed when with `datetime.timezone.utc` as timezone.
(cherry picked from commit 86c20910aed48f7d5b2ebaa91fa40d47c52d7db3)
---
airflow/models/dag.py | 4 +--
tests/models/test_dag.py | 40 +++++++++++++++++++++++++++
tests/serialization/test_dag_serialization.py | 2 ++
3 files changed, 44 insertions(+), 2 deletions(-)
diff --git a/airflow/models/dag.py b/airflow/models/dag.py
index 1861eda..13d69c2 100644
--- a/airflow/models/dag.py
+++ b/airflow/models/dag.py
@@ -485,7 +485,7 @@ class DAG(LoggingMixin):
else:
# absolute (e.g. 3 AM)
naive = cron.get_next(datetime)
- tz = pendulum.timezone(self.timezone.name)
+ tz = self.timezone
following = timezone.make_aware(naive, tz)
return timezone.convert_to_utc(following)
elif self.normalized_schedule_interval is not None:
@@ -513,7 +513,7 @@ class DAG(LoggingMixin):
else:
# absolute (e.g. 3 AM)
naive = cron.get_prev(datetime)
- tz = pendulum.timezone(self.timezone.name)
+ tz = self.timezone
previous = timezone.make_aware(naive, tz)
return timezone.convert_to_utc(previous)
elif self.normalized_schedule_interval is not None:
diff --git a/tests/models/test_dag.py b/tests/models/test_dag.py
index 939baf4..34d761d 100644
--- a/tests/models/test_dag.py
+++ b/tests/models/test_dag.py
@@ -621,6 +621,46 @@ class TestDag(unittest.TestCase):
_next = dag.following_schedule(_next)
assert _next.isoformat() == "2015-01-02T02:00:00+00:00"
+ def test_previous_schedule_datetime_timezone(self):
+ # Check that we don't get an AttributeError 'name' for self.timezone
+
+ start = datetime.datetime(2018, 3, 25, 2, tzinfo=datetime.timezone.utc)
+ dag = DAG('tz_dag', start_date=start, schedule_interval='@hourly')
+ when = dag.previous_schedule(start)
+ assert when.isoformat() == "2018-03-25T01:00:00+00:00"
+
+ def test_following_schedule_datetime_timezone(self):
+ # Check that we don't get an AttributeError 'name' for self.timezone
+
+ start = datetime.datetime(2018, 3, 25, 2, tzinfo=datetime.timezone.utc)
+ dag = DAG('tz_dag', start_date=start, schedule_interval='@hourly')
+ when = dag.following_schedule(start)
+ assert when.isoformat() == "2018-03-25T03:00:00+00:00"
+
+ def test_following_schedule_datetime_timezone_utc0530(self):
+ # Check that we don't get an AttributeError 'name' for self.timezone
+ class UTC0530(datetime.tzinfo):
+ """tzinfo derived concrete class named "+0530" with offset of 19800"""
+
+ # can be configured here
+ _offset = datetime.timedelta(seconds=19800)
+ _dst = datetime.timedelta(0)
+ _name = "+0530"
+
+ def utcoffset(self, dt):
+ return self.__class__._offset
+
+ def dst(self, dt):
+ return self.__class__._dst
+
+ def tzname(self, dt):
+ return self.__class__._name
+
+ start = datetime.datetime(2018, 3, 25, 10, tzinfo=UTC0530())
+ dag = DAG('tz_dag', start_date=start, schedule_interval='@hourly')
+ when = dag.following_schedule(start)
+ assert when.isoformat() == "2018-03-25T05:30:00+00:00"
+
def test_dagtag_repr(self):
clear_db_dags()
dag = DAG('dag-test-dagtag', start_date=DEFAULT_DATE, tags=['tag-1', 'tag-2'])
diff --git a/tests/serialization/test_dag_serialization.py b/tests/serialization/test_dag_serialization.py
index 05edfda..7b0b476 100644
--- a/tests/serialization/test_dag_serialization.py
+++ b/tests/serialization/test_dag_serialization.py
@@ -27,6 +27,7 @@ from datetime import datetime, timedelta, timezone
from glob import glob
from unittest import mock
+import pendulum
import pytest
from dateutil.relativedelta import FR, relativedelta
from kubernetes.client import models as k8s
@@ -444,6 +445,7 @@ class TestStringifiedDAGs(unittest.TestCase):
datetime(2019, 7, 30, tzinfo=timezone.utc),
datetime(2019, 8, 1, tzinfo=timezone.utc),
),
+ (pendulum.datetime(2019, 8, 1, tz='UTC'), None, pendulum.datetime(2019, 8, 1, tz='UTC')),
]
)
def test_deserialization_start_date(self, dag_start_date, task_start_date, expected_task_start_date):