Skip to content

Commit

Permalink
added support for None to be implicitly interpreted as NoneType in ty…
Browse files Browse the repository at this point in the history
…pe-checking/coercing
  • Loading branch information
tclose committed Mar 26, 2024
1 parent e284b65 commit 83e1aae
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 1 deletion.
72 changes: 72 additions & 0 deletions pydra/utils/tests/test_typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -737,6 +737,46 @@ def test_generic_is_subclass3():
assert not TypeParser.is_subclass(ty.List[float], ty.List[int])


def test_none_is_subclass1():
assert TypeParser.is_subclass(None, ty.Union[int, None])


def test_none_is_subclass2():
assert not TypeParser.is_subclass(None, ty.Union[int, float])


def test_none_is_subclass3():
assert TypeParser.is_subclass(ty.Tuple[int, None], ty.Tuple[int, None])


def test_none_is_subclass4():
assert TypeParser.is_subclass(None, None)


def test_none_is_subclass5():
assert not TypeParser.is_subclass(None, int)


def test_none_is_subclass6():
assert not TypeParser.is_subclass(int, None)


def test_none_is_subclass7():
assert TypeParser.is_subclass(None, type(None))


def test_none_is_subclass8():
assert TypeParser.is_subclass(type(None), None)


def test_none_is_subclass9():
assert TypeParser.is_subclass(type(None), type(None))


def test_none_is_subclass10():
assert TypeParser.is_subclass(type(None), type(None))


@pytest.mark.skipif(
sys.version_info < (3, 9), reason="Cannot subscript tuple in < Py3.9"
)
Expand Down Expand Up @@ -780,3 +820,35 @@ def test_type_is_instance3():

def test_type_is_instance4():
assert TypeParser.is_instance(Json, type)


def test_type_is_instance5():
assert TypeParser.is_instance(None, None)


def test_type_is_instance6():
assert TypeParser.is_instance(None, type(None))


def test_type_is_instance7():
assert not TypeParser.is_instance(None, int)


def test_type_is_instance8():
assert not TypeParser.is_instance(1, None)


def test_type_is_instance9():
assert TypeParser.is_instance(None, ty.Union[int, None])


def test_type_is_instance10():
assert TypeParser.is_instance(1, ty.Union[int, None])


def test_type_is_instance11():
assert not TypeParser.is_instance(None, ty.Union[int, str])


def test_type_is_instance12():
assert not TypeParser.is_instance((1, None), ty.Tuple[int, None])
7 changes: 6 additions & 1 deletion pydra/utils/typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -603,7 +603,7 @@ def matches_type(
def is_instance(
cls,
obj: object,
candidates: ty.Union[ty.Type[ty.Any], ty.Sequence[ty.Type[ty.Any]]],
candidates: ty.Union[ty.Type[ty.Any], ty.Sequence[ty.Type[ty.Any]], None],
) -> bool:
"""Checks whether the object is an instance of cls or that cls is typing.Any,
extending the built-in isinstance to check nested type args
Expand All @@ -615,6 +615,8 @@ def is_instance(
candidates : type or ty.Iterable[type]
the candidate types to check the object against
"""
if candidates is None:
candidates = [type(None)]

Check warning on line 619 in pydra/utils/typing.py

View check run for this annotation

Codecov / codecov/patch

pydra/utils/typing.py#L619

Added line #L619 was not covered by tests
if not isinstance(candidates, ty.Sequence):
candidates = [candidates]
for candidate in candidates:
Expand Down Expand Up @@ -656,6 +658,9 @@ def is_subclass(
any_ok : bool
whether klass=typing.Any should return True or False
"""
if klass is None:
# Implicitly convert None to NoneType, like in other typing
klass = type(None)

Check warning on line 663 in pydra/utils/typing.py

View check run for this annotation

Codecov / codecov/patch

pydra/utils/typing.py#L663

Added line #L663 was not covered by tests
if not isinstance(candidates, ty.Sequence):
candidates = [candidates]
if ty.Any in candidates:
Expand Down

0 comments on commit 83e1aae

Please sign in to comment.