1import functools
2import inspect
3import os
4import sys
5import warnings
6from collections import defaultdict
7from collections import deque
8from types import TracebackType
9from typing import Any
10from typing import Callable
11from typing import cast
12from typing import Dict
13from typing import Generator
14from typing import Generic
15from typing import Iterable
16from typing import Iterator
17from typing import List
18from typing import Optional
19from typing import Sequence
20from typing import Set
21from typing import Tuple
22from typing import TypeVar
23from typing import Union
24
25import attr
26import py
27
28import _pytest
29from _pytest._code import getfslineno
30from _pytest._code.code import FormattedExcinfo
31from _pytest._code.code import TerminalRepr
32from _pytest._io import TerminalWriter
33from _pytest.compat import _format_args
34from _pytest.compat import _PytestWrapper
35from _pytest.compat import final
36from _pytest.compat import get_real_func
37from _pytest.compat import get_real_method
38from _pytest.compat import getfuncargnames
39from _pytest.compat import getimfunc
40from _pytest.compat import getlocation
41from _pytest.compat import is_generator
42from _pytest.compat import NOTSET
43from _pytest.compat import order_preserving_dict
44from _pytest.compat import overload
45from _pytest.compat import safe_getattr
46from _pytest.compat import TYPE_CHECKING
47from _pytest.config import _PluggyPlugin
48from _pytest.config import Config
49from _pytest.config.argparsing import Parser
50from _pytest.deprecated import FILLFUNCARGS
51from _pytest.mark import Mark
52from _pytest.mark import ParameterSet
53from _pytest.outcomes import fail
54from _pytest.outcomes import TEST_OUTCOME
55from _pytest.pathlib import absolutepath
56
57if TYPE_CHECKING:
58    from typing import Deque
59    from typing import NoReturn
60    from typing import Type
61    from typing_extensions import Literal
62
63    from _pytest import nodes
64    from _pytest.main import Session
65    from _pytest.python import CallSpec2
66    from _pytest.python import Function
67    from _pytest.python import Metafunc
68
69    _Scope = Literal["session", "package", "module", "class", "function"]
70
71
72# The value of the fixture -- return/yield of the fixture function (type variable).
73_FixtureValue = TypeVar("_FixtureValue")
74# The type of the fixture function (type variable).
75_FixtureFunction = TypeVar("_FixtureFunction", bound=Callable[..., object])
76# The type of a fixture function (type alias generic in fixture value).
77_FixtureFunc = Union[
78    Callable[..., _FixtureValue], Callable[..., Generator[_FixtureValue, None, None]]
79]
80# The type of FixtureDef.cached_result (type alias generic in fixture value).
81_FixtureCachedResult = Union[
82    Tuple[
83        # The result.
84        _FixtureValue,
85        # Cache key.
86        object,
87        None,
88    ],
89    Tuple[
90        None,
91        # Cache key.
92        object,
93        # Exc info if raised.
94        Tuple["Type[BaseException]", BaseException, TracebackType],
95    ],
96]
97
98
99@attr.s(frozen=True)
100class PseudoFixtureDef(Generic[_FixtureValue]):
101    cached_result = attr.ib(type="_FixtureCachedResult[_FixtureValue]")
102    scope = attr.ib(type="_Scope")
103
104
105def pytest_sessionstart(session: "Session") -> None:
106    import _pytest.python
107    import _pytest.nodes
108
109    scopename2class.update(
110        {
111            "package": _pytest.python.Package,
112            "class": _pytest.python.Class,
113            "module": _pytest.python.Module,
114            "function": _pytest.nodes.Item,
115            "session": _pytest.main.Session,
116        }
117    )
118    session._fixturemanager = FixtureManager(session)
119
120
121scopename2class = {}  # type: Dict[str, Type[nodes.Node]]
122
123
124def get_scope_package(node, fixturedef: "FixtureDef[object]"):
125    import pytest
126
127    cls = pytest.Package
128    current = node
129    fixture_package_name = "{}/{}".format(fixturedef.baseid, "__init__.py")
130    while current and (
131        type(current) is not cls or fixture_package_name != current.nodeid
132    ):
133        current = current.parent
134    if current is None:
135        return node.session
136    return current
137
138
139def get_scope_node(node, scope):
140    cls = scopename2class.get(scope)
141    if cls is None:
142        raise ValueError("unknown scope")
143    return node.getparent(cls)
144
145
146def add_funcarg_pseudo_fixture_def(
147    collector, metafunc: "Metafunc", fixturemanager: "FixtureManager"
148) -> None:
149    # This function will transform all collected calls to functions
150    # if they use direct funcargs (i.e. direct parametrization)
151    # because we want later test execution to be able to rely on
152    # an existing FixtureDef structure for all arguments.
153    # XXX we can probably avoid this algorithm  if we modify CallSpec2
154    # to directly care for creating the fixturedefs within its methods.
155    if not metafunc._calls[0].funcargs:
156        # This function call does not have direct parametrization.
157        return
158    # Collect funcargs of all callspecs into a list of values.
159    arg2params = {}  # type: Dict[str, List[object]]
160    arg2scope = {}  # type: Dict[str, _Scope]
161    for callspec in metafunc._calls:
162        for argname, argvalue in callspec.funcargs.items():
163            assert argname not in callspec.params
164            callspec.params[argname] = argvalue
165            arg2params_list = arg2params.setdefault(argname, [])
166            callspec.indices[argname] = len(arg2params_list)
167            arg2params_list.append(argvalue)
168            if argname not in arg2scope:
169                scopenum = callspec._arg2scopenum.get(argname, scopenum_function)
170                arg2scope[argname] = scopes[scopenum]
171        callspec.funcargs.clear()
172
173    # Register artificial FixtureDef's so that later at test execution
174    # time we can rely on a proper FixtureDef to exist for fixture setup.
175    arg2fixturedefs = metafunc._arg2fixturedefs
176    for argname, valuelist in arg2params.items():
177        # If we have a scope that is higher than function, we need
178        # to make sure we only ever create an according fixturedef on
179        # a per-scope basis. We thus store and cache the fixturedef on the
180        # node related to the scope.
181        scope = arg2scope[argname]
182        node = None
183        if scope != "function":
184            node = get_scope_node(collector, scope)
185            if node is None:
186                assert scope == "class" and isinstance(collector, _pytest.python.Module)
187                # Use module-level collector for class-scope (for now).
188                node = collector
189        if node and argname in node._name2pseudofixturedef:
190            arg2fixturedefs[argname] = [node._name2pseudofixturedef[argname]]
191        else:
192            fixturedef = FixtureDef(
193                fixturemanager=fixturemanager,
194                baseid="",
195                argname=argname,
196                func=get_direct_param_fixture_func,
197                scope=arg2scope[argname],
198                params=valuelist,
199                unittest=False,
200                ids=None,
201            )
202            arg2fixturedefs[argname] = [fixturedef]
203            if node is not None:
204                node._name2pseudofixturedef[argname] = fixturedef
205
206
207def getfixturemarker(obj: object) -> Optional["FixtureFunctionMarker"]:
208    """Return fixturemarker or None if it doesn't exist or raised
209    exceptions."""
210    try:
211        fixturemarker = getattr(
212            obj, "_pytestfixturefunction", None
213        )  # type: Optional[FixtureFunctionMarker]
214    except TEST_OUTCOME:
215        # some objects raise errors like request (from flask import request)
216        # we don't expect them to be fixture functions
217        return None
218    return fixturemarker
219
220
221# Parametrized fixture key, helper alias for code below.
222_Key = Tuple[object, ...]
223
224
225def get_parametrized_fixture_keys(item: "nodes.Item", scopenum: int) -> Iterator[_Key]:
226    """Return list of keys for all parametrized arguments which match
227    the specified scope. """
228    assert scopenum < scopenum_function  # function
229    try:
230        callspec = item.callspec  # type: ignore[attr-defined]
231    except AttributeError:
232        pass
233    else:
234        cs = callspec  # type: CallSpec2
235        # cs.indices.items() is random order of argnames.  Need to
236        # sort this so that different calls to
237        # get_parametrized_fixture_keys will be deterministic.
238        for argname, param_index in sorted(cs.indices.items()):
239            if cs._arg2scopenum[argname] != scopenum:
240                continue
241            if scopenum == 0:  # session
242                key = (argname, param_index)  # type: _Key
243            elif scopenum == 1:  # package
244                key = (argname, param_index, item.fspath.dirpath())
245            elif scopenum == 2:  # module
246                key = (argname, param_index, item.fspath)
247            elif scopenum == 3:  # class
248                item_cls = item.cls  # type: ignore[attr-defined]
249                key = (argname, param_index, item.fspath, item_cls)
250            yield key
251
252
253# Algorithm for sorting on a per-parametrized resource setup basis.
254# It is called for scopenum==0 (session) first and performs sorting
255# down to the lower scopes such as to minimize number of "high scope"
256# setups and teardowns.
257
258
259def reorder_items(items: "Sequence[nodes.Item]") -> "List[nodes.Item]":
260    argkeys_cache = {}  # type: Dict[int, Dict[nodes.Item, Dict[_Key, None]]]
261    items_by_argkey = {}  # type: Dict[int, Dict[_Key, Deque[nodes.Item]]]
262    for scopenum in range(0, scopenum_function):
263        d = {}  # type: Dict[nodes.Item, Dict[_Key, None]]
264        argkeys_cache[scopenum] = d
265        item_d = defaultdict(deque)  # type: Dict[_Key, Deque[nodes.Item]]
266        items_by_argkey[scopenum] = item_d
267        for item in items:
268            # cast is a workaround for https://github.com/python/typeshed/issues/3800.
269            keys = cast(
270                "Dict[_Key, None]",
271                order_preserving_dict.fromkeys(
272                    get_parametrized_fixture_keys(item, scopenum), None
273                ),
274            )
275            if keys:
276                d[item] = keys
277                for key in keys:
278                    item_d[key].append(item)
279    # cast is a workaround for https://github.com/python/typeshed/issues/3800.
280    items_dict = cast(
281        "Dict[nodes.Item, None]", order_preserving_dict.fromkeys(items, None)
282    )
283    return list(reorder_items_atscope(items_dict, argkeys_cache, items_by_argkey, 0))
284
285
286def fix_cache_order(
287    item: "nodes.Item",
288    argkeys_cache: "Dict[int, Dict[nodes.Item, Dict[_Key, None]]]",
289    items_by_argkey: "Dict[int, Dict[_Key, Deque[nodes.Item]]]",
290) -> None:
291    for scopenum in range(0, scopenum_function):
292        for key in argkeys_cache[scopenum].get(item, []):
293            items_by_argkey[scopenum][key].appendleft(item)
294
295
296def reorder_items_atscope(
297    items: "Dict[nodes.Item, None]",
298    argkeys_cache: "Dict[int, Dict[nodes.Item, Dict[_Key, None]]]",
299    items_by_argkey: "Dict[int, Dict[_Key, Deque[nodes.Item]]]",
300    scopenum: int,
301) -> "Dict[nodes.Item, None]":
302    if scopenum >= scopenum_function or len(items) < 3:
303        return items
304    ignore = set()  # type: Set[Optional[_Key]]
305    items_deque = deque(items)
306    items_done = order_preserving_dict()  # type: Dict[nodes.Item, None]
307    scoped_items_by_argkey = items_by_argkey[scopenum]
308    scoped_argkeys_cache = argkeys_cache[scopenum]
309    while items_deque:
310        no_argkey_group = order_preserving_dict()  # type: Dict[nodes.Item, None]
311        slicing_argkey = None
312        while items_deque:
313            item = items_deque.popleft()
314            if item in items_done or item in no_argkey_group:
315                continue
316            argkeys = order_preserving_dict.fromkeys(
317                (k for k in scoped_argkeys_cache.get(item, []) if k not in ignore), None
318            )
319            if not argkeys:
320                no_argkey_group[item] = None
321            else:
322                slicing_argkey, _ = argkeys.popitem()
323                # We don't have to remove relevant items from later in the
324                # deque because they'll just be ignored.
325                matching_items = [
326                    i for i in scoped_items_by_argkey[slicing_argkey] if i in items
327                ]
328                for i in reversed(matching_items):
329                    fix_cache_order(i, argkeys_cache, items_by_argkey)
330                    items_deque.appendleft(i)
331                break
332        if no_argkey_group:
333            no_argkey_group = reorder_items_atscope(
334                no_argkey_group, argkeys_cache, items_by_argkey, scopenum + 1
335            )
336            for item in no_argkey_group:
337                items_done[item] = None
338        ignore.add(slicing_argkey)
339    return items_done
340
341
342def fillfixtures(function: "Function") -> None:
343    """Fill missing funcargs for a test function."""
344    warnings.warn(FILLFUNCARGS, stacklevel=2)
345    try:
346        request = function._request
347    except AttributeError:
348        # XXX this special code path is only expected to execute
349        # with the oejskit plugin.  It uses classes with funcargs
350        # and we thus have to work a bit to allow this.
351        fm = function.session._fixturemanager
352        assert function.parent is not None
353        fi = fm.getfixtureinfo(function.parent, function.obj, None)
354        function._fixtureinfo = fi
355        request = function._request = FixtureRequest(function)
356        request._fillfixtures()
357        # Prune out funcargs for jstests.
358        newfuncargs = {}
359        for name in fi.argnames:
360            newfuncargs[name] = function.funcargs[name]
361        function.funcargs = newfuncargs
362    else:
363        request._fillfixtures()
364
365
366def get_direct_param_fixture_func(request):
367    return request.param
368
369
370@attr.s(slots=True)
371class FuncFixtureInfo:
372    # Original function argument names.
373    argnames = attr.ib(type=Tuple[str, ...])
374    # Argnames that function immediately requires. These include argnames +
375    # fixture names specified via usefixtures and via autouse=True in fixture
376    # definitions.
377    initialnames = attr.ib(type=Tuple[str, ...])
378    names_closure = attr.ib(type=List[str])
379    name2fixturedefs = attr.ib(type=Dict[str, Sequence["FixtureDef[Any]"]])
380
381    def prune_dependency_tree(self) -> None:
382        """Recompute names_closure from initialnames and name2fixturedefs.
383
384        Can only reduce names_closure, which means that the new closure will
385        always be a subset of the old one. The order is preserved.
386
387        This method is needed because direct parametrization may shadow some
388        of the fixtures that were included in the originally built dependency
389        tree. In this way the dependency tree can get pruned, and the closure
390        of argnames may get reduced.
391        """
392        closure = set()  # type: Set[str]
393        working_set = set(self.initialnames)
394        while working_set:
395            argname = working_set.pop()
396            # Argname may be smth not included in the original names_closure,
397            # in which case we ignore it. This currently happens with pseudo
398            # FixtureDefs which wrap 'get_direct_param_fixture_func(request)'.
399            # So they introduce the new dependency 'request' which might have
400            # been missing in the original tree (closure).
401            if argname not in closure and argname in self.names_closure:
402                closure.add(argname)
403                if argname in self.name2fixturedefs:
404                    working_set.update(self.name2fixturedefs[argname][-1].argnames)
405
406        self.names_closure[:] = sorted(closure, key=self.names_closure.index)
407
408
409class FixtureRequest:
410    """A request for a fixture from a test or fixture function.
411
412    A request object gives access to the requesting test context and has
413    an optional ``param`` attribute in case the fixture is parametrized
414    indirectly.
415    """
416
417    def __init__(self, pyfuncitem) -> None:
418        self._pyfuncitem = pyfuncitem
419        #: Fixture for which this request is being performed.
420        self.fixturename = None  # type: Optional[str]
421        #: Scope string, one of "function", "class", "module", "session".
422        self.scope = "function"  # type: _Scope
423        self._fixture_defs = {}  # type: Dict[str, FixtureDef[Any]]
424        fixtureinfo = pyfuncitem._fixtureinfo  # type: FuncFixtureInfo
425        self._arg2fixturedefs = fixtureinfo.name2fixturedefs.copy()
426        self._arg2index = {}  # type: Dict[str, int]
427        self._fixturemanager = (
428            pyfuncitem.session._fixturemanager
429        )  # type: FixtureManager
430
431    @property
432    def fixturenames(self) -> List[str]:
433        """Names of all active fixtures in this request."""
434        result = list(self._pyfuncitem._fixtureinfo.names_closure)
435        result.extend(set(self._fixture_defs).difference(result))
436        return result
437
438    @property
439    def node(self):
440        """Underlying collection node (depends on current request scope)."""
441        return self._getscopeitem(self.scope)
442
443    def _getnextfixturedef(self, argname: str) -> "FixtureDef[Any]":
444        fixturedefs = self._arg2fixturedefs.get(argname, None)
445        if fixturedefs is None:
446            # We arrive here because of a dynamic call to
447            # getfixturevalue(argname) usage which was naturally
448            # not known at parsing/collection time.
449            assert self._pyfuncitem.parent is not None
450            parentid = self._pyfuncitem.parent.nodeid
451            fixturedefs = self._fixturemanager.getfixturedefs(argname, parentid)
452            # TODO: Fix this type ignore. Either add assert or adjust types.
453            #       Can this be None here?
454            self._arg2fixturedefs[argname] = fixturedefs  # type: ignore[assignment]
455        # fixturedefs list is immutable so we maintain a decreasing index.
456        index = self._arg2index.get(argname, 0) - 1
457        if fixturedefs is None or (-index > len(fixturedefs)):
458            raise FixtureLookupError(argname, self)
459        self._arg2index[argname] = index
460        return fixturedefs[index]
461
462    @property
463    def config(self) -> Config:
464        """The pytest config object associated with this request."""
465        return self._pyfuncitem.config  # type: ignore[no-any-return] # noqa: F723
466
467    @property
468    def function(self):
469        """Test function object if the request has a per-function scope."""
470        if self.scope != "function":
471            raise AttributeError(
472                "function not available in {}-scoped context".format(self.scope)
473            )
474        return self._pyfuncitem.obj
475
476    @property
477    def cls(self):
478        """Class (can be None) where the test function was collected."""
479        if self.scope not in ("class", "function"):
480            raise AttributeError(
481                "cls not available in {}-scoped context".format(self.scope)
482            )
483        clscol = self._pyfuncitem.getparent(_pytest.python.Class)
484        if clscol:
485            return clscol.obj
486
487    @property
488    def instance(self):
489        """Instance (can be None) on which test function was collected."""
490        # unittest support hack, see _pytest.unittest.TestCaseFunction.
491        try:
492            return self._pyfuncitem._testcase
493        except AttributeError:
494            function = getattr(self, "function", None)
495            return getattr(function, "__self__", None)
496
497    @property
498    def module(self):
499        """Python module object where the test function was collected."""
500        if self.scope not in ("function", "class", "module"):
501            raise AttributeError(
502                "module not available in {}-scoped context".format(self.scope)
503            )
504        return self._pyfuncitem.getparent(_pytest.python.Module).obj
505
506    @property
507    def fspath(self) -> py.path.local:
508        """The file system path of the test module which collected this test."""
509        if self.scope not in ("function", "class", "module", "package"):
510            raise AttributeError(
511                "module not available in {}-scoped context".format(self.scope)
512            )
513        # TODO: Remove ignore once _pyfuncitem is properly typed.
514        return self._pyfuncitem.fspath  # type: ignore
515
516    @property
517    def keywords(self):
518        """Keywords/markers dictionary for the underlying node."""
519        return self.node.keywords
520
521    @property
522    def session(self):
523        """Pytest session object."""
524        return self._pyfuncitem.session
525
526    def addfinalizer(self, finalizer: Callable[[], object]) -> None:
527        """Add finalizer/teardown function to be called after the last test
528        within the requesting test context finished execution."""
529        # XXX usually this method is shadowed by fixturedef specific ones.
530        self._addfinalizer(finalizer, scope=self.scope)
531
532    def _addfinalizer(self, finalizer: Callable[[], object], scope) -> None:
533        colitem = self._getscopeitem(scope)
534        self._pyfuncitem.session._setupstate.addfinalizer(
535            finalizer=finalizer, colitem=colitem
536        )
537
538    def applymarker(self, marker) -> None:
539        """Apply a marker to a single test function invocation.
540
541        This method is useful if you don't want to have a keyword/marker
542        on all function invocations.
543
544        :param marker:
545            A :py:class:`_pytest.mark.MarkDecorator` object created by a call
546            to ``pytest.mark.NAME(...)``.
547        """
548        self.node.add_marker(marker)
549
550    def raiseerror(self, msg: Optional[str]) -> "NoReturn":
551        """Raise a FixtureLookupError with the given message."""
552        raise self._fixturemanager.FixtureLookupError(None, self, msg)
553
554    def _fillfixtures(self) -> None:
555        item = self._pyfuncitem
556        fixturenames = getattr(item, "fixturenames", self.fixturenames)
557        for argname in fixturenames:
558            if argname not in item.funcargs:
559                item.funcargs[argname] = self.getfixturevalue(argname)
560
561    def getfixturevalue(self, argname: str) -> Any:
562        """Dynamically run a named fixture function.
563
564        Declaring fixtures via function argument is recommended where possible.
565        But if you can only decide whether to use another fixture at test
566        setup time, you may use this function to retrieve it inside a fixture
567        or test function body.
568
569        :raises pytest.FixtureLookupError:
570            If the given fixture could not be found.
571        """
572        fixturedef = self._get_active_fixturedef(argname)
573        assert fixturedef.cached_result is not None
574        return fixturedef.cached_result[0]
575
576    def _get_active_fixturedef(
577        self, argname: str
578    ) -> Union["FixtureDef[object]", PseudoFixtureDef[object]]:
579        try:
580            return self._fixture_defs[argname]
581        except KeyError:
582            try:
583                fixturedef = self._getnextfixturedef(argname)
584            except FixtureLookupError:
585                if argname == "request":
586                    cached_result = (self, [0], None)
587                    scope = "function"  # type: _Scope
588                    return PseudoFixtureDef(cached_result, scope)
589                raise
590        # Remove indent to prevent the python3 exception
591        # from leaking into the call.
592        self._compute_fixture_value(fixturedef)
593        self._fixture_defs[argname] = fixturedef
594        return fixturedef
595
596    def _get_fixturestack(self) -> List["FixtureDef[Any]"]:
597        current = self
598        values = []  # type: List[FixtureDef[Any]]
599        while 1:
600            fixturedef = getattr(current, "_fixturedef", None)
601            if fixturedef is None:
602                values.reverse()
603                return values
604            values.append(fixturedef)
605            assert isinstance(current, SubRequest)
606            current = current._parent_request
607
608    def _compute_fixture_value(self, fixturedef: "FixtureDef[object]") -> None:
609        """Create a SubRequest based on "self" and call the execute method
610        of the given FixtureDef object.
611
612        This will force the FixtureDef object to throw away any previous
613        results and compute a new fixture value, which will be stored into
614        the FixtureDef object itself.
615        """
616        # prepare a subrequest object before calling fixture function
617        # (latter managed by fixturedef)
618        argname = fixturedef.argname
619        funcitem = self._pyfuncitem
620        scope = fixturedef.scope
621        try:
622            param = funcitem.callspec.getparam(argname)
623        except (AttributeError, ValueError):
624            param = NOTSET
625            param_index = 0
626            has_params = fixturedef.params is not None
627            fixtures_not_supported = getattr(funcitem, "nofuncargs", False)
628            if has_params and fixtures_not_supported:
629                msg = (
630                    "{name} does not support fixtures, maybe unittest.TestCase subclass?\n"
631                    "Node id: {nodeid}\n"
632                    "Function type: {typename}"
633                ).format(
634                    name=funcitem.name,
635                    nodeid=funcitem.nodeid,
636                    typename=type(funcitem).__name__,
637                )
638                fail(msg, pytrace=False)
639            if has_params:
640                frame = inspect.stack()[3]
641                frameinfo = inspect.getframeinfo(frame[0])
642                source_path = py.path.local(frameinfo.filename)
643                source_lineno = frameinfo.lineno
644                rel_source_path = source_path.relto(funcitem.config.rootdir)
645                if rel_source_path:
646                    source_path_str = rel_source_path
647                else:
648                    source_path_str = str(source_path)
649                msg = (
650                    "The requested fixture has no parameter defined for test:\n"
651                    "    {}\n\n"
652                    "Requested fixture '{}' defined in:\n{}"
653                    "\n\nRequested here:\n{}:{}".format(
654                        funcitem.nodeid,
655                        fixturedef.argname,
656                        getlocation(fixturedef.func, funcitem.config.rootdir),
657                        source_path_str,
658                        source_lineno,
659                    )
660                )
661                fail(msg, pytrace=False)
662        else:
663            param_index = funcitem.callspec.indices[argname]
664            # If a parametrize invocation set a scope it will override
665            # the static scope defined with the fixture function.
666            paramscopenum = funcitem.callspec._arg2scopenum.get(argname)
667            if paramscopenum is not None:
668                scope = scopes[paramscopenum]
669
670        subrequest = SubRequest(self, scope, param, param_index, fixturedef)
671
672        # Check if a higher-level scoped fixture accesses a lower level one.
673        subrequest._check_scope(argname, self.scope, scope)
674        try:
675            # Call the fixture function.
676            fixturedef.execute(request=subrequest)
677        finally:
678            self._schedule_finalizers(fixturedef, subrequest)
679
680    def _schedule_finalizers(
681        self, fixturedef: "FixtureDef[object]", subrequest: "SubRequest"
682    ) -> None:
683        # If fixture function failed it might have registered finalizers.
684        self.session._setupstate.addfinalizer(
685            functools.partial(fixturedef.finish, request=subrequest), subrequest.node
686        )
687
688    def _check_scope(self, argname, invoking_scope: "_Scope", requested_scope) -> None:
689        if argname == "request":
690            return
691        if scopemismatch(invoking_scope, requested_scope):
692            # Try to report something helpful.
693            lines = self._factorytraceback()
694            fail(
695                "ScopeMismatch: You tried to access the %r scoped "
696                "fixture %r with a %r scoped request object, "
697                "involved factories\n%s"
698                % ((requested_scope, argname, invoking_scope, "\n".join(lines))),
699                pytrace=False,
700            )
701
702    def _factorytraceback(self) -> List[str]:
703        lines = []
704        for fixturedef in self._get_fixturestack():
705            factory = fixturedef.func
706            fs, lineno = getfslineno(factory)
707            p = self._pyfuncitem.session.fspath.bestrelpath(fs)
708            args = _format_args(factory)
709            lines.append("%s:%d:  def %s%s" % (p, lineno + 1, factory.__name__, args))
710        return lines
711
712    def _getscopeitem(self, scope):
713        if scope == "function":
714            # This might also be a non-function Item despite its attribute name.
715            return self._pyfuncitem
716        if scope == "package":
717            # FIXME: _fixturedef is not defined on FixtureRequest (this class),
718            # but on FixtureRequest (a subclass).
719            node = get_scope_package(self._pyfuncitem, self._fixturedef)  # type: ignore[attr-defined]
720        else:
721            node = get_scope_node(self._pyfuncitem, scope)
722        if node is None and scope == "class":
723            # Fallback to function item itself.
724            node = self._pyfuncitem
725        assert node, 'Could not obtain a node for scope "{}" for function {!r}'.format(
726            scope, self._pyfuncitem
727        )
728        return node
729
730    def __repr__(self) -> str:
731        return "<FixtureRequest for %r>" % (self.node)
732
733
734@final
735class SubRequest(FixtureRequest):
736    """A sub request for handling getting a fixture from a test function/fixture."""
737
738    def __init__(
739        self,
740        request: "FixtureRequest",
741        scope: "_Scope",
742        param,
743        param_index: int,
744        fixturedef: "FixtureDef[object]",
745    ) -> None:
746        self._parent_request = request
747        self.fixturename = fixturedef.argname
748        if param is not NOTSET:
749            self.param = param
750        self.param_index = param_index
751        self.scope = scope
752        self._fixturedef = fixturedef
753        self._pyfuncitem = request._pyfuncitem
754        self._fixture_defs = request._fixture_defs
755        self._arg2fixturedefs = request._arg2fixturedefs
756        self._arg2index = request._arg2index
757        self._fixturemanager = request._fixturemanager
758
759    def __repr__(self) -> str:
760        return "<SubRequest {!r} for {!r}>".format(self.fixturename, self._pyfuncitem)
761
762    def addfinalizer(self, finalizer: Callable[[], object]) -> None:
763        self._fixturedef.addfinalizer(finalizer)
764
765    def _schedule_finalizers(
766        self, fixturedef: "FixtureDef[object]", subrequest: "SubRequest"
767    ) -> None:
768        # If the executing fixturedef was not explicitly requested in the argument list (via
769        # getfixturevalue inside the fixture call) then ensure this fixture def will be finished
770        # first.
771        if fixturedef.argname not in self.fixturenames:
772            fixturedef.addfinalizer(
773                functools.partial(self._fixturedef.finish, request=self)
774            )
775        super()._schedule_finalizers(fixturedef, subrequest)
776
777
778scopes = ["session", "package", "module", "class", "function"]  # type: List[_Scope]
779scopenum_function = scopes.index("function")
780
781
782def scopemismatch(currentscope: "_Scope", newscope: "_Scope") -> bool:
783    return scopes.index(newscope) > scopes.index(currentscope)
784
785
786def scope2index(scope: str, descr: str, where: Optional[str] = None) -> int:
787    """Look up the index of ``scope`` and raise a descriptive value error
788    if not defined."""
789    strscopes = scopes  # type: Sequence[str]
790    try:
791        return strscopes.index(scope)
792    except ValueError:
793        fail(
794            "{} {}got an unexpected scope value '{}'".format(
795                descr, "from {} ".format(where) if where else "", scope
796            ),
797            pytrace=False,
798        )
799
800
801@final
802class FixtureLookupError(LookupError):
803    """Could not return a requested fixture (missing or invalid)."""
804
805    def __init__(
806        self, argname: Optional[str], request: FixtureRequest, msg: Optional[str] = None
807    ) -> None:
808        self.argname = argname
809        self.request = request
810        self.fixturestack = request._get_fixturestack()
811        self.msg = msg
812
813    def formatrepr(self) -> "FixtureLookupErrorRepr":
814        tblines = []  # type: List[str]
815        addline = tblines.append
816        stack = [self.request._pyfuncitem.obj]
817        stack.extend(map(lambda x: x.func, self.fixturestack))
818        msg = self.msg
819        if msg is not None:
820            # The last fixture raise an error, let's present
821            # it at the requesting side.
822            stack = stack[:-1]
823        for function in stack:
824            fspath, lineno = getfslineno(function)
825            try:
826                lines, _ = inspect.getsourcelines(get_real_func(function))
827            except (OSError, IndexError, TypeError):
828                error_msg = "file %s, line %s: source code not available"
829                addline(error_msg % (fspath, lineno + 1))
830            else:
831                addline("file {}, line {}".format(fspath, lineno + 1))
832                for i, line in enumerate(lines):
833                    line = line.rstrip()
834                    addline("  " + line)
835                    if line.lstrip().startswith("def"):
836                        break
837
838        if msg is None:
839            fm = self.request._fixturemanager
840            available = set()
841            parentid = self.request._pyfuncitem.parent.nodeid
842            for name, fixturedefs in fm._arg2fixturedefs.items():
843                faclist = list(fm._matchfactories(fixturedefs, parentid))
844                if faclist:
845                    available.add(name)
846            if self.argname in available:
847                msg = " recursive dependency involving fixture '{}' detected".format(
848                    self.argname
849                )
850            else:
851                msg = "fixture '{}' not found".format(self.argname)
852            msg += "\n available fixtures: {}".format(", ".join(sorted(available)))
853            msg += "\n use 'pytest --fixtures [testpath]' for help on them."
854
855        return FixtureLookupErrorRepr(fspath, lineno, tblines, msg, self.argname)
856
857
858class FixtureLookupErrorRepr(TerminalRepr):
859    def __init__(
860        self,
861        filename: Union[str, py.path.local],
862        firstlineno: int,
863        tblines: Sequence[str],
864        errorstring: str,
865        argname: Optional[str],
866    ) -> None:
867        self.tblines = tblines
868        self.errorstring = errorstring
869        self.filename = filename
870        self.firstlineno = firstlineno
871        self.argname = argname
872
873    def toterminal(self, tw: TerminalWriter) -> None:
874        # tw.line("FixtureLookupError: %s" %(self.argname), red=True)
875        for tbline in self.tblines:
876            tw.line(tbline.rstrip())
877        lines = self.errorstring.split("\n")
878        if lines:
879            tw.line(
880                "{}       {}".format(FormattedExcinfo.fail_marker, lines[0].strip()),
881                red=True,
882            )
883            for line in lines[1:]:
884                tw.line(
885                    "{}       {}".format(FormattedExcinfo.flow_marker, line.strip()),
886                    red=True,
887                )
888        tw.line()
889        tw.line("%s:%d" % (self.filename, self.firstlineno + 1))
890
891
892def fail_fixturefunc(fixturefunc, msg: str) -> "NoReturn":
893    fs, lineno = getfslineno(fixturefunc)
894    location = "{}:{}".format(fs, lineno + 1)
895    source = _pytest._code.Source(fixturefunc)
896    fail(msg + ":\n\n" + str(source.indent()) + "\n" + location, pytrace=False)
897
898
899def call_fixture_func(
900    fixturefunc: "_FixtureFunc[_FixtureValue]", request: FixtureRequest, kwargs
901) -> _FixtureValue:
902    if is_generator(fixturefunc):
903        fixturefunc = cast(
904            Callable[..., Generator[_FixtureValue, None, None]], fixturefunc
905        )
906        generator = fixturefunc(**kwargs)
907        try:
908            fixture_result = next(generator)
909        except StopIteration:
910            raise ValueError(
911                "{} did not yield a value".format(request.fixturename)
912            ) from None
913        finalizer = functools.partial(_teardown_yield_fixture, fixturefunc, generator)
914        request.addfinalizer(finalizer)
915    else:
916        fixturefunc = cast(Callable[..., _FixtureValue], fixturefunc)
917        fixture_result = fixturefunc(**kwargs)
918    return fixture_result
919
920
921def _teardown_yield_fixture(fixturefunc, it) -> None:
922    """Execute the teardown of a fixture function by advancing the iterator
923    after the yield and ensure the iteration ends (if not it means there is
924    more than one yield in the function)."""
925    try:
926        next(it)
927    except StopIteration:
928        pass
929    else:
930        fail_fixturefunc(fixturefunc, "fixture function has more than one 'yield'")
931
932
933def _eval_scope_callable(
934    scope_callable: "Callable[[str, Config], _Scope]",
935    fixture_name: str,
936    config: Config,
937) -> "_Scope":
938    try:
939        # Type ignored because there is no typing mechanism to specify
940        # keyword arguments, currently.
941        result = scope_callable(fixture_name=fixture_name, config=config)  # type: ignore[call-arg]
942    except Exception as e:
943        raise TypeError(
944            "Error evaluating {} while defining fixture '{}'.\n"
945            "Expected a function with the signature (*, fixture_name, config)".format(
946                scope_callable, fixture_name
947            )
948        ) from e
949    if not isinstance(result, str):
950        fail(
951            "Expected {} to return a 'str' while defining fixture '{}', but it returned:\n"
952            "{!r}".format(scope_callable, fixture_name, result),
953            pytrace=False,
954        )
955    return result
956
957
958@final
959class FixtureDef(Generic[_FixtureValue]):
960    """A container for a factory definition."""
961
962    def __init__(
963        self,
964        fixturemanager: "FixtureManager",
965        baseid,
966        argname: str,
967        func: "_FixtureFunc[_FixtureValue]",
968        scope: "Union[_Scope, Callable[[str, Config], _Scope]]",
969        params: Optional[Sequence[object]],
970        unittest: bool = False,
971        ids: Optional[
972            Union[
973                Tuple[Union[None, str, float, int, bool], ...],
974                Callable[[Any], Optional[object]],
975            ]
976        ] = None,
977    ) -> None:
978        self._fixturemanager = fixturemanager
979        self.baseid = baseid or ""
980        self.has_location = baseid is not None
981        self.func = func
982        self.argname = argname
983        if callable(scope):
984            scope_ = _eval_scope_callable(scope, argname, fixturemanager.config)
985        else:
986            scope_ = scope
987        self.scopenum = scope2index(
988            # TODO: Check if the `or` here is really necessary.
989            scope_ or "function",  # type: ignore[unreachable]
990            descr="Fixture '{}'".format(func.__name__),
991            where=baseid,
992        )
993        self.scope = scope_
994        self.params = params  # type: Optional[Sequence[object]]
995        self.argnames = getfuncargnames(
996            func, name=argname, is_method=unittest
997        )  # type: Tuple[str, ...]
998        self.unittest = unittest
999        self.ids = ids
1000        self.cached_result = None  # type: Optional[_FixtureCachedResult[_FixtureValue]]
1001        self._finalizers = []  # type: List[Callable[[], object]]
1002
1003    def addfinalizer(self, finalizer: Callable[[], object]) -> None:
1004        self._finalizers.append(finalizer)
1005
1006    def finish(self, request: SubRequest) -> None:
1007        exc = None
1008        try:
1009            while self._finalizers:
1010                try:
1011                    func = self._finalizers.pop()
1012                    func()
1013                except BaseException as e:
1014                    # XXX Only first exception will be seen by user,
1015                    #     ideally all should be reported.
1016                    if exc is None:
1017                        exc = e
1018            if exc:
1019                raise exc
1020        finally:
1021            hook = self._fixturemanager.session.gethookproxy(request.node.fspath)
1022            hook.pytest_fixture_post_finalizer(fixturedef=self, request=request)
1023            # Even if finalization fails, we invalidate the cached fixture
1024            # value and remove all finalizers because they may be bound methods
1025            # which will keep instances alive.
1026            self.cached_result = None
1027            self._finalizers = []
1028
1029    def execute(self, request: SubRequest) -> _FixtureValue:
1030        # Get required arguments and register our own finish()
1031        # with their finalization.
1032        for argname in self.argnames:
1033            fixturedef = request._get_active_fixturedef(argname)
1034            if argname != "request":
1035                # PseudoFixtureDef is only for "request".
1036                assert isinstance(fixturedef, FixtureDef)
1037                fixturedef.addfinalizer(functools.partial(self.finish, request=request))
1038
1039        my_cache_key = self.cache_key(request)
1040        if self.cached_result is not None:
1041            # note: comparison with `==` can fail (or be expensive) for e.g.
1042            # numpy arrays (#6497).
1043            cache_key = self.cached_result[1]
1044            if my_cache_key is cache_key:
1045                if self.cached_result[2] is not None:
1046                    _, val, tb = self.cached_result[2]
1047                    raise val.with_traceback(tb)
1048                else:
1049                    result = self.cached_result[0]
1050                    return result
1051            # We have a previous but differently parametrized fixture instance
1052            # so we need to tear it down before creating a new one.
1053            self.finish(request)
1054            assert self.cached_result is None
1055
1056        hook = self._fixturemanager.session.gethookproxy(request.node.fspath)
1057        result = hook.pytest_fixture_setup(fixturedef=self, request=request)
1058        return result
1059
1060    def cache_key(self, request: SubRequest) -> object:
1061        return request.param_index if not hasattr(request, "param") else request.param
1062
1063    def __repr__(self) -> str:
1064        return "<FixtureDef argname={!r} scope={!r} baseid={!r}>".format(
1065            self.argname, self.scope, self.baseid
1066        )
1067
1068
1069def resolve_fixture_function(
1070    fixturedef: FixtureDef[_FixtureValue], request: FixtureRequest
1071) -> "_FixtureFunc[_FixtureValue]":
1072    """Get the actual callable that can be called to obtain the fixture
1073    value, dealing with unittest-specific instances and bound methods."""
1074    fixturefunc = fixturedef.func
1075    if fixturedef.unittest:
1076        if request.instance is not None:
1077            # Bind the unbound method to the TestCase instance.
1078            fixturefunc = fixturedef.func.__get__(request.instance)  # type: ignore[union-attr]
1079    else:
1080        # The fixture function needs to be bound to the actual
1081        # request.instance so that code working with "fixturedef" behaves
1082        # as expected.
1083        if request.instance is not None:
1084            # Handle the case where fixture is defined not in a test class, but some other class
1085            # (for example a plugin class with a fixture), see #2270.
1086            if hasattr(fixturefunc, "__self__") and not isinstance(
1087                request.instance, fixturefunc.__self__.__class__  # type: ignore[union-attr]
1088            ):
1089                return fixturefunc
1090            fixturefunc = getimfunc(fixturedef.func)
1091            if fixturefunc != fixturedef.func:
1092                fixturefunc = fixturefunc.__get__(request.instance)  # type: ignore[union-attr]
1093    return fixturefunc
1094
1095
1096def pytest_fixture_setup(
1097    fixturedef: FixtureDef[_FixtureValue], request: SubRequest
1098) -> _FixtureValue:
1099    """Execution of fixture setup."""
1100    kwargs = {}
1101    for argname in fixturedef.argnames:
1102        fixdef = request._get_active_fixturedef(argname)
1103        assert fixdef.cached_result is not None
1104        result, arg_cache_key, exc = fixdef.cached_result
1105        request._check_scope(argname, request.scope, fixdef.scope)
1106        kwargs[argname] = result
1107
1108    fixturefunc = resolve_fixture_function(fixturedef, request)
1109    my_cache_key = fixturedef.cache_key(request)
1110    try:
1111        result = call_fixture_func(fixturefunc, request, kwargs)
1112    except TEST_OUTCOME:
1113        exc_info = sys.exc_info()
1114        assert exc_info[0] is not None
1115        fixturedef.cached_result = (None, my_cache_key, exc_info)
1116        raise
1117    fixturedef.cached_result = (result, my_cache_key, None)
1118    return result
1119
1120
1121def _ensure_immutable_ids(
1122    ids: Optional[
1123        Union[
1124            Iterable[Union[None, str, float, int, bool]],
1125            Callable[[Any], Optional[object]],
1126        ]
1127    ],
1128) -> Optional[
1129    Union[
1130        Tuple[Union[None, str, float, int, bool], ...],
1131        Callable[[Any], Optional[object]],
1132    ]
1133]:
1134    if ids is None:
1135        return None
1136    if callable(ids):
1137        return ids
1138    return tuple(ids)
1139
1140
1141def _params_converter(
1142    params: Optional[Iterable[object]],
1143) -> Optional[Tuple[object, ...]]:
1144    return tuple(params) if params is not None else None
1145
1146
1147def wrap_function_to_error_out_if_called_directly(function, fixture_marker):
1148    """Wrap the given fixture function so we can raise an error about it being called directly,
1149    instead of used as an argument in a test function."""
1150    message = (
1151        'Fixture "{name}" called directly. Fixtures are not meant to be called directly,\n'
1152        "but are created automatically when test functions request them as parameters.\n"
1153        "See https://docs.pytest.org/en/stable/fixture.html for more information about fixtures, and\n"
1154        "https://docs.pytest.org/en/stable/deprecations.html#calling-fixtures-directly about how to update your code."
1155    ).format(name=fixture_marker.name or function.__name__)
1156
1157    @functools.wraps(function)
1158    def result(*args, **kwargs):
1159        fail(message, pytrace=False)
1160
1161    # Keep reference to the original function in our own custom attribute so we don't unwrap
1162    # further than this point and lose useful wrappings like @mock.patch (#3774).
1163    result.__pytest_wrapped__ = _PytestWrapper(function)  # type: ignore[attr-defined]
1164
1165    return result
1166
1167
1168@final
1169@attr.s(frozen=True)
1170class FixtureFunctionMarker:
1171    scope = attr.ib(type="Union[_Scope, Callable[[str, Config], _Scope]]")
1172    params = attr.ib(type=Optional[Tuple[object, ...]], converter=_params_converter)
1173    autouse = attr.ib(type=bool, default=False)
1174    ids = attr.ib(
1175        type=Union[
1176            Tuple[Union[None, str, float, int, bool], ...],
1177            Callable[[Any], Optional[object]],
1178        ],
1179        default=None,
1180        converter=_ensure_immutable_ids,
1181    )
1182    name = attr.ib(type=Optional[str], default=None)
1183
1184    def __call__(self, function: _FixtureFunction) -> _FixtureFunction:
1185        if inspect.isclass(function):
1186            raise ValueError("class fixtures not supported (maybe in the future)")
1187
1188        if getattr(function, "_pytestfixturefunction", False):
1189            raise ValueError(
1190                "fixture is being applied more than once to the same function"
1191            )
1192
1193        function = wrap_function_to_error_out_if_called_directly(function, self)
1194
1195        name = self.name or function.__name__
1196        if name == "request":
1197            location = getlocation(function)
1198            fail(
1199                "'request' is a reserved word for fixtures, use another name:\n  {}".format(
1200                    location
1201                ),
1202                pytrace=False,
1203            )
1204
1205        # Type ignored because https://github.com/python/mypy/issues/2087.
1206        function._pytestfixturefunction = self  # type: ignore[attr-defined]
1207        return function
1208
1209
1210@overload
1211def fixture(
1212    fixture_function: _FixtureFunction,
1213    *,
1214    scope: "Union[_Scope, Callable[[str, Config], _Scope]]" = ...,
1215    params: Optional[Iterable[object]] = ...,
1216    autouse: bool = ...,
1217    ids: Optional[
1218        Union[
1219            Iterable[Union[None, str, float, int, bool]],
1220            Callable[[Any], Optional[object]],
1221        ]
1222    ] = ...,
1223    name: Optional[str] = ...
1224) -> _FixtureFunction:
1225    ...
1226
1227
1228@overload  # noqa: F811
1229def fixture(  # noqa: F811
1230    fixture_function: None = ...,
1231    *,
1232    scope: "Union[_Scope, Callable[[str, Config], _Scope]]" = ...,
1233    params: Optional[Iterable[object]] = ...,
1234    autouse: bool = ...,
1235    ids: Optional[
1236        Union[
1237            Iterable[Union[None, str, float, int, bool]],
1238            Callable[[Any], Optional[object]],
1239        ]
1240    ] = ...,
1241    name: Optional[str] = None
1242) -> FixtureFunctionMarker:
1243    ...
1244
1245
1246def fixture(  # noqa: F811
1247    fixture_function: Optional[_FixtureFunction] = None,
1248    *,
1249    scope: "Union[_Scope, Callable[[str, Config], _Scope]]" = "function",
1250    params: Optional[Iterable[object]] = None,
1251    autouse: bool = False,
1252    ids: Optional[
1253        Union[
1254            Iterable[Union[None, str, float, int, bool]],
1255            Callable[[Any], Optional[object]],
1256        ]
1257    ] = None,
1258    name: Optional[str] = None
1259) -> Union[FixtureFunctionMarker, _FixtureFunction]:
1260    """Decorator to mark a fixture factory function.
1261
1262    This decorator can be used, with or without parameters, to define a
1263    fixture function.
1264
1265    The name of the fixture function can later be referenced to cause its
1266    invocation ahead of running tests: test modules or classes can use the
1267    ``pytest.mark.usefixtures(fixturename)`` marker.
1268
1269    Test functions can directly use fixture names as input arguments in which
1270    case the fixture instance returned from the fixture function will be
1271    injected.
1272
1273    Fixtures can provide their values to test functions using ``return`` or
1274    ``yield`` statements. When using ``yield`` the code block after the
1275    ``yield`` statement is executed as teardown code regardless of the test
1276    outcome, and must yield exactly once.
1277
1278    :param scope:
1279        The scope for which this fixture is shared; one of ``"function"``
1280        (default), ``"class"``, ``"module"``, ``"package"`` or ``"session"``.
1281
1282        This parameter may also be a callable which receives ``(fixture_name, config)``
1283        as parameters, and must return a ``str`` with one of the values mentioned above.
1284
1285        See :ref:`dynamic scope` in the docs for more information.
1286
1287    :param params:
1288        An optional list of parameters which will cause multiple invocations
1289        of the fixture function and all of the tests using it. The current
1290        parameter is available in ``request.param``.
1291
1292    :param autouse:
1293        If True, the fixture func is activated for all tests that can see it.
1294        If False (the default), an explicit reference is needed to activate
1295        the fixture.
1296
1297    :param ids:
1298        List of string ids each corresponding to the params so that they are
1299        part of the test id. If no ids are provided they will be generated
1300        automatically from the params.
1301
1302    :param name:
1303        The name of the fixture. This defaults to the name of the decorated
1304        function. If a fixture is used in the same module in which it is
1305        defined, the function name of the fixture will be shadowed by the
1306        function arg that requests the fixture; one way to resolve this is to
1307        name the decorated function ``fixture_<fixturename>`` and then use
1308        ``@pytest.fixture(name='<fixturename>')``.
1309    """
1310    fixture_marker = FixtureFunctionMarker(
1311        scope=scope, params=params, autouse=autouse, ids=ids, name=name,
1312    )
1313
1314    # Direct decoration.
1315    if fixture_function:
1316        return fixture_marker(fixture_function)
1317
1318    return fixture_marker
1319
1320
1321def yield_fixture(
1322    fixture_function=None,
1323    *args,
1324    scope="function",
1325    params=None,
1326    autouse=False,
1327    ids=None,
1328    name=None
1329):
1330    """(Return a) decorator to mark a yield-fixture factory function.
1331
1332    .. deprecated:: 3.0
1333        Use :py:func:`pytest.fixture` directly instead.
1334    """
1335    return fixture(
1336        fixture_function,
1337        *args,
1338        scope=scope,
1339        params=params,
1340        autouse=autouse,
1341        ids=ids,
1342        name=name,
1343    )
1344
1345
1346@fixture(scope="session")
1347def pytestconfig(request: FixtureRequest) -> Config:
1348    """Session-scoped fixture that returns the :class:`_pytest.config.Config` object.
1349
1350    Example::
1351
1352        def test_foo(pytestconfig):
1353            if pytestconfig.getoption("verbose") > 0:
1354                ...
1355
1356    """
1357    return request.config
1358
1359
1360def pytest_addoption(parser: Parser) -> None:
1361    parser.addini(
1362        "usefixtures",
1363        type="args",
1364        default=[],
1365        help="list of default fixtures to be used with this project",
1366    )
1367
1368
1369class FixtureManager:
1370    """pytest fixture definitions and information is stored and managed
1371    from this class.
1372
1373    During collection fm.parsefactories() is called multiple times to parse
1374    fixture function definitions into FixtureDef objects and internal
1375    data structures.
1376
1377    During collection of test functions, metafunc-mechanics instantiate
1378    a FuncFixtureInfo object which is cached per node/func-name.
1379    This FuncFixtureInfo object is later retrieved by Function nodes
1380    which themselves offer a fixturenames attribute.
1381
1382    The FuncFixtureInfo object holds information about fixtures and FixtureDefs
1383    relevant for a particular function. An initial list of fixtures is
1384    assembled like this:
1385
1386    - ini-defined usefixtures
1387    - autouse-marked fixtures along the collection chain up from the function
1388    - usefixtures markers at module/class/function level
1389    - test function funcargs
1390
1391    Subsequently the funcfixtureinfo.fixturenames attribute is computed
1392    as the closure of the fixtures needed to setup the initial fixtures,
1393    i.e. fixtures needed by fixture functions themselves are appended
1394    to the fixturenames list.
1395
1396    Upon the test-setup phases all fixturenames are instantiated, retrieved
1397    by a lookup of their FuncFixtureInfo.
1398    """
1399
1400    FixtureLookupError = FixtureLookupError
1401    FixtureLookupErrorRepr = FixtureLookupErrorRepr
1402
1403    def __init__(self, session: "Session") -> None:
1404        self.session = session
1405        self.config = session.config  # type: Config
1406        self._arg2fixturedefs = {}  # type: Dict[str, List[FixtureDef[Any]]]
1407        self._holderobjseen = set()  # type: Set[object]
1408        self._nodeid_and_autousenames = [
1409            ("", self.config.getini("usefixtures"))
1410        ]  # type: List[Tuple[str, List[str]]]
1411        session.config.pluginmanager.register(self, "funcmanage")
1412
1413    def _get_direct_parametrize_args(self, node: "nodes.Node") -> List[str]:
1414        """Return all direct parametrization arguments of a node, so we don't
1415        mistake them for fixtures.
1416
1417        Check https://github.com/pytest-dev/pytest/issues/5036.
1418
1419        These things are done later as well when dealing with parametrization
1420        so this could be improved.
1421        """
1422        parametrize_argnames = []  # type: List[str]
1423        for marker in node.iter_markers(name="parametrize"):
1424            if not marker.kwargs.get("indirect", False):
1425                p_argnames, _ = ParameterSet._parse_parametrize_args(
1426                    *marker.args, **marker.kwargs
1427                )
1428                parametrize_argnames.extend(p_argnames)
1429
1430        return parametrize_argnames
1431
1432    def getfixtureinfo(
1433        self, node: "nodes.Node", func, cls, funcargs: bool = True
1434    ) -> FuncFixtureInfo:
1435        if funcargs and not getattr(node, "nofuncargs", False):
1436            argnames = getfuncargnames(func, name=node.name, cls=cls)
1437        else:
1438            argnames = ()
1439
1440        usefixtures = tuple(
1441            arg for mark in node.iter_markers(name="usefixtures") for arg in mark.args
1442        )
1443        initialnames = usefixtures + argnames
1444        fm = node.session._fixturemanager
1445        initialnames, names_closure, arg2fixturedefs = fm.getfixtureclosure(
1446            initialnames, node, ignore_args=self._get_direct_parametrize_args(node)
1447        )
1448        return FuncFixtureInfo(argnames, initialnames, names_closure, arg2fixturedefs)
1449
1450    def pytest_plugin_registered(self, plugin: _PluggyPlugin) -> None:
1451        nodeid = None
1452        try:
1453            p = absolutepath(plugin.__file__)  # type: ignore[attr-defined]
1454        except AttributeError:
1455            pass
1456        else:
1457            from _pytest import nodes
1458
1459            # Construct the base nodeid which is later used to check
1460            # what fixtures are visible for particular tests (as denoted
1461            # by their test id).
1462            if p.name.startswith("conftest.py"):
1463                try:
1464                    nodeid = str(p.parent.relative_to(self.config.rootpath))
1465                except ValueError:
1466                    nodeid = ""
1467                if nodeid == ".":
1468                    nodeid = ""
1469                if os.sep != nodes.SEP:
1470                    nodeid = nodeid.replace(os.sep, nodes.SEP)
1471
1472        self.parsefactories(plugin, nodeid)
1473
1474    def _getautousenames(self, nodeid: str) -> List[str]:
1475        """Return a list of fixture names to be used."""
1476        autousenames = []  # type: List[str]
1477        for baseid, basenames in self._nodeid_and_autousenames:
1478            if nodeid.startswith(baseid):
1479                if baseid:
1480                    i = len(baseid)
1481                    nextchar = nodeid[i : i + 1]
1482                    if nextchar and nextchar not in ":/":
1483                        continue
1484                autousenames.extend(basenames)
1485        return autousenames
1486
1487    def getfixtureclosure(
1488        self, fixturenames: Tuple[str, ...], parentnode, ignore_args: Sequence[str] = ()
1489    ) -> Tuple[Tuple[str, ...], List[str], Dict[str, Sequence[FixtureDef[Any]]]]:
1490        # Collect the closure of all fixtures, starting with the given
1491        # fixturenames as the initial set.  As we have to visit all
1492        # factory definitions anyway, we also return an arg2fixturedefs
1493        # mapping so that the caller can reuse it and does not have
1494        # to re-discover fixturedefs again for each fixturename
1495        # (discovering matching fixtures for a given name/node is expensive).
1496
1497        parentid = parentnode.nodeid
1498        fixturenames_closure = self._getautousenames(parentid)
1499
1500        def merge(otherlist: Iterable[str]) -> None:
1501            for arg in otherlist:
1502                if arg not in fixturenames_closure:
1503                    fixturenames_closure.append(arg)
1504
1505        merge(fixturenames)
1506
1507        # At this point, fixturenames_closure contains what we call "initialnames",
1508        # which is a set of fixturenames the function immediately requests. We
1509        # need to return it as well, so save this.
1510        initialnames = tuple(fixturenames_closure)
1511
1512        arg2fixturedefs = {}  # type: Dict[str, Sequence[FixtureDef[Any]]]
1513        lastlen = -1
1514        while lastlen != len(fixturenames_closure):
1515            lastlen = len(fixturenames_closure)
1516            for argname in fixturenames_closure:
1517                if argname in ignore_args:
1518                    continue
1519                if argname in arg2fixturedefs:
1520                    continue
1521                fixturedefs = self.getfixturedefs(argname, parentid)
1522                if fixturedefs:
1523                    arg2fixturedefs[argname] = fixturedefs
1524                    merge(fixturedefs[-1].argnames)
1525
1526        def sort_by_scope(arg_name: str) -> int:
1527            try:
1528                fixturedefs = arg2fixturedefs[arg_name]
1529            except KeyError:
1530                return scopes.index("function")
1531            else:
1532                return fixturedefs[-1].scopenum
1533
1534        fixturenames_closure.sort(key=sort_by_scope)
1535        return initialnames, fixturenames_closure, arg2fixturedefs
1536
1537    def pytest_generate_tests(self, metafunc: "Metafunc") -> None:
1538        """Generate new tests based on parametrized fixtures used by the given metafunc"""
1539
1540        def get_parametrize_mark_argnames(mark: Mark) -> Sequence[str]:
1541            args, _ = ParameterSet._parse_parametrize_args(*mark.args, **mark.kwargs)
1542            return args
1543
1544        for argname in metafunc.fixturenames:
1545            # Get the FixtureDefs for the argname.
1546            fixture_defs = metafunc._arg2fixturedefs.get(argname)
1547            if not fixture_defs:
1548                # Will raise FixtureLookupError at setup time if not parametrized somewhere
1549                # else (e.g @pytest.mark.parametrize)
1550                continue
1551
1552            # If the test itself parametrizes using this argname, give it
1553            # precedence.
1554            if any(
1555                argname in get_parametrize_mark_argnames(mark)
1556                for mark in metafunc.definition.iter_markers("parametrize")
1557            ):
1558                continue
1559
1560            # In the common case we only look at the fixture def with the
1561            # closest scope (last in the list). But if the fixture overrides
1562            # another fixture, while requesting the super fixture, keep going
1563            # in case the super fixture is parametrized (#1953).
1564            for fixturedef in reversed(fixture_defs):
1565                # Fixture is parametrized, apply it and stop.
1566                if fixturedef.params is not None:
1567                    metafunc.parametrize(
1568                        argname,
1569                        fixturedef.params,
1570                        indirect=True,
1571                        scope=fixturedef.scope,
1572                        ids=fixturedef.ids,
1573                    )
1574                    break
1575
1576                # Not requesting the overridden super fixture, stop.
1577                if argname not in fixturedef.argnames:
1578                    break
1579
1580                # Try next super fixture, if any.
1581
1582    def pytest_collection_modifyitems(self, items: "List[nodes.Item]") -> None:
1583        # Separate parametrized setups.
1584        items[:] = reorder_items(items)
1585
1586    def parsefactories(
1587        self, node_or_obj, nodeid=NOTSET, unittest: bool = False
1588    ) -> None:
1589        if nodeid is not NOTSET:
1590            holderobj = node_or_obj
1591        else:
1592            holderobj = node_or_obj.obj
1593            nodeid = node_or_obj.nodeid
1594        if holderobj in self._holderobjseen:
1595            return
1596
1597        self._holderobjseen.add(holderobj)
1598        autousenames = []
1599        for name in dir(holderobj):
1600            # The attribute can be an arbitrary descriptor, so the attribute
1601            # access below can raise. safe_getatt() ignores such exceptions.
1602            obj = safe_getattr(holderobj, name, None)
1603            marker = getfixturemarker(obj)
1604            if not isinstance(marker, FixtureFunctionMarker):
1605                # Magic globals  with __getattr__ might have got us a wrong
1606                # fixture attribute.
1607                continue
1608
1609            if marker.name:
1610                name = marker.name
1611
1612            # During fixture definition we wrap the original fixture function
1613            # to issue a warning if called directly, so here we unwrap it in
1614            # order to not emit the warning when pytest itself calls the
1615            # fixture function.
1616            obj = get_real_method(obj, holderobj)
1617
1618            fixture_def = FixtureDef(
1619                fixturemanager=self,
1620                baseid=nodeid,
1621                argname=name,
1622                func=obj,
1623                scope=marker.scope,
1624                params=marker.params,
1625                unittest=unittest,
1626                ids=marker.ids,
1627            )
1628
1629            faclist = self._arg2fixturedefs.setdefault(name, [])
1630            if fixture_def.has_location:
1631                faclist.append(fixture_def)
1632            else:
1633                # fixturedefs with no location are at the front
1634                # so this inserts the current fixturedef after the
1635                # existing fixturedefs from external plugins but
1636                # before the fixturedefs provided in conftests.
1637                i = len([f for f in faclist if not f.has_location])
1638                faclist.insert(i, fixture_def)
1639            if marker.autouse:
1640                autousenames.append(name)
1641
1642        if autousenames:
1643            self._nodeid_and_autousenames.append((nodeid or "", autousenames))
1644
1645    def getfixturedefs(
1646        self, argname: str, nodeid: str
1647    ) -> Optional[Sequence[FixtureDef[Any]]]:
1648        """Get a list of fixtures which are applicable to the given node id.
1649
1650        :param str argname: Name of the fixture to search for.
1651        :param str nodeid: Full node id of the requesting test.
1652        :rtype: Sequence[FixtureDef]
1653        """
1654        try:
1655            fixturedefs = self._arg2fixturedefs[argname]
1656        except KeyError:
1657            return None
1658        return tuple(self._matchfactories(fixturedefs, nodeid))
1659
1660    def _matchfactories(
1661        self, fixturedefs: Iterable[FixtureDef[Any]], nodeid: str
1662    ) -> Iterator[FixtureDef[Any]]:
1663        from _pytest import nodes
1664
1665        for fixturedef in fixturedefs:
1666            if nodes.ischildnode(fixturedef.baseid, nodeid):
1667                yield fixturedef
1668