def __init__( self, fixturemanager, baseid, argname, func, scope, params, unittest=False, ids=None, ): self._fixturemanager = fixturemanager self.baseid = baseid or "" self.has_location = baseid is not None self.func = func self.argname = argname self.scope = scope self.scopenum = scope2index( scope or "function", descr="Fixture '{}'".format(func.__name__), where=baseid, ) self.params = params self.argnames = getfuncargnames(func, is_method=unittest) self.unittest = unittest self.ids = ids self._finalizers = []
def decorator(fn: Callable): decorated_arg_names = set(getfuncargnames(fn)) if wrapped_param not in decorated_arg_names: raise TypeError( f'The decorated method must include an arg named {wrapped_param} ' f'as the wrapped fixture func.') # Don't include the wrapped param in the argspec we expose to pytest decorated_arg_names -= {wrapped_param} fixture_arg_names = set(getfuncargnames(fixturefunc)) - set(ignore) all_arg_names = fixture_arg_names | decorated_arg_names | {'request'} def extension_impl(**all_args): request = all_args['request'] ### # kwargs requested by the wrapped fixture # fixture_args = { name: value for name, value in all_args.items() if name in fixture_arg_names } ### # kwargs requested by the decorated method # decorated_args = { name: value for name, value in all_args.items() if name in decorated_arg_names } @functools.wraps(fixturefunc) def wrapped(**overridden_args): kwargs = { **fixture_args, **overridden_args, } return call_fixture_func(fixturefunc, request, kwargs) decorated_args[wrapped_param] = wrapped return call_fixture_func(fn, request, decorated_args) extension = build_wrapped_method(fn.__name__, all_arg_names, extension_impl) return extension
def test_wrapped_getfuncargnames(self): from _pytest.compat import getfuncargnames def wrap(f): def func(): pass func.__wrapped__ = f return func @wrap def f(x): pass l = getfuncargnames(f) assert l == ("x",)
def getfixtureinfo(self, node, func, cls, funcargs=True): if funcargs and not hasattr(node, "nofuncargs"): argnames = getfuncargnames(func, cls=cls) else: argnames = () usefixtures = getattr(func, "usefixtures", None) initialnames = argnames if usefixtures is not None: initialnames = usefixtures.args + initialnames fm = node.session._fixturemanager names_closure, arg2fixturedefs = fm.getfixtureclosure( initialnames, node) return FuncFixtureInfo(argnames, names_closure, arg2fixturedefs)
def getfixtureinfo(self, node, func, cls, funcargs=True): if funcargs and not getattr(node, "nofuncargs", False): argnames = getfuncargnames(func, cls=cls) else: argnames = () usefixtures = flatten( mark.args for mark in node.iter_markers(name="usefixtures") ) initialnames = argnames initialnames = tuple(usefixtures) + initialnames fm = node.session._fixturemanager names_closure, arg2fixturedefs = fm.getfixtureclosure(initialnames, node) return FuncFixtureInfo(argnames, names_closure, arg2fixturedefs)
def getfixtureinfo(self, node, func, cls, funcargs=True): if funcargs and not getattr(node, "nofuncargs", False): argnames = getfuncargnames(func, cls=cls) else: argnames = () usefixtures = flatten( mark.args for mark in node.iter_markers(name="usefixtures")) initialnames = tuple(usefixtures) + argnames fm = node.session._fixturemanager initialnames, names_closure, arg2fixturedefs = fm.getfixtureclosure( initialnames, node) return FuncFixtureInfo(argnames, initialnames, names_closure, arg2fixturedefs)
def test_wrapped_getfuncargnames_patching(self): from _pytest.compat import getfuncargnames def wrap(f): def func(): pass func.__wrapped__ = f func.patchings = ["qwe"] return func @wrap def f(x, y, z): pass l = getfuncargnames(f) assert l == ("y", "z")
def it_includes_extended_and_wrapped_args_in_spec(self): def fixture(fixture_unique): pass @wrap_fixture(fixture) def extended_fixture(extension_unique, wrapped): pass args = getfuncargnames(extended_fixture) expected = {'fixture_unique', 'extension_unique'} actual = set(args) - {'request'} assert expected == actual
def getfixtureinfo(self, node, func, cls, funcargs=True): if funcargs and not hasattr(node, "nofuncargs"): argnames = getfuncargnames(func, cls=cls) else: argnames = () usefixtures = getattr(func, "usefixtures", None) initialnames = argnames if usefixtures is not None: initialnames = usefixtures.args + initialnames fm = node.session._fixturemanager names_closure, arg2fixturedefs = fm.getfixtureclosure(initialnames, node) return FuncFixtureInfo(argnames, names_closure, arg2fixturedefs)
def test_getfuncargnames_patching(self): from _pytest.compat import getfuncargnames from unittest.mock import patch class T: def original(self, x, y, z): pass @patch.object(T, "original") def f(x, y, z): pass values = getfuncargnames(f) assert values == ("y", "z")
def __init__(self, fixturemanager, baseid, argname, func, scope, params, unittest=False, ids=None): self._fixturemanager = fixturemanager self.baseid = baseid or '' self.has_location = baseid is not None self.func = func self.argname = argname self.scope = scope self.scopenum = scopes.index(scope or "function") self.params = params startindex = unittest and 1 or None self.argnames = getfuncargnames(func, startindex=startindex) self.unittest = unittest self.ids = ids self._finalizer = []
def __init__(self, func): self.config = None self.function = func self.definition = MiniFuncDef(func.__name__) self._calls = [] # non-default parameters self.fixturenames = getfuncargnames(func) # get parametrization marks self.pmarks = get_pytest_parametrize_marks(self.function) if self.is_parametrized: self.update_callspecs() self.required_fixtures = set(self.fixturenames) - set( self._calls[0].funcargs) else: self.required_fixtures = self.fixturenames
def test_wrapped_getfuncargnames(self): from _pytest.compat import getfuncargnames def wrap(f): def func(): pass func.__wrapped__ = f return func @wrap def f(x): pass values = getfuncargnames(f) assert values == ("x",)
def decorator_factory(func): """ py.test introsepects the names of arguments in functions to pass in fixtures This means we need to dynamically construct the inner call to `func` to contain these names. """ from _pytest.compat import getfuncargnames args = getfuncargnames(func) monkey_args = set(args + ('monkeypatch', )) wrapper_str = trim(""" @pytest.fixture(autouse={autouse}) def {fixture_name}({monkey_args}): val = func({args}) if isinstance(path_or_obj, str): monkeypatch.setattr(path_or_obj, val, raising=raising) elif isinstance(path_or_obj, (tuple, list)): for item in path_or_obj: monkeypatch.setattr(item, val, raising=raising) else: monkeypatch.setattr(path_or_obj, key, value=val, raising=raising) return val """).format( fixture_name=func.__name__, args=', '.join(args), monkey_args=', '.join(monkey_args), autouse=repr(autouse) ) # Execute the template string in a temporary namespace and support # tracing utilities by setting a value for frame.f_globals['__name__'] namespace = { 'func': func, 'key': key, 'path_or_obj': path_or_obj, 'pytest': pytest, 'raising': raising, 'wraps': wraps, '__name__': 'patcher_%s' % func.__name__, } exec(wrapper_str, namespace) return namespace[func.__name__]
def decorator_factory(func): """ py.test introsepects the names of arguments in functions to pass in fixtures This means we need to dynamically construct the inner call to `func` to contain these names. """ from _pytest.compat import getfuncargnames args = getfuncargnames(func) monkey_args = set(args + ('monkeypatch', )) wrapper_str = """ @pytest.fixture(autouse={autouse}) def {fixture_name}({monkey_args}): val = func({args}) if isinstance(path_or_obj, str): monkeypatch.setattr(path_or_obj, val, raising=raising) elif isinstance(path_or_obj, (tuple, list)): for item in path_or_obj: monkeypatch.setattr(item, val, raising=raising) else: monkeypatch.setattr(path_or_obj, key, value=val, raising=raising) return val """.format( fixture_name=func.__name__, args=', '.join(args), monkey_args=', '.join(monkey_args), autouse=repr(autouse) ) # Execute the template string in a temporary namespace and support # tracing utilities by setting a value for frame.f_globals['__name__'] namespace = { 'func': func, 'key': key, 'path_or_obj': path_or_obj, 'pytest': pytest, 'raising': raising, 'wraps': wraps, '__name__': 'patcher_%s' % func.__name__, } exec(wrapper_str, namespace) return namespace[func.__name__]
def __init__(self, fixturemanager, baseid, argname, func, scope, params, unittest=False, ids=None): self._fixturemanager = fixturemanager self.baseid = baseid or '' self.has_location = baseid is not None self.func = func self.argname = argname self.scope = scope self.scopenum = scope2index( scope or "function", descr='fixture {0}'.format(func.__name__), where=baseid ) self.params = params startindex = unittest and 1 or None self.argnames = getfuncargnames(func, startindex=startindex) self.unittest = unittest self.ids = ids self._finalizer = []
def __init__(self, func): from .plugin import PYTEST_CONFIG # late import to ensure config has been loaded by now self.config = PYTEST_CONFIG self.function = func self.definition = MiniFuncDef(func.__name__) self._calls = [] # non-default parameters self.fixturenames = getfuncargnames(func) # add declared used fixtures with @pytest.mark.usefixtures self.fixturenames_not_in_sig = [f for f in get_pytest_usefixture_marks(func) if f not in self.fixturenames] if self.fixturenames_not_in_sig: self.fixturenames = tuple(self.fixturenames_not_in_sig + list(self.fixturenames)) # get parametrization marks self.pmarks = get_pytest_parametrize_marks(self.function) if self.is_parametrized: self.update_callspecs() # preserve order self.required_fixtures = tuple(f for f in self.fixturenames if f not in self._calls[0].funcargs) else: self.required_fixtures = self.fixturenames
def __init__(self, func): from .plugin import PYTEST_CONFIG # late import to ensure config has been loaded by now self.config = PYTEST_CONFIG # self.config can be `None` if the same module is reloaded by another thread/process inside a test (parallelism) # In that case, a priori we are outside the pytest main runner so we can silently ignore, this # MetaFunc will not be used/read by anyone. # See https://github.com/smarie/python-pytest-cases/issues/242 # # if self.config is None: # if pytest_is_running(): # raise ValueError("Internal error - config has not been correctly loaded. Please report") self.function = func self.definition = MiniFuncDef(func.__name__) self._calls = [] # non-default parameters self.fixturenames = getfuncargnames(func) # add declared used fixtures with @pytest.mark.usefixtures self.fixturenames_not_in_sig = [ f for f in get_pytest_usefixture_marks(func) if f not in self.fixturenames ] if self.fixturenames_not_in_sig: self.fixturenames = tuple(self.fixturenames_not_in_sig + list(self.fixturenames)) # get parametrization marks self.pmarks = get_pytest_parametrize_marks(self.function) if self.is_parametrized: self.update_callspecs() # preserve order self.required_fixtures = tuple(f for f in self.fixturenames if f not in self._calls[0].funcargs) else: self.required_fixtures = self.fixturenames