Skip to content

Commit 564adcf

Browse files
authored
Deprecate PY* constants into the airflow module (#37575)
1 parent 581e2e4 commit 564adcf

File tree

9 files changed

+85
-26
lines changed

9 files changed

+85
-26
lines changed

airflow/__init__.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
# configuration is therefore initted early here, simply by importing it.
4040
from airflow import configuration, settings
4141

42-
__all__ = ["__version__", "DAG", "PY36", "PY37", "PY38", "PY39", "PY310", "PY311", "XComArg"]
42+
__all__ = ["__version__", "DAG", "Dataset", "XComArg"]
4343

4444
# Make `airflow` a namespace package, supporting installing
4545
# airflow.providers.* in different locations (i.e. one in site, and one in user
@@ -55,13 +55,6 @@
5555
if not os.environ.get("_AIRFLOW__AS_LIBRARY", None):
5656
settings.initialize()
5757

58-
PY36 = sys.version_info >= (3, 6)
59-
PY37 = sys.version_info >= (3, 7)
60-
PY38 = sys.version_info >= (3, 8)
61-
PY39 = sys.version_info >= (3, 9)
62-
PY310 = sys.version_info >= (3, 10)
63-
PY311 = sys.version_info >= (3, 11)
64-
6558
# Things to lazy import in form {local_name: ('target_module', 'target_name', 'deprecated')}
6659
__lazy_imports: dict[str, tuple[str, str, bool]] = {
6760
"DAG": (".models.dag", "DAG", False),
@@ -77,6 +70,16 @@ def __getattr__(name: str):
7770
# PEP-562: Lazy loaded attributes on python modules
7871
module_path, attr_name, deprecated = __lazy_imports.get(name, ("", "", False))
7972
if not module_path:
73+
if name.startswith("PY3") and (py_minor := name[3:]) in ("6", "7", "8", "9", "10", "11", "12"):
74+
import warnings
75+
76+
warnings.warn(
77+
f"Python version constraint {name!r} is deprecated and will be removed in the future. "
78+
f"Please get version info from the 'sys.version_info'.",
79+
DeprecationWarning,
80+
)
81+
return sys.version_info >= (3, int(py_minor))
82+
8083
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
8184
elif deprecated:
8285
import warnings

airflow/utils/hashlib_wrapper.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,12 @@
1818
from __future__ import annotations
1919

2020
import hashlib
21+
import sys
2122
from typing import TYPE_CHECKING
2223

2324
if TYPE_CHECKING:
2425
from _typeshed import ReadableBuffer
2526

26-
from airflow import PY39
27-
2827

2928
def md5(__string: ReadableBuffer = b"") -> hashlib._Hash:
3029
"""
@@ -33,6 +32,6 @@ def md5(__string: ReadableBuffer = b"") -> hashlib._Hash:
3332
:param __string: The data to hash. Default to empty str byte.
3433
:return: The hashed value.
3534
"""
36-
if PY39:
35+
if sys.version_info >= (3, 9):
3736
return hashlib.md5(__string, usedforsecurity=False) # type: ignore
3837
return hashlib.md5(__string)

pyproject.toml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1462,8 +1462,17 @@ combine-as-imports = true
14621462
banned-module-level-imports = ["numpy", "pandas"]
14631463

14641464
[tool.ruff.lint.flake8-tidy-imports.banned-api]
1465+
# Direct import from the airflow package modules and constraints
14651466
"airflow.AirflowException".msg = "Use airflow.exceptions.AirflowException instead."
14661467
"airflow.Dataset".msg = "Use airflow.datasets.Dataset instead."
1468+
"airflow.PY36".msg = "Use sys.version_info >= (3, 6) instead."
1469+
"airflow.PY37".msg = "Use sys.version_info >= (3, 7) instead."
1470+
"airflow.PY38".msg = "Use sys.version_info >= (3, 8) instead."
1471+
"airflow.PY39".msg = "Use sys.version_info >= (3, 9) instead."
1472+
"airflow.PY310".msg = "Use sys.version_info >= (3, 10) instead."
1473+
"airflow.PY311".msg = "Use sys.version_info >= (3, 11) instead."
1474+
"airflow.PY312".msg = "Use sys.version_info >= (3, 12) instead."
1475+
# Deprecated imports
14671476
"airflow.models.baseoperator.BaseOperatorLink".msg = "Use airflow.models.baseoperatorlink.BaseOperatorLink"
14681477
# Deprecated in Python 3.11, Pending Removal in Python 3.15: https://github.com/python/cpython/issues/90817
14691478
# Deprecation warning in Python 3.11 also recommends using locale.getencoding but it available in Python 3.11

tests/core/test_airflow_module.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
from __future__ import annotations
18+
19+
import sys
20+
21+
import pytest
22+
23+
import airflow
24+
from airflow.exceptions import AirflowException
25+
26+
TEST_CASES = {
27+
"PY36": sys.version_info >= (3, 6),
28+
"PY37": sys.version_info >= (3, 7),
29+
"PY38": sys.version_info >= (3, 8),
30+
"PY39": sys.version_info >= (3, 9),
31+
"PY310": sys.version_info >= (3, 10),
32+
"PY311": sys.version_info >= (3, 11),
33+
"PY312": sys.version_info >= (3, 12),
34+
}
35+
36+
37+
@pytest.mark.parametrize("py_attr, expected", TEST_CASES.items())
38+
def test_lazy_load_py_versions(py_attr, expected):
39+
with pytest.warns(DeprecationWarning, match=f"Python version constraint '{py_attr}' is deprecated"):
40+
# If there is no warning, then most possible it imported somewhere else.
41+
assert getattr(airflow, py_attr) is expected
42+
43+
44+
@pytest.mark.parametrize("py_attr", ["PY35", "PY313"])
45+
def test_wrong_py_version(py_attr):
46+
with pytest.raises(AttributeError, match=f"'airflow' has no attribute '{py_attr}'"):
47+
getattr(airflow, py_attr)
48+
49+
50+
def test_deprecated_exception():
51+
warning_pattern = "Import 'AirflowException' directly from the airflow module is deprecated"
52+
with pytest.warns(DeprecationWarning, match=warning_pattern):
53+
# If there is no warning, then most possible it imported somewhere else.
54+
assert getattr(airflow, "AirflowException") is AirflowException

tests/dag_processing/test_processor.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,14 @@
1919

2020
import datetime
2121
import os
22+
import sys
2223
from unittest import mock
2324
from unittest.mock import MagicMock, patch
2425
from zipfile import ZipFile
2526

2627
import pytest
2728

28-
from airflow import PY311, settings
29+
from airflow import settings
2930
from airflow.callbacks.callback_requests import TaskCallbackRequest
3031
from airflow.configuration import TEST_DAGS_FOLDER, conf
3132
from airflow.dag_processing.manager import DagFileProcessorAgent
@@ -53,6 +54,7 @@
5354
pytestmark = pytest.mark.db_test
5455

5556
DEFAULT_DATE = timezone.datetime(2016, 1, 1)
57+
PY311 = sys.version_info >= (3, 11)
5658

5759
# Include the words "airflow" and "dag" in the file contents,
5860
# tricking airflow into thinking these

tests/decorators/test_python.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222

2323
import pytest
2424

25-
from airflow import PY38, PY311
2625
from airflow.decorators import setup, task as task_decorator, teardown
2726
from airflow.decorators.base import DecoratedMappedOperator
2827
from airflow.exceptions import AirflowException, XComNotFound
@@ -49,6 +48,8 @@
4948
from airflow.models.dagrun import DagRun
5049

5150
DEFAULT_DATE = timezone.datetime(2016, 1, 1)
51+
PY38 = sys.version_info >= (3, 8)
52+
PY311 = sys.version_info >= (3, 11)
5253

5354

5455
class TestAirflowTaskDecorator(BasePythonTest):

tests/operators/test_python.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@
3737
import pytest
3838
from slugify import slugify
3939

40-
from airflow import PY311
4140
from airflow.decorators import task_group
4241
from airflow.exceptions import AirflowException, DeserializingResultError, RemovedInAirflow3Warning
4342
from airflow.models.baseoperator import BaseOperator
@@ -75,6 +74,7 @@
7574
TEMPLATE_SEARCHPATH = os.path.join(AIRFLOW_MAIN_FOLDER, "tests", "config_templates")
7675
LOGGER_NAME = "airflow.task.operators"
7776
DEFAULT_PYTHON_VERSION = f"{sys.version_info[0]}.{sys.version_info[1]}"
77+
PY311 = sys.version_info >= (3, 11)
7878

7979

8080
class BasePythonTest:

tests/providers/apache/hive/hooks/test_hive.py

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,22 +17,13 @@
1717
# under the License.
1818
from __future__ import annotations
1919

20-
import pytest
21-
22-
from airflow import PY311
23-
24-
if PY311:
25-
pytest.skip(
26-
"The tests are skipped because Apache Hive provider is not supported on Python 3.11",
27-
allow_module_level=True,
28-
)
29-
3020
import datetime
3121
import itertools
3222
from collections import namedtuple
3323
from unittest import mock
3424

3525
import pandas as pd
26+
import pytest
3627
from hmsclient import HMSClient
3728

3829
from airflow.exceptions import AirflowException

tests/serialization/serializers/test_serializers.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import datetime
2020
import decimal
21+
import sys
2122
from importlib import metadata
2223
from unittest.mock import patch
2324

@@ -31,11 +32,10 @@
3132
from pendulum import DateTime
3233
from pendulum.tz.timezone import FixedTimezone, Timezone
3334

34-
from airflow import PY39
3535
from airflow.models.param import Param, ParamsDict
3636
from airflow.serialization.serde import DATA, deserialize, serialize
3737

38-
if PY39:
38+
if sys.version_info >= (3, 9):
3939
from zoneinfo import ZoneInfo
4040
else:
4141
from backports.zoneinfo import ZoneInfo

0 commit comments

Comments
 (0)