From a0cefb32138fe2ff7ca1d7797de58bc85faf967b Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Wed, 16 Sep 2015 06:33:53 -0400 Subject: [PATCH 1/7] Use inspect.signature instead of inspect.getargspec --- _pytest/python.py | 26 +++++++++++++++++++++++--- testing/test_runner.py | 5 ++++- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/_pytest/python.py b/_pytest/python.py index 414ec545e..618aef058 100644 --- a/_pytest/python.py +++ b/_pytest/python.py @@ -32,6 +32,26 @@ 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 _has_positional_arg(func): + sig = inspect.signature(func) + params = list(sig.parameters.values()) + if len(params): + return params[0].kind in (sig.POSITIONAL_ONLY, sig.POSITIONAL_OR_KEYWORD) + else: + return False + + def _format_args(func): + return str(inspect.signature(func)) +else: + def _has_positional_arg(func): + return inspect.getargspec(func)[0] is not None + + def _format_args(func): + return inspect.formatargspec(*inspect.getargspec(func)) + + def filter_traceback(entry): return entry.path != cutdir1 and not entry.path.relto(cutdir2) @@ -586,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() @@ -597,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 @@ -1580,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/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 From 859259ddae9508d218d1de71eba51ff43636c1f1 Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Wed, 16 Sep 2015 06:43:16 -0400 Subject: [PATCH 2/7] Simplify --- _pytest/python.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_pytest/python.py b/_pytest/python.py index 618aef058..6f811c296 100644 --- a/_pytest/python.py +++ b/_pytest/python.py @@ -37,7 +37,7 @@ if hasattr(inspect, 'signature'): def _has_positional_arg(func): sig = inspect.signature(func) params = list(sig.parameters.values()) - if len(params): + if params: return params[0].kind in (sig.POSITIONAL_ONLY, sig.POSITIONAL_OR_KEYWORD) else: return False From 9c19728d2ba9da18b7face1e3b97fe3012ecfbb2 Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Wed, 16 Sep 2015 06:45:51 -0400 Subject: [PATCH 3/7] Fix checking for args --- _pytest/python.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_pytest/python.py b/_pytest/python.py index 6f811c296..ce3ae471f 100644 --- a/_pytest/python.py +++ b/_pytest/python.py @@ -46,7 +46,7 @@ if hasattr(inspect, 'signature'): return str(inspect.signature(func)) else: def _has_positional_arg(func): - return inspect.getargspec(func)[0] is not None + return bool(inspect.getargspec(func).args) def _format_args(func): return inspect.formatargspec(*inspect.getargspec(func)) From 08a572086bd0f67a9fe45d0b073f1c1db6a17038 Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Wed, 16 Sep 2015 11:02:36 -0400 Subject: [PATCH 4/7] Fix lookup of special values --- _pytest/python.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/_pytest/python.py b/_pytest/python.py index ce3ae471f..ddd9d78e6 100644 --- a/_pytest/python.py +++ b/_pytest/python.py @@ -38,7 +38,8 @@ if hasattr(inspect, 'signature'): sig = inspect.signature(func) params = list(sig.parameters.values()) if params: - return params[0].kind in (sig.POSITIONAL_ONLY, sig.POSITIONAL_OR_KEYWORD) + return params[0].kind in (params[0].POSITIONAL_ONLY, + params[0].POSITIONAL_OR_KEYWORD) else: return False From 9a84c9edb616bcffb275905eea53eab810879f12 Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Wed, 16 Sep 2015 11:02:48 -0400 Subject: [PATCH 5/7] Add tests for argument formatting --- testing/python/metafunc.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/testing/python/metafunc.py b/testing/python/metafunc.py index ce84f7a57..afce579e6 100644 --- a/testing/python/metafunc.py +++ b/testing/python/metafunc.py @@ -21,6 +21,7 @@ class TestMetafunc: metafunc = self.Metafunc(function) assert not metafunc.fixturenames repr(metafunc._calls) + assert funcargs._format_args(function) == '()' def test_function_basic(self): def func(arg1, arg2="qwe"): pass @@ -29,6 +30,7 @@ class TestMetafunc: assert 'arg1' in metafunc.fixturenames assert metafunc.function is func assert metafunc.cls is None + assert funcargs._format_args(func) == "(arg1, arg2='qwe')" def test_addcall_no_args(self): def func(arg1): pass @@ -38,6 +40,7 @@ class TestMetafunc: call = metafunc._calls[0] assert call.id == "0" assert not hasattr(call, 'param') + assert funcargs._format_args(func) == "(arg1)" def test_addcall_id(self): def func(arg1): pass @@ -85,6 +88,7 @@ class TestMetafunc: metafunc.parametrize("y", [1,2]) pytest.raises(ValueError, lambda: metafunc.parametrize("y", [5,6])) pytest.raises(ValueError, lambda: metafunc.parametrize("y", [5,6])) + assert funcargs._format_args(func) == '(x, y)' def test_parametrize_and_id(self): def func(x, y): pass From bf74401fd311cc91aa64aa072314dcc21b345ea8 Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Wed, 16 Sep 2015 11:05:54 -0400 Subject: [PATCH 6/7] Use __code__.co_argcount --- _pytest/python.py | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/_pytest/python.py b/_pytest/python.py index ddd9d78e6..10cb599c2 100644 --- a/_pytest/python.py +++ b/_pytest/python.py @@ -34,25 +34,17 @@ REGEX_TYPE = type(re.compile('')) if hasattr(inspect, 'signature'): - def _has_positional_arg(func): - sig = inspect.signature(func) - params = list(sig.parameters.values()) - if params: - return params[0].kind in (params[0].POSITIONAL_ONLY, - params[0].POSITIONAL_OR_KEYWORD) - else: - return False - def _format_args(func): return str(inspect.signature(func)) else: - def _has_positional_arg(func): - return bool(inspect.getargspec(func).args) - 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) From 7f71ce0ab2b3a307e4c55a6ed1b1ecf56af312e6 Mon Sep 17 00:00:00 2001 From: Michael Droettboom Date: Wed, 16 Sep 2015 16:52:37 -0400 Subject: [PATCH 7/7] Reorganize tests --- testing/python/metafunc.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/testing/python/metafunc.py b/testing/python/metafunc.py index afce579e6..04e4a4aeb 100644 --- a/testing/python/metafunc.py +++ b/testing/python/metafunc.py @@ -21,7 +21,6 @@ class TestMetafunc: metafunc = self.Metafunc(function) assert not metafunc.fixturenames repr(metafunc._calls) - assert funcargs._format_args(function) == '()' def test_function_basic(self): def func(arg1, arg2="qwe"): pass @@ -30,7 +29,6 @@ class TestMetafunc: assert 'arg1' in metafunc.fixturenames assert metafunc.function is func assert metafunc.cls is None - assert funcargs._format_args(func) == "(arg1, arg2='qwe')" def test_addcall_no_args(self): def func(arg1): pass @@ -40,7 +38,6 @@ class TestMetafunc: call = metafunc._calls[0] assert call.id == "0" assert not hasattr(call, 'param') - assert funcargs._format_args(func) == "(arg1)" def test_addcall_id(self): def func(arg1): pass @@ -88,7 +85,6 @@ class TestMetafunc: metafunc.parametrize("y", [1,2]) pytest.raises(ValueError, lambda: metafunc.parametrize("y", [5,6])) pytest.raises(ValueError, lambda: metafunc.parametrize("y", [5,6])) - assert funcargs._format_args(func) == '(x, y)' def test_parametrize_and_id(self): def func(x, y): pass @@ -477,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("""