2828
2929from .common_mini_six import string_types
3030from .common_pytest_lazy_values import get_lazy_args
31- from .common_pytest_marks import PYTEST35_OR_GREATER , PYTEST46_OR_GREATER , PYTEST37_OR_GREATER , PYTEST7_OR_GREATER
31+ from .common_pytest_marks import PYTEST35_OR_GREATER , PYTEST46_OR_GREATER , PYTEST37_OR_GREATER , PYTEST7_OR_GREATER , PYTEST8_OR_GREATER
3232from .common_pytest import get_pytest_nodeid , get_pytest_function_scopeval , is_function_node , get_param_names , \
33- get_param_argnames_as_list , has_function_scope , set_callspec_arg_scope_to_function
33+ get_param_argnames_as_list , has_function_scope , set_callspec_arg_scope_to_function , in_callspec_explicit_args
3434
3535from .fixture_core1_unions import NOT_USED , USED , is_fixture_union_params , UnionFixtureAlternative
3636
4141from .case_parametrizer_new import get_current_cases
4242
4343
44- _DEBUG = False
44+ _DEBUG = True
45+ """Note: this is a manual flag to turn when developing (do not forget to also call pytest with -s)"""
4546
4647
4748# @pytest.hookimpl(hookwrapper=True, tryfirst=True)
@@ -753,7 +754,7 @@ def remove_all(self, values):
753754 self ._update_fixture_defs ()
754755
755756
756- def getfixtureclosure (fm , fixturenames , parentnode , ignore_args = ()):
757+ def _getfixtureclosure (fm , fixturenames , parentnode , ignore_args = ()):
757758 """
758759 Replaces pytest's getfixtureclosure method to handle unions.
759760 """
@@ -764,7 +765,10 @@ def getfixtureclosure(fm, fixturenames, parentnode, ignore_args=()):
764765 # new argument "ignore_args" in 4.6+
765766 kwargs ['ignore_args' ] = ignore_args
766767
767- if PYTEST37_OR_GREATER :
768+ if PYTEST8_OR_GREATER :
769+ # two outputs and sig change
770+ ref_fixturenames , ref_arg2fixturedefs = fm .__class__ .getfixtureclosure (fm , parentnode , fixturenames , ** kwargs )
771+ elif PYTEST37_OR_GREATER :
768772 # three outputs
769773 initial_names , ref_fixturenames , ref_arg2fixturedefs = \
770774 fm .__class__ .getfixtureclosure (fm , fixturenames , parentnode , ** kwargs )
@@ -781,12 +785,19 @@ def getfixtureclosure(fm, fixturenames, parentnode, ignore_args=()):
781785 assert set (super_closure ) == set (ref_fixturenames )
782786 assert dict (arg2fixturedefs ) == ref_arg2fixturedefs
783787
784- if PYTEST37_OR_GREATER :
788+ if PYTEST37_OR_GREATER and not PYTEST8_OR_GREATER :
785789 return _init_fixnames , super_closure , arg2fixturedefs
786790 else :
787791 return super_closure , arg2fixturedefs
788792
789793
794+ if PYTEST8_OR_GREATER :
795+ def getfixtureclosure (fm , parentnode , initialnames , ignore_args ):
796+ return _getfixtureclosure (fm , fixturenames = initialnames , parentnode = parentnode , ignore_args = ignore_args )
797+ else :
798+ getfixtureclosure = _getfixtureclosure
799+
800+
790801def create_super_closure (fm ,
791802 parentnode ,
792803 fixturenames ,
@@ -835,6 +846,11 @@ def _merge(new_items, into_list):
835846 # we cannot sort yet - merge the fixture names into the _init_fixnames
836847 _merge (fixturenames , _init_fixnames )
837848
849+ # Bugfix GH#330 in progress...
850+ # TODO analyze why in the test "fixture_union_0simplest
851+ # the first node contains second, and the second contains first
852+ # or TODO check the test for get_callspecs, it is maybe simpler
853+
838854 # Finally create the closure
839855 fixture_defs_mgr = FixtureDefsCache (fm , parentnode )
840856 closure_tree = FixtureClosureNode (fixture_defs_mgr = fixture_defs_mgr )
@@ -1035,7 +1051,8 @@ def create_call_list_from_pending_parametrizations(self):
10351051
10361052 if _DEBUG :
10371053 print ("\n " .join (["%s[%s]: funcargs=%s, params=%s" % (get_pytest_nodeid (self .metafunc ),
1038- c .id , c .funcargs , c .params )
1054+ c .id , c .params if PYTEST8_OR_GREATER else c .funcargs ,
1055+ c .params )
10391056 for c in calls ]) + "\n " )
10401057
10411058 # clean EMPTY_ID set by @parametrize when there is at least a MultiParamsAlternative
@@ -1107,7 +1124,7 @@ def _cleanup_calls_list(metafunc,
11071124
11081125 # A/ set to "not used" all parametrized fixtures that were not used in some branches
11091126 for fixture , p_to_apply in pending_dct .items ():
1110- if fixture not in c . params and fixture not in c . funcargs :
1127+ if not in_callspec_explicit_args ( c , fixture ) :
11111128 # parametrize with a single "not used" value and discard the id
11121129 if isinstance (p_to_apply , UnionParamz ):
11131130 c_with_dummy = _parametrize_calls (metafunc , [c ], p_to_apply .union_fixture_name , [NOT_USED ],
@@ -1132,7 +1149,7 @@ def _cleanup_calls_list(metafunc,
11321149 # For this we use a dirty hack: we add a parameter with they name in the callspec, it seems to be propagated
11331150 # in the `request`. TODO is there a better way?
11341151 for fixture_name in _not_always_used_func_scoped :
1135- if fixture_name not in c . params and fixture_name not in c . funcargs :
1152+ if not in_callspec_explicit_args ( c , fixture_name ) :
11361153 if not n .requires (fixture_name ):
11371154 # explicitly add it as discarded by creating a parameter value for it.
11381155 c .params [fixture_name ] = NOT_USED
0 commit comments