From 14665b4a827f3abfb14d18034c3455e6a781226f Mon Sep 17 00:00:00 2001 From: Taylor Salo Date: Tue, 18 Nov 2025 12:40:57 -0500 Subject: [PATCH 1/5] Raise exception on nonstandard spaces with res. --- niworkflows/utils/spaces.py | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/niworkflows/utils/spaces.py b/niworkflows/utils/spaces.py index fc5e93e4dff..d43d2af2edb 100644 --- a/niworkflows/utils/spaces.py +++ b/niworkflows/utils/spaces.py @@ -708,11 +708,17 @@ def __call__(self, parser, namespace, values, option_string=None): if not values: # option was called without any output spaces, so user does not want outputs spaces.checkpoint() + + invalid_spaces = [] for val in values: val = val.rstrip(':') + space = val.split(':')[0] + if space in NONSTANDARD_REFERENCES and (':res-' in val or ':resolution-' in val): + invalid_spaces.append(val) + if ( - val not in NONSTANDARD_REFERENCES - and not val.split(':')[0].startswith('fs') + space not in NONSTANDARD_REFERENCES + and not space.startswith('fs') and ':res-' not in val and ':resolution-' not in val ): @@ -721,8 +727,16 @@ def __call__(self, parser, namespace, values, option_string=None): # https://github.com/nipreps/niworkflows/pull/457#discussion_r375510227 # https://github.com/nipreps/niworkflows/pull/494 val = f'{val}:res-native' + for sp in Reference.from_string(val): spaces.add(sp) + + if invalid_spaces: + raise ValueError( + 'Resolutions are not allowed for nonstandard spaces. ' + f'Invalid space(s): {", ".join(invalid_spaces)}' + ) + setattr(namespace, self.dest, spaces) From cf38963095ad6df99b6ca899a5aaaed080a06502 Mon Sep 17 00:00:00 2001 From: Taylor Salo Date: Tue, 18 Nov 2025 14:03:38 -0500 Subject: [PATCH 2/5] Add test for new behavior. --- niworkflows/utils/tests/test_spaces.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/niworkflows/utils/tests/test_spaces.py b/niworkflows/utils/tests/test_spaces.py index 1f37c56b778..7635715d492 100644 --- a/niworkflows/utils/tests/test_spaces.py +++ b/niworkflows/utils/tests/test_spaces.py @@ -104,3 +104,15 @@ def test_space_action_edgecases(parser, flag, expected): pargs = parser.parse_known_args(flag)[0] spaces = pargs.spaces assert spaces.is_cached() is expected + + +@pytest.mark.parametrize( + ('spaces', 'expected'), + [ + (('func:res-01',), 'Resolutions are not allowed for nonstandard spaces.'), + (('shouldraise',), 'space identifier "shouldraise" is invalid.') + ], +) +def test_space_action_invalid_spaces(parser, spaces, expected): + with pytest.raises(ValueError, match=expected): + parser.parse_known_args(args=('--spaces',) + spaces)[0] From f3ff974ab548163063a93ff11f47653b23a63e17 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 18 Nov 2025 19:03:52 +0000 Subject: [PATCH 3/5] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- niworkflows/utils/tests/test_spaces.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/niworkflows/utils/tests/test_spaces.py b/niworkflows/utils/tests/test_spaces.py index 7635715d492..1742f70e0b1 100644 --- a/niworkflows/utils/tests/test_spaces.py +++ b/niworkflows/utils/tests/test_spaces.py @@ -110,7 +110,7 @@ def test_space_action_edgecases(parser, flag, expected): ('spaces', 'expected'), [ (('func:res-01',), 'Resolutions are not allowed for nonstandard spaces.'), - (('shouldraise',), 'space identifier "shouldraise" is invalid.') + (('shouldraise',), 'space identifier "shouldraise" is invalid.'), ], ) def test_space_action_invalid_spaces(parser, spaces, expected): From b137279007ab281df0eebb12934d609f604f20e7 Mon Sep 17 00:00:00 2001 From: Taylor Salo Date: Wed, 19 Nov 2025 10:01:08 -0500 Subject: [PATCH 4/5] Catch all modifiers on non-standard spaces. --- niworkflows/utils/spaces.py | 4 ++-- niworkflows/utils/tests/test_spaces.py | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/niworkflows/utils/spaces.py b/niworkflows/utils/spaces.py index d43d2af2edb..31ed75d7534 100644 --- a/niworkflows/utils/spaces.py +++ b/niworkflows/utils/spaces.py @@ -713,7 +713,7 @@ def __call__(self, parser, namespace, values, option_string=None): for val in values: val = val.rstrip(':') space = val.split(':')[0] - if space in NONSTANDARD_REFERENCES and (':res-' in val or ':resolution-' in val): + if space in NONSTANDARD_REFERENCES and ':' in val: invalid_spaces.append(val) if ( @@ -733,7 +733,7 @@ def __call__(self, parser, namespace, values, option_string=None): if invalid_spaces: raise ValueError( - 'Resolutions are not allowed for nonstandard spaces. ' + 'Modifiers are not allowed for nonstandard spaces. ' f'Invalid space(s): {", ".join(invalid_spaces)}' ) diff --git a/niworkflows/utils/tests/test_spaces.py b/niworkflows/utils/tests/test_spaces.py index 1742f70e0b1..ae9c4644be0 100644 --- a/niworkflows/utils/tests/test_spaces.py +++ b/niworkflows/utils/tests/test_spaces.py @@ -109,7 +109,8 @@ def test_space_action_edgecases(parser, flag, expected): @pytest.mark.parametrize( ('spaces', 'expected'), [ - (('func:res-01',), 'Resolutions are not allowed for nonstandard spaces.'), + (('func:res-01',), 'Modifiers are not allowed for nonstandard spaces.'), + (('anat:den-91k',), 'Modifiers are not allowed for nonstandard spaces.'), (('shouldraise',), 'space identifier "shouldraise" is invalid.'), ], ) From a8fe5a8546eb8da93f77e7051f207139860deadb Mon Sep 17 00:00:00 2001 From: Chris Markiewicz Date: Mon, 1 Dec 2025 11:18:12 -0500 Subject: [PATCH 5/5] Update niworkflows/utils/spaces.py --- niworkflows/utils/spaces.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/niworkflows/utils/spaces.py b/niworkflows/utils/spaces.py index 31ed75d7534..09a2b84bdf2 100644 --- a/niworkflows/utils/spaces.py +++ b/niworkflows/utils/spaces.py @@ -712,7 +712,7 @@ def __call__(self, parser, namespace, values, option_string=None): invalid_spaces = [] for val in values: val = val.rstrip(':') - space = val.split(':')[0] + space = val.split(':', 1)[0] if space in NONSTANDARD_REFERENCES and ':' in val: invalid_spaces.append(val)