You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airflow.apache.org by as...@apache.org on 2022/09/09 08:41:30 UTC
[airflow] branch main updated: Fix 'from airflow import version' lazy import (#26239)
This is an automated email from the ASF dual-hosted git repository.
ash pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/main by this push:
new b7a603cf89 Fix 'from airflow import version' lazy import (#26239)
b7a603cf89 is described below
commit b7a603cf89728e02a187409c83983d58cc554457
Author: Tzu-ping Chung <ur...@gmail.com>
AuthorDate: Fri Sep 9 16:41:03 2022 +0800
Fix 'from airflow import version' lazy import (#26239)
This incorrectly accesses the version *attribute* in airflow.version
instead of the airflow.version module itself, breaking compatibility.
I actually rewrote the entire __getattr__ hook; much of the logic seems
to be quite redundant.
---
airflow/__init__.py | 44 ++++++++++++++++++++------------------------
1 file changed, 20 insertions(+), 24 deletions(-)
diff --git a/airflow/__init__.py b/airflow/__init__.py
index 24fea0d574..c7e020dc5a 100644
--- a/airflow/__init__.py
+++ b/airflow/__init__.py
@@ -26,12 +26,13 @@ in their PYTHONPATH. airflow_login should be based off the
isort:skip_file
"""
-
# flake8: noqa: F401
+from __future__ import annotations
+
import os
import sys
-from typing import Callable, Optional
+from typing import Callable
from airflow import settings
@@ -47,7 +48,7 @@ __path__ = __import__("pkgutil").extend_path(__path__, __name__) # type: ignore
if not os.environ.get("_AIRFLOW__AS_LIBRARY", None):
settings.initialize()
-login: Optional[Callable] = None
+login: Callable | None = None
PY36 = sys.version_info >= (3, 6)
PY37 = sys.version_info >= (3, 7)
@@ -55,36 +56,31 @@ PY38 = sys.version_info >= (3, 8)
PY39 = sys.version_info >= (3, 9)
PY310 = sys.version_info >= (3, 10)
-# Things to lazy import in form 'name': 'path.to.module'
-__lazy_imports = {
- 'DAG': 'airflow.models.dag',
- 'Dataset': 'airflow.datasets',
- 'XComArg': 'airflow.models.xcom_arg',
- 'AirflowException': 'airflow.exceptions',
- 'version': 'airflow.version',
+# Things to lazy import in form {local_name: ('target_module', 'target_name')}
+__lazy_imports: dict[str, tuple[str, str]] = {
+ 'DAG': ('.models.dag', 'DAG'),
+ 'Dataset': ('.datasets', 'Dataset'),
+ 'XComArg': ('.models.xcom_arg', 'XComArg'),
+ 'AirflowException': ('.exceptions', 'AirflowException'),
+ 'version': ('.version', ''),
+ '__version__': ('.version', 'version'),
}
def __getattr__(name: str):
# PEP-562: Lazy loaded attributes on python modules
- module_attr = name.rsplit('.', 1)[-1]
- path: Optional[str]
- if name == '__version__':
- module_attr = 'version'
- path = 'airflow.version'
- else:
- path = __lazy_imports.get(name)
- if not path:
+ module_path, attr_name = __lazy_imports.get(name, ('', ''))
+ if not module_path:
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
- import operator
+ import importlib
- # Strip off the "airflow." prefix because of how `__import__` works (it always returns the top level
- # module)
- without_prefix = path.split('.', 1)[-1]
+ mod = importlib.import_module(module_path, __name__)
+ if attr_name:
+ val = getattr(mod, attr_name)
+ else:
+ val = mod
- getter = operator.attrgetter(f'{without_prefix}.{module_attr}')
- val = getter(__import__(path))
# Store for next time
globals()[name] = val
return val