|
65 | 65 | from _pytest.pathlib import bestrelpath |
66 | 66 | from _pytest.scope import HIGH_SCOPES |
67 | 67 | from _pytest.scope import Scope |
68 | | -from _pytest.stash import StashKey |
69 | 68 |
|
70 | 69 |
|
71 | 70 | if TYPE_CHECKING: |
@@ -149,66 +148,6 @@ def get_scope_node( |
149 | 148 | assert_never(scope) |
150 | 149 |
|
151 | 150 |
|
152 | | -def resolve_unique_values_and_their_indices_in_parametersets( |
153 | | - argnames: Sequence[str], |
154 | | - parametersets: Sequence[ParameterSet], |
155 | | -) -> Tuple[Dict[str, List[object]], List[Tuple[int]]]: |
156 | | - """Resolve unique values and their indices in parameter sets. The index of a value |
157 | | - is determined by when it appears in the possible values for the first time. |
158 | | - For example, given ``argnames`` and ``parametersets`` below, the result would be: |
159 | | -
|
160 | | - :: |
161 | | -
|
162 | | - argnames = ["A", "B", "C"] |
163 | | - parametersets = [("a1", "b1", "c1"), ("a1", "b2", "c1"), ("a1", "b3", "c2")] |
164 | | - result[0] = {"A": ["a1"], "B": ["b1", "b2", "b3"], "C": ["c1", "c2"]} |
165 | | - result[1] = [(0, 0, 0), (0, 1, 0), (0, 2, 1)] |
166 | | -
|
167 | | - result is used in reordering `indirect`ly parametrized with multiple |
168 | | - parameters or directly parametrized tests to keep items using the same fixture or |
169 | | - pseudo-fixture values respectively, close together. |
170 | | -
|
171 | | - :param argnames: |
172 | | - Argument names passed to ``parametrize()``. |
173 | | - :param parametersets: |
174 | | - The parameter sets, each containing a set of values corresponding |
175 | | - to ``argnames``. |
176 | | - :returns: |
177 | | - Tuple of unique parameter values and their indices in parametersets. |
178 | | - """ |
179 | | - indices = [] |
180 | | - argname_value_indices_for_hashable_ones: Dict[str, Dict[object, int]] = defaultdict( |
181 | | - dict |
182 | | - ) |
183 | | - argvalues_count: Dict[str, int] = defaultdict(lambda: 0) |
184 | | - unique_values: Dict[str, List[object]] = defaultdict(list) |
185 | | - for i, argname in enumerate(argnames): |
186 | | - argname_indices = [] |
187 | | - for parameterset in parametersets: |
188 | | - value = parameterset.values[i] |
189 | | - try: |
190 | | - argname_indices.append( |
191 | | - argname_value_indices_for_hashable_ones[argname][value] |
192 | | - ) |
193 | | - except KeyError: # New unique value |
194 | | - argname_value_indices_for_hashable_ones[argname][ |
195 | | - value |
196 | | - ] = argvalues_count[argname] |
197 | | - argname_indices.append(argvalues_count[argname]) |
198 | | - argvalues_count[argname] += 1 |
199 | | - unique_values[argname].append(value) |
200 | | - except TypeError: # `value` is not hashable |
201 | | - argname_indices.append(argvalues_count[argname]) |
202 | | - argvalues_count[argname] += 1 |
203 | | - unique_values[argname].append(value) |
204 | | - indices.append(argname_indices) |
205 | | - return unique_values, list(zip(*indices)) |
206 | | - |
207 | | - |
208 | | -# Used for storing artificial fixturedefs for direct parametrization. |
209 | | -name2pseudofixturedef_key = StashKey[Dict[str, "FixtureDef[Any]"]]() |
210 | | - |
211 | | - |
212 | 151 | def getfixturemarker(obj: object) -> Optional["FixtureFunctionMarker"]: |
213 | 152 | """Return fixturemarker or None if it doesn't exist or raised |
214 | 153 | exceptions.""" |
@@ -352,15 +291,9 @@ def fix_cache_order( |
352 | 291 | item: nodes.Item, |
353 | 292 | argkeys_cache: Dict[Scope, Dict[nodes.Item, Dict[FixtureArgKey, None]]], |
354 | 293 | items_by_argkey: Dict[Scope, Dict[FixtureArgKey, "Deque[nodes.Item]"]], |
355 | | - ignore: Set[Optional[FixtureArgKey]], |
356 | | - current_scope: Scope, |
357 | 294 | ) -> None: |
358 | 295 | for scope in HIGH_SCOPES: |
359 | | - if current_scope < scope: |
360 | | - continue |
361 | 296 | for key in argkeys_cache[scope].get(item, []): |
362 | | - if key in ignore: |
363 | | - continue |
364 | 297 | items_by_argkey[scope][key].appendleft(item) |
365 | 298 |
|
366 | 299 |
|
@@ -404,11 +337,17 @@ def reorder_items_atscope( |
404 | 337 | else: |
405 | 338 | slicing_argkey, _ = argkeys.popitem() |
406 | 339 | # deque because they'll just be ignored. |
407 | | - unique_matching_items = dict.fromkeys(scoped_items_by_argkey[slicing_argkey]) |
408 | | - for i in reversed(unique_matching_items if sys.version_info.minor > 7 else list(unique_matching_items)): |
| 340 | + unique_matching_items = dict.fromkeys( |
| 341 | + scoped_items_by_argkey[slicing_argkey] |
| 342 | + ) |
| 343 | + for i in reversed( |
| 344 | + unique_matching_items |
| 345 | + if sys.version_info.minor > 7 |
| 346 | + else list(unique_matching_items) |
| 347 | + ): |
409 | 348 | if i not in items: |
410 | 349 | continue |
411 | | - fix_cache_order(i, argkeys_cache, items_by_argkey, ignore, scope) |
| 350 | + fix_cache_order(i, argkeys_cache, items_by_argkey) |
412 | 351 | items_deque.appendleft(i) |
413 | 352 | break |
414 | 353 | if no_argkey_group: |
@@ -447,18 +386,6 @@ class FuncFixtureInfo: |
447 | 386 | name2fixturedefs: Dict[str, Sequence["FixtureDef[Any]"]] |
448 | 387 | name2num_fixturedefs_used: Dict[str, int] |
449 | 388 |
|
450 | | - def prune_dependency_tree(self) -> None: |
451 | | - """Recompute names_closure from initialnames and name2fixturedefs. |
452 | | -
|
453 | | - Can only reduce names_closure, which means that the new closure will |
454 | | - always be a subset of the old one. The order is preserved. |
455 | | -
|
456 | | - This method is needed because dynamic direct parametrization may shadow |
457 | | - some of the fixtures that were included in the originally built dependency |
458 | | - tree. In this way the dependency tree can get pruned, and the closure |
459 | | - of argnames may get reduced. |
460 | | - """ |
461 | | - |
462 | 389 |
|
463 | 390 | class FixtureRequest: |
464 | 391 | """A request for a fixture from a test or fixture function. |
@@ -1585,19 +1512,15 @@ def getfixtureclosure( |
1585 | 1512 | ignore_args: Sequence[str] = (), |
1586 | 1513 | ) -> Tuple[List[str], Dict[str, List[FixtureDef[Any]]]]: |
1587 | 1514 | # Collect the closure of all fixtures, starting with the given |
1588 | | - # fixturenames as the initial set. As we have to visit all |
1589 | | - # factory definitions anyway, we also return an arg2fixturedefs |
| 1515 | + # initialnames as the initial set. As we have to visit all |
| 1516 | + # factory definitions anyway, we also populate arg2fixturedefs |
1590 | 1517 | # mapping so that the caller can reuse it and does not have |
1591 | 1518 | # to re-discover fixturedefs again for each fixturename |
1592 | 1519 | # (discovering matching fixtures for a given name/node is expensive). |
1593 | 1520 |
|
1594 | 1521 | parentid = parentnode.nodeid |
1595 | 1522 | fixturenames_closure: Dict[str, int] = {} |
1596 | 1523 |
|
1597 | | - # At this point, fixturenames_closure contains what we call "initialnames", |
1598 | | - # which is a set of fixturenames the function immediately requests. We |
1599 | | - # need to return it as well, so save this. |
1600 | | - |
1601 | 1524 | arg2num_fixturedefs_used: Dict[str, int] = defaultdict(lambda: 0) |
1602 | 1525 | arg2num_def_used_in_path: Dict[str, int] = defaultdict(lambda: 0) |
1603 | 1526 | nodes_in_fixture_tree: Deque[Tuple[str, bool]] = deque( |
|
0 commit comments