--- contrib/python/pytest/py3/_pytest/fixtures.py (54693a02d00937a28e5176cac9fa36e9ea9a9a4b) +++ contrib/python/pytest/py3/_pytest/fixtures.py (d19830d8860a577c5e2a88ca771220910c8ad740) @@ -1538,6 +1538,7 @@ class FixtureManager: # (discovering matching fixtures for a given name/node is expensive). parentid = parentnode.nodeid + parentnodesids = set(nodes.iterparentnodeids(parentid)) fixturenames_closure = list(initialnames) arg2fixturedefs: Dict[str, Sequence[FixtureDef[Any]]] = {} @@ -1549,7 +1550,7 @@ class FixtureManager: continue if argname in arg2fixturedefs: continue - fixturedefs = self.getfixturedefs(argname, parentid) + fixturedefs = self.getfixturedefs(argname, parentid, _parentnodeids=parentnodesids) if fixturedefs: arg2fixturedefs[argname] = fixturedefs for arg in fixturedefs[-1].argnames: @@ -1574,6 +1575,12 @@ class FixtureManager: args, _ = ParameterSet._parse_parametrize_args(*mark.args, **mark.kwargs) return args + parametrized_argnames = set( + argname + for mark in metafunc.definition.iter_markers("parametrize") + for argname in get_parametrize_mark_argnames(mark) + ) + for argname in metafunc.fixturenames: # Get the FixtureDefs for the argname. fixture_defs = metafunc._arg2fixturedefs.get(argname) @@ -1584,10 +1591,7 @@ class FixtureManager: # If the test itself parametrizes using this argname, give it # precedence. - if any( - argname in get_parametrize_mark_argnames(mark) - for mark in metafunc.definition.iter_markers("parametrize") - ): + if argname in parametrized_argnames: continue # In the common case we only look at the fixture def with the @@ -1721,7 +1725,7 @@ class FixtureManager: self._nodeid_autousenames.setdefault(nodeid or "", []).extend(autousenames) def getfixturedefs( - self, argname: str, nodeid: str + self, argname: str, nodeid: str, /, _parentnodeids: Optional[set[str]] = None ) -> Optional[Sequence[FixtureDef[Any]]]: """Get FixtureDefs for a fixture name which are applicable to a given node. @@ -1738,12 +1742,14 @@ class FixtureManager: fixturedefs = self._arg2fixturedefs[argname] except KeyError: return None - return tuple(self._matchfactories(fixturedefs, nodeid)) + + if not _parentnodeids: + _parentnodeids = set(nodes.iterparentnodeids(nodeid)) + return tuple(self._matchfactories(fixturedefs, _parentnodeids)) def _matchfactories( - self, fixturedefs: Iterable[FixtureDef[Any]], nodeid: str + self, fixturedefs: Iterable[FixtureDef[Any]], _parentnodeids: set[str] ) -> Iterator[FixtureDef[Any]]: - parentnodeids = set(nodes.iterparentnodeids(nodeid)) for fixturedef in fixturedefs: - if fixturedef.baseid in parentnodeids: + if fixturedef.baseid in _parentnodeids: yield fixturedef --- contrib/python/pytest/py3/_pytest/scope.py (54693a02d00937a28e5176cac9fa36e9ea9a9a4b) +++ contrib/python/pytest/py3/_pytest/scope.py (d19830d8860a577c5e2a88ca771220910c8ad740) @@ -53,8 +53,32 @@ class Scope(Enum): return _ALL_SCOPES[index + 1] def __lt__(self, other: "Scope") -> bool: - self_index = _SCOPE_INDICES[self] - other_index = _SCOPE_INDICES[other] + if self == other: + return False + self_index = 0 + if self is Scope.Function: + self_index = 0 + elif self is Scope.Class: + self_index = 1 + elif self is Scope.Module: + self_index = 2 + elif self is Scope.Package: + self_index = 3 + elif self is Scope.Session: + self_index = 4 + + other_index = 0 + if other is Scope.Function: + other_index = 0 + elif other is Scope.Class: + other_index = 1 + elif other is Scope.Module: + other_index = 2 + elif other is Scope.Package: + other_index = 3 + elif other is Scope.Session: + other_index = 4 + return self_index < other_index @classmethod