[svn r63300] * refining pyfuncarg setup, now there is explicit registration!
* porting monkeypatch and pytester funcargs to the new method * fixing a kind-of-a-bug with MultiCalls --HG-- branch : trunk
This commit is contained in:
		
							parent
							
								
									5bf92423b7
								
							
						
					
					
						commit
						74958be548
					
				| 
						 | 
					@ -29,7 +29,7 @@ class MultiCall:
 | 
				
			||||||
    NONEASRESULT = object()
 | 
					    NONEASRESULT = object()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self, methods, *args, **kwargs):
 | 
					    def __init__(self, methods, *args, **kwargs):
 | 
				
			||||||
        self.methods = methods
 | 
					        self.methods = methods[:]
 | 
				
			||||||
        self.args = args 
 | 
					        self.args = args 
 | 
				
			||||||
        self.kwargs = kwargs 
 | 
					        self.kwargs = kwargs 
 | 
				
			||||||
        self.results = []
 | 
					        self.results = []
 | 
				
			||||||
| 
						 | 
					@ -69,6 +69,7 @@ class MultiCall:
 | 
				
			||||||
    def exclude_other_results(self):
 | 
					    def exclude_other_results(self):
 | 
				
			||||||
        self._ex1 = True
 | 
					        self._ex1 = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class PyPlugins:
 | 
					class PyPlugins:
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
        Manage Plugins: Load plugins and manage calls to plugins. 
 | 
					        Manage Plugins: Load plugins and manage calls to plugins. 
 | 
				
			||||||
| 
						 | 
					@ -79,7 +80,6 @@ class PyPlugins:
 | 
				
			||||||
        if plugins is None:
 | 
					        if plugins is None:
 | 
				
			||||||
            plugins = []
 | 
					            plugins = []
 | 
				
			||||||
        self._plugins = plugins
 | 
					        self._plugins = plugins
 | 
				
			||||||
        self._callbacks = []
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def import_module(self, modspec):
 | 
					    def import_module(self, modspec):
 | 
				
			||||||
        # XXX allow modspec to specify version / lookup 
 | 
					        # XXX allow modspec to specify version / lookup 
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,6 +6,13 @@ from py._com import PyPlugins, MultiCall
 | 
				
			||||||
pytest_plugins = "xfail"
 | 
					pytest_plugins = "xfail"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TestMultiCall:
 | 
					class TestMultiCall:
 | 
				
			||||||
 | 
					    def test_uses_copy_of_methods(self):
 | 
				
			||||||
 | 
					        l = [lambda: 42]
 | 
				
			||||||
 | 
					        mc = MultiCall(l)
 | 
				
			||||||
 | 
					        l[:] = []
 | 
				
			||||||
 | 
					        res = mc.execute()
 | 
				
			||||||
 | 
					        return res == 42
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_call_passing(self):
 | 
					    def test_call_passing(self):
 | 
				
			||||||
        class P1:
 | 
					        class P1:
 | 
				
			||||||
            def m(self, __call__, x):
 | 
					            def m(self, __call__, x):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -41,6 +41,7 @@ class Config(object):
 | 
				
			||||||
        self.pytestplugins = pytestplugins
 | 
					        self.pytestplugins = pytestplugins
 | 
				
			||||||
        self._conftest = Conftest(onimport=self._onimportconftest)
 | 
					        self._conftest = Conftest(onimport=self._onimportconftest)
 | 
				
			||||||
        self._setupstate = SetupState() 
 | 
					        self._setupstate = SetupState() 
 | 
				
			||||||
 | 
					        self._funcarg2maker = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _onimportconftest(self, conftestmodule):
 | 
					    def _onimportconftest(self, conftestmodule):
 | 
				
			||||||
        self.trace("loaded conftestmodule %r" %(conftestmodule,))
 | 
					        self.trace("loaded conftestmodule %r" %(conftestmodule,))
 | 
				
			||||||
| 
						 | 
					@ -285,7 +286,23 @@ class Config(object):
 | 
				
			||||||
            roots.append(pydir)
 | 
					            roots.append(pydir)
 | 
				
			||||||
        return roots 
 | 
					        return roots 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def register_funcargmaker(self, argname, maker):
 | 
				
			||||||
 | 
					        """ register a setup method for the given argument name. """
 | 
				
			||||||
 | 
					        self._funcarg2maker.setdefault(argname, []).append(maker)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _makefuncarg(self, argname, pyfuncitem):
 | 
				
			||||||
 | 
					        makerlist = self._getmakerlist(argname)
 | 
				
			||||||
 | 
					        mcall = py._com.MultiCall(makerlist, pyfuncitem)
 | 
				
			||||||
 | 
					        return mcall.execute(firstresult=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _getmakerlist(self, argname):
 | 
				
			||||||
 | 
					        makerlist = self._funcarg2maker.get(argname, None)
 | 
				
			||||||
 | 
					        if makerlist is None:
 | 
				
			||||||
 | 
					            msg = "funcarg %r not registered, available are: %s" % (
 | 
				
			||||||
 | 
					                  argname, ", ".join(self._funcarg2maker.keys()))
 | 
				
			||||||
 | 
					            raise KeyError(msg)
 | 
				
			||||||
 | 
					        assert makerlist
 | 
				
			||||||
 | 
					        return makerlist[:]
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# helpers
 | 
					# helpers
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,7 +2,10 @@ import os
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class MonkeypatchPlugin:
 | 
					class MonkeypatchPlugin:
 | 
				
			||||||
    """ setattr-monkeypatching with automatical reversal after test. """
 | 
					    """ setattr-monkeypatching with automatical reversal after test. """
 | 
				
			||||||
    def pytest_pyfuncarg_monkeypatch(self, pyfuncitem):
 | 
					    def pytest_configure(self, config):
 | 
				
			||||||
 | 
					        config.register_funcargmaker("monkeypatch", self.argmaker)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def argmaker(self, pyfuncitem):
 | 
				
			||||||
        monkeypatch = MonkeyPatch()
 | 
					        monkeypatch = MonkeyPatch()
 | 
				
			||||||
        pyfuncitem.addfinalizer(monkeypatch.finalize)
 | 
					        pyfuncitem.addfinalizer(monkeypatch.finalize)
 | 
				
			||||||
        return monkeypatch
 | 
					        return monkeypatch
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,21 +7,20 @@ from py.__.test import event
 | 
				
			||||||
from py.__.test.config import Config as pytestConfig
 | 
					from py.__.test.config import Config as pytestConfig
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class PytesterPlugin:
 | 
					class PytesterPlugin:
 | 
				
			||||||
    def pytest_pyfuncarg_linecomp(self, pyfuncitem):
 | 
					    def pytest_configure(self, config):
 | 
				
			||||||
        return LineComp()
 | 
					        config.register_funcargmaker("linecomp", lambda x: LineComp())
 | 
				
			||||||
 | 
					        config.register_funcargmaker("LineMatcher", lambda x: LineMatcher)
 | 
				
			||||||
 | 
					        config.register_funcargmaker("EventRecorder", lambda x: EventRecorder)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def pytest_pyfuncarg_LineMatcher(self, pyfuncitem):
 | 
					        config.register_funcargmaker("testdir", self.maketestdir)
 | 
				
			||||||
        return LineMatcher
 | 
					        config.register_funcargmaker("eventrecorder", self.makeeventrecorder)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def pytest_pyfuncarg_testdir(self, pyfuncitem):
 | 
					    def maketestdir(self, pyfuncitem):
 | 
				
			||||||
        tmptestdir = TmpTestdir(pyfuncitem)
 | 
					        tmptestdir = TmpTestdir(pyfuncitem)
 | 
				
			||||||
        pyfuncitem.addfinalizer(tmptestdir.finalize)
 | 
					        pyfuncitem.addfinalizer(tmptestdir.finalize)
 | 
				
			||||||
        return tmptestdir
 | 
					        return tmptestdir
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
    def pytest_pyfuncarg_EventRecorder(self, pyfuncitem):
 | 
					    def makeeventrecorder(self, pyfuncitem):
 | 
				
			||||||
        return EventRecorder
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def pytest_pyfuncarg_eventrecorder(self, pyfuncitem):
 | 
					 | 
				
			||||||
        evrec = EventRecorder(py._com.pyplugins)
 | 
					        evrec = EventRecorder(py._com.pyplugins)
 | 
				
			||||||
        pyfuncitem.addfinalizer(lambda: evrec.pyplugins.unregister(evrec))
 | 
					        pyfuncitem.addfinalizer(lambda: evrec.pyplugins.unregister(evrec))
 | 
				
			||||||
        return evrec
 | 
					        return evrec
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -375,14 +375,23 @@ class Function(FunctionMixin, py.test.collect.Item):
 | 
				
			||||||
        return kwargs
 | 
					        return kwargs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def lookup_onearg(self, argname):
 | 
					    def lookup_onearg(self, argname):
 | 
				
			||||||
        value = self.config.pytestplugins.call_firstresult(
 | 
					        try:
 | 
				
			||||||
            "pytest_pyfuncarg_" + argname, pyfuncitem=self)
 | 
					            makerlist = self.config._getmakerlist(argname)
 | 
				
			||||||
 | 
					        except KeyError:
 | 
				
			||||||
 | 
					            makerlist = []
 | 
				
			||||||
 | 
					        l = self.config.pytestplugins.listattr("pytest_pyfuncarg_" + argname)
 | 
				
			||||||
 | 
					        makerlist.extend(l)
 | 
				
			||||||
 | 
					        mc = py._com.MultiCall(makerlist, self)
 | 
				
			||||||
 | 
					        #print "mc.methods", mc.methods
 | 
				
			||||||
 | 
					        value = mc.execute(firstresult=True)
 | 
				
			||||||
        if value is not None:
 | 
					        if value is not None:
 | 
				
			||||||
            return value
 | 
					            return value
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
            metainfo = self.repr_metainfo()
 | 
					            metainfo = self.repr_metainfo()
 | 
				
			||||||
            #self.config.bus.notify("pyfuncarg_lookuperror", argname)
 | 
					            #self.config.bus.notify("pyfuncarg_lookuperror", argname)
 | 
				
			||||||
            raise LookupError("funcargument %r not found for: %s" %(argname,metainfo.verboseline()))
 | 
					            msg = "funcargument %r not found for: %s" %(argname,metainfo.verboseline())
 | 
				
			||||||
 | 
					            msg += "\n list of makers: %r" %(l,)
 | 
				
			||||||
 | 
					            raise LookupError(msg)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __eq__(self, other):
 | 
					    def __eq__(self, other):
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,33 @@
 | 
				
			||||||
import py
 | 
					import py
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class TestFuncArgsSetup:
 | 
				
			||||||
 | 
					    def test_register_funcarg_simple(self, testdir):
 | 
				
			||||||
 | 
					        item = testdir.getitem("def test_func(hello): pass")
 | 
				
			||||||
 | 
					        def maker(pyfuncitem):
 | 
				
			||||||
 | 
					            assert item == pyfuncitem
 | 
				
			||||||
 | 
					            return 42 
 | 
				
			||||||
 | 
					        item.config.register_funcargmaker("hello", maker)
 | 
				
			||||||
 | 
					        arg = item.config._makefuncarg("hello", item)
 | 
				
			||||||
 | 
					        assert arg == 42
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_register_funcarg_two(self, testdir):
 | 
				
			||||||
 | 
					        item = testdir.getitem("def test_func(hello): pass")
 | 
				
			||||||
 | 
					        def maker1(pyfuncitem):
 | 
				
			||||||
 | 
					            assert item == pyfuncitem
 | 
				
			||||||
 | 
					            return 1
 | 
				
			||||||
 | 
					        def maker2(__call__, pyfuncitem):
 | 
				
			||||||
 | 
					            assert item == pyfuncitem
 | 
				
			||||||
 | 
					            res = __call__.execute(firstresult=True)
 | 
				
			||||||
 | 
					            return res + 1
 | 
				
			||||||
 | 
					        item.config.register_funcargmaker("two", maker1)
 | 
				
			||||||
 | 
					        item.config.register_funcargmaker("two", maker2)
 | 
				
			||||||
 | 
					        arg = item.config._makefuncarg("two", item)
 | 
				
			||||||
 | 
					        assert arg == 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_register_funcarg_error(self, testdir):
 | 
				
			||||||
 | 
					        item = testdir.getitem("def test_func(hello): pass")
 | 
				
			||||||
 | 
					        config = item.config
 | 
				
			||||||
 | 
					        py.test.raises(KeyError, 'item.config._makefuncarg("notexist", item)')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TestConfigCmdlineParsing:
 | 
					class TestConfigCmdlineParsing:
 | 
				
			||||||
    def test_config_cmdline_options(self, testdir):
 | 
					    def test_config_cmdline_options(self, testdir):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue