Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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