Skip to content

Commit

Permalink
added unittests for multi_input_obj coercion
Browse files Browse the repository at this point in the history
  • Loading branch information
tclose committed May 21, 2024
1 parent 40c0e17 commit cb0814c
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 19 deletions.
64 changes: 62 additions & 2 deletions pydra/utils/tests/test_typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import tempfile
import pytest
from pydra import mark
from ...engine.specs import File, LazyOutField
from ...engine.specs import File, LazyOutField, MultiInputObj

Check warning on line 10 in pydra/utils/tests/test_typing.py

View check run for this annotation

Codecov / codecov/patch

pydra/utils/tests/test_typing.py#L10

Added line #L10 was not covered by tests
from ..typing import TypeParser
from pydra import Workflow
from fileformats.application import Json, Yaml, Xml
Expand Down Expand Up @@ -249,7 +249,7 @@ def test_type_check_fail3():
def test_type_check_fail4():
with pytest.raises(TypeError) as exc_info:
TypeParser(ty.Sequence)(lz(ty.Dict[str, int]))
assert exc_info_matches(exc_info, "Cannot coerce <class 'dict'> into")
assert exc_info_matches(exc_info, "Cannot coerce .*(d|D)ict.* into")

Check warning on line 252 in pydra/utils/tests/test_typing.py

View check run for this annotation

Codecov / codecov/patch

pydra/utils/tests/test_typing.py#L252

Added line #L252 was not covered by tests


def test_type_check_fail5():
Expand Down Expand Up @@ -1043,3 +1043,63 @@ def test_type_is_instance11():
@pytest.mark.skipif(sys.version_info < (3, 10), reason="No UnionType < Py3.10")
def test_type_is_instance11a():
assert not TypeParser.is_instance(None, int | str)


def test_multi_input_obj_coerce1():
assert TypeParser(MultiInputObj[str])("a") == ["a"]

Check warning on line 1049 in pydra/utils/tests/test_typing.py

View check run for this annotation

Codecov / codecov/patch

pydra/utils/tests/test_typing.py#L1048-L1049

Added lines #L1048 - L1049 were not covered by tests


def test_multi_input_obj_coerce2():
assert TypeParser(MultiInputObj[str])(["a"]) == ["a"]

Check warning on line 1053 in pydra/utils/tests/test_typing.py

View check run for this annotation

Codecov / codecov/patch

pydra/utils/tests/test_typing.py#L1052-L1053

Added lines #L1052 - L1053 were not covered by tests


def test_multi_input_obj_coerce3():
assert TypeParser(MultiInputObj[ty.List[str]])(["a"]) == [["a"]]

Check warning on line 1057 in pydra/utils/tests/test_typing.py

View check run for this annotation

Codecov / codecov/patch

pydra/utils/tests/test_typing.py#L1056-L1057

Added lines #L1056 - L1057 were not covered by tests


def test_multi_input_obj_coerce3a():
assert TypeParser(MultiInputObj[ty.Union[int, ty.List[str]]])(["a"]) == [["a"]]

Check warning on line 1061 in pydra/utils/tests/test_typing.py

View check run for this annotation

Codecov / codecov/patch

pydra/utils/tests/test_typing.py#L1060-L1061

Added lines #L1060 - L1061 were not covered by tests


def test_multi_input_obj_coerce3b():
assert TypeParser(MultiInputObj[ty.Union[int, ty.List[str]]])([["a"]]) == [["a"]]

Check warning on line 1065 in pydra/utils/tests/test_typing.py

View check run for this annotation

Codecov / codecov/patch

pydra/utils/tests/test_typing.py#L1064-L1065

Added lines #L1064 - L1065 were not covered by tests


def test_multi_input_obj_coerce4():
assert TypeParser(MultiInputObj[ty.Union[int, ty.List[str]]])([1]) == [1]

Check warning on line 1069 in pydra/utils/tests/test_typing.py

View check run for this annotation

Codecov / codecov/patch

pydra/utils/tests/test_typing.py#L1068-L1069

Added lines #L1068 - L1069 were not covered by tests


def test_multi_input_obj_coerce4a():

Check warning on line 1072 in pydra/utils/tests/test_typing.py

View check run for this annotation

Codecov / codecov/patch

pydra/utils/tests/test_typing.py#L1072

Added line #L1072 was not covered by tests
with pytest.raises(TypeError):
TypeParser(MultiInputObj[ty.Union[int, ty.List[str]]])([[1]])

Check warning on line 1074 in pydra/utils/tests/test_typing.py

View check run for this annotation

Codecov / codecov/patch

pydra/utils/tests/test_typing.py#L1074

Added line #L1074 was not covered by tests


def test_multi_input_obj_check_type1():
TypeParser(MultiInputObj[str])(lz(str))

Check warning on line 1078 in pydra/utils/tests/test_typing.py

View check run for this annotation

Codecov / codecov/patch

pydra/utils/tests/test_typing.py#L1077-L1078

Added lines #L1077 - L1078 were not covered by tests


def test_multi_input_obj_check_type2():
TypeParser(MultiInputObj[str])(lz(ty.List[str]))

Check warning on line 1082 in pydra/utils/tests/test_typing.py

View check run for this annotation

Codecov / codecov/patch

pydra/utils/tests/test_typing.py#L1081-L1082

Added lines #L1081 - L1082 were not covered by tests


def test_multi_input_obj_check_type3():
TypeParser(MultiInputObj[ty.List[str]])(lz(ty.List[str]))

Check warning on line 1086 in pydra/utils/tests/test_typing.py

View check run for this annotation

Codecov / codecov/patch

pydra/utils/tests/test_typing.py#L1085-L1086

Added lines #L1085 - L1086 were not covered by tests


def test_multi_input_obj_check_type3a():
TypeParser(MultiInputObj[ty.Union[int, ty.List[str]]])(lz(ty.List[str]))

Check warning on line 1090 in pydra/utils/tests/test_typing.py

View check run for this annotation

Codecov / codecov/patch

pydra/utils/tests/test_typing.py#L1089-L1090

Added lines #L1089 - L1090 were not covered by tests


def test_multi_input_obj_check_type3b():
TypeParser(MultiInputObj[ty.Union[int, ty.List[str]]])(lz(ty.List[ty.List[str]]))

Check warning on line 1094 in pydra/utils/tests/test_typing.py

View check run for this annotation

Codecov / codecov/patch

pydra/utils/tests/test_typing.py#L1093-L1094

Added lines #L1093 - L1094 were not covered by tests


def test_multi_input_obj_check_type4():
TypeParser(MultiInputObj[ty.Union[int, ty.List[str]]])(lz(ty.List[int]))

Check warning on line 1098 in pydra/utils/tests/test_typing.py

View check run for this annotation

Codecov / codecov/patch

pydra/utils/tests/test_typing.py#L1097-L1098

Added lines #L1097 - L1098 were not covered by tests


def test_multi_input_obj_check_type4a():

Check warning on line 1101 in pydra/utils/tests/test_typing.py

View check run for this annotation

Codecov / codecov/patch

pydra/utils/tests/test_typing.py#L1101

Added line #L1101 was not covered by tests
with pytest.raises(TypeError):
TypeParser(MultiInputObj[ty.Union[int, ty.List[str]]])(

Check warning on line 1103 in pydra/utils/tests/test_typing.py

View check run for this annotation

Codecov / codecov/patch

pydra/utils/tests/test_typing.py#L1103

Added line #L1103 was not covered by tests
lz(ty.List[ty.List[int]])
)
58 changes: 41 additions & 17 deletions pydra/utils/typing.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import inspect
from pathlib import Path
import os
from copy import copy
import sys
import types
import typing as ty
Expand All @@ -13,6 +14,7 @@
MultiInputObj,
MultiOutputObj,
)
from ..utils import add_exc_note
from fileformats import field

try:
Expand Down Expand Up @@ -366,18 +368,26 @@ def coerce_obj(obj, type_):
f"Cannot coerce {obj!r} into {type_}{msg}{self.label_str}"
) from e

# Special handling for MultiInputObjects (which are annoying)
if isinstance(self.pattern, tuple) and self.pattern[0] == MultiInputObj:
try:
self.check_coercible(object_, self.pattern[1][0])
except TypeError:
pass
try:
return expand_and_coerce(object_, self.pattern)
except TypeError as e:

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

View check run for this annotation

Codecov / codecov/patch

pydra/utils/typing.py#L373

Added line #L373 was not covered by tests
# Special handling for MultiInputObjects (which are annoying)
if isinstance(self.pattern, tuple) and self.pattern[0] == MultiInputObj:
# Attempt to coerce the object into arg type of the MultiInputObj first,
# and if that fails, try to coerce it into a list of the arg type
inner_type_parser = copy(self)
inner_type_parser.pattern = self.pattern[1][0]
try:
return [inner_type_parser.coerce(object_)]
except TypeError:
add_exc_note(

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

View check run for this annotation

Codecov / codecov/patch

pydra/utils/typing.py#L378-L383

Added lines #L378 - L383 were not covered by tests
e,
"Also failed to coerce to the arg-type of the MultiInputObj "
f"({self.pattern[1][0]})",
)
raise e

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

View check run for this annotation

Codecov / codecov/patch

pydra/utils/typing.py#L388

Added line #L388 was not covered by tests
else:
obj = [object_]
else:
obj = object_

return expand_and_coerce(obj, self.pattern)
raise e

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

View check run for this annotation

Codecov / codecov/patch

pydra/utils/typing.py#L390

Added line #L390 was not covered by tests

def check_type(self, type_: ty.Type[ty.Any]):
"""Checks the given type to see whether it matches or is a subtype of the
Expand Down Expand Up @@ -537,12 +547,26 @@ def check_sequence(tp_args, pattern_args):
for arg in tp_args:
expand_and_check(arg, pattern_args[0])

# Special handling for MultiInputObjects (which are annoying)
if isinstance(self.pattern, tuple) and self.pattern[0] == MultiInputObj:
pattern = (ty.Union, [self.pattern[1][0], (ty.List, self.pattern[1])])
else:
pattern = self.pattern
return expand_and_check(type_, pattern)
try:
return expand_and_check(type_, self.pattern)
except TypeError as e:

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

View check run for this annotation

Codecov / codecov/patch

pydra/utils/typing.py#L552

Added line #L552 was not covered by tests
# Special handling for MultiInputObjects (which are annoying)
if isinstance(self.pattern, tuple) and self.pattern[0] == MultiInputObj:
# Attempt to coerce the object into arg type of the MultiInputObj first,
# and if that fails, try to coerce it into a list of the arg type
inner_type_parser = copy(self)
inner_type_parser.pattern = self.pattern[1][0]
try:
inner_type_parser.check_type(type_)
except TypeError:
add_exc_note(

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

View check run for this annotation

Codecov / codecov/patch

pydra/utils/typing.py#L557-L562

Added lines #L557 - L562 were not covered by tests
e,
"Also failed to coerce to the arg-type of the MultiInputObj "
f"({self.pattern[1][0]})",
)
raise e

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

View check run for this annotation

Codecov / codecov/patch

pydra/utils/typing.py#L567

Added line #L567 was not covered by tests
else:
raise e

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

View check run for this annotation

Codecov / codecov/patch

pydra/utils/typing.py#L569

Added line #L569 was not covered by tests

def check_coercible(self, source: ty.Any, target: ty.Union[type, ty.Any]):
"""Checks whether the source object is coercible to the target type given the coercion
Expand Down

0 comments on commit cb0814c

Please sign in to comment.