⬅ pytest_cases/fixture_core2.py source

1 # Authors: Sylvain MARIE <sylvain.marie@se.com>
2 # + All contributors to <https://github.com/smarie/python-pytest-cases>
3 #
4 # License: 3-clause BSD, <https://github.com/smarie/python-pytest-cases/blob/master/LICENSE>
5 from __future__ import division
6  
7 from inspect import isgeneratorfunction
8 from itertools import product
9 from warnings import warn
10  
11 from decopatch import function_decorator, DECORATED
12 from makefun import with_signature, add_signature_parameters, remove_signature_parameters, wraps
13  
14 import pytest
15 import sys
16  
17 try: # python 3.3+
18 from inspect import signature, Parameter
19 except ImportError:
20 from funcsigs import signature, Parameter # noqa
21  
  • E261 At least two spaces before inline comment
22 try: # native coroutines, python 3.5+
23 from inspect import iscoroutinefunction
24 except ImportError:
25 def iscoroutinefunction(obj):
26 return False
27  
  • E261 At least two spaces before inline comment
28 try: # native async generators, python 3.6+
29 from inspect import isasyncgenfunction
30 except ImportError:
31 def isasyncgenfunction(obj):
32 return False
33  
34 try: # type hints, python 3+
35 from typing import Callable, Union, Any, List, Iterable, Sequence # noqa
36 from types import ModuleType # noqa
37 except ImportError:
38 pass
39  
40 from .common_pytest_lazy_values import get_lazy_args
41 from .common_pytest import get_pytest_parametrize_marks, make_marked_parameter_value, get_param_argnames_as_list, \
42 combine_ids, is_marked_parameter_value, pytest_fixture, resolve_ids, extract_parameterset_info, make_test_ids
43 from .common_pytest_marks import PYTEST3_OR_GREATER, PYTEST8_OR_GREATER
44 from .fixture__creation import get_caller_module, check_name_available, WARN, CHANGE
45 from .fixture_core1_unions import ignore_unused, is_used_request, NOT_USED, _make_unpack_fixture
46  
47  
48 def param_fixture(argname, # type: str
49 argvalues, # type: Iterable[Any]
50 autouse=False, # type: bool
51 ids=None, # type: Union[Callable, Iterable[str]]
52 scope="function", # type: str
53 hook=None, # type: Callable[[Callable], Callable]
54 debug=False, # type: bool
55 **kwargs):
56 """
57 Identical to `param_fixtures` but for a single parameter name, so that you can assign its output to a single
58 variable.
59  
60 ```python
61 import pytest
62 from pytest_cases import param_fixtures, param_fixture
63  
64 # create a single parameter fixture
65 my_parameter = param_fixture("my_parameter", [1, 2, 3, 4])
66  
67 @pytest.fixture
68 def fixture_uses_param(my_parameter):
69 ...
70  
71 def test_uses_param(my_parameter, fixture_uses_param):
72 ...
73 ```
74  
75 :param argname: see fixture `name`
76 :param argvalues: see fixture `params`
77 :param autouse: see fixture `autouse`
78 :param ids: see fixture `ids`
79 :param scope: see fixture `scope`
80 :param hook: an optional hook to apply to each fixture function that is created during this call. The hook function
81 will be called every time a fixture is about to be created. It will receive a single argument (the function
82 implementing the fixture) and should return the function to use. For example you can use `saved_fixture` from
83 `pytest-harvest` as a hook in order to save all such created fixtures in the fixture store.
84 :param debug: print debug messages on stdout to analyze fixture creation (use pytest -s to see them)
85 :param kwargs: any other argument for 'fixture'
86 :return: the create fixture
87 """
88 if "," in argname:
89 raise ValueError("`param_fixture` is an alias for `param_fixtures` that can only be used for a single "
90 "parameter name. Use `param_fixtures` instead - but note that it creates several fixtures.")
91 elif len(argname.replace(' ', '')) == 0:
92 raise ValueError("empty argname")
93  
94 # todo what if this is called in a class ?
95 caller_module = get_caller_module()
96  
97 return _create_param_fixture(caller_module, argname, argvalues, autouse=autouse, ids=ids, scope=scope,
98 hook=hook, debug=debug, **kwargs)
99  
100  
101 def _create_param_fixture(fixtures_dest,
102 argname, # type: str
103 argvalues, # type: Sequence[Any]
104 autouse=False, # type: bool
105 ids=None, # type: Union[Callable, Iterable[str]]
106 scope="function", # type: str
107 hook=None, # type: Callable[[Callable], Callable]
108 auto_simplify=False,
109 debug=False,
110 **kwargs):
111 """ Internal method shared with param_fixture and param_fixtures """
112  
113 if auto_simplify and len(argvalues) == 1:
114 # Simplification: do not parametrize the fixture, it will directly return the single value
115 argvalue_to_return = argvalues[0]
116 if is_marked_parameter_value(argvalue_to_return):
117 # Warning in that case the argvalues should not be a pytest.param.
118 # argvalue_to_return = get_marked_parameter_values(argvalue_to_return)
119 raise ValueError("When auto_simplify=True the argvalue can not be a pytest.param")
120  
121 # create the fixture - set its name so that the optional hook can read it easily
122 @with_signature("%s(request)" % argname)
123 def __param_fixture(request):
124 # do not forget to resolve the lazy values !
125 return get_lazy_args(argvalue_to_return, request)
126  
127 if debug:
  • T001 Print found.
128 print("Creating unparametrized fixture %r returning %r" % (argname, argvalue_to_return))
129  
130 fix = fixture(name=argname, scope=scope, autouse=autouse, ids=ids, hook=hook, **kwargs)(__param_fixture)
131 else:
132 # create the fixture - set its name so that the optional hook can read it easily
133 @with_signature("%s(request)" % argname)
134 def __param_fixture(request):
135 return get_lazy_args(request.param, request)
136  
137 if debug:
  • T001 Print found.
138 print("Creating parametrized fixture %r returning %r" % (argname, argvalues))
139  
140 fix = fixture(name=argname, scope=scope, autouse=autouse, params=argvalues, ids=ids,
141 hook=hook, **kwargs)(__param_fixture)
142  
143 # Dynamically add fixture to caller's module as explained in https://github.com/pytest-dev/pytest/issues/2424
144 check_name_available(fixtures_dest, argname, if_name_exists=WARN, caller=param_fixture)
145 setattr(fixtures_dest, argname, fix)
146  
147 return fix
148  
149  
150 def param_fixtures(argnames, # type: str
151 argvalues, # type: Iterable[Any]
152 autouse=False, # type: bool
153 ids=None, # type: Union[Callable, Iterable[str]]
154 scope="function", # type: str
155 hook=None, # type: Callable[[Callable], Callable]
156 debug=False, # type: bool
157 **kwargs):
158 """
159 Creates one or several "parameters" fixtures - depending on the number or coma-separated names in `argnames`. The
160 created fixtures are automatically registered into the callers' module, but you may wish to assign them to
161 variables for convenience. In that case make sure that you use the same names, e.g.
162 `p, q = param_fixtures('p,q', [(0, 1), (2, 3)])`.
163  
164 Note that the (argnames, argvalues, ids) signature is similar to `@pytest.mark.parametrize` for consistency,
165 see https://docs.pytest.org/en/latest/reference.html?highlight=pytest.param#pytest-mark-parametrize
166  
167 ```python
168 import pytest
169 from pytest_cases import param_fixtures, param_fixture
170  
171 # create a 2-tuple parameter fixture
172 arg1, arg2 = param_fixtures("arg1, arg2", [(1, 2), (3, 4)])
173  
174 @pytest.fixture
175 def fixture_uses_param2(arg2):
176 ...
177  
178 def test_uses_param2(arg1, arg2, fixture_uses_param2):
179 ...
180 ```
181  
182 :param argnames: same as `@pytest.mark.parametrize` `argnames`.
183 :param argvalues: same as `@pytest.mark.parametrize` `argvalues`.
184 :param autouse: see fixture `autouse`
185 :param ids: same as `@pytest.mark.parametrize` `ids`
186 :param scope: see fixture `scope`
187 :param hook: an optional hook to apply to each fixture function that is created during this call. The hook function
188 will be called every time a fixture is about to be created. It will receive a single argument (the function
189 implementing the fixture) and should return the function to use. For example you can use `saved_fixture` from
190 `pytest-harvest` as a hook in order to save all such created fixtures in the fixture store.
191 :param debug: print debug messages on stdout to analyze fixture creation (use pytest -s to see them)
192 :param kwargs: any other argument for the created 'fixtures'
193 :return: the created fixtures
194 """
195 argnames_lst = get_param_argnames_as_list(argnames)
196  
197 caller_module = get_caller_module()
198  
199 if len(argnames_lst) < 2:
200 return _create_param_fixture(caller_module, argnames, argvalues, autouse=autouse, ids=ids, scope=scope,
201 hook=hook, debug=debug, **kwargs)
202 else:
203 return _create_params_fixture(caller_module, argnames_lst, argvalues, autouse=autouse, ids=ids, scope=scope,
204 hook=hook, debug=debug, **kwargs)
205  
206  
207 def _create_params_fixture(fixtures_dest,
208 argnames_lst, # type: Sequence[str]
209 argvalues, # type: Sequence[Any]
210 autouse=False, # type: bool
211 ids=None, # type: Union[Callable, Iterable[str]]
212 scope="function", # type: str
213 hook=None, # type: Callable[[Callable], Callable]
214 debug=False, # type: bool
215 **kwargs):
216 argnames = ','.join(argnames_lst)
217 created_fixtures = []
218  
219 # create the root fixture that will contain all parameter values
220 # note: we sort the list so that the first in alphabetical order appears first. Indeed pytest uses this order.
221 root_fixture_name = "%s__param_fixtures_root" % ('_'.join(sorted(argnames_lst)))
222  
223 # Dynamically add fixture to caller's module as explained in https://github.com/pytest-dev/pytest/issues/2424
224 root_fixture_name = check_name_available(fixtures_dest, root_fixture_name, if_name_exists=CHANGE,
225 caller=param_fixtures)
226  
227 if debug:
  • T001 Print found.
228 print("Creating parametrized 'root' fixture %r returning %r" % (root_fixture_name, argvalues))
229  
230 @fixture(name=root_fixture_name, autouse=autouse, scope=scope, hook=hook, **kwargs)
231 @pytest.mark.parametrize(argnames, argvalues, ids=ids)
232 @with_signature("%s(%s)" % (root_fixture_name, argnames))
233 def _root_fixture(**_kwargs):
234 return tuple(_kwargs[k] for k in argnames_lst)
235  
236 # Override once again the symbol with the correct contents
237 setattr(fixtures_dest, root_fixture_name, _root_fixture)
238  
239 # finally create the sub-fixtures
240 for param_idx, argname in enumerate(argnames_lst):
241 # create the fixture
242 # To fix late binding issue with `param_idx` we add an extra layer of scope: a factory function
243 # See https://stackoverflow.com/questions/3431676/creating-functions-in-a-loop
244 def _create_fixture(_param_idx):
245  
246 if debug:
  • T001 Print found.
247 print("Creating nonparametrized 'view' fixture %r returning %r[%s]"
248 % (argname, root_fixture_name, _param_idx))
249  
250 @fixture(name=argname, scope=scope, autouse=autouse, hook=hook, **kwargs)
251 @with_signature("%s(%s)" % (argname, root_fixture_name))
252 def _param_fixture(**_kwargs):
253 params = _kwargs.pop(root_fixture_name)
254 return params[_param_idx]
255  
256 return _param_fixture
257  
258 # create it
259 fix = _create_fixture(param_idx)
260  
261 # add to module
262 check_name_available(fixtures_dest, argname, if_name_exists=WARN, caller=param_fixtures)
263 setattr(fixtures_dest, argname, fix)
264  
265 # collect to return the whole list eventually
266 created_fixtures.append(fix)
267  
268 return created_fixtures
269  
270  
271 # Fix for https://github.com/smarie/python-pytest-cases/issues/71
272 # In order for pytest to allow users to import this symbol in conftest.py
273 # they should be declared as optional plugin hooks.
274 # A workaround otherwise would be to remove the 'pytest_' name prefix
275 # See https://github.com/pytest-dev/pytest/issues/6475
276 @pytest.hookimpl(optionalhook=True)
277 def pytest_fixture_plus(*args,
278 **kwargs):
279 warn("`pytest_fixture_plus` and `fixture_plus` are deprecated. Please use the new alias `fixture`. "
280 "See https://github.com/pytest-dev/pytest/issues/6475", category=DeprecationWarning, stacklevel=2)
281 if len(args) == 1:
282 if callable(args[0]):
283 return _decorate_fixture_plus(args[0], _caller_module_offset_when_unpack=2, **kwargs)
284  
285 def _fixture_plus(f):
286 return _decorate_fixture_plus(f, *args, _caller_module_offset_when_unpack=2, **kwargs)
287 return _fixture_plus
288  
289  
290 fixture_plus = pytest_fixture_plus
291 """Deprecated too"""
292  
293  
294 @function_decorator
295 def fixture(scope="function", # type: str
296 autouse=False, # type: bool
297 name=None, # type: str
298 unpack_into=None, # type: Iterable[str]
299 hook=None, # type: Callable[[Callable], Callable]
300 fixture_func=DECORATED, # noqa
301 **kwargs):
302 """ decorator to mark a fixture factory function.
303  
304 Identical to `@pytest.fixture` decorator, except that
305  
306 - when used in a fixture union (either explicit `fixture_union` or indirect through `@parametrize`+`fixture_ref`
307 or `@parametrize_with_cases`), it will not be setup/teardown unnecessarily in tests that do not require it.
308  
309 - it supports multi-parametrization with `@pytest.mark.parametrize` as requested in
310 https://github.com/pytest-dev/pytest/issues/3960. As a consequence it does not support the `params` and `ids`
311 arguments anymore.
312  
313 - it supports a new argument `unpack_into` where you can provide names for fixtures where to unpack this fixture
314 into.
315  
316 As a consequence it does not support the `params` and `ids` arguments anymore.
317  
318 :param scope: the scope for which this fixture is shared, one of "function" (default), "class", "module" or
319 "session".
320 :param autouse: if True, the fixture func is activated for all tests that can see it. If False (the default) then
321 an explicit reference is needed to activate the fixture.
322 :param name: the name of the fixture. This defaults to the name of the decorated function. Note: If a fixture is
323 used in the same module in which it is defined, the function name of the fixture will be shadowed by the
324 function arg that requests the fixture; one way to resolve this is to name the decorated function
325 ``fixture_<fixturename>`` and then use ``@pytest.fixture(name='<fixturename>')``.
326 :param unpack_into: an optional iterable of names, or string containing coma-separated names, for additional
327 fixtures to create to represent parts of this fixture. See `unpack_fixture` for details.
328 :param hook: an optional hook to apply to each fixture function that is created during this call. The hook function
329 will be called every time a fixture is about to be created. It will receive a single argument (the function
330 implementing the fixture) and should return the function to use. For example you can use `saved_fixture` from
331 `pytest-harvest` as a hook in order to save all such created fixtures in the fixture store.
332 :param kwargs: other keyword arguments for `@pytest.fixture`
333 """
334 # todo what if this is called in a class ?
335  
336 # the offset is 3 because of @function_decorator (decopatch library)
337 return _decorate_fixture_plus(fixture_func, scope=scope, autouse=autouse, name=name, unpack_into=unpack_into,
338 hook=hook, _caller_module_offset_when_unpack=3, **kwargs)
339  
340  
341 class FixtureParam(object):
342 __slots__ = 'argnames',
343  
344 def __init__(self, argnames):
345 self.argnames = argnames
346  
347 def __repr__(self):
348 return "FixtureParam(argnames=%s)" % self.argnames
349  
350  
351 class CombinedFixtureParamValue(object):
352 """Represents a parameter value created when @parametrize is used on a @fixture """
353 __slots__ = 'param_defs', 'argvalues',
354  
355 def __init__(self,
356 param_defs, # type: Iterable[FixtureParam]
357 argvalues):
358 self.param_defs = param_defs
359 self.argvalues = argvalues
360  
361 def iterparams(self):
362 return ((pdef.argnames, v) for pdef, v in zip(self.param_defs, self.argvalues))
363  
364 def __repr__(self):
365 list_str = " ; ".join(["<%r: %s>" % (a, v) for a, v in self.iterparams()])
366 return "CombinedFixtureParamValue(%s)" % list_str
367  
368  
369 def _decorate_fixture_plus(fixture_func,
370 scope="function", # type: str
371 autouse=False, # type: bool
372 name=None, # type: str
373 unpack_into=None, # type: Iterable[str]
374 hook=None, # type: Callable[[Callable], Callable]
375 _caller_module_offset_when_unpack=3, # type: int
376 **kwargs):
377 """ decorator to mark a fixture factory function.
378  
379 Identical to `@pytest.fixture` decorator, except that
380  
381 - it supports multi-parametrization with `@pytest.mark.parametrize` as requested in
382 https://github.com/pytest-dev/pytest/issues/3960. As a consequence it does not support the `params` and `ids`
383 arguments anymore.
384  
385 - it supports a new argument `unpack_into` where you can provide names for fixtures where to unpack this fixture
386 into.
387  
388 :param scope: the scope for which this fixture is shared, one of "function" (default), "class", "module" or
389 "session".
390 :param autouse: if True, the fixture func is activated for all tests that can see it. If False (the default) then
391 an explicit reference is needed to activate the fixture.
392 :param name: the name of the fixture. This defaults to the name of the decorated function. Note: If a fixture is
393 used in the same module in which it is defined, the function name of the fixture will be shadowed by the
394 function arg that requests the fixture; one way to resolve this is to name the decorated function
395 ``fixture_<fixturename>`` and then use ``@pytest.fixture(name='<fixturename>')``.
396 :param unpack_into: an optional iterable of names, or string containing coma-separated names, for additional
397 fixtures to create to represent parts of this fixture. See `unpack_fixture` for details.
398 :param hook: an optional hook to apply to each fixture function that is created during this call. The hook function
399 will be called every time a fixture is about to be created. It will receive a single argument (the function
400 implementing the fixture) and should return the function to use. For example you can use `saved_fixture` from
401 `pytest-harvest` as a hook in order to save all such created fixtures in the fixture store.
402 :param kwargs: other keyword arguments for `@pytest.fixture`
403 """
404 if name is not None:
405 # Compatibility for the 'name' argument
406 if PYTEST3_OR_GREATER:
407 # pytest version supports "name" keyword argument
408 kwargs['name'] = name
409 elif name is not None:
410 # 'name' argument is not supported in this old version, use the __name__ trick.
411 fixture_func.__name__ = name
412  
413 # if unpacking is requested, do it first
414 if unpack_into is not None:
415 # get the future fixture name if needed
416 if name is None:
417 name = fixture_func.__name__
418  
419 # get caller module to create the symbols
420 caller_module = get_caller_module(frame_offset=_caller_module_offset_when_unpack)
421  
422 # note that we cannot use in_cls=True since we have no way to assign the unpacked fixtures to the class
423 _make_unpack_fixture(caller_module, unpack_into, name, hook=hook, in_cls=False)
424  
425 # (1) Collect all @pytest.mark.parametrize markers (including those created by usage of @cases_data)
426 parametrizer_marks = get_pytest_parametrize_marks(fixture_func, pop=PYTEST8_OR_GREATER)
427 if len(parametrizer_marks) < 1:
428 # make the fixture union-aware
429 wrapped_fixture_func = ignore_unused(fixture_func)
430  
431 # resolve possibly infinite generators of ids here
432 if 'params' in kwargs and 'ids' in kwargs:
433 kwargs['ids'] = resolve_ids(kwargs['ids'], kwargs['params'], full_resolve=False)
434  
435 # transform the created wrapper into a fixture
436 return pytest_fixture(scope=scope, autouse=autouse, hook=hook, **kwargs)(wrapped_fixture_func)
437  
438 else:
439 if 'params' in kwargs:
440 raise ValueError(
441 "With `fixture` you cannot mix usage of the keyword argument `params` and of "
442 "the pytest.mark.parametrize marks")
443  
444 # (2) create the huge "param" containing all params combined
445 # --loop (use the same order to get it right)
446 param_defs = []
447 params_values = []
448 params_ids = []
449 params_marks = []
450 for pmark in parametrizer_marks:
451 # -- pmark is a single @pytest.parametrize mark. --
452  
453 # check number of parameter names in this parameterset
454 if len(pmark.param_names) < 1:
455 raise ValueError("Fixture function '%s' decorated with '@fixture' has an empty parameter "
456 "name in a @pytest.mark.parametrize mark")
457  
458 # remember the argnames
459 param_defs.append(FixtureParam(pmark.param_names))
460  
461 # separate specific configuration (pytest.param()) from the values
462 custom_pids, _pmarks, _pvalues = extract_parameterset_info(pmark.param_names, pmark.param_values, check_nb=True)
463  
464 # get the ids by merging/creating the various possibilities
465 _paramids = make_test_ids(argnames=pmark.param_names, argvalues=_pvalues,
466 global_ids=pmark.param_ids, id_marks=custom_pids)
467  
468 # Finally store the ids, marks, and values for this parameterset
469 params_ids.append(_paramids)
470 params_marks.append(tuple(_pmarks))
471 params_values.append(tuple(_pvalues))
472  
473 # (3) generate the ids and values, possibly reapplying marks
474 if len(param_defs) == 1:
475 # A single @parametrize : we can simplify - that will be more readable
476 final_ids = params_ids[0]
477 final_marks = params_marks[0]
478 # note: we dot his even for a single @parametrize as it allows `current_case` to get the parameter names easily
479 final_values = [CombinedFixtureParamValue(param_defs, (v,)) for v in params_values[0]]
480  
481 # reapply the marks
482 for i, marks in enumerate(final_marks):
483 if marks is not None:
484 final_values[i] = make_marked_parameter_value((final_values[i],), marks=marks)
485 else:
486 # Multiple @parametrize: since pytest does not support several, we merge them with "appearance" of several
487 # --equivalent id
488 final_ids = combine_ids(product(*params_ids))
489 # --merge all values, we'll unpack them in the wrapper below
490 final_values = [CombinedFixtureParamValue(param_defs, v) for v in product(*params_values)]
491  
492 final_marks = tuple(product(*params_marks))
493  
494 # reapply the marks
495 for i, marks in enumerate(final_marks):
496 ms = [m for mm in marks if mm is not None for m in mm]
497 if len(ms) > 0:
498 final_values[i] = make_marked_parameter_value((final_values[i],), marks=ms)
499  
500 if len(final_values) != len(final_ids):
501 raise ValueError("Internal error related to fixture parametrization- please report")
502  
503 # (4) wrap the fixture function so as to remove the parameter names and add 'request' if needed
504 all_param_names = tuple(v for pnames in param_defs for v in pnames.argnames)
505  
506 # --create the new signature that we want to expose to pytest
507 old_sig = signature(fixture_func)
508 for p in all_param_names:
509 if p not in old_sig.parameters:
510 raise ValueError("parameter '%s' not found in fixture signature '%s%s'"
511 "" % (p, fixture_func.__name__, old_sig))
512 new_sig = remove_signature_parameters(old_sig, *all_param_names)
513 # add request if needed
514 func_needs_request = 'request' in old_sig.parameters
515 if not func_needs_request:
516 # Add it last so that `self` argument in class functions remains the first
517 new_sig = add_signature_parameters(new_sig, last=Parameter('request', kind=Parameter.POSITIONAL_OR_KEYWORD))
518  
519 # --common routine used below. Fills kwargs with the appropriate names and values from fixture_params
520 def _map_arguments(*_args, **_kwargs):
521 request = _kwargs['request'] if func_needs_request else _kwargs.pop('request')
522  
523 # sanity check: we have created this combined value in the combined parametrization.
524 _paramz = request.param
525 if not isinstance(_paramz, CombinedFixtureParamValue):
526 # This can happen when indirect parametrization has been used.
527 # In that case we can work but this parameter will not appear in `current_cases` fixture
528 _paramz = CombinedFixtureParamValue(param_defs, _paramz if len(param_defs) > 1 else (_paramz,))
529  
530 # populate the parameters
531 for p_names, p_argvals in _paramz.iterparams():
532 if len(p_names) == 1:
533 # a single parameter for that generated fixture (@pytest.mark.parametrize with a single name)
534 _kwargs[p_names[0]] = get_lazy_args(p_argvals, request)
535 else:
536 # several parameters for that generated fixture (@pytest.mark.parametrize with several names)
537 # unpack all of them and inject them in the kwargs
538 for old_p_name, old_p_value in zip(p_names, p_argvals):
539 _kwargs[old_p_name] = get_lazy_args(old_p_value, request)
540  
541 return _args, _kwargs
542  
543 # --Finally create the fixture function, a wrapper of user-provided fixture with the new signature
  • E225 Missing whitespace around operator
544 if isasyncgenfunction(fixture_func)and sys.version_info >= (3, 6):
  • E117 Over-indented
545 from .pep525 import _decorate_fixture_plus_asyncgen_pep525
546 wrapped_fixture_func = _decorate_fixture_plus_asyncgen_pep525(fixture_func, new_sig, _map_arguments)
547 elif iscoroutinefunction(fixture_func) and sys.version_info >= (3, 5):
  • E117 Over-indented
548 from .pep492 import _decorate_fixture_plus_coroutine_pep492
549 wrapped_fixture_func = _decorate_fixture_plus_coroutine_pep492(fixture_func, new_sig, _map_arguments)
550 elif isgeneratorfunction(fixture_func):
551 # generator function (with a yield statement)
552 if sys.version_info >= (3, 3):
553 from .pep380 import _decorate_fixture_plus_generator_pep380
554 wrapped_fixture_func = _decorate_fixture_plus_generator_pep380(fixture_func, new_sig, _map_arguments)
555 else:
556 @wraps(fixture_func, new_sig=new_sig)
557 def wrapped_fixture_func(*_args, **_kwargs):
558 if not is_used_request(_kwargs['request']):
559 yield NOT_USED
560 else:
561 _args, _kwargs = _map_arguments(*_args, **_kwargs)
562 for res in fixture_func(*_args, **_kwargs):
563 yield res
564 else:
565 # normal function with return statement
566 @wraps(fixture_func, new_sig=new_sig)
567 def wrapped_fixture_func(*_args, **_kwargs):
568 if not is_used_request(_kwargs['request']):
569 return NOT_USED
570 else:
571 _args, _kwargs = _map_arguments(*_args, **_kwargs)
572 return fixture_func(*_args, **_kwargs)
573  
574 # transform the created wrapper into a fixture
575 _make_fix = pytest_fixture(scope=scope, params=final_values, autouse=autouse, hook=hook, ids=final_ids, **kwargs)
576 return _make_fix(wrapped_fixture_func)