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 Apr 5, 2024
1 parent 03478e5 commit 2af4705
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 @@ -6,7 +6,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 9 in pydra/utils/tests/test_typing.py

View check run for this annotation

Codecov / codecov/patch

pydra/utils/tests/test_typing.py#L9

Added line #L9 was not covered by tests
from ..typing import TypeParser
from pydra import Workflow
from fileformats.application import Json, Yaml, Xml
Expand Down Expand Up @@ -202,7 +202,7 @@ def test_type_check_fail3():


def test_type_check_fail4():
with pytest.raises(TypeError, match="Cannot coerce <class 'dict'> into"):
with pytest.raises(TypeError, match="Cannot coerce .*(d|D)ict.* into"):
TypeParser(ty.Sequence)(lz(ty.Dict[str, int]))


Expand Down Expand Up @@ -780,3 +780,63 @@ def test_type_is_instance3():

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


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

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

View check run for this annotation

Codecov / codecov/patch

pydra/utils/tests/test_typing.py#L785-L786

Added lines #L785 - L786 were not covered by tests


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

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

View check run for this annotation

Codecov / codecov/patch

pydra/utils/tests/test_typing.py#L789-L790

Added lines #L789 - L790 were not covered by tests


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

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

View check run for this annotation

Codecov / codecov/patch

pydra/utils/tests/test_typing.py#L793-L794

Added lines #L793 - L794 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 798 in pydra/utils/tests/test_typing.py

View check run for this annotation

Codecov / codecov/patch

pydra/utils/tests/test_typing.py#L797-L798

Added lines #L797 - L798 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 802 in pydra/utils/tests/test_typing.py

View check run for this annotation

Codecov / codecov/patch

pydra/utils/tests/test_typing.py#L801-L802

Added lines #L801 - L802 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 806 in pydra/utils/tests/test_typing.py

View check run for this annotation

Codecov / codecov/patch

pydra/utils/tests/test_typing.py#L805-L806

Added lines #L805 - L806 were not covered by tests


def test_multi_input_obj_coerce4a():

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

View check run for this annotation

Codecov / codecov/patch

pydra/utils/tests/test_typing.py#L809

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

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

View check run for this annotation

Codecov / codecov/patch

pydra/utils/tests/test_typing.py#L811

Added line #L811 was not covered by tests


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

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

View check run for this annotation

Codecov / codecov/patch

pydra/utils/tests/test_typing.py#L814-L815

Added lines #L814 - L815 were not covered by tests


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

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

View check run for this annotation

Codecov / codecov/patch

pydra/utils/tests/test_typing.py#L818-L819

Added lines #L818 - L819 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 823 in pydra/utils/tests/test_typing.py

View check run for this annotation

Codecov / codecov/patch

pydra/utils/tests/test_typing.py#L822-L823

Added lines #L822 - L823 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 827 in pydra/utils/tests/test_typing.py

View check run for this annotation

Codecov / codecov/patch

pydra/utils/tests/test_typing.py#L826-L827

Added lines #L826 - L827 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 831 in pydra/utils/tests/test_typing.py

View check run for this annotation

Codecov / codecov/patch

pydra/utils/tests/test_typing.py#L830-L831

Added lines #L830 - L831 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 835 in pydra/utils/tests/test_typing.py

View check run for this annotation

Codecov / codecov/patch

pydra/utils/tests/test_typing.py#L834-L835

Added lines #L834 - L835 were not covered by tests


def test_multi_input_obj_check_type4a():

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

View check run for this annotation

Codecov / codecov/patch

pydra/utils/tests/test_typing.py#L838

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

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

View check run for this annotation

Codecov / codecov/patch

pydra/utils/tests/test_typing.py#L840

Added line #L840 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 typing as ty
import logging
Expand All @@ -12,6 +13,7 @@
MultiInputObj,
MultiOutputObj,
)
from ..utils import add_exc_note
from fileformats import field

try:
Expand Down Expand Up @@ -337,18 +339,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 344 in pydra/utils/typing.py

View check run for this annotation

Codecov / codecov/patch

pydra/utils/typing.py#L344

Added line #L344 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 354 in pydra/utils/typing.py

View check run for this annotation

Codecov / codecov/patch

pydra/utils/typing.py#L349-L354

Added lines #L349 - L354 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 359 in pydra/utils/typing.py

View check run for this annotation

Codecov / codecov/patch

pydra/utils/typing.py#L359

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

return expand_and_coerce(obj, self.pattern)
raise e

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

View check run for this annotation

Codecov / codecov/patch

pydra/utils/typing.py#L361

Added line #L361 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 @@ -485,12 +495,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 500 in pydra/utils/typing.py

View check run for this annotation

Codecov / codecov/patch

pydra/utils/typing.py#L500

Added line #L500 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 510 in pydra/utils/typing.py

View check run for this annotation

Codecov / codecov/patch

pydra/utils/typing.py#L505-L510

Added lines #L505 - L510 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 515 in pydra/utils/typing.py

View check run for this annotation

Codecov / codecov/patch

pydra/utils/typing.py#L515

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

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

View check run for this annotation

Codecov / codecov/patch

pydra/utils/typing.py#L517

Added line #L517 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 2af4705

Please sign in to comment.