66import sys
77import warnings
88from collections import OrderedDict , deque , defaultdict
9+
10+ import six
911from more_itertools import flatten
1012
1113import attr
2931 safe_getattr ,
3032 FuncargnamesCompatAttr ,
3133)
34+ from _pytest .deprecated import FIXTURE_FUNCTION_CALL , RemovedInPytest4Warning
3235from _pytest .outcomes import fail , TEST_OUTCOME
3336
3437FIXTURE_MSG = 'fixtures cannot have "pytest_funcarg__" prefix and be decorated with @pytest.fixture:\n {}'
@@ -798,7 +801,7 @@ def call_fixture_func(fixturefunc, request, kwargs):
798801
799802def _teardown_yield_fixture (fixturefunc , it ):
800803 """Executes the teardown of a fixture function by advancing the iterator after the
801- yield and ensure the iteration ends (if not it means there is more than one yield in the function"""
804+ yield and ensure the iteration ends (if not it means there is more than one yield in the function) """
802805 try :
803806 next (it )
804807 except StopIteration :
@@ -928,6 +931,13 @@ def pytest_fixture_setup(fixturedef, request):
928931 request ._check_scope (argname , request .scope , fixdef .scope )
929932 kwargs [argname ] = result
930933
934+ # if function has been defined with @pytest.fixture, we want to
935+ # pass the special __being_called_by_pytest parameter so we don't raise a warning
936+ # this is an ugly hack, see #3720 for an opportunity to improve this
937+ defined_using_fixture_decorator = hasattr (fixturedef .func , "_pytestfixturefunction" )
938+ if defined_using_fixture_decorator :
939+ kwargs ["__being_called_by_pytest" ] = True
940+
931941 fixturefunc = resolve_fixture_function (fixturedef , request )
932942 my_cache_key = request .param_index
933943 try :
@@ -947,6 +957,44 @@ def _ensure_immutable_ids(ids):
947957 return tuple (ids )
948958
949959
960+ def wrap_function_to_warning_if_called_directly (function , fixture_marker ):
961+ """Wrap the given fixture function so we can issue warnings about it being called directly, instead of
962+ used as an argument in a test function.
963+
964+ The warning is emitted only in Python 3, because I didn't find a reliable way to make the wrapper function
965+ keep the original signature, and we probably will drop Python 2 in Pytest 4 anyway.
966+ """
967+ is_yield_function = is_generator (function )
968+ msg = FIXTURE_FUNCTION_CALL .format (name = fixture_marker .name or function .__name__ )
969+ warning = RemovedInPytest4Warning (msg )
970+
971+ if is_yield_function :
972+
973+ @functools .wraps (function )
974+ def result (* args , ** kwargs ):
975+ __tracebackhide__ = True
976+ __being_called_by_pytest = kwargs .pop ("__being_called_by_pytest" , False )
977+ if not __being_called_by_pytest :
978+ warnings .warn (warning , stacklevel = 3 )
979+ for x in function (* args , ** kwargs ):
980+ yield x
981+
982+ else :
983+
984+ @functools .wraps (function )
985+ def result (* args , ** kwargs ):
986+ __tracebackhide__ = True
987+ __being_called_by_pytest = kwargs .pop ("__being_called_by_pytest" , False )
988+ if not __being_called_by_pytest :
989+ warnings .warn (warning , stacklevel = 3 )
990+ return function (* args , ** kwargs )
991+
992+ if six .PY2 :
993+ result .__wrapped__ = function
994+
995+ return result
996+
997+
950998@attr .s (frozen = True )
951999class FixtureFunctionMarker (object ):
9521000 scope = attr .ib ()
@@ -964,6 +1012,8 @@ def __call__(self, function):
9641012 "fixture is being applied more than once to the same function"
9651013 )
9661014
1015+ function = wrap_function_to_warning_if_called_directly (function , self )
1016+
9671017 function ._pytestfixturefunction = self
9681018 return function
9691019
0 commit comments