From f56e0df969debaea7bd860b89945b03e27116e94 Mon Sep 17 00:00:00 2001 From: Muhamed Fazal PS Date: Thu, 16 Jul 2026 19:46:03 +0530 Subject: [PATCH 1/2] fix: improve error message when parametrize values is not iterable When a trailing comma in argnames causes a scalar value to be parsed as a single-element tuple, TypeError is raised on len(None). Catch this and show a helpful error message. Part of #14619 --- src/_pytest/mark/structures.py | 49 +++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index 5449b17a1c6..958beed868d 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -211,26 +211,37 @@ def _for_parametrize( parameters = cls._parse_parametrize_parameters(argvalues, force_tuple) del argvalues - if parameters: - # Check all parameter sets have the correct number of values. - for param in parameters: - if len(param.values) != len(argnames): - msg = ( - '{nodeid}: in "parametrize" the number of names ({names_len}):\n' - " {names}\n" - "must be equal to the number of values ({values_len}):\n" - " {values}" - ) - fail( - msg.format( - nodeid=nodeid, - values=param.values, - names=argnames, - names_len=len(argnames), - values_len=len(param.values), - ), - pytrace=False, + for param in parameters: + try: + values_len = len(param.values) + except TypeError: + fail( + "{nodeid}: in \"parametrize\" cannot determine the number of " + "values: {values!r} is not iterable. This can happen when " + "a trailing comma in the argnames string causes a scalar " + "value to be parsed as a single-element tuple.".format( + nodeid=nodeid, + values=param.values, ) + ) + return # never reached, but appease type checkers + if values_len != len(argnames): + msg = ( + '{nodeid}: in "parametrize" the number of names ({names_len}):\n' + " {names}\n" + "must be equal to the number of values ({values_len}):\n" + " {values}" + ) + fail( + msg.format( + nodeid=nodeid, + values=param.values, + names=argnames, + names_len=len(argnames), + values_len=len(param.values), + ), + pytrace=False, + ) else: # Empty parameter set (likely computed at runtime): create a single # parameter set with NOTSET values, with the "empty parameter set" mark applied to it. From 93201c9fcce25299e034fc5b0310ffb35e9a63b6 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 16 Jul 2026 14:16:34 +0000 Subject: [PATCH 2/2] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/_pytest/mark/structures.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index 958beed868d..599d252656b 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -216,13 +216,10 @@ def _for_parametrize( values_len = len(param.values) except TypeError: fail( - "{nodeid}: in \"parametrize\" cannot determine the number of " - "values: {values!r} is not iterable. This can happen when " + f'{nodeid}: in "parametrize" cannot determine the number of ' + f"values: {param.values!r} is not iterable. This can happen when " "a trailing comma in the argnames string causes a scalar " - "value to be parsed as a single-element tuple.".format( - nodeid=nodeid, - values=param.values, - ) + "value to be parsed as a single-element tuple." ) return # never reached, but appease type checkers if values_len != len(argnames):