11""" Python test discovery, setup and run of test functions. """
2- import collections
32import enum
43import fnmatch
54import inspect
65import os
76import sys
87import warnings
8+ from collections import Counter
9+ from collections .abc import Sequence
910from functools import partial
1011from textwrap import dedent
1112
@@ -240,9 +241,6 @@ class PyobjContext:
240241class PyobjMixin (PyobjContext ):
241242 _ALLOW_MARKERS = True
242243
243- def __init__ (self , * k , ** kw ):
244- super ().__init__ (* k , ** kw )
245-
246244 @property
247245 def obj (self ):
248246 """Underlying Python object."""
@@ -394,12 +392,8 @@ def _genfunctions(self, name, funcobj):
394392 methods .append (module .pytest_generate_tests )
395393 if hasattr (cls , "pytest_generate_tests" ):
396394 methods .append (cls ().pytest_generate_tests )
397- if methods :
398- self .ihook .pytest_generate_tests .call_extra (
399- methods , dict (metafunc = metafunc )
400- )
401- else :
402- self .ihook .pytest_generate_tests (metafunc = metafunc )
395+
396+ self .ihook .pytest_generate_tests .call_extra (methods , dict (metafunc = metafunc ))
403397
404398 if not metafunc ._calls :
405399 yield Function (name , parent = self , fixtureinfo = fixtureinfo )
@@ -444,13 +438,12 @@ def _inject_setup_module_fixture(self):
444438 Using a fixture to invoke this methods ensures we play nicely and unsurprisingly with
445439 other fixtures (#517).
446440 """
447- setup_module = _get_non_fixture_func (self .obj , "setUpModule" )
448- if setup_module is None :
449- setup_module = _get_non_fixture_func (self .obj , "setup_module" )
450-
451- teardown_module = _get_non_fixture_func (self .obj , "tearDownModule" )
452- if teardown_module is None :
453- teardown_module = _get_non_fixture_func (self .obj , "teardown_module" )
441+ setup_module = _get_first_non_fixture_func (
442+ self .obj , ("setUpModule" , "setup_module" )
443+ )
444+ teardown_module = _get_first_non_fixture_func (
445+ self .obj , ("tearDownModule" , "teardown_module" )
446+ )
454447
455448 if setup_module is None and teardown_module is None :
456449 return
@@ -472,8 +465,10 @@ def _inject_setup_function_fixture(self):
472465 Using a fixture to invoke this methods ensures we play nicely and unsurprisingly with
473466 other fixtures (#517).
474467 """
475- setup_function = _get_non_fixture_func (self .obj , "setup_function" )
476- teardown_function = _get_non_fixture_func (self .obj , "teardown_function" )
468+ setup_function = _get_first_non_fixture_func (self .obj , ("setup_function" ,))
469+ teardown_function = _get_first_non_fixture_func (
470+ self .obj , ("teardown_function" ,)
471+ )
477472 if setup_function is None and teardown_function is None :
478473 return
479474
@@ -557,15 +552,15 @@ def __init__(self, fspath, parent=None, config=None, session=None, nodeid=None):
557552 def setup (self ):
558553 # not using fixtures to call setup_module here because autouse fixtures
559554 # from packages are not called automatically (#4085)
560- setup_module = _get_non_fixture_func ( self . obj , "setUpModule" )
561- if setup_module is None :
562- setup_module = _get_non_fixture_func ( self . obj , "setup_module" )
555+ setup_module = _get_first_non_fixture_func (
556+ self . obj , ( "setUpModule" , "setup_module" )
557+ )
563558 if setup_module is not None :
564559 _call_with_optional_argument (setup_module , self .obj )
565560
566- teardown_module = _get_non_fixture_func ( self . obj , "tearDownModule" )
567- if teardown_module is None :
568- teardown_module = _get_non_fixture_func ( self . obj , "teardown_module" )
561+ teardown_module = _get_first_non_fixture_func (
562+ self . obj , ( "tearDownModule" , "teardown_module" )
563+ )
569564 if teardown_module is not None :
570565 func = partial (_call_with_optional_argument , teardown_module , self .obj )
571566 self .addfinalizer (func )
@@ -656,27 +651,6 @@ def collect(self):
656651 pkg_prefixes .add (path )
657652
658653
659- def _get_xunit_setup_teardown (holder , attr_name , param_obj = None ):
660- """
661- Return a callable to perform xunit-style setup or teardown if
662- the function exists in the ``holder`` object.
663- The ``param_obj`` parameter is the parameter which will be passed to the function
664- when the callable is called without arguments, defaults to the ``holder`` object.
665- Return ``None`` if a suitable callable is not found.
666- """
667- # TODO: only needed because of Package!
668- param_obj = param_obj if param_obj is not None else holder
669- result = _get_non_fixture_func (holder , attr_name )
670- if result is not None :
671- arg_count = result .__code__ .co_argcount
672- if inspect .ismethod (result ):
673- arg_count -= 1
674- if arg_count :
675- return lambda : result (param_obj )
676- else :
677- return result
678-
679-
680654def _call_with_optional_argument (func , arg ):
681655 """Call the given function with the given argument if func accepts one argument, otherwise
682656 calls func without arguments"""
@@ -689,14 +663,15 @@ def _call_with_optional_argument(func, arg):
689663 func ()
690664
691665
692- def _get_non_fixture_func (obj , name ):
666+ def _get_first_non_fixture_func (obj , names ):
693667 """Return the attribute from the given object to be used as a setup/teardown
694668 xunit-style function, but only if not marked as a fixture to
695669 avoid calling it twice.
696670 """
697- meth = getattr (obj , name , None )
698- if fixtures .getfixturemarker (meth ) is None :
699- return meth
671+ for name in names :
672+ meth = getattr (obj , name , None )
673+ if meth is not None and fixtures .getfixturemarker (meth ) is None :
674+ return meth
700675
701676
702677class Class (PyCollector ):
@@ -736,7 +711,7 @@ def _inject_setup_class_fixture(self):
736711 Using a fixture to invoke this methods ensures we play nicely and unsurprisingly with
737712 other fixtures (#517).
738713 """
739- setup_class = _get_non_fixture_func (self .obj , "setup_class" )
714+ setup_class = _get_first_non_fixture_func (self .obj , ( "setup_class" ,) )
740715 teardown_class = getattr (self .obj , "teardown_class" , None )
741716 if setup_class is None and teardown_class is None :
742717 return
@@ -760,7 +735,7 @@ def _inject_setup_method_fixture(self):
760735 Using a fixture to invoke this methods ensures we play nicely and unsurprisingly with
761736 other fixtures (#517).
762737 """
763- setup_method = _get_non_fixture_func (self .obj , "setup_method" )
738+ setup_method = _get_first_non_fixture_func (self .obj , ( "setup_method" ,) )
764739 teardown_method = getattr (self .obj , "teardown_method" , None )
765740 if setup_method is None and teardown_method is None :
766741 return
@@ -1070,12 +1045,9 @@ def _resolve_arg_value_types(self, argnames, indirect):
10701045 * "params" if the argname should be the parameter of a fixture of the same name.
10711046 * "funcargs" if the argname should be a parameter to the parametrized test function.
10721047 """
1073- valtypes = {}
1074- if indirect is True :
1075- valtypes = dict .fromkeys (argnames , "params" )
1076- elif indirect is False :
1077- valtypes = dict .fromkeys (argnames , "funcargs" )
1078- elif isinstance (indirect , (tuple , list )):
1048+ if isinstance (indirect , bool ):
1049+ valtypes = dict .fromkeys (argnames , "params" if indirect else "funcargs" )
1050+ elif isinstance (indirect , Sequence ):
10791051 valtypes = dict .fromkeys (argnames , "funcargs" )
10801052 for arg in indirect :
10811053 if arg not in argnames :
@@ -1086,6 +1058,13 @@ def _resolve_arg_value_types(self, argnames, indirect):
10861058 pytrace = False ,
10871059 )
10881060 valtypes [arg ] = "params"
1061+ else :
1062+ fail (
1063+ "In {func}: expected Sequence or boolean for indirect, got {type}" .format (
1064+ type = type (indirect ).__name__ , func = self .function .__name__
1065+ ),
1066+ pytrace = False ,
1067+ )
10891068 return valtypes
10901069
10911070 def _validate_if_using_arg_names (self , argnames , indirect ):
@@ -1213,7 +1192,7 @@ def idmaker(argnames, parametersets, idfn=None, ids=None, config=None, item=None
12131192 if len (set (ids )) != len (ids ):
12141193 # The ids are not unique
12151194 duplicates = [testid for testid in ids if ids .count (testid ) > 1 ]
1216- counters = collections . defaultdict ( lambda : 0 )
1195+ counters = Counter ( )
12171196 for index , testid in enumerate (ids ):
12181197 if testid in duplicates :
12191198 ids [index ] = testid + str (counters [testid ])
@@ -1402,14 +1381,11 @@ def __init__(
14021381 # https://github.com/pytest-dev/pytest/issues/4569
14031382
14041383 self .keywords .update (
1405- dict .fromkeys (
1406- [
1407- mark .name
1408- for mark in self .iter_markers ()
1409- if mark .name not in self .keywords
1410- ],
1411- True ,
1412- )
1384+ {
1385+ mark .name : True
1386+ for mark in self .iter_markers ()
1387+ if mark .name not in self .keywords
1388+ }
14131389 )
14141390
14151391 if fixtureinfo is None :
0 commit comments