diff --git a/pydra/engine/tests/test_helpers.py b/pydra/engine/tests/test_helpers.py index 06ce39220..a3ea023e1 100644 --- a/pydra/engine/tests/test_helpers.py +++ b/pydra/engine/tests/test_helpers.py @@ -50,7 +50,7 @@ def test_hash_file(tmpdir): with open(outdir / "test.file", "w") as fp: fp.write("test") assert ( - hash_function(File(outdir / "test.file")) == "37fcc546dce7e59585f3217bb4c30299" + hash_function(File(outdir / "test.file")) == "f32ab20c4a86616e32bf2504e1ac5a22" ) diff --git a/pydra/engine/tests/test_specs.py b/pydra/engine/tests/test_specs.py index 4f54cd404..8221751d0 100644 --- a/pydra/engine/tests/test_specs.py +++ b/pydra/engine/tests/test_specs.py @@ -124,7 +124,10 @@ def test_lazy_getvale(): lf = LazyIn(task=tn) with pytest.raises(Exception) as excinfo: lf.inp_c - assert str(excinfo.value) == "Task tn has no input attribute inp_c" + assert ( + str(excinfo.value) + == "Task 'tn' has no input attribute 'inp_c', available: 'inp_a', 'inp_b'" + ) def test_input_file_hash_1(tmp_path): @@ -140,7 +143,7 @@ def test_input_file_hash_1(tmp_path): fields = [("in_file", File)] input_spec = SpecInfo(name="Inputs", fields=fields, bases=(BaseSpec,)) inputs = make_klass(input_spec) - assert inputs(in_file=outfile).hash == "0e9306e5cae1de1b4dff1f27cca03bce" + assert inputs(in_file=outfile).hash == "02fa5f6f1bbde7f25349f54335e1adaf" def test_input_file_hash_2(tmp_path): @@ -154,7 +157,7 @@ def test_input_file_hash_2(tmp_path): # checking specific hash value hash1 = inputs(in_file=file).hash - assert hash1 == "17e4e2b4d8ce8f36bf3fd65804958dbb" + assert hash1 == "aaa50d60ed33d3a316d58edc882a34c3" # checking if different name doesn't affect the hash file_diffname = tmp_path / "in_file_2.txt" @@ -185,7 +188,7 @@ def test_input_file_hash_2a(tmp_path): # checking specific hash value hash1 = inputs(in_file=file).hash - assert hash1 == "17e4e2b4d8ce8f36bf3fd65804958dbb" + assert hash1 == "aaa50d60ed33d3a316d58edc882a34c3" # checking if different name doesn't affect the hash file_diffname = tmp_path / "in_file_2.txt" @@ -204,7 +207,7 @@ def test_input_file_hash_2a(tmp_path): # checking if string is also accepted hash4 = inputs(in_file=str(file)).hash - assert hash4 == "aee7c7ae25509fb4c92a081d58d17a67" + assert hash4 == "800af2b5b334c9e3e5c40c0e49b7ffb5" def test_input_file_hash_3(tmp_path): @@ -278,7 +281,7 @@ def test_input_file_hash_4(tmp_path): # checking specific hash value hash1 = inputs(in_file=[[file, 3]]).hash - assert hash1 == "11b7e9c90bc8d9dc5ccfc8d4526ba091" + assert hash1 == "0693adbfac9f675af87e900065b1de00" # the same file, but int field changes hash1a = inputs(in_file=[[file, 5]]).hash @@ -315,7 +318,7 @@ def test_input_file_hash_5(tmp_path): # checking specific hash value hash1 = inputs(in_file=[{"file": file, "int": 3}]).hash - assert hash1 == "5fd53b79e55bbf62a4bb3027eb753a2c" + assert hash1 == "56e6e2c9f3bdf0cd5bd3060046dea480" # the same file, but int field changes hash1a = inputs(in_file=[{"file": file, "int": 5}]).hash diff --git a/pydra/engine/tests/test_workflow.py b/pydra/engine/tests/test_workflow.py index 598021c83..c6aab6544 100644 --- a/pydra/engine/tests/test_workflow.py +++ b/pydra/engine/tests/test_workflow.py @@ -37,6 +37,7 @@ from ..core import Workflow from ... import mark from ..specs import SpecInfo, BaseSpec, ShellSpec +from pydra.utils import exc_info_matches def test_wf_no_input_spec(): @@ -102,13 +103,15 @@ def test_wf_dict_input_and_output_spec(): wf.inputs.a = "any-string" wf.inputs.b = {"foo": 1, "bar": False} - with pytest.raises(TypeError, match="Cannot coerce 1.0 into "): + with pytest.raises(TypeError) as exc_info: wf.inputs.a = 1.0 - with pytest.raises( - TypeError, - match=("Could not coerce object, 'bad-value', to any of the union types "), - ): + assert exc_info_matches(exc_info, "Cannot coerce 1.0 into ") + + with pytest.raises(TypeError) as exc_info: wf.inputs.b = {"foo": 1, "bar": "bad-value"} + assert exc_info_matches( + exc_info, "Could not coerce object, 'bad-value', to any of the union types" + ) result = wf() assert result.output.a == "any-string" @@ -5002,14 +5005,13 @@ def test_wf_input_output_typing(): output_spec={"alpha": int, "beta": ty.List[int]}, ) - with pytest.raises( - TypeError, match="Cannot coerce into " - ): + with pytest.raises(TypeError) as exc_info: list_mult_sum( scalar=wf.lzin.y, in_list=wf.lzin.y, name="A", ) + exc_info_matches(exc_info, "Cannot coerce into ") wf.add( # Split over workflow input "x" on "scalar" input list_mult_sum( diff --git a/pydra/utils/__init__.py b/pydra/utils/__init__.py index 9008779e2..cfde94dbf 100644 --- a/pydra/utils/__init__.py +++ b/pydra/utils/__init__.py @@ -1 +1 @@ -from .misc import user_cache_dir, add_exc_note # noqa: F401 +from .misc import user_cache_dir, add_exc_note, exc_info_matches # noqa: F401 diff --git a/pydra/utils/misc.py b/pydra/utils/misc.py index 9a40769c9..45b6a5c3b 100644 --- a/pydra/utils/misc.py +++ b/pydra/utils/misc.py @@ -1,4 +1,5 @@ from pathlib import Path +import re import platformdirs from pydra._version import __version__ @@ -31,3 +32,14 @@ def add_exc_note(e: Exception, note: str) -> Exception: else: e.args = (e.args[0] + "\n" + note,) return e + + +def exc_info_matches(exc_info, match, regex=False): + if exc_info.value.__cause__ is not None: + msg = str(exc_info.value.__cause__) + else: + msg = str(exc_info.value) + if regex: + return re.match(".*" + match, msg) + else: + return match in msg diff --git a/pydra/utils/tests/test_typing.py b/pydra/utils/tests/test_typing.py index df87a87f2..45d1ef46f 100644 --- a/pydra/utils/tests/test_typing.py +++ b/pydra/utils/tests/test_typing.py @@ -1,7 +1,6 @@ import os import itertools import sys -import re import typing as ty from pathlib import Path import tempfile @@ -22,6 +21,7 @@ MyOtherFormatX, MyHeader, ) +from pydra.utils import exc_info_matches def lz(tp: ty.Type): @@ -29,17 +29,6 @@ def lz(tp: ty.Type): return LazyOutField(name="foo", field="boo", type=tp) -def exc_info_matches(exc_info, match, regex=False): - if exc_info.value.__cause__ is not None: - msg = str(exc_info.value.__cause__) - else: - msg = str(exc_info.value) - if regex: - return re.match(".*" + match, msg) - else: - return match in msg - - PathTypes = ty.Union[str, os.PathLike] @@ -154,7 +143,8 @@ def test_type_check_basic16(): @pytest.mark.skipif(sys.version_info < (3, 10), reason="No UnionType < Py3.10") def test_type_check_basic16a(): with pytest.raises( - TypeError, match="Cannot coerce to any of the union types" + TypeError, + match="Incorrect type for lazy field: is not a subclass of", ): TypeParser(Path | File | bool | int)(lz(float)) @@ -234,7 +224,7 @@ def test_type_check_fail2(): @pytest.mark.skipif(sys.version_info < (3, 10), reason="No UnionType < Py3.10") def test_type_check_fail2a(): - with pytest.raises(TypeError, match="to any of the union types"): + with pytest.raises(TypeError, match="Incorrect type for lazy field: "): TypeParser(Path | File)(lz(int)) @@ -249,7 +239,10 @@ 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 .*(d|D)ict.* into") + assert exc_info_matches( + exc_info, + "Cannot coerce typing.Dict[str, int] into ", + ) def test_type_check_fail5(): @@ -366,13 +359,13 @@ def test_type_coercion_basic12(): @pytest.mark.skipif(sys.version_info < (3, 10), reason="No UnionType < Py3.10") def test_type_coercion_basic12a(): - with pytest.raises(TypeError, match="explicitly excluded"): + with pytest.raises(TypeError) as exc_info: TypeParser( list, coercible=[(ty.Sequence, ty.Sequence)], not_coercible=[(str, ty.Sequence)], )("a-string") - + assert exc_info_matches(exc_info, "explicitly excluded") assert TypeParser(Path | File | int, coercible=[(ty.Any, ty.Any)])(1.0) == 1 @@ -480,8 +473,9 @@ def test_type_coercion_fail2(): @pytest.mark.skipif(sys.version_info < (3, 10), reason="No UnionType < Py3.10") def test_type_coercion_fail2a(): - with pytest.raises(TypeError, match="to any of the union types"): + with pytest.raises(TypeError) as exc_info: TypeParser(Path | File, coercible=[(ty.Any, ty.Any)])(1) + assert exc_info_matches(exc_info, "to any of the union types") def test_type_coercion_fail3():