Skip to content

Commit

Permalink
Fix check on subclass for typing.Union in _infer_multiple_outputs
Browse files Browse the repository at this point in the history
… for Python 3.10+ (#36728)

* Fix check on subclass for `typing.Union` in `_infer_multiple_outputs` for Python 3.10+

* Limit PEP 604 test by Python 3.10
  • Loading branch information
Taragolis authored Jan 11, 2024
1 parent 8b33e25 commit f1d8297
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 2 deletions.
2 changes: 1 addition & 1 deletion airflow/decorators/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
22 changes: 21 additions & 1 deletion tests/decorators/test_python.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -110,6 +109,27 @@ def t1() -> TypeDictClass:

assert t1().operator.multiple_outputs is True

# 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`
# 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_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:

Expand Down

0 comments on commit f1d8297

Please sign in to comment.