diff --git a/_pytest/python.py b/_pytest/python.py index 7b9921b9a..95388ffcb 100644 --- a/_pytest/python.py +++ b/_pytest/python.py @@ -32,6 +32,19 @@ exc_clear = getattr(sys, 'exc_clear', lambda: None) # The type of re.compile objects is not exposed in Python. REGEX_TYPE = type(re.compile('')) + +if hasattr(inspect, 'signature'): + def _format_args(func): + return str(inspect.signature(func)) +else: + def _format_args(func): + return inspect.formatargspec(*inspect.getargspec(func)) + + +def _has_positional_arg(func): + return func.__code__.co_argcount + + def filter_traceback(entry): return entry.path != cutdir1 and not entry.path.relto(cutdir2) @@ -593,7 +606,7 @@ class Module(pytest.File, PyCollector): #XXX: nose compat hack, move to nose plugin # if it takes a positional arg, its probably a pytest style one # so we pass the current module object - if inspect.getargspec(setup_module)[0]: + if _has_positional_arg(setup_module): setup_module(self.obj) else: setup_module() @@ -604,7 +617,7 @@ class Module(pytest.File, PyCollector): #XXX: nose compat hack, move to nose plugin # if it takes a positional arg, it's probably a pytest style one # so we pass the current module object - if inspect.getargspec(fin)[0]: + if _has_positional_arg(fin): finalizer = lambda: fin(self.obj) else: finalizer = fin @@ -1587,7 +1600,7 @@ class FixtureRequest(FuncargnamesCompatAttr): factory = fixturedef.func fs, lineno = getfslineno(factory) p = self._pyfuncitem.session.fspath.bestrelpath(fs) - args = inspect.formatargspec(*inspect.getargspec(factory)) + args = _format_args(factory) lines.append("%s:%d: def %s%s" %( p, lineno, factory.__name__, args)) return lines diff --git a/testing/python/metafunc.py b/testing/python/metafunc.py index ce84f7a57..04e4a4aeb 100644 --- a/testing/python/metafunc.py +++ b/testing/python/metafunc.py @@ -473,6 +473,20 @@ class TestMetafunc: *6 passed* """) + def test_format_args(self): + def function1(): pass + assert funcargs._format_args(function1) == '()' + + def function2(arg1): pass + assert funcargs._format_args(function2) == "(arg1)" + + def function3(arg1, arg2="qwe"): pass + assert funcargs._format_args(function3) == "(arg1, arg2='qwe')" + + def function4(arg1, *args, **kwargs): pass + assert funcargs._format_args(function4) == "(arg1, *args, **kwargs)" + + class TestMetafuncFunctional: def test_attributes(self, testdir): p = testdir.makepyfile(""" diff --git a/testing/test_runner.py b/testing/test_runner.py index 3641ab8ca..b01727dbb 100644 --- a/testing/test_runner.py +++ b/testing/test_runner.py @@ -349,7 +349,10 @@ reporttypes = [ @pytest.mark.parametrize('reporttype', reporttypes, ids=[x.__name__ for x in reporttypes]) def test_report_extra_parameters(reporttype): - args = py.std.inspect.getargspec(reporttype.__init__)[0][1:] + if hasattr(py.std.inspect, 'signature'): + args = list(py.std.inspect.signature(reporttype.__init__).parameters.keys())[1:] + else: + args = py.std.inspect.getargspec(reporttype.__init__)[0][1:] basekw = dict.fromkeys(args, []) report = reporttype(newthing=1, **basekw) assert report.newthing == 1