summaryrefslogtreecommitdiff
path: root/src/_pytest/fixtures.py
diff options
context:
space:
mode:
authorRan Benita <ran@unusedvar.com>2020-09-27 22:20:31 +0300
committerRan Benita <ran@unusedvar.com>2020-11-13 11:25:09 +0200
commitf1e6fdcddbfe8991935685ccc5049dd957ec4382 (patch)
tree854c010eef3a9accb203ccbf114b12648dc5b997 /src/_pytest/fixtures.py
parentb0505788821604f0b0787683d47a0ca693fd0426 (diff)
downloadpytest-f1e6fdcddbfe8991935685ccc5049dd957ec4382.tar.gz
Export types of builtin fixture for type annotations
In order to allow users to type annotate fixtures they request, the types need to be imported from the `pytest` namespace. They are/were always available to import from the `_pytest` namespace, but that is not guaranteed to be stable. These types are only exported for the purpose of typing. Specifically, the following are *not* public: - Construction (`__init__`) - Subclassing - staticmethods and classmethods We try to combat them being used anyway by: - Marking the classes as `@final` when possible (already done). - Not documenting private stuff in the API Reference. - Using `_`-prefixed names or marking as `:meta private:` for private stuff. - Adding a keyword-only `_ispytest=False` to private constructors, warning if False, and changing pytest itself to pass True. In the future it will (hopefully) become a hard error. Hopefully that will be enough.
Diffstat (limited to 'src/_pytest/fixtures.py')
-rw-r--r--src/_pytest/fixtures.py15
1 files changed, 12 insertions, 3 deletions
diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py
index cef998c03..273bcafd3 100644
--- a/src/_pytest/fixtures.py
+++ b/src/_pytest/fixtures.py
@@ -49,6 +49,7 @@ from _pytest.compat import safe_getattr
from _pytest.config import _PluggyPlugin
from _pytest.config import Config
from _pytest.config.argparsing import Parser
+from _pytest.deprecated import check_ispytest
from _pytest.deprecated import FILLFUNCARGS
from _pytest.deprecated import YIELD_FIXTURE
from _pytest.mark import Mark
@@ -367,7 +368,7 @@ def _fill_fixtures_impl(function: "Function") -> None:
assert function.parent is not None
fi = fm.getfixtureinfo(function.parent, function.obj, None)
function._fixtureinfo = fi
- request = function._request = FixtureRequest(function)
+ request = function._request = FixtureRequest(function, _ispytest=True)
request._fillfixtures()
# Prune out funcargs for jstests.
newfuncargs = {}
@@ -429,7 +430,8 @@ class FixtureRequest:
indirectly.
"""
- def __init__(self, pyfuncitem) -> None:
+ def __init__(self, pyfuncitem, *, _ispytest: bool = False) -> None:
+ check_ispytest(_ispytest)
self._pyfuncitem = pyfuncitem
#: Fixture for which this request is being performed.
self.fixturename: Optional[str] = None
@@ -674,7 +676,9 @@ class FixtureRequest:
if paramscopenum is not None:
scope = scopes[paramscopenum]
- subrequest = SubRequest(self, scope, param, param_index, fixturedef)
+ subrequest = SubRequest(
+ self, scope, param, param_index, fixturedef, _ispytest=True
+ )
# Check if a higher-level scoped fixture accesses a lower level one.
subrequest._check_scope(argname, self.scope, scope)
@@ -751,7 +755,10 @@ class SubRequest(FixtureRequest):
param,
param_index: int,
fixturedef: "FixtureDef[object]",
+ *,
+ _ispytest: bool = False,
) -> None:
+ check_ispytest(_ispytest)
self._parent_request = request
self.fixturename = fixturedef.argname
if param is not NOTSET:
@@ -769,6 +776,8 @@ class SubRequest(FixtureRequest):
return f"<SubRequest {self.fixturename!r} for {self._pyfuncitem!r}>"
def addfinalizer(self, finalizer: Callable[[], object]) -> None:
+ """Add finalizer/teardown function to be called after the last test
+ within the requesting test context finished execution."""
self._fixturedef.addfinalizer(finalizer)
def _schedule_finalizers(