When defining fixtures in Pytest, the decorator fixture
supports both parentheses and arguments, such as(scope = "session")
, and parentheses and arguments. The following code is an example of both uses in the Pytest documentation.
Source: Pytest documentation
python
@pytest.fixture
def smtp():
return smtplib.SMTP("smtp.gmail.com")
python
@pytest.fixture(scope="module")
def smtp():
return smtplib.SMTP("smtp.gmail.com")
I tried to find out how to describe such a decorator.
To be precise, in the former parenthesis and no-argument usage, fixture
is called a decorator, and in the latter parenthesis and no-argument usage, fixture
is a decorator-creating decorator (decomaker
). .. ([PEP 318 --Decorators for Functions and Methods]
(https://www.python.org/dev/peps/pep-0318/#current-syntax))
In Pytest's fixture source, the fixture was implemented as follows:
python
def fixture(scope="function", params=None, autouse=False, ids=None, name=None):
""" (return a) decorator to mark a fixture factory function.
This decorator ....(Abbreviation)
"""
if callable(scope) and params is None and autouse == False:
# direct decoration
return FixtureFunctionMarker(
"function", params, autouse, name=name)(scope)
if params is not None and not isinstance(params, (list, tuple)):
params = list(params)
return FixtureFunctionMarker(scope, params, autouse, ids=ids, name=name)
If fixture
is used as a decorator with parentheses and no arguments, the scope
argument to fixture
is passed the function object defined in the function definition following the decorator (smtp
in the example above). I will.
ʻIf callable (on the line of ..., check if
scope is
callable(at the same time, if the argument that follows is the default value), and if so, decomaker
FixtureFunctionMakerCreate an instance of, and pass
scope to its
() `.
On the other hand, if fixture is used with parentheses and arguments, it returns the decorator (decomaker instance) itself. Python passes smtp
to the returned decorator and assigns the return value to the name smtp
.
It's unpleasant to use the initial argument scope
for a completely different purpose, but it can be aggregated into a single function, creating a user-friendly decorator interface.
Recommended Posts