This is an automated email from the ASF dual-hosted git repository. ephraimanierobi pushed a commit to branch v2-5-test in repository https://gitbox.apache.org/repos/asf/airflow.git
commit 5bf2a4a829e9505120a964087f4224cc66fef206 Author: Jarek Potiuk <[email protected]> AuthorDate: Tue Feb 14 00:51:20 2023 +0100 Fix circular imports when airflow starts (#29494) * Fix circular imports when airflow starts from scratch When airflow CLI is started without generated config file the CLI fails with circular imports. Some of the util classes imported during such start were importing "constants" (in fact variables) from the setttings and this happened before settings were fully initialized. This PR moves all relevant top-level imports to be local imports and moves initialization of the State class with settings-defined colors to initialization() method in order to avoid those circular imports. * Update airflow/models/xcom.py Co-authored-by: Tzu-ping Chung <[email protected]> --------- Co-authored-by: Tzu-ping Chung <[email protected]> (cherry picked from commit 47b67f13da667de4eb69233404d4d5a33574dd58) --- airflow/models/xcom.py | 5 ++++- airflow/settings.py | 5 ++++- airflow/utils/state.py | 3 --- airflow/utils/timezone.py | 12 ++++++++++-- tests/cli/commands/test_db_command.py | 4 ++-- tests/models/test_taskinstance.py | 5 +++-- 6 files changed, 23 insertions(+), 11 deletions(-) diff --git a/airflow/models/xcom.py b/airflow/models/xcom.py index 6294fa3d7f..831f05e6c9 100644 --- a/airflow/models/xcom.py +++ b/airflow/models/xcom.py @@ -769,7 +769,10 @@ class LazyXComAccess(collections.abc.Sequence): yield self._query return - session = settings.Session() + Session = getattr(settings, "Session", None) + if Session is None: + raise RuntimeError("Session must be set before!") + session = Session() try: yield self._query.with_session(session) finally: diff --git a/airflow/settings.py b/airflow/settings.py index 537c49141a..dcf0513d56 100644 --- a/airflow/settings.py +++ b/airflow/settings.py @@ -39,6 +39,7 @@ from airflow.exceptions import RemovedInAirflow3Warning from airflow.executors import executor_constants from airflow.logging_config import configure_logging from airflow.utils.orm_event_handlers import setup_event_handlers +from airflow.utils.state import State if TYPE_CHECKING: from airflow.www.utils import UIAlert @@ -408,7 +409,7 @@ def dispose_orm(): global engine global Session - if Session: + if Session is not None: # type: ignore[truthy-function] Session.remove() Session = None if engine: @@ -567,6 +568,8 @@ def initialize(): import_local_settings() global LOGGING_CLASS_PATH LOGGING_CLASS_PATH = configure_logging() + State.state_color.update(STATE_COLORS) + configure_adapters() # The webservers import this file from models.py with the default settings. configure_orm() diff --git a/airflow/utils/state.py b/airflow/utils/state.py index 6558af9f2a..6f89174bd6 100644 --- a/airflow/utils/state.py +++ b/airflow/utils/state.py @@ -19,8 +19,6 @@ from __future__ import annotations from enum import Enum -from airflow.settings import STATE_COLORS - class TaskInstanceState(str, Enum): """ @@ -122,7 +120,6 @@ class State: TaskInstanceState.SCHEDULED: "tan", TaskInstanceState.DEFERRED: "mediumpurple", } - state_color.update(STATE_COLORS) # type: ignore @classmethod def color(cls, state): diff --git a/airflow/utils/timezone.py b/airflow/utils/timezone.py index 062e7ad955..bbe38aba2e 100644 --- a/airflow/utils/timezone.py +++ b/airflow/utils/timezone.py @@ -24,8 +24,6 @@ import pendulum from dateutil.relativedelta import relativedelta from pendulum.datetime import DateTime -from airflow.settings import TIMEZONE - # UTC time zone as a tzinfo instance. utc = pendulum.tz.timezone("UTC") @@ -104,6 +102,8 @@ def convert_to_utc(value: dt.datetime | None) -> DateTime | None: return value if not is_localized(value): + from airflow.settings import TIMEZONE + value = pendulum.instance(value, TIMEZONE) return pendulum.instance(value.astimezone(utc)) @@ -133,6 +133,8 @@ def make_aware(value: dt.datetime | None, timezone: dt.tzinfo | None = None) -> :return: localized datetime in settings.TIMEZONE or timezone """ if timezone is None: + from airflow.settings import TIMEZONE + timezone = TIMEZONE if not value: @@ -168,6 +170,8 @@ def make_naive(value, timezone=None): :return: naive datetime """ if timezone is None: + from airflow.settings import TIMEZONE + timezone = TIMEZONE # Emulate the behavior of astimezone() on Python < 3.6. @@ -191,6 +195,8 @@ def datetime(*args, **kwargs): :return: datetime.datetime """ if "tzinfo" not in kwargs: + from airflow.settings import TIMEZONE + kwargs["tzinfo"] = TIMEZONE return dt.datetime(*args, **kwargs) @@ -203,6 +209,8 @@ def parse(string: str, timezone=None) -> DateTime: :param string: time string :param timezone: the timezone """ + from airflow.settings import TIMEZONE + return pendulum.parse(string, tz=timezone or TIMEZONE, strict=False) # type: ignore diff --git a/tests/cli/commands/test_db_command.py b/tests/cli/commands/test_db_command.py index 53c62e84cf..17d7f49da4 100644 --- a/tests/cli/commands/test_db_command.py +++ b/tests/cli/commands/test_db_command.py @@ -285,7 +285,7 @@ class TestCLIDBClean: coerced to tz-aware with default timezone """ timestamp = "2021-01-01 00:00:00" - with patch("airflow.utils.timezone.TIMEZONE", pendulum.timezone(timezone)): + with patch("airflow.settings.TIMEZONE", pendulum.timezone(timezone)): args = self.parser.parse_args(["db", "clean", "--clean-before-timestamp", f"{timestamp}", "-y"]) db_command.cleanup_tables(args) run_cleanup_mock.assert_called_once_with( @@ -304,7 +304,7 @@ class TestCLIDBClean: When tz included in the string then default timezone should not be used. """ timestamp = "2021-01-01 00:00:00+03:00" - with patch("airflow.utils.timezone.TIMEZONE", pendulum.timezone(timezone)): + with patch("airflow.settings.TIMEZONE", pendulum.timezone(timezone)): args = self.parser.parse_args(["db", "clean", "--clean-before-timestamp", f"{timestamp}", "-y"]) db_command.cleanup_tables(args) diff --git a/tests/models/test_taskinstance.py b/tests/models/test_taskinstance.py index bb2b676a59..9b126c68c9 100644 --- a/tests/models/test_taskinstance.py +++ b/tests/models/test_taskinstance.py @@ -70,6 +70,7 @@ from airflow.operators.python import PythonOperator from airflow.sensors.base import BaseSensorOperator from airflow.sensors.python import PythonSensor from airflow.serialization.serialized_objects import SerializedBaseOperator +from airflow.settings import TIMEZONE from airflow.stats import Stats from airflow.ti_deps.dep_context import DepContext from airflow.ti_deps.dependencies_deps import REQUEUEABLE_DEPS, RUNNING_DEPS @@ -2307,13 +2308,13 @@ class TestTaskInstance: ) context = ti.get_template_context() with pytest.deprecated_call(): - assert context["execution_date"] == pendulum.DateTime(2021, 9, 6, tzinfo=timezone.TIMEZONE) + assert context["execution_date"] == pendulum.DateTime(2021, 9, 6, tzinfo=TIMEZONE) with pytest.deprecated_call(): assert context["next_ds"] == "2021-09-07" with pytest.deprecated_call(): assert context["next_ds_nodash"] == "20210907" with pytest.deprecated_call(): - assert context["next_execution_date"] == pendulum.DateTime(2021, 9, 7, tzinfo=timezone.TIMEZONE) + assert context["next_execution_date"] == pendulum.DateTime(2021, 9, 7, tzinfo=TIMEZONE) with pytest.deprecated_call(): assert context["prev_ds"] is None, "Does not make sense for custom timetable" with pytest.deprecated_call():
