Skip to content

Commit 167d5fb

Browse files
committed
WIP: store _param_ids_from/_param_ids_generated with Marks
1 parent 0da413f commit 167d5fb

File tree

3 files changed

+44
-6
lines changed

3 files changed

+44
-6
lines changed

src/_pytest/mark/structures.py

+21-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
import warnings
33
from collections import namedtuple
44
from collections.abc import MutableMapping
5+
from typing import List
6+
from typing import Optional
57
from typing import Set
68

79
import attr
@@ -144,7 +146,13 @@ class Mark:
144146
#: keyword arguments of the mark decorator
145147
kwargs = attr.ib() # Dict[str, object]
146148

147-
def combined_with(self, other):
149+
_param_ids_from = attr.ib(type=Optional["Mark"], default=None)
150+
_param_ids_generated = attr.ib(type=Optional[List[str]], default=None)
151+
152+
def _has_param_ids(self):
153+
return "ids" in self.kwargs or len(self.args) >= 4
154+
155+
def combined_with(self, other: "Mark") -> "Mark":
148156
"""
149157
:param other: the mark to combine with
150158
:type other: Mark
@@ -153,8 +161,19 @@ def combined_with(self, other):
153161
combines by appending args and merging the mappings
154162
"""
155163
assert self.name == other.name
164+
165+
param_ids_from = None # type: Optional[Mark]
166+
if self.name == "parametrize":
167+
if other._has_param_ids():
168+
param_ids_from = other
169+
elif self._has_param_ids():
170+
param_ids_from = self
171+
156172
return Mark(
157-
self.name, self.args + other.args, dict(self.kwargs, **other.kwargs)
173+
self.name,
174+
self.args + other.args,
175+
dict(self.kwargs, **other.kwargs),
176+
param_ids_from=param_ids_from,
158177
)
159178

160179

src/_pytest/python.py

+20-1
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,25 @@ def pytest_generate_tests(metafunc):
132132
_validate_parametrize_spelling(metafunc)
133133

134134
for marker in metafunc.definition.iter_markers(name="parametrize"):
135-
metafunc.parametrize(*marker.args, **marker.kwargs)
135+
args, kwargs = marker.args, marker.kwargs
136+
if marker._param_ids_from:
137+
ids = marker._param_ids_from._param_ids_generated
138+
if ids is None:
139+
save_ids = True
140+
else:
141+
save_ids = False
142+
if len(args) > 3:
143+
args = args.copy()
144+
args[3] = ids
145+
else:
146+
assert "ids" in kwargs
147+
kwargs = kwargs.copy()
148+
kwargs["ids"] = ids
149+
150+
new_ids = metafunc.parametrize(*args, **kwargs)
151+
152+
if marker._param_ids_from and save_ids:
153+
object.__setattr__(marker._param_ids_from, "_param_ids_generated", new_ids)
136154

137155

138156
def pytest_configure(config):
@@ -1024,6 +1042,7 @@ def parametrize(self, argnames, argvalues, indirect=False, ids=None, scope=None)
10241042
)
10251043
newcalls.append(newcallspec)
10261044
self._calls = newcalls
1045+
return ids
10271046

10281047
def _resolve_arg_ids(self, argnames, ids, parameters, item):
10291048
"""Resolves the actual ids for the given argnames, based on the ``ids`` parameter given

testing/python/metafunc.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -1849,12 +1849,12 @@ def test_converted_to_str(a, b):
18491849
"""
18501850
)
18511851
result = testdir.runpytest("-vv", "-s")
1852-
result.stdout.fnmatch_lines_random( # random for py35.
1852+
result.stdout.fnmatch_lines(
18531853
[
18541854
"test_parametrize_iterator.py::test1[param0] PASSED",
18551855
"test_parametrize_iterator.py::test1[param1] PASSED",
1856-
"test_parametrize_iterator.py::test2[param2] PASSED",
1857-
"test_parametrize_iterator.py::test2[param3] PASSED",
1856+
"test_parametrize_iterator.py::test2[param0] PASSED",
1857+
"test_parametrize_iterator.py::test2[param1] PASSED",
18581858
"test_parametrize_iterator.py::test_converted_to_str[0] PASSED",
18591859
"test_parametrize_iterator.py::test_converted_to_str[1] PASSED",
18601860
"*= 6 passed in *",

0 commit comments

Comments
 (0)