From afc67ac6e452025ce599e473e548e9e9e841ffde Mon Sep 17 00:00:00 2001 From: Andrey Anshin Date: Thu, 11 Jan 2024 03:46:39 +0400 Subject: [PATCH 1/2] Fix check on subclass for `typing.Union` in `_infer_multiple_outputs` for Python 3.10+ --- airflow/decorators/base.py | 2 +- tests/decorators/test_python.py | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/airflow/decorators/base.py b/airflow/decorators/base.py index 119672dd427aa..2518fe1b53a3a 100644 --- a/airflow/decorators/base.py +++ b/airflow/decorators/base.py @@ -350,7 +350,7 @@ def fake(): except TypeError: # Can't evaluate return type. return False ttype = getattr(return_type, "__origin__", return_type) - return issubclass(ttype, Mapping) + return isinstance(ttype, type) and issubclass(ttype, Mapping) def __attrs_post_init__(self): if "self" in self.function_signature.parameters: diff --git a/tests/decorators/test_python.py b/tests/decorators/test_python.py index 98aab562b8ce1..10da056dd5f9e 100644 --- a/tests/decorators/test_python.py +++ b/tests/decorators/test_python.py @@ -97,7 +97,6 @@ def identity_dict_with_decorator_call(x: int, y: int) -> resolve(annotation): assert identity_dict_with_decorator_call(5, 5).operator.multiple_outputs is True - @pytest.mark.skipif(sys.version_info < (3, 8), reason="PEP 589 is implemented in Python 3.8") def test_infer_multiple_outputs_typed_dict(self): from typing import TypedDict @@ -110,6 +109,17 @@ def t1() -> TypeDictClass: assert t1().operator.multiple_outputs is True + def test_infer_multiple_outputs_union_type(self): + @task_decorator + def t1() -> str | None: + # Before PEP 604 which are implemented in Python 3.10 `str | None` + # returns `types.UnionType` which are class and could be check in `issubclass()`. + # However in Python 3.10+ this construction returns object `typing.Union` + # which can not be used in `issubclass()` + return "foo" + + assert t1().operator.multiple_outputs is False + def test_infer_multiple_outputs_forward_annotation(self): if TYPE_CHECKING: From ba656f3380a29073a7fcdd55849684db09f6b06f Mon Sep 17 00:00:00 2001 From: Andrey Anshin Date: Thu, 11 Jan 2024 09:49:27 +0400 Subject: [PATCH 2/2] Limit PEP 604 test by Python 3.10 --- tests/decorators/test_python.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tests/decorators/test_python.py b/tests/decorators/test_python.py index 10da056dd5f9e..69b52d77248ff 100644 --- a/tests/decorators/test_python.py +++ b/tests/decorators/test_python.py @@ -109,7 +109,10 @@ def t1() -> TypeDictClass: assert t1().operator.multiple_outputs is True - def test_infer_multiple_outputs_union_type(self): + # We do not enable `from __future__ import annotations` for particular this test module, + # that mean `str | None` annotation would raise TypeError in Python 3.9 and below + @pytest.mark.skipif(sys.version_info < (3, 10), reason="PEP 604 is implemented in Python 3.10") + def test_infer_multiple_outputs_pep_604_union_type(self): @task_decorator def t1() -> str | None: # Before PEP 604 which are implemented in Python 3.10 `str | None` @@ -120,6 +123,13 @@ def t1() -> str | None: assert t1().operator.multiple_outputs is False + def test_infer_multiple_outputs_union_type(self): + @task_decorator + def t1() -> Union[str, None]: + return "foo" + + assert t1().operator.multiple_outputs is False + def test_infer_multiple_outputs_forward_annotation(self): if TYPE_CHECKING: