funcargs work mostly according to the documentation

--HG--
branch : trunk
This commit is contained in:
holger krekel 2009-04-14 18:30:26 +02:00
parent f0a277008a
commit 763d0d72a5
20 changed files with 136 additions and 160 deletions

View File

@ -5,10 +5,10 @@ rsyncignore = ['c-extension/greenlet/build']
import py import py
class PylibTestconfigPlugin: class PylibTestconfigPlugin:
def pytest_funcarg__specssh(self, pyfuncitem): def pytest_funcarg__specssh(self, request):
return getspecssh(pyfuncitem.config) return getspecssh(request.config)
def pytest_funcarg__specsocket(self, pyfuncitem): def pytest_funcarg__specsocket(self, request):
return getsocketspec(pyfuncitem.config) return getsocketspec(request.config)
def pytest_addoption(self, parser): def pytest_addoption(self, parser):
group = parser.addgroup("pylib", "py lib testing options") group = parser.addgroup("pylib", "py lib testing options")

View File

@ -1,28 +1,25 @@
""" RSync filter test
"""
import py import py
from py.__.test.dist.nodemanage import NodeManager from py.__.test.dist.nodemanage import NodeManager
def pytest_funcarg__source(pyfuncitem): class pytest_funcarg__mysetup:
return py.test.ensuretemp(pyfuncitem.getmodpath()).mkdir("source") def __init__(self, request):
def pytest_funcarg__dest(pyfuncitem): basetemp = request.config.ensuretemp(request.getfspath().purebasename)
dest = py.test.ensuretemp(pyfuncitem.getmodpath()).mkdir("dest") basetemp = basetemp.mkdir(request.funcname)
return dest self.source = basetemp.mkdir("source")
self.dest = basetemp.mkdir("dest")
class TestNodeManager: class TestNodeManager:
@py.test.mark.xfail("consider / forbid implicit rsyncdirs?") @py.test.mark.xfail("consider / forbid implicit rsyncdirs?")
def test_rsync_roots_no_roots(self, source, dest): def test_rsync_roots_no_roots(self, mysetup):
source.ensure("dir1", "file1").write("hello") mysetup.source.ensure("dir1", "file1").write("hello")
config = py.test.config._reparse([source]) config = py.test.config._reparse([source])
nodemanager = NodeManager(config, ["popen//chdir=%s" % dest]) nodemanager = NodeManager(config, ["popen//chdir=%s" % mysetup.dest])
assert nodemanager.config.topdir == source == config.topdir assert nodemanager.config.topdir == source == config.topdir
nodemanager.rsync_roots() nodemanager.rsync_roots()
p, = nodemanager.gwmanager.multi_exec("import os ; channel.send(os.getcwd())").receive_each() p, = nodemanager.gwmanager.multi_exec("import os ; channel.send(os.getcwd())").receive_each()
p = py.path.local(p) p = py.path.local(p)
print "remote curdir", p print "remote curdir", p
assert p == dest.join(config.topdir.basename) assert p == mysetup.dest.join(config.topdir.basename)
assert p.join("dir1").check() assert p.join("dir1").check()
assert p.join("dir1", "file1").check() assert p.join("dir1", "file1").check()
@ -33,8 +30,9 @@ class TestNodeManager:
nodemanager.setup_nodes([].append) nodemanager.setup_nodes([].append)
nodemanager.wait_nodesready(timeout=2.0) nodemanager.wait_nodesready(timeout=2.0)
def test_popen_rsync_subdir(self, testdir, source, dest): def test_popen_rsync_subdir(self, testdir, mysetup):
dir1 = source.mkdir("dir1") source, dest = mysetup.source, mysetup.dest
dir1 = mysetup.source.mkdir("dir1")
dir2 = dir1.mkdir("dir2") dir2 = dir1.mkdir("dir2")
dir2.ensure("hello") dir2.ensure("hello")
for rsyncroot in (dir1, source): for rsyncroot in (dir1, source):
@ -53,7 +51,8 @@ class TestNodeManager:
assert dest.join("dir1", "dir2", 'hello').check() assert dest.join("dir1", "dir2", 'hello').check()
nodemanager.gwmanager.exit() nodemanager.gwmanager.exit()
def test_init_rsync_roots(self, source, dest): def test_init_rsync_roots(self, mysetup):
source, dest = mysetup.source, mysetup.dest
dir2 = source.ensure("dir1", "dir2", dir=1) dir2 = source.ensure("dir1", "dir2", dir=1)
source.ensure("dir1", "somefile", dir=1) source.ensure("dir1", "somefile", dir=1)
dir2.ensure("hello") dir2.ensure("hello")
@ -68,7 +67,8 @@ class TestNodeManager:
assert not dest.join("dir1").check() assert not dest.join("dir1").check()
assert not dest.join("bogus").check() assert not dest.join("bogus").check()
def test_rsyncignore(self, source, dest): def test_rsyncignore(self, mysetup):
source, dest = mysetup.source, mysetup.dest
dir2 = source.ensure("dir1", "dir2", dir=1) dir2 = source.ensure("dir1", "dir2", dir=1)
dir5 = source.ensure("dir5", "dir6", "bogus") dir5 = source.ensure("dir5", "dir6", "bogus")
dirf = source.ensure("dir5", "file") dirf = source.ensure("dir5", "file")
@ -86,7 +86,8 @@ class TestNodeManager:
assert dest.join("dir5","file").check() assert dest.join("dir5","file").check()
assert not dest.join("dir6").check() assert not dest.join("dir6").check()
def test_optimise_popen(self, source, dest): def test_optimise_popen(self, mysetup):
source, dest = mysetup.source, mysetup.dest
specs = ["popen"] * 3 specs = ["popen"] * 3
source.join("conftest.py").write("rsyncdirs = ['a']") source.join("conftest.py").write("rsyncdirs = ['a']")
source.ensure('a', dir=1) source.ensure('a', dir=1)
@ -97,7 +98,8 @@ class TestNodeManager:
assert gwspec._samefilesystem() assert gwspec._samefilesystem()
assert not gwspec.chdir assert not gwspec.chdir
def test_setup_DEBUG(self, source, testdir): def test_setup_DEBUG(self, mysetup, testdir):
source = mysetup.source
specs = ["popen"] * 2 specs = ["popen"] * 2
source.join("conftest.py").write("rsyncdirs = ['a']") source.join("conftest.py").write("rsyncdirs = ['a']")
source.ensure('a', dir=1) source.ensure('a', dir=1)

View File

@ -31,8 +31,8 @@ class EventQueue:
print str(kwargs["excrepr"]) print str(kwargs["excrepr"])
class MySetup: class MySetup:
def __init__(self, pyfuncitem): def __init__(self, request):
self.pyfuncitem = pyfuncitem self.request = request
def geteventargs(self, eventname, timeout=2.0): def geteventargs(self, eventname, timeout=2.0):
eq = EventQueue(self.config.pluginmanager, self.queue) eq = EventQueue(self.config.pluginmanager, self.queue)
@ -55,17 +55,11 @@ class MySetup:
print "exiting:", gw print "exiting:", gw
gw.exit() gw.exit()
def pytest_funcarg__mysetup(pyfuncitem): def pytest_funcarg__mysetup(request):
mysetup = MySetup(pyfuncitem) mysetup = MySetup(request)
#pyfuncitem.addfinalizer(mysetup.finalize) #pyfuncitem.addfinalizer(mysetup.finalize)
return mysetup return mysetup
def pytest_funcarg__testdir(__call__, pyfuncitem):
# decorate to make us always change to testdir
testdir = __call__.execute(firstresult=True)
testdir.chdir()
return testdir
def test_node_hash_equality(mysetup): def test_node_hash_equality(mysetup):
node = mysetup.makenode() node = mysetup.makenode()
node2 = mysetup.makenode() node2 = mysetup.makenode()

View File

@ -1,19 +1,19 @@
import py import py
class _pytestPlugin: class _pytestPlugin:
def pytest_funcarg___pytest(self, pyfuncitem): def pytest_funcarg___pytest(self, request):
return PytestArg(pyfuncitem) return PytestArg(request)
class PytestArg: class PytestArg:
def __init__(self, pyfuncitem): def __init__(self, request):
self.pyfuncitem = pyfuncitem self.request = request
def getcallrecorder(self, apiclass, comregistry=None): def getcallrecorder(self, apiclass, comregistry=None):
if comregistry is None: if comregistry is None:
comregistry = self.pyfuncitem.config.pluginmanager.comregistry comregistry = self.request.config.pluginmanager.comregistry
callrecorder = CallRecorder(comregistry) callrecorder = CallRecorder(comregistry)
callrecorder.start_recording(apiclass) callrecorder.start_recording(apiclass)
self.pyfuncitem.addfinalizer(callrecorder.finalize) self.request.addfinalizer(callrecorder.finalize)
return callrecorder return callrecorder

View File

@ -22,7 +22,6 @@ class DefaultPlugin:
rep = runner.ItemTestReport(item, excinfo, "execute", outerr) rep = runner.ItemTestReport(item, excinfo, "execute", outerr)
item.config.api.pytest_itemtestreport(rep=rep) item.config.api.pytest_itemtestreport(rep=rep)
# XXX make this access pyfuncitem.args or funcargs
def pytest_pyfunc_call(self, pyfuncitem, args, kwargs): def pytest_pyfunc_call(self, pyfuncitem, args, kwargs):
pyfuncitem.obj(*args, **kwargs) pyfuncitem.obj(*args, **kwargs)

View File

@ -2,14 +2,14 @@ import py
class IocapturePlugin: class IocapturePlugin:
""" capture sys.stdout/sys.stderr / fd1/fd2. """ """ capture sys.stdout/sys.stderr / fd1/fd2. """
def pytest_funcarg__stdcapture(self, pyfuncitem): def pytest_funcarg__stdcapture(self, request):
capture = Capture(py.io.StdCapture) capture = Capture(py.io.StdCapture)
pyfuncitem.addfinalizer(capture.finalize) request.addfinalizer(capture.finalize)
return capture return capture
def pytest_funcarg__stdcapturefd(self, pyfuncitem): def pytest_funcarg__stdcapturefd(self, request):
capture = Capture(py.io.StdCaptureFD) capture = Capture(py.io.StdCaptureFD)
pyfuncitem.addfinalizer(capture.finalize) request.addfinalizer(capture.finalize)
return capture return capture
class Capture: class Capture:

View File

@ -2,9 +2,9 @@ import os
class MonkeypatchPlugin: class MonkeypatchPlugin:
""" setattr-monkeypatching with automatical reversal after test. """ """ setattr-monkeypatching with automatical reversal after test. """
def pytest_funcarg__monkeypatch(self, pyfuncitem): def pytest_funcarg__monkeypatch(self, request):
monkeypatch = MonkeyPatch() monkeypatch = MonkeyPatch()
pyfuncitem.addfinalizer(monkeypatch.finalize) request.addfinalizer(monkeypatch.finalize)
return monkeypatch return monkeypatch
notset = object() notset = object()

View File

@ -6,37 +6,23 @@ from py.__.test.plugin import api
class PlugintesterPlugin: class PlugintesterPlugin:
""" test support code for testing pytest plugins. """ """ test support code for testing pytest plugins. """
def pytest_funcarg__plugintester(self, pyfuncitem): def pytest_funcarg__plugintester(self, request):
pt = PluginTester(pyfuncitem) return PluginTester(request)
pyfuncitem.addfinalizer(pt.finalize)
return pt
class Support(object): class PluginTester:
def __init__(self, pyfuncitem): def __init__(self, request):
""" instantiated per function that requests it. """ self.request = request
self.pyfuncitem = pyfuncitem
def getmoditem(self):
for colitem in self.pyfuncitem.listchain():
if isinstance(colitem, colitem.Module):
return colitem
def finalize(self):
""" called after test function finished execution"""
class PluginTester(Support):
def testdir(self): def testdir(self):
# XXX import differently, eg.
# FSTester = self.pyfuncitem.config.pluginmanager.getpluginattr("pytester", "FSTester")
from pytest_pytester import TmpTestdir from pytest_pytester import TmpTestdir
crunner = TmpTestdir(self.pyfuncitem) crunner = TmpTestdir(self.request)
self.pyfuncitem.addfinalizer(crunner.finalize) self.request.addfinalizer(crunner.finalize)
# #
for colitem in self.pyfuncitem.listchain(): #for colitem in self.request.listchain():
if isinstance(colitem, py.test.collect.Module) and \ # if isinstance(colitem, py.test.collect.Module) and \
colitem.name.startswith("pytest_"): # colitem.name.startswith("pytest_"):
crunner.plugins.append(colitem.fspath.purebasename) # crunner.plugins.append(colitem.fspath.purebasename)
break # break
return crunner return crunner
def apicheck(self, pluginclass): def apicheck(self, pluginclass):

View File

@ -11,19 +11,19 @@ import api
class PytesterPlugin: class PytesterPlugin:
def pytest_funcarg__linecomp(self, pyfuncitem): def pytest_funcarg__linecomp(self, request):
return LineComp() return LineComp()
def pytest_funcarg__LineMatcher(self, pyfuncitem): def pytest_funcarg__LineMatcher(self, request):
return LineMatcher return LineMatcher
def pytest_funcarg__testdir(self, pyfuncitem): def pytest_funcarg__testdir(self, request):
tmptestdir = TmpTestdir(pyfuncitem) tmptestdir = TmpTestdir(request)
return tmptestdir return tmptestdir
def pytest_funcarg__eventrecorder(self, pyfuncitem): def pytest_funcarg__eventrecorder(self, request):
evrec = EventRecorder(py._com.comregistry) evrec = EventRecorder(py._com.comregistry)
pyfuncitem.addfinalizer(lambda: evrec.comregistry.unregister(evrec)) request.addfinalizer(lambda: evrec.comregistry.unregister(evrec))
return evrec return evrec
def test_generic(plugintester): def test_generic(plugintester):
@ -38,11 +38,11 @@ class RunResult:
self.stderr = LineMatcher(errlines) self.stderr = LineMatcher(errlines)
class TmpTestdir: class TmpTestdir:
def __init__(self, pyfuncitem): def __init__(self, request):
self.pyfuncitem = pyfuncitem self.request = request
# XXX remove duplication with tmpdir plugin # XXX remove duplication with tmpdir plugin
basetmp = pyfuncitem.config.ensuretemp("testdir") basetmp = request.config.ensuretemp("testdir")
name = pyfuncitem.name name = request.funcname
for i in range(100): for i in range(100):
try: try:
tmpdir = basetmp.mkdir(name + str(i)) tmpdir = basetmp.mkdir(name + str(i))
@ -57,7 +57,7 @@ class TmpTestdir:
self._syspathremove = [] self._syspathremove = []
self.chdir() # always chdir self.chdir() # always chdir
assert hasattr(self, '_olddir') assert hasattr(self, '_olddir')
self.pyfuncitem.addfinalizer(self.finalize) self.request.addfinalizer(self.finalize)
def __repr__(self): def __repr__(self):
return "<TmpTestdir %r>" % (self.tmpdir,) return "<TmpTestdir %r>" % (self.tmpdir,)
@ -78,7 +78,7 @@ class TmpTestdir:
sorter.callrecorder = CallRecorder(registry) sorter.callrecorder = CallRecorder(registry)
sorter.callrecorder.start_recording(api.PluginHooks) sorter.callrecorder.start_recording(api.PluginHooks)
sorter.api = sorter.callrecorder.api sorter.api = sorter.callrecorder.api
self.pyfuncitem.addfinalizer(sorter.callrecorder.finalize) self.request.addfinalizer(sorter.callrecorder.finalize)
return sorter return sorter
def chdir(self): def chdir(self):
@ -90,7 +90,7 @@ class TmpTestdir:
items = kwargs.items() items = kwargs.items()
if args: if args:
source = "\n".join(map(str, args)) source = "\n".join(map(str, args))
basename = self.pyfuncitem.name basename = self.request.funcname
items.insert(0, (basename, source)) items.insert(0, (basename, source))
ret = None ret = None
for name, value in items: for name, value in items:
@ -139,7 +139,7 @@ class TmpTestdir:
# used from runner functional tests # used from runner functional tests
item = self.getitem(source) item = self.getitem(source)
# the test class where we are called from wants to provide the runner # the test class where we are called from wants to provide the runner
testclassinstance = self.pyfuncitem.obj.im_self testclassinstance = self.request.function.im_self
runner = testclassinstance.getrunner() runner = testclassinstance.getrunner()
return runner(item, **runnerargs) return runner(item, **runnerargs)
@ -200,7 +200,7 @@ class TmpTestdir:
return self.config.getfsnode(path) return self.config.getfsnode(path)
def getmodulecol(self, source, configargs=(), withinit=False): def getmodulecol(self, source, configargs=(), withinit=False):
kw = {self.pyfuncitem.name: py.code.Source(source).strip()} kw = {self.request.funcname: py.code.Source(source).strip()}
path = self.makepyfile(**kw) path = self.makepyfile(**kw)
if withinit: if withinit:
self.makepyfile(__init__ = "#") self.makepyfile(__init__ = "#")
@ -455,3 +455,10 @@ class LineMatcher:
return extralines return extralines
def test_parseconfig(testdir):
config1 = testdir.parseconfig()
config2 = testdir.parseconfig()
assert config2 != config1
assert config1 != py.test.config

View File

@ -382,10 +382,15 @@ class TestApigenLinkRole:
"resolve_linkrole('source', 'py/foo/bar.py')") "resolve_linkrole('source', 'py/foo/bar.py')")
def pytest_funcarg__testdir(__call__, pyfuncitem): def pytest_funcarg__testdir(request):
testdir = __call__.execute(firstresult=True) testdir = request.call_next_provider()
testdir.makepyfile(confrest="from py.__.misc.rest import Project") testdir.makepyfile(confrest="from py.__.misc.rest import Project")
testdir.plugins.append(RestdocPlugin()) testdir.plugins.append(RestdocPlugin())
count = 0
for p in testdir.plugins:
if isinstance(p, RestdocPlugin):
count += 1
assert count < 2
return testdir return testdir
class TestDoctest: class TestDoctest:

View File

@ -1,4 +1,3 @@
import uuid
import py import py
from pytest_resultlog import ResultLog from pytest_resultlog import ResultLog
@ -65,7 +64,7 @@ class JSONResultArchive(object):
self._flush() self._flush()
def append_data(self, data): def append_data(self, data):
runid = uuid.uuid4() runid = py.std.uuid.uuid4()
for item in data: for item in data:
item = item.copy() item = item.copy()
item['runid'] = str(runid) item['runid'] = str(runid)
@ -100,7 +99,7 @@ class SQLiteResultArchive(object):
def append_data(self, data): def append_data(self, data):
flat_data = [] flat_data = []
runid = uuid.uuid4() runid = py.std.uuid.uuid4()
for item in data: for item in data:
item = item.copy() item = item.copy()
item['runid'] = str(runid) item['runid'] = str(runid)

View File

@ -157,6 +157,7 @@ class TestWithFunctionIntegration:
# ignorant regarding formatting details. # ignorant regarding formatting details.
def getresultlog(self, testdir, arg): def getresultlog(self, testdir, arg):
resultlog = testdir.tmpdir.join("resultlog") resultlog = testdir.tmpdir.join("resultlog")
testdir.plugins.append("resultlog")
args = ["--resultlog=%s" % resultlog] + [arg] args = ["--resultlog=%s" % resultlog] + [arg]
testdir.runpytest(*args) testdir.runpytest(*args)
return filter(None, resultlog.readlines(cr=0)) return filter(None, resultlog.readlines(cr=0))
@ -166,7 +167,6 @@ class TestWithFunctionIntegration:
ok = testdir.makepyfile(test_collection_ok="") ok = testdir.makepyfile(test_collection_ok="")
skip = testdir.makepyfile(test_collection_skip="import py ; py.test.skip('hello')") skip = testdir.makepyfile(test_collection_skip="import py ; py.test.skip('hello')")
fail = testdir.makepyfile(test_collection_fail="XXX") fail = testdir.makepyfile(test_collection_fail="XXX")
lines = self.getresultlog(testdir, ok) lines = self.getresultlog(testdir, ok)
assert not lines assert not lines
@ -226,6 +226,7 @@ class TestWithFunctionIntegration:
def test_generic(plugintester, LineMatcher): def test_generic(plugintester, LineMatcher):
plugintester.apicheck(ResultlogPlugin) plugintester.apicheck(ResultlogPlugin)
testdir = plugintester.testdir() testdir = plugintester.testdir()
testdir.plugins.append("resultlog")
testdir.makepyfile(""" testdir.makepyfile("""
import py import py
def test_pass(): def test_pass():

View File

@ -13,9 +13,9 @@ class TmpdirPlugin:
""" provide temporary directories to test functions and methods. """ provide temporary directories to test functions and methods.
""" """
def pytest_funcarg__tmpdir(self, pyfuncitem): def pytest_funcarg__tmpdir(self, request):
name = pyfuncitem.name name = request.funcname
return pyfuncitem.config.mktemp(name, numbered=True) return request.config.mktemp(name, numbered=True)
# =============================================================================== # ===============================================================================
# #
@ -29,7 +29,7 @@ def test_generic(plugintester):
def test_funcarg(testdir): def test_funcarg(testdir):
item = testdir.getitem("def test_func(tmpdir): pass") item = testdir.getitem("def test_func(tmpdir): pass")
plugin = TmpdirPlugin() plugin = TmpdirPlugin()
p = plugin.pytest_funcarg__tmpdir(item) p = plugin.pytest_funcarg__tmpdir(item.getrequest("tmpdir"))
assert p.check() assert p.check()
bn = p.basename.strip("0123456789-") bn = p.basename.strip("0123456789-")
assert bn.endswith("test_func") assert bn.endswith("test_func")

View File

@ -18,6 +18,7 @@ class PluginManager(object):
def register(self, plugin): def register(self, plugin):
self.api.pytest_plugin_registered(plugin=plugin) self.api.pytest_plugin_registered(plugin=plugin)
import types
self.comregistry.register(plugin) self.comregistry.register(plugin)
def unregister(self, plugin): def unregister(self, plugin):

View File

@ -177,7 +177,7 @@ class Module(py.test.collect.File, PyCollectorMixin):
#print "*" * 20, "INVOKE assertion", self #print "*" * 20, "INVOKE assertion", self
py.magic.invoke(assertion=1) py.magic.invoke(assertion=1)
mod = self.obj mod = self.obj
self.config.pluginmanager.register(mod) #self.config.pluginmanager.register(mod)
if hasattr(mod, 'setup_module'): if hasattr(mod, 'setup_module'):
self.obj.setup_module(mod) self.obj.setup_module(mod)
@ -187,7 +187,7 @@ class Module(py.test.collect.File, PyCollectorMixin):
if not self.config.option.nomagic: if not self.config.option.nomagic:
#print "*" * 20, "revoke assertion", self #print "*" * 20, "revoke assertion", self
py.magic.revoke(assertion=1) py.magic.revoke(assertion=1)
self.config.pluginmanager.unregister(self.obj) #self.config.pluginmanager.unregister(self.obj)
class Class(PyCollectorMixin, py.test.collect.Collector): class Class(PyCollectorMixin, py.test.collect.Collector):
@ -366,7 +366,8 @@ class Function(FunctionMixin, py.test.collect.Item):
if i < startindex: if i < startindex:
continue continue
try: try:
self.funcargs[argname] = self.lookup_onearg(argname) argvalue = self.getrequest(argname).call_next_provider()
self.funcargs[argname] = argvalue
except LookupError, e: except LookupError, e:
numdefaults = len(funcobj.func_defaults or ()) numdefaults = len(funcobj.func_defaults or ())
if i + numdefaults >= len(argnames): if i + numdefaults >= len(argnames):
@ -374,15 +375,6 @@ class Function(FunctionMixin, py.test.collect.Item):
else: else:
raise raise
def lookup_onearg(self, argname):
prefix = "pytest_funcarg__"
#makerlist = self.config.pluginmanager.listattr(prefix + argname)
value = self.config.pluginmanager.call_firstresult(prefix + argname, pyfuncitem=self)
if value is not None:
return value
else:
self._raisefuncargerror(argname, prefix)
def _raisefuncargerror(self, argname, prefix="pytest_funcarg__"): def _raisefuncargerror(self, argname, prefix="pytest_funcarg__"):
metainfo = self.repr_metainfo() metainfo = self.repr_metainfo()
available = [] available = []
@ -419,9 +411,11 @@ class FuncargRequest:
""" error on performing funcarg request. """ """ error on performing funcarg request. """
def __init__(self, pyfuncitem, argname): def __init__(self, pyfuncitem, argname):
# XXX make pyfuncitem _pyfuncitem
self.pyfuncitem = pyfuncitem self.pyfuncitem = pyfuncitem
self.argname = argname self.argname = argname
self.function = pyfuncitem.obj self.function = pyfuncitem.obj
self.funcname = pyfuncitem.name
self.config = pyfuncitem.config self.config = pyfuncitem.config
extra = [] extra = []
current = pyfuncitem current = pyfuncitem
@ -434,11 +428,19 @@ class FuncargRequest:
extra=extra, extra=extra,
) )
def __repr__(self):
return "<FuncargRequest %r for %r>" %(self.argname, self.pyfuncitem)
def call_next_provider(self): def call_next_provider(self):
if not self._methods: if not self._methods:
raise self.Error("no provider methods left") raise self.Error("no provider methods left")
nextmethod = self._methods.pop() nextmethod = self._methods.pop()
print "calling", nextmethod
return nextmethod(request=self) return nextmethod(request=self)
def addfinalizer(self, finalizer): def addfinalizer(self, finalizer):
self.pyfuncitem.addfinalizer(finalizer) self.pyfuncitem.addfinalizer(finalizer)
def getfspath(self):
return self.pyfuncitem.fspath

View File

@ -1,2 +1,3 @@
pytest_plugins = "pytest_xfail", "pytest_pytester", "pytest_tmpdir" pytest_plugins = "pytest_xfail", "pytest_pytester", "pytest_tmpdir"

View File

@ -4,7 +4,7 @@ class TestFuncargs:
def test_funcarg_lookupfails(self, testdir): def test_funcarg_lookupfails(self, testdir):
testdir.makeconftest(""" testdir.makeconftest("""
class ConftestPlugin: class ConftestPlugin:
def pytest_funcarg__something(self, pyfuncitem): def pytest_funcarg__xyz(self, request):
return 42 return 42
""") """)
item = testdir.getitem("def test_func(some): pass") item = testdir.getitem("def test_func(some): pass")
@ -15,8 +15,8 @@ class TestFuncargs:
def test_funcarg_lookup_default(self, testdir): def test_funcarg_lookup_default(self, testdir):
item = testdir.getitem("def test_func(some, other=42): pass") item = testdir.getitem("def test_func(some, other=42): pass")
class Provider: class Provider:
def pytest_funcarg__some(self, pyfuncitem): def pytest_funcarg__some(self, request):
return pyfuncitem.name return request.funcname
item.config.pluginmanager.register(Provider()) item.config.pluginmanager.register(Provider())
item.setupargs() item.setupargs()
assert len(item.funcargs) == 1 assert len(item.funcargs) == 1
@ -24,8 +24,8 @@ class TestFuncargs:
def test_funcarg_lookup_default_gets_overriden(self, testdir): def test_funcarg_lookup_default_gets_overriden(self, testdir):
item = testdir.getitem("def test_func(some=42, other=13): pass") item = testdir.getitem("def test_func(some=42, other=13): pass")
class Provider: class Provider:
def pytest_funcarg__other(self, pyfuncitem): def pytest_funcarg__other(self, request):
return pyfuncitem.name return request.funcname
item.config.pluginmanager.register(Provider()) item.config.pluginmanager.register(Provider())
item.setupargs() item.setupargs()
assert len(item.funcargs) == 1 assert len(item.funcargs) == 1
@ -36,9 +36,9 @@ class TestFuncargs:
def test_funcarg_basic(self, testdir): def test_funcarg_basic(self, testdir):
item = testdir.getitem("def test_func(some, other): pass") item = testdir.getitem("def test_func(some, other): pass")
class Provider: class Provider:
def pytest_funcarg__some(self, pyfuncitem): def pytest_funcarg__some(self, request):
return pyfuncitem.name return request.funcname
def pytest_funcarg__other(self, pyfuncitem): def pytest_funcarg__other(self, request):
return 42 return 42
item.config.pluginmanager.register(Provider()) item.config.pluginmanager.register(Provider())
item.setupargs() item.setupargs()
@ -46,26 +46,10 @@ class TestFuncargs:
assert item.funcargs['some'] == "test_func" assert item.funcargs['some'] == "test_func"
assert item.funcargs['other'] == 42 assert item.funcargs['other'] == 42
def test_funcarg_addfinalizer(self, testdir):
item = testdir.getitem("def test_func(some): pass")
l = []
class Provider:
def pytest_funcarg__some(self, pyfuncitem):
pyfuncitem.addfinalizer(lambda: l.append(42))
return 3
item.config.pluginmanager.register(Provider())
item.setupargs()
assert len(item.funcargs) == 1
assert item.funcargs['some'] == 3
assert len(l) == 0
item.teardown()
assert len(l) == 1
assert l[0] == 42
def test_funcarg_lookup_modulelevel(self, testdir): def test_funcarg_lookup_modulelevel(self, testdir):
modcol = testdir.getmodulecol(""" modcol = testdir.getmodulecol("""
def pytest_funcarg__something(pyfuncitem): def pytest_funcarg__something(request):
return pyfuncitem.name return request.funcname
class TestClass: class TestClass:
def test_method(self, something): def test_method(self, something):
@ -74,14 +58,10 @@ class TestFuncargs:
pass pass
""") """)
item1, item2 = testdir.genitems([modcol]) item1, item2 = testdir.genitems([modcol])
modcol.setup()
assert modcol.config.pluginmanager.isregistered(modcol.obj)
item1.setupargs() item1.setupargs()
assert item1.funcargs['something'] == "test_method" assert item1.funcargs['something'] == "test_method"
item2.setupargs() item2.setupargs()
assert item2.funcargs['something'] == "test_func" assert item2.funcargs['something'] == "test_func"
modcol.teardown()
assert not modcol.config.pluginmanager.isregistered(modcol.obj)
class TestRequest: class TestRequest:
def test_request_attributes(self, testdir): def test_request_attributes(self, testdir):
@ -92,7 +72,9 @@ class TestRequest:
req = item.getrequest("other") req = item.getrequest("other")
assert req.argname == "other" assert req.argname == "other"
assert req.function == item.obj assert req.function == item.obj
assert req.funcname == "test_func"
assert req.config == item.config assert req.config == item.config
assert repr(req).find(req.funcname) != -1
def test_request_contains_funcargs_methods(self, testdir): def test_request_contains_funcargs_methods(self, testdir):
modcol = testdir.getmodulecol(""" modcol = testdir.getmodulecol("""
@ -131,3 +113,9 @@ class TestRequest:
l = [1] l = [1]
req.addfinalizer(l.pop) req.addfinalizer(l.pop)
item.teardown() item.teardown()
def test_request_getmodulepath(self, testdir):
modcol = testdir.getmodulecol("def test_somefunc(): pass")
item, = testdir.genitems([modcol])
req = item.getrequest("hello")
assert req.getfspath() == modcol.fspath

View File

@ -1,31 +1,27 @@
import py import py
def pytest_funcarg__pickletransport(pyfuncitem): def setglobals(request):
return ImmutablePickleTransport()
def pytest_pyfunc_call(__call__, pyfuncitem, args, kwargs):
# for each function call we patch py._com.comregistry
# so that the unpickling of config objects
# (which bind to this mechanism) doesn't do harm
# usually config objects are no meant to be unpickled in
# the same system
oldconfig = py.test.config oldconfig = py.test.config
oldcom = py._com.comregistry oldcom = py._com.comregistry
print "setting py.test.config to None" print "setting py.test.config to None"
py.test.config = None py.test.config = None
py._com.comregistry = py._com.Registry() py._com.comregistry = py._com.Registry()
try: def resetglobals():
return __call__.execute(firstresult=True)
finally:
print "setting py.test.config to", oldconfig print "setting py.test.config to", oldconfig
py.test.config = oldconfig py.test.config = oldconfig
py._com.comregistry = oldcom py._com.comregistry = oldcom
request.addfinalizer(resetglobals)
def pytest_funcarg__testdir(request):
setglobals(request)
return request.call_next_provider()
class ImmutablePickleTransport: class ImmutablePickleTransport:
def __init__(self): def __init__(self, request):
from py.__.test.dist.mypickle import ImmutablePickler from py.__.test.dist.mypickle import ImmutablePickler
self.p1 = ImmutablePickler(uneven=0) self.p1 = ImmutablePickler(uneven=0)
self.p2 = ImmutablePickler(uneven=1) self.p2 = ImmutablePickler(uneven=1)
setglobals(request)
def p1_to_p2(self, obj): def p1_to_p2(self, obj):
return self.p2.loads(self.p1.dumps(obj)) return self.p2.loads(self.p1.dumps(obj))
@ -39,6 +35,8 @@ class ImmutablePickleTransport:
return p2config return p2config
class TestImmutablePickling: class TestImmutablePickling:
pytest_funcarg__pickletransport = ImmutablePickleTransport
def test_pickle_config(self, testdir, pickletransport): def test_pickle_config(self, testdir, pickletransport):
config1 = testdir.parseconfig() config1 = testdir.parseconfig()
assert config1.topdir == testdir.tmpdir assert config1.topdir == testdir.tmpdir

View File

@ -34,13 +34,6 @@ class TestModule:
x = l.pop() x = l.pop()
assert x is None assert x is None
def test_module_participates_as_plugin(self, testdir):
modcol = testdir.getmodulecol("")
modcol.setup()
assert modcol.config.pluginmanager.isregistered(modcol.obj)
modcol.teardown()
assert not modcol.config.pluginmanager.isregistered(modcol.obj)
def test_module_considers_pluginmanager_at_import(self, testdir): def test_module_considers_pluginmanager_at_import(self, testdir):
modcol = testdir.getmodulecol("pytest_plugins='xasdlkj',") modcol = testdir.getmodulecol("pytest_plugins='xasdlkj',")
py.test.raises(ImportError, "modcol.obj") py.test.raises(ImportError, "modcol.obj")

View File

@ -10,7 +10,7 @@ class TestTracebackCutting:
def test_traceback_argsetup(self, testdir): def test_traceback_argsetup(self, testdir):
testdir.makeconftest(""" testdir.makeconftest("""
class ConftestPlugin: class ConftestPlugin:
def pytest_funcarg__hello(self, pyfuncitem): def pytest_funcarg__hello(self, request):
raise ValueError("xyz") raise ValueError("xyz")
""") """)
p = testdir.makepyfile("def test(hello): pass") p = testdir.makepyfile("def test(hello): pass")