internally make varnames() deal with classes's __init__,

although it's not needed by pytest itself atm.  Also
fix caching.  Fixes issue376.
This commit is contained in:
holger krekel 2013-11-19 15:33:52 +01:00
parent dde0a81677
commit 9b21d3f206
3 changed files with 37 additions and 8 deletions

View File

@ -48,6 +48,10 @@ Unreleased
- xfail a test on pypy that checks wrong encoding/ascii (pypy does
not error out). fixes issue385.
- internally make varnames() deal with classes's __init__,
although it's not needed by pytest itself atm. Also
fix caching. Fixes issue376.
Changes between 2.4.1 and 2.4.2
-----------------------------------

View File

@ -304,19 +304,36 @@ class MultiCall:
return kwargs
def varnames(func):
""" return argument name tuple for a function, method, class or callable.
In case of a class, its "__init__" method is considered.
For methods the "self" parameter is not included unless you are passing
an unbound method with Python3 (which has no supports for unbound methods)
"""
cache = getattr(func, "__dict__", {})
try:
return func._varnames
except AttributeError:
return cache["_varnames"]
except KeyError:
pass
if not inspect.isfunction(func) and not inspect.ismethod(func):
func = getattr(func, '__call__', func)
ismethod = inspect.ismethod(func)
if inspect.isclass(func):
try:
func = func.__init__
except AttributeError:
return ()
ismethod = True
else:
if not inspect.isfunction(func) and not inspect.ismethod(func):
func = getattr(func, '__call__', func)
ismethod = inspect.ismethod(func)
rawcode = py.code.getrawcode(func)
try:
x = rawcode.co_varnames[ismethod:rawcode.co_argcount]
except AttributeError:
x = ()
py.builtin._getfuncdict(func)['_varnames'] = x
try:
cache["_varnames"] = x
except TypeError:
pass
return x
class HookRelay:

View File

@ -438,6 +438,15 @@ def test_varnames():
assert varnames(A().f) == ('y',)
assert varnames(B()) == ('z',)
def test_varnames_class():
class C:
def __init__(self, x):
pass
class D:
pass
assert varnames(C) == ("x",)
assert varnames(D) == ()
class TestMultiCall:
def test_uses_copy_of_methods(self):
l = [lambda: 42]
@ -654,8 +663,7 @@ def test_default_markers(testdir):
def test_importplugin_issue375(testdir):
testdir.makepyfile(qwe="import aaaa")
with pytest.raises(ImportError) as excinfo:
importplugin("qwe")
excinfo = pytest.raises(ImportError, lambda: importplugin("qwe"))
assert "qwe" not in str(excinfo.value)
assert "aaaa" in str(excinfo.value)