6
6
import sys
7
7
import warnings
8
8
from collections import OrderedDict , deque , defaultdict
9
+
10
+ import six
9
11
from more_itertools import flatten
10
12
11
13
import attr
29
31
safe_getattr ,
30
32
FuncargnamesCompatAttr ,
31
33
)
34
+ from _pytest .deprecated import FIXTURE_FUNCTION_CALL , RemovedInPytest4Warning
32
35
from _pytest .outcomes import fail , TEST_OUTCOME
33
36
34
37
FIXTURE_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):
798
801
799
802
def _teardown_yield_fixture (fixturefunc , it ):
800
803
"""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) """
802
805
try :
803
806
next (it )
804
807
except StopIteration :
@@ -928,6 +931,13 @@ def pytest_fixture_setup(fixturedef, request):
928
931
request ._check_scope (argname , request .scope , fixdef .scope )
929
932
kwargs [argname ] = result
930
933
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
+
931
941
fixturefunc = resolve_fixture_function (fixturedef , request )
932
942
my_cache_key = request .param_index
933
943
try :
@@ -947,6 +957,44 @@ def _ensure_immutable_ids(ids):
947
957
return tuple (ids )
948
958
949
959
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
+
950
998
@attr .s (frozen = True )
951
999
class FixtureFunctionMarker (object ):
952
1000
scope = attr .ib ()
@@ -964,6 +1012,8 @@ def __call__(self, function):
964
1012
"fixture is being applied more than once to the same function"
965
1013
)
966
1014
1015
+ function = wrap_function_to_warning_if_called_directly (function , self )
1016
+
967
1017
function ._pytestfixturefunction = self
968
1018
return function
969
1019
0 commit comments