remove/reduce internal global state: py._com.registry is now fully contained and always instantiated from the py.test PluginManager class.
--HG-- branch : trunk
This commit is contained in:
		
							parent
							
								
									8737254a74
								
							
						
					
					
						commit
						425e4849f3
					
				| 
						 | 
					@ -14,6 +14,5 @@ def pytest(argv=None):
 | 
				
			||||||
    except SystemExit:
 | 
					    except SystemExit:
 | 
				
			||||||
        pass
 | 
					        pass
 | 
				
			||||||
    # we need to reset the global py.test.config object
 | 
					    # we need to reset the global py.test.config object
 | 
				
			||||||
    py._com.comregistry = py._com.comregistry.__class__([])
 | 
					 | 
				
			||||||
    py.test.config = py.test.config.__class__(
 | 
					    py.test.config = py.test.config.__class__(
 | 
				
			||||||
        pluginmanager=py.test._PluginManager(py._com.comregistry))
 | 
					        pluginmanager=py.test._PluginManager())
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,12 +25,6 @@ py.apipkg.initpkg(__name__, dict(
 | 
				
			||||||
    _pydirs = '.impl._metainfo:pydirs',
 | 
					    _pydirs = '.impl._metainfo:pydirs',
 | 
				
			||||||
    version = 'py:__version__', # backward compatibility
 | 
					    version = 'py:__version__', # backward compatibility
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    _com = {
 | 
					 | 
				
			||||||
        'Registry': '.impl._com:Registry',
 | 
					 | 
				
			||||||
        'MultiCall':  '.impl._com:MultiCall',
 | 
					 | 
				
			||||||
        'comregistry': '.impl._com:comregistry',
 | 
					 | 
				
			||||||
        'HookRelay': '.impl._com:HookRelay',
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    cmdline = {
 | 
					    cmdline = {
 | 
				
			||||||
        'pytest':     '.impl.cmdline.pytest:main',
 | 
					        'pytest':     '.impl.cmdline.pytest:main',
 | 
				
			||||||
        'pylookup':   '.impl.cmdline.pylookup:main',
 | 
					        'pylookup':   '.impl.cmdline.pylookup:main',
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										125
									
								
								py/impl/_com.py
								
								
								
								
							
							
						
						
									
										125
									
								
								py/impl/_com.py
								
								
								
								
							| 
						 | 
					@ -1,125 +0,0 @@
 | 
				
			||||||
"""
 | 
					 | 
				
			||||||
py lib plugins and plugin call management
 | 
					 | 
				
			||||||
"""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import py
 | 
					 | 
				
			||||||
import inspect
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
__all__ = ['Registry', 'MultiCall', 'comregistry', 'HookRelay']
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class MultiCall:
 | 
					 | 
				
			||||||
    """ execute a call into multiple python functions/methods.  """
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def __init__(self, methods, kwargs, firstresult=False):
 | 
					 | 
				
			||||||
        self.methods = methods[:]
 | 
					 | 
				
			||||||
        self.kwargs = kwargs.copy()
 | 
					 | 
				
			||||||
        self.kwargs['__multicall__'] = self
 | 
					 | 
				
			||||||
        self.results = []
 | 
					 | 
				
			||||||
        self.firstresult = firstresult
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def __repr__(self):
 | 
					 | 
				
			||||||
        status = "%d results, %d meths" % (len(self.results), len(self.methods))
 | 
					 | 
				
			||||||
        return "<MultiCall %s, kwargs=%r>" %(status, self.kwargs)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def execute(self):
 | 
					 | 
				
			||||||
        while self.methods:
 | 
					 | 
				
			||||||
            method = self.methods.pop()
 | 
					 | 
				
			||||||
            kwargs = self.getkwargs(method)
 | 
					 | 
				
			||||||
            res = method(**kwargs)
 | 
					 | 
				
			||||||
            if res is not None:
 | 
					 | 
				
			||||||
                self.results.append(res) 
 | 
					 | 
				
			||||||
                if self.firstresult:
 | 
					 | 
				
			||||||
                    return res
 | 
					 | 
				
			||||||
        if not self.firstresult:
 | 
					 | 
				
			||||||
            return self.results 
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def getkwargs(self, method):
 | 
					 | 
				
			||||||
        kwargs = {}
 | 
					 | 
				
			||||||
        for argname in varnames(method):
 | 
					 | 
				
			||||||
            try:
 | 
					 | 
				
			||||||
                kwargs[argname] = self.kwargs[argname]
 | 
					 | 
				
			||||||
            except KeyError:
 | 
					 | 
				
			||||||
                pass # might be optional param
 | 
					 | 
				
			||||||
        return kwargs 
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def varnames(func):
 | 
					 | 
				
			||||||
    ismethod = inspect.ismethod(func)
 | 
					 | 
				
			||||||
    rawcode = py.code.getrawcode(func)
 | 
					 | 
				
			||||||
    try:
 | 
					 | 
				
			||||||
        return rawcode.co_varnames[ismethod:]
 | 
					 | 
				
			||||||
    except AttributeError:
 | 
					 | 
				
			||||||
        return ()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class Registry:
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
        Manage Plugins: register/unregister call calls to plugins. 
 | 
					 | 
				
			||||||
    """
 | 
					 | 
				
			||||||
    def __init__(self, plugins=None):
 | 
					 | 
				
			||||||
        if plugins is None:
 | 
					 | 
				
			||||||
            plugins = []
 | 
					 | 
				
			||||||
        self._plugins = plugins
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def register(self, plugin):
 | 
					 | 
				
			||||||
        assert not isinstance(plugin, str)
 | 
					 | 
				
			||||||
        assert not plugin in self._plugins
 | 
					 | 
				
			||||||
        self._plugins.append(plugin)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def unregister(self, plugin):
 | 
					 | 
				
			||||||
        self._plugins.remove(plugin)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def isregistered(self, plugin):
 | 
					 | 
				
			||||||
        return plugin in self._plugins 
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def __iter__(self):
 | 
					 | 
				
			||||||
        return iter(self._plugins)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def listattr(self, attrname, plugins=None, extra=(), reverse=False):
 | 
					 | 
				
			||||||
        l = []
 | 
					 | 
				
			||||||
        if plugins is None:
 | 
					 | 
				
			||||||
            plugins = self._plugins
 | 
					 | 
				
			||||||
        candidates = list(plugins) + list(extra)
 | 
					 | 
				
			||||||
        for plugin in candidates:
 | 
					 | 
				
			||||||
            try:
 | 
					 | 
				
			||||||
                l.append(getattr(plugin, attrname))
 | 
					 | 
				
			||||||
            except AttributeError:
 | 
					 | 
				
			||||||
                continue 
 | 
					 | 
				
			||||||
        if reverse:
 | 
					 | 
				
			||||||
            l.reverse()
 | 
					 | 
				
			||||||
        return l
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class HookRelay: 
 | 
					 | 
				
			||||||
    def __init__(self, hookspecs, registry):
 | 
					 | 
				
			||||||
        self._hookspecs = hookspecs
 | 
					 | 
				
			||||||
        self._registry = registry
 | 
					 | 
				
			||||||
        for name, method in vars(hookspecs).items():
 | 
					 | 
				
			||||||
            if name[:1] != "_":
 | 
					 | 
				
			||||||
                setattr(self, name, self._makecall(name))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def _makecall(self, name, extralookup=None):
 | 
					 | 
				
			||||||
        hookspecmethod = getattr(self._hookspecs, name)
 | 
					 | 
				
			||||||
        firstresult = getattr(hookspecmethod, 'firstresult', False)
 | 
					 | 
				
			||||||
        return HookCaller(self, name, firstresult=firstresult,
 | 
					 | 
				
			||||||
            extralookup=extralookup)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def _getmethods(self, name, extralookup=()):
 | 
					 | 
				
			||||||
        return self._registry.listattr(name, extra=extralookup)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def _performcall(self, name, multicall):
 | 
					 | 
				
			||||||
        return multicall.execute()
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
class HookCaller:
 | 
					 | 
				
			||||||
    def __init__(self, hookrelay, name, firstresult, extralookup=None):
 | 
					 | 
				
			||||||
        self.hookrelay = hookrelay 
 | 
					 | 
				
			||||||
        self.name = name 
 | 
					 | 
				
			||||||
        self.firstresult = firstresult 
 | 
					 | 
				
			||||||
        self.extralookup = extralookup and [extralookup] or ()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def __repr__(self):
 | 
					 | 
				
			||||||
        return "<HookCaller %r>" %(self.name,)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def __call__(self, **kwargs):
 | 
					 | 
				
			||||||
        methods = self.hookrelay._getmethods(self.name, self.extralookup)
 | 
					 | 
				
			||||||
        mc = MultiCall(methods, kwargs, firstresult=self.firstresult)
 | 
					 | 
				
			||||||
        return self.hookrelay._performcall(self.name, mc)
 | 
					 | 
				
			||||||
   
 | 
					 | 
				
			||||||
comregistry = Registry([])
 | 
					 | 
				
			||||||
| 
						 | 
					@ -107,9 +107,8 @@ class Config(object):
 | 
				
			||||||
        # warning global side effects:
 | 
					        # warning global side effects:
 | 
				
			||||||
        # * registering to py lib plugins 
 | 
					        # * registering to py lib plugins 
 | 
				
			||||||
        # * setting py.test.config 
 | 
					        # * setting py.test.config 
 | 
				
			||||||
        py._com.comregistry = py._com.Registry()
 | 
					 | 
				
			||||||
        self.__init__(
 | 
					        self.__init__(
 | 
				
			||||||
            pluginmanager=py.test._PluginManager(py._com.comregistry),
 | 
					            pluginmanager=py.test._PluginManager(),
 | 
				
			||||||
            topdir=py.path.local(),
 | 
					            topdir=py.path.local(),
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        # we have to set py.test.config because preparse()
 | 
					        # we have to set py.test.config because preparse()
 | 
				
			||||||
| 
						 | 
					@ -310,6 +309,6 @@ def gettopdir(args):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# this is the one per-process instance of py.test configuration 
 | 
					# this is the one per-process instance of py.test configuration 
 | 
				
			||||||
config_per_process = Config(
 | 
					config_per_process = Config(
 | 
				
			||||||
    pluginmanager=py.test._PluginManager(py._com.comregistry)
 | 
					    pluginmanager=py.test._PluginManager()
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,6 +2,7 @@
 | 
				
			||||||
managing loading and interacting with pytest plugins. 
 | 
					managing loading and interacting with pytest plugins. 
 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
import py
 | 
					import py
 | 
				
			||||||
 | 
					import inspect
 | 
				
			||||||
from py.plugin import hookspec
 | 
					from py.plugin import hookspec
 | 
				
			||||||
from py.impl.test.outcome import Skipped
 | 
					from py.impl.test.outcome import Skipped
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,15 +17,10 @@ def check_old_use(mod, modname):
 | 
				
			||||||
class PluginManager(object):
 | 
					class PluginManager(object):
 | 
				
			||||||
    class Error(Exception):
 | 
					    class Error(Exception):
 | 
				
			||||||
        """signals a plugin specific error."""
 | 
					        """signals a plugin specific error."""
 | 
				
			||||||
    def __init__(self, comregistry=None):
 | 
					    def __init__(self):
 | 
				
			||||||
        if comregistry is None: 
 | 
					        self.registry = Registry()
 | 
				
			||||||
            comregistry = py._com.Registry()
 | 
					 | 
				
			||||||
        self.comregistry = comregistry 
 | 
					 | 
				
			||||||
        self._name2plugin = {}
 | 
					        self._name2plugin = {}
 | 
				
			||||||
 | 
					        self.hook = HookRelay(hookspecs=hookspec, registry=self.registry) 
 | 
				
			||||||
        self.hook = py._com.HookRelay(
 | 
					 | 
				
			||||||
            hookspecs=hookspec, 
 | 
					 | 
				
			||||||
            registry=self.comregistry) 
 | 
					 | 
				
			||||||
        self.register(self)
 | 
					        self.register(self)
 | 
				
			||||||
        for spec in default_plugins:
 | 
					        for spec in default_plugins:
 | 
				
			||||||
            self.import_plugin(spec) 
 | 
					            self.import_plugin(spec) 
 | 
				
			||||||
| 
						 | 
					@ -39,18 +35,18 @@ class PluginManager(object):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def register(self, plugin, name=None):
 | 
					    def register(self, plugin, name=None):
 | 
				
			||||||
        assert not self.isregistered(plugin), plugin
 | 
					        assert not self.isregistered(plugin), plugin
 | 
				
			||||||
        assert not self.comregistry.isregistered(plugin), plugin
 | 
					        assert not self.registry.isregistered(plugin), plugin
 | 
				
			||||||
        name = self._getpluginname(plugin, name)
 | 
					        name = self._getpluginname(plugin, name)
 | 
				
			||||||
        if name in self._name2plugin:
 | 
					        if name in self._name2plugin:
 | 
				
			||||||
            return False
 | 
					            return False
 | 
				
			||||||
        self._name2plugin[name] = plugin
 | 
					        self._name2plugin[name] = plugin
 | 
				
			||||||
        self.hook.pytest_plugin_registered(manager=self, plugin=plugin)
 | 
					        self.hook.pytest_plugin_registered(manager=self, plugin=plugin)
 | 
				
			||||||
        self.comregistry.register(plugin)
 | 
					        self.registry.register(plugin)
 | 
				
			||||||
        return True
 | 
					        return True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def unregister(self, plugin):
 | 
					    def unregister(self, plugin):
 | 
				
			||||||
        self.hook.pytest_plugin_unregistered(plugin=plugin)
 | 
					        self.hook.pytest_plugin_unregistered(plugin=plugin)
 | 
				
			||||||
        self.comregistry.unregister(plugin)
 | 
					        self.registry.unregister(plugin)
 | 
				
			||||||
        for name, value in list(self._name2plugin.items()):
 | 
					        for name, value in list(self._name2plugin.items()):
 | 
				
			||||||
            if value == plugin:
 | 
					            if value == plugin:
 | 
				
			||||||
                del self._name2plugin[name]
 | 
					                del self._name2plugin[name]
 | 
				
			||||||
| 
						 | 
					@ -63,7 +59,7 @@ class PluginManager(object):
 | 
				
			||||||
                return True
 | 
					                return True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def getplugins(self):
 | 
					    def getplugins(self):
 | 
				
			||||||
        return list(self.comregistry)
 | 
					        return list(self.registry)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def getplugin(self, name):
 | 
					    def getplugin(self, name):
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
| 
						 | 
					@ -143,7 +139,7 @@ class PluginManager(object):
 | 
				
			||||||
    #
 | 
					    #
 | 
				
			||||||
    # 
 | 
					    # 
 | 
				
			||||||
    def listattr(self, attrname, plugins=None, extra=()):
 | 
					    def listattr(self, attrname, plugins=None, extra=()):
 | 
				
			||||||
        return self.comregistry.listattr(attrname, plugins=plugins, extra=extra)
 | 
					        return self.registry.listattr(attrname, plugins=plugins, extra=extra)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def notify_exception(self, excinfo=None):
 | 
					    def notify_exception(self, excinfo=None):
 | 
				
			||||||
        if excinfo is None:
 | 
					        if excinfo is None:
 | 
				
			||||||
| 
						 | 
					@ -153,8 +149,8 @@ class PluginManager(object):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def do_addoption(self, parser):
 | 
					    def do_addoption(self, parser):
 | 
				
			||||||
        mname = "pytest_addoption"
 | 
					        mname = "pytest_addoption"
 | 
				
			||||||
        methods = self.comregistry.listattr(mname, reverse=True)
 | 
					        methods = self.registry.listattr(mname, reverse=True)
 | 
				
			||||||
        mc = py._com.MultiCall(methods, {'parser': parser})
 | 
					        mc = MultiCall(methods, {'parser': parser})
 | 
				
			||||||
        mc.execute()
 | 
					        mc.execute()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def pytest_plugin_registered(self, plugin):
 | 
					    def pytest_plugin_registered(self, plugin):
 | 
				
			||||||
| 
						 | 
					@ -168,7 +164,7 @@ class PluginManager(object):
 | 
				
			||||||
                {'config': self._config})
 | 
					                {'config': self._config})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def call_plugin(self, plugin, methname, kwargs):
 | 
					    def call_plugin(self, plugin, methname, kwargs):
 | 
				
			||||||
        return py._com.MultiCall(
 | 
					        return MultiCall(
 | 
				
			||||||
                methods=self.listattr(methname, plugins=[plugin]), 
 | 
					                methods=self.listattr(methname, plugins=[plugin]), 
 | 
				
			||||||
                kwargs=kwargs, firstresult=True).execute()
 | 
					                kwargs=kwargs, firstresult=True).execute()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -210,3 +206,118 @@ def importplugin(importspec):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class MultiCall:
 | 
				
			||||||
 | 
					    """ execute a call into multiple python functions/methods.  """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __init__(self, methods, kwargs, firstresult=False):
 | 
				
			||||||
 | 
					        self.methods = methods[:]
 | 
				
			||||||
 | 
					        self.kwargs = kwargs.copy()
 | 
				
			||||||
 | 
					        self.kwargs['__multicall__'] = self
 | 
				
			||||||
 | 
					        self.results = []
 | 
				
			||||||
 | 
					        self.firstresult = firstresult
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __repr__(self):
 | 
				
			||||||
 | 
					        status = "%d results, %d meths" % (len(self.results), len(self.methods))
 | 
				
			||||||
 | 
					        return "<MultiCall %s, kwargs=%r>" %(status, self.kwargs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def execute(self):
 | 
				
			||||||
 | 
					        while self.methods:
 | 
				
			||||||
 | 
					            method = self.methods.pop()
 | 
				
			||||||
 | 
					            kwargs = self.getkwargs(method)
 | 
				
			||||||
 | 
					            res = method(**kwargs)
 | 
				
			||||||
 | 
					            if res is not None:
 | 
				
			||||||
 | 
					                self.results.append(res) 
 | 
				
			||||||
 | 
					                if self.firstresult:
 | 
				
			||||||
 | 
					                    return res
 | 
				
			||||||
 | 
					        if not self.firstresult:
 | 
				
			||||||
 | 
					            return self.results 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def getkwargs(self, method):
 | 
				
			||||||
 | 
					        kwargs = {}
 | 
				
			||||||
 | 
					        for argname in varnames(method):
 | 
				
			||||||
 | 
					            try:
 | 
				
			||||||
 | 
					                kwargs[argname] = self.kwargs[argname]
 | 
				
			||||||
 | 
					            except KeyError:
 | 
				
			||||||
 | 
					                pass # might be optional param
 | 
				
			||||||
 | 
					        return kwargs 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def varnames(func):
 | 
				
			||||||
 | 
					    ismethod = inspect.ismethod(func)
 | 
				
			||||||
 | 
					    rawcode = py.code.getrawcode(func)
 | 
				
			||||||
 | 
					    try:
 | 
				
			||||||
 | 
					        return rawcode.co_varnames[ismethod:]
 | 
				
			||||||
 | 
					    except AttributeError:
 | 
				
			||||||
 | 
					        return ()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Registry:
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					        Manage Plugins: register/unregister call calls to plugins. 
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					    def __init__(self, plugins=None):
 | 
				
			||||||
 | 
					        if plugins is None:
 | 
				
			||||||
 | 
					            plugins = []
 | 
				
			||||||
 | 
					        self._plugins = plugins
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def register(self, plugin):
 | 
				
			||||||
 | 
					        assert not isinstance(plugin, str)
 | 
				
			||||||
 | 
					        assert not plugin in self._plugins
 | 
				
			||||||
 | 
					        self._plugins.append(plugin)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def unregister(self, plugin):
 | 
				
			||||||
 | 
					        self._plugins.remove(plugin)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def isregistered(self, plugin):
 | 
				
			||||||
 | 
					        return plugin in self._plugins 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __iter__(self):
 | 
				
			||||||
 | 
					        return iter(self._plugins)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def listattr(self, attrname, plugins=None, extra=(), reverse=False):
 | 
				
			||||||
 | 
					        l = []
 | 
				
			||||||
 | 
					        if plugins is None:
 | 
				
			||||||
 | 
					            plugins = self._plugins
 | 
				
			||||||
 | 
					        candidates = list(plugins) + list(extra)
 | 
				
			||||||
 | 
					        for plugin in candidates:
 | 
				
			||||||
 | 
					            try:
 | 
				
			||||||
 | 
					                l.append(getattr(plugin, attrname))
 | 
				
			||||||
 | 
					            except AttributeError:
 | 
				
			||||||
 | 
					                continue 
 | 
				
			||||||
 | 
					        if reverse:
 | 
				
			||||||
 | 
					            l.reverse()
 | 
				
			||||||
 | 
					        return l
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class HookRelay: 
 | 
				
			||||||
 | 
					    def __init__(self, hookspecs, registry):
 | 
				
			||||||
 | 
					        self._hookspecs = hookspecs
 | 
				
			||||||
 | 
					        self._registry = registry
 | 
				
			||||||
 | 
					        for name, method in vars(hookspecs).items():
 | 
				
			||||||
 | 
					            if name[:1] != "_":
 | 
				
			||||||
 | 
					                setattr(self, name, self._makecall(name))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _makecall(self, name, extralookup=None):
 | 
				
			||||||
 | 
					        hookspecmethod = getattr(self._hookspecs, name)
 | 
				
			||||||
 | 
					        firstresult = getattr(hookspecmethod, 'firstresult', False)
 | 
				
			||||||
 | 
					        return HookCaller(self, name, firstresult=firstresult,
 | 
				
			||||||
 | 
					            extralookup=extralookup)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _getmethods(self, name, extralookup=()):
 | 
				
			||||||
 | 
					        return self._registry.listattr(name, extra=extralookup)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def _performcall(self, name, multicall):
 | 
				
			||||||
 | 
					        return multicall.execute()
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					class HookCaller:
 | 
				
			||||||
 | 
					    def __init__(self, hookrelay, name, firstresult, extralookup=None):
 | 
				
			||||||
 | 
					        self.hookrelay = hookrelay 
 | 
				
			||||||
 | 
					        self.name = name 
 | 
				
			||||||
 | 
					        self.firstresult = firstresult 
 | 
				
			||||||
 | 
					        self.extralookup = extralookup and [extralookup] or ()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __repr__(self):
 | 
				
			||||||
 | 
					        return "<HookCaller %r>" %(self.name,)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __call__(self, **kwargs):
 | 
				
			||||||
 | 
					        methods = self.hookrelay._getmethods(self.name, self.extralookup)
 | 
				
			||||||
 | 
					        mc = MultiCall(methods, kwargs, firstresult=self.firstresult)
 | 
				
			||||||
 | 
					        return self.hookrelay._performcall(self.name, mc)
 | 
				
			||||||
 | 
					   
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,21 +1,17 @@
 | 
				
			||||||
import py
 | 
					import py
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from py.impl.test.pluginmanager import HookRelay
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def pytest_funcarg___pytest(request):
 | 
					def pytest_funcarg___pytest(request):
 | 
				
			||||||
    return PytestArg(request)
 | 
					    return PytestArg(request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class PytestArg:
 | 
					class PytestArg:
 | 
				
			||||||
    def __init__(self, request):
 | 
					    def __init__(self, request):
 | 
				
			||||||
        self.request = request 
 | 
					        self.request = request 
 | 
				
			||||||
        self.monkeypatch = self.request.getfuncargvalue("monkeypatch")
 | 
					 | 
				
			||||||
        self.comregistry = py._com.Registry()
 | 
					 | 
				
			||||||
        self.monkeypatch.setattr(py._com, 'comregistry', self.comregistry)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def gethookrecorder(self, hookspecs, registry=None):
 | 
					    def gethookrecorder(self, hook):
 | 
				
			||||||
        if registry is not None:
 | 
					        hookrecorder = HookRecorder(hook._registry)
 | 
				
			||||||
            self.monkeypatch.setattr(py._com, 'comregistry', registry) 
 | 
					        hookrecorder.start_recording(hook._hookspecs)
 | 
				
			||||||
            self.comregistry = registry 
 | 
					 | 
				
			||||||
        hookrecorder = HookRecorder(self.comregistry) 
 | 
					 | 
				
			||||||
        hookrecorder.start_recording(hookspecs)
 | 
					 | 
				
			||||||
        self.request.addfinalizer(hookrecorder.finish_recording)
 | 
					        self.request.addfinalizer(hookrecorder.finish_recording)
 | 
				
			||||||
        return hookrecorder 
 | 
					        return hookrecorder 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,8 +28,8 @@ class ParsedCall:
 | 
				
			||||||
        return "<ParsedCall %r(**%r)>" %(self._name, d)
 | 
					        return "<ParsedCall %r(**%r)>" %(self._name, d)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class HookRecorder:
 | 
					class HookRecorder:
 | 
				
			||||||
    def __init__(self, comregistry):
 | 
					    def __init__(self, registry):
 | 
				
			||||||
        self._comregistry = comregistry
 | 
					        self._registry = registry
 | 
				
			||||||
        self.calls = []
 | 
					        self.calls = []
 | 
				
			||||||
        self._recorders = {}
 | 
					        self._recorders = {}
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
| 
						 | 
					@ -46,12 +42,12 @@ class HookRecorder:
 | 
				
			||||||
                setattr(RecordCalls, name, self._makecallparser(method))
 | 
					                setattr(RecordCalls, name, self._makecallparser(method))
 | 
				
			||||||
        recorder = RecordCalls()
 | 
					        recorder = RecordCalls()
 | 
				
			||||||
        self._recorders[hookspecs] = recorder
 | 
					        self._recorders[hookspecs] = recorder
 | 
				
			||||||
        self._comregistry.register(recorder)
 | 
					        self._registry.register(recorder)
 | 
				
			||||||
        self.hook = py._com.HookRelay(hookspecs, registry=self._comregistry)
 | 
					        self.hook = HookRelay(hookspecs, registry=self._registry)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def finish_recording(self):
 | 
					    def finish_recording(self):
 | 
				
			||||||
        for recorder in self._recorders.values():
 | 
					        for recorder in self._recorders.values():
 | 
				
			||||||
            self._comregistry.unregister(recorder)
 | 
					            self._registry.unregister(recorder)
 | 
				
			||||||
        self._recorders.clear()
 | 
					        self._recorders.clear()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _makecallparser(self, method):
 | 
					    def _makecallparser(self, method):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,11 +22,6 @@ def pytest_funcarg__testdir(request):
 | 
				
			||||||
    tmptestdir = TmpTestdir(request)
 | 
					    tmptestdir = TmpTestdir(request)
 | 
				
			||||||
    return tmptestdir
 | 
					    return tmptestdir
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def pytest_funcarg__reportrecorder(request):
 | 
					 | 
				
			||||||
    reprec = ReportRecorder(py._com.comregistry)
 | 
					 | 
				
			||||||
    request.addfinalizer(lambda: reprec.comregistry.unregister(reprec))
 | 
					 | 
				
			||||||
    return reprec
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
rex_outcome = re.compile("(\d+) (\w+)")
 | 
					rex_outcome = re.compile("(\d+) (\w+)")
 | 
				
			||||||
class RunResult:
 | 
					class RunResult:
 | 
				
			||||||
    def __init__(self, ret, outlines, errlines):
 | 
					    def __init__(self, ret, outlines, errlines):
 | 
				
			||||||
| 
						 | 
					@ -71,10 +66,10 @@ class TmpTestdir:
 | 
				
			||||||
    def __repr__(self):
 | 
					    def __repr__(self):
 | 
				
			||||||
        return "<TmpTestdir %r>" % (self.tmpdir,)
 | 
					        return "<TmpTestdir %r>" % (self.tmpdir,)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def Config(self, comregistry=None, topdir=None):
 | 
					    def Config(self, registry=None, topdir=None):
 | 
				
			||||||
        if topdir is None:
 | 
					        if topdir is None:
 | 
				
			||||||
            topdir = self.tmpdir.dirpath()
 | 
					            topdir = self.tmpdir.dirpath()
 | 
				
			||||||
        return pytestConfig(comregistry, topdir=topdir)
 | 
					        return pytestConfig(registry, topdir=topdir)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def finalize(self):
 | 
					    def finalize(self):
 | 
				
			||||||
        for p in self._syspathremove:
 | 
					        for p in self._syspathremove:
 | 
				
			||||||
| 
						 | 
					@ -89,19 +84,13 @@ class TmpTestdir:
 | 
				
			||||||
                    del sys.modules[name]
 | 
					                    del sys.modules[name]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def getreportrecorder(self, obj):
 | 
					    def getreportrecorder(self, obj):
 | 
				
			||||||
        if isinstance(obj, py._com.Registry):
 | 
					        if hasattr(obj, 'config'):
 | 
				
			||||||
            registry = obj
 | 
					            obj = obj.config
 | 
				
			||||||
        elif hasattr(obj, 'comregistry'):
 | 
					        if hasattr(obj, 'hook'):
 | 
				
			||||||
            registry = obj.comregistry
 | 
					            obj = obj.hook
 | 
				
			||||||
        elif hasattr(obj, 'pluginmanager'):
 | 
					        assert hasattr(obj, '_hookspecs'), obj
 | 
				
			||||||
            registry = obj.pluginmanager.comregistry
 | 
					        reprec = ReportRecorder(obj)
 | 
				
			||||||
        elif hasattr(obj, 'config'):
 | 
					        reprec.hookrecorder = self._pytest.gethookrecorder(obj)
 | 
				
			||||||
            registry = obj.config.pluginmanager.comregistry
 | 
					 | 
				
			||||||
        else:
 | 
					 | 
				
			||||||
            raise ValueError("obj %r provides no comregistry" %(obj,))
 | 
					 | 
				
			||||||
        assert isinstance(registry, py._com.Registry)
 | 
					 | 
				
			||||||
        reprec = ReportRecorder(registry)
 | 
					 | 
				
			||||||
        reprec.hookrecorder = self._pytest.gethookrecorder(hookspec, registry)
 | 
					 | 
				
			||||||
        reprec.hook = reprec.hookrecorder.hook
 | 
					        reprec.hook = reprec.hookrecorder.hook
 | 
				
			||||||
        return reprec
 | 
					        return reprec
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -334,9 +323,10 @@ class PseudoPlugin:
 | 
				
			||||||
        self.__dict__.update(vars) 
 | 
					        self.__dict__.update(vars) 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ReportRecorder(object):
 | 
					class ReportRecorder(object):
 | 
				
			||||||
    def __init__(self, comregistry):
 | 
					    def __init__(self, hook):
 | 
				
			||||||
        self.comregistry = comregistry
 | 
					        self.hook = hook
 | 
				
			||||||
        comregistry.register(self)
 | 
					        self.registry = hook._registry
 | 
				
			||||||
 | 
					        self.registry.register(self)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def getcall(self, name):
 | 
					    def getcall(self, name):
 | 
				
			||||||
        return self.hookrecorder.getcall(name)
 | 
					        return self.hookrecorder.getcall(name)
 | 
				
			||||||
| 
						 | 
					@ -401,7 +391,7 @@ class ReportRecorder(object):
 | 
				
			||||||
        self.hookrecorder.calls[:] = []
 | 
					        self.hookrecorder.calls[:] = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def unregister(self):
 | 
					    def unregister(self):
 | 
				
			||||||
        self.comregistry.unregister(self)
 | 
					        self.registry.unregister(self)
 | 
				
			||||||
        self.hookrecorder.finish_recording()
 | 
					        self.hookrecorder.finish_recording()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class LineComp:
 | 
					class LineComp:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,9 +1,10 @@
 | 
				
			||||||
import py
 | 
					import py
 | 
				
			||||||
 | 
					import sys
 | 
				
			||||||
from py.plugin.pytest__pytest import HookRecorder
 | 
					from py.plugin.pytest__pytest import HookRecorder
 | 
				
			||||||
 | 
					from py.impl.test.pluginmanager import Registry
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_hookrecorder_basic():
 | 
					def test_hookrecorder_basic():
 | 
				
			||||||
    comregistry = py._com.Registry() 
 | 
					    rec = HookRecorder(Registry())
 | 
				
			||||||
    rec = HookRecorder(comregistry)
 | 
					 | 
				
			||||||
    class ApiClass:
 | 
					    class ApiClass:
 | 
				
			||||||
        def xyz(self, arg):
 | 
					        def xyz(self, arg):
 | 
				
			||||||
            pass
 | 
					            pass
 | 
				
			||||||
| 
						 | 
					@ -15,9 +16,7 @@ def test_hookrecorder_basic():
 | 
				
			||||||
    py.test.raises(ValueError, "rec.popcall('abc')")
 | 
					    py.test.raises(ValueError, "rec.popcall('abc')")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_hookrecorder_basic_no_args_hook():
 | 
					def test_hookrecorder_basic_no_args_hook():
 | 
				
			||||||
    import sys
 | 
					    rec = HookRecorder(Registry())
 | 
				
			||||||
    comregistry = py._com.Registry() 
 | 
					 | 
				
			||||||
    rec = HookRecorder(comregistry)
 | 
					 | 
				
			||||||
    apimod = type(sys)('api')
 | 
					    apimod = type(sys)('api')
 | 
				
			||||||
    def xyz():
 | 
					    def xyz():
 | 
				
			||||||
        pass
 | 
					        pass
 | 
				
			||||||
| 
						 | 
					@ -27,23 +26,20 @@ def test_hookrecorder_basic_no_args_hook():
 | 
				
			||||||
    call = rec.popcall("xyz")
 | 
					    call = rec.popcall("xyz")
 | 
				
			||||||
    assert call._name == "xyz"
 | 
					    assert call._name == "xyz"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
reg = py._com.comregistry
 | 
					 | 
				
			||||||
def test_functional_default(testdir, _pytest):
 | 
					 | 
				
			||||||
    assert _pytest.comregistry == py._com.comregistry 
 | 
					 | 
				
			||||||
    assert _pytest.comregistry != reg
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def test_functional(testdir, linecomp):
 | 
					def test_functional(testdir, linecomp):
 | 
				
			||||||
    reprec = testdir.inline_runsource("""
 | 
					    reprec = testdir.inline_runsource("""
 | 
				
			||||||
        import py
 | 
					        import py
 | 
				
			||||||
 | 
					        from py.impl.test.pluginmanager import HookRelay, Registry
 | 
				
			||||||
        pytest_plugins="_pytest"
 | 
					        pytest_plugins="_pytest"
 | 
				
			||||||
        def test_func(_pytest):
 | 
					        def test_func(_pytest):
 | 
				
			||||||
            class ApiClass:
 | 
					            class ApiClass:
 | 
				
			||||||
                def xyz(self, arg):  pass 
 | 
					                def xyz(self, arg):  pass 
 | 
				
			||||||
            rec = _pytest.gethookrecorder(ApiClass)
 | 
					            hook = HookRelay(ApiClass, Registry())
 | 
				
			||||||
 | 
					            rec = _pytest.gethookrecorder(hook)
 | 
				
			||||||
            class Plugin:
 | 
					            class Plugin:
 | 
				
			||||||
                def xyz(self, arg):
 | 
					                def xyz(self, arg):
 | 
				
			||||||
                    return arg + 1
 | 
					                    return arg + 1
 | 
				
			||||||
            rec._comregistry.register(Plugin())
 | 
					            rec._registry.register(Plugin())
 | 
				
			||||||
            res = rec.hook.xyz(arg=41)
 | 
					            res = rec.hook.xyz(arg=41)
 | 
				
			||||||
            assert res == [42]
 | 
					            assert res == [42]
 | 
				
			||||||
    """)
 | 
					    """)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,10 +2,9 @@ import py
 | 
				
			||||||
from py.plugin.pytest_pytester import LineMatcher, LineComp
 | 
					from py.plugin.pytest_pytester import LineMatcher, LineComp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_reportrecorder(testdir):
 | 
					def test_reportrecorder(testdir):
 | 
				
			||||||
    registry = py._com.Registry()
 | 
					 | 
				
			||||||
    recorder = testdir.getreportrecorder(registry)
 | 
					 | 
				
			||||||
    assert not recorder.getfailures()
 | 
					 | 
				
			||||||
    item = testdir.getitem("def test_func(): pass")
 | 
					    item = testdir.getitem("def test_func(): pass")
 | 
				
			||||||
 | 
					    recorder = testdir.getreportrecorder(item.config)
 | 
				
			||||||
 | 
					    assert not recorder.getfailures()
 | 
				
			||||||
    class rep:
 | 
					    class rep:
 | 
				
			||||||
        excinfo = None
 | 
					        excinfo = None
 | 
				
			||||||
        passed = False
 | 
					        passed = False
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,17 +8,17 @@
 | 
				
			||||||
import py
 | 
					import py
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
from py.impl.test.dist.gwmanage import GatewayManager, HostRSync
 | 
					from py.impl.test.dist.gwmanage import GatewayManager, HostRSync
 | 
				
			||||||
 | 
					from py.impl.test.pluginmanager import HookRelay, Registry
 | 
				
			||||||
from py.plugin import hookspec
 | 
					from py.plugin import hookspec
 | 
				
			||||||
import execnet
 | 
					import execnet
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def pytest_funcarg__hookrecorder(request):
 | 
					def pytest_funcarg__hookrecorder(request):
 | 
				
			||||||
    _pytest = request.getfuncargvalue('_pytest')
 | 
					    _pytest = request.getfuncargvalue('_pytest')
 | 
				
			||||||
    hook = request.getfuncargvalue('hook')
 | 
					    hook = request.getfuncargvalue('hook')
 | 
				
			||||||
    return _pytest.gethookrecorder(hook._hookspecs, hook._registry)
 | 
					    return _pytest.gethookrecorder(hook)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def pytest_funcarg__hook(request):
 | 
					def pytest_funcarg__hook(request):
 | 
				
			||||||
    registry = py._com.Registry()
 | 
					    return HookRelay(hookspec, Registry())
 | 
				
			||||||
    return py._com.HookRelay(hookspec, registry)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TestGatewayManagerPopen:
 | 
					class TestGatewayManagerPopen:
 | 
				
			||||||
    def test_popen_no_default_chdir(self, hook):
 | 
					    def test_popen_no_default_chdir(self, hook):
 | 
				
			||||||
| 
						 | 
					@ -90,7 +90,6 @@ class pytest_funcarg__mysetup:
 | 
				
			||||||
        tmp = request.getfuncargvalue('tmpdir')
 | 
					        tmp = request.getfuncargvalue('tmpdir')
 | 
				
			||||||
        self.source = tmp.mkdir("source")
 | 
					        self.source = tmp.mkdir("source")
 | 
				
			||||||
        self.dest = tmp.mkdir("dest")
 | 
					        self.dest = tmp.mkdir("dest")
 | 
				
			||||||
        request.getfuncargvalue("_pytest") # to have patching of py._com.comregistry
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TestHRSync:
 | 
					class TestHRSync:
 | 
				
			||||||
    def test_hrsync_filter(self, mysetup):
 | 
					    def test_hrsync_filter(self, mysetup):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -264,9 +264,6 @@ def test_options_on_small_file_do_not_blow_up(testdir):
 | 
				
			||||||
                 ['--traceconfig'], ['-v'], ['-v', '-v']):
 | 
					                 ['--traceconfig'], ['-v'], ['-v', '-v']):
 | 
				
			||||||
        runfiletest(opts + [path])
 | 
					        runfiletest(opts + [path])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_default_registry():
 | 
					 | 
				
			||||||
    assert py.test.config.pluginmanager.comregistry is py._com.comregistry
 | 
					 | 
				
			||||||
   
 | 
					 | 
				
			||||||
def test_ensuretemp():
 | 
					def test_ensuretemp():
 | 
				
			||||||
    # XXX test for deprecation
 | 
					    # XXX test for deprecation
 | 
				
			||||||
    d1 = py.test.ensuretemp('hello') 
 | 
					    d1 = py.test.ensuretemp('hello') 
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,14 +3,11 @@ import pickle
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def setglobals(request):
 | 
					def setglobals(request):
 | 
				
			||||||
    oldconfig = py.test.config 
 | 
					    oldconfig = py.test.config 
 | 
				
			||||||
    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()
 | 
					 | 
				
			||||||
    def resetglobals():
 | 
					    def resetglobals():
 | 
				
			||||||
        py.builtin.print_("setting py.test.config to", oldconfig)
 | 
					        py.builtin.print_("setting py.test.config to", oldconfig)
 | 
				
			||||||
        py.test.config = oldconfig
 | 
					        py.test.config = oldconfig
 | 
				
			||||||
        py._com.comregistry = oldcom
 | 
					 | 
				
			||||||
    request.addfinalizer(resetglobals)
 | 
					    request.addfinalizer(resetglobals)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def pytest_funcarg__testdir(request):
 | 
					def pytest_funcarg__testdir(request):
 | 
				
			||||||
| 
						 | 
					@ -190,7 +187,7 @@ def test_config__setstate__wired_correctly_in_childprocess(testdir):
 | 
				
			||||||
        from py.impl.test.dist.mypickle import PickleChannel
 | 
					        from py.impl.test.dist.mypickle import PickleChannel
 | 
				
			||||||
        channel = PickleChannel(channel)
 | 
					        channel = PickleChannel(channel)
 | 
				
			||||||
        config = channel.receive()
 | 
					        config = channel.receive()
 | 
				
			||||||
        assert py.test.config.pluginmanager.comregistry == py._com.comregistry, "comregistry wrong"
 | 
					        assert py.test.config == config 
 | 
				
			||||||
    """)
 | 
					    """)
 | 
				
			||||||
    channel = PickleChannel(channel)
 | 
					    channel = PickleChannel(channel)
 | 
				
			||||||
    config = testdir.parseconfig()
 | 
					    config = testdir.parseconfig()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,7 @@
 | 
				
			||||||
import py, os
 | 
					import py, os
 | 
				
			||||||
from py.impl.test.pluginmanager import PluginManager, canonical_importname
 | 
					from py.impl.test.pluginmanager import PluginManager, canonical_importname
 | 
				
			||||||
 | 
					from py.impl.test.pluginmanager import Registry, MultiCall, HookRelay, varnames
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TestBootstrapping:
 | 
					class TestBootstrapping:
 | 
				
			||||||
    def test_consider_env_fails_to_import(self, monkeypatch):
 | 
					    def test_consider_env_fails_to_import(self, monkeypatch):
 | 
				
			||||||
| 
						 | 
					@ -278,3 +280,184 @@ def test_namespace_has_default_and_env_plugins(testdir):
 | 
				
			||||||
    """)
 | 
					    """)
 | 
				
			||||||
    result = testdir.runpython(p)
 | 
					    result = testdir.runpython(p)
 | 
				
			||||||
    assert result.ret == 0
 | 
					    assert result.ret == 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_varnames():
 | 
				
			||||||
 | 
					    def f(x):
 | 
				
			||||||
 | 
					        pass
 | 
				
			||||||
 | 
					    class A:
 | 
				
			||||||
 | 
					        def f(self, y):
 | 
				
			||||||
 | 
					            pass
 | 
				
			||||||
 | 
					    assert varnames(f) == ("x",)
 | 
				
			||||||
 | 
					    assert varnames(A().f) == ('y',)
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					class TestMultiCall:
 | 
				
			||||||
 | 
					    def test_uses_copy_of_methods(self):
 | 
				
			||||||
 | 
					        l = [lambda: 42]
 | 
				
			||||||
 | 
					        mc = MultiCall(l, {})
 | 
				
			||||||
 | 
					        repr(mc)
 | 
				
			||||||
 | 
					        l[:] = []
 | 
				
			||||||
 | 
					        res = mc.execute()
 | 
				
			||||||
 | 
					        return res == 42
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_call_passing(self):
 | 
				
			||||||
 | 
					        class P1:
 | 
				
			||||||
 | 
					            def m(self, __multicall__, x):
 | 
				
			||||||
 | 
					                assert len(__multicall__.results) == 1
 | 
				
			||||||
 | 
					                assert not __multicall__.methods
 | 
				
			||||||
 | 
					                return 17
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        class P2:
 | 
				
			||||||
 | 
					            def m(self, __multicall__, x):
 | 
				
			||||||
 | 
					                assert __multicall__.results == []
 | 
				
			||||||
 | 
					                assert __multicall__.methods
 | 
				
			||||||
 | 
					                return 23 
 | 
				
			||||||
 | 
					               
 | 
				
			||||||
 | 
					        p1 = P1() 
 | 
				
			||||||
 | 
					        p2 = P2() 
 | 
				
			||||||
 | 
					        multicall = MultiCall([p1.m, p2.m], {'x': 23})
 | 
				
			||||||
 | 
					        assert "23" in repr(multicall)
 | 
				
			||||||
 | 
					        reslist = multicall.execute()
 | 
				
			||||||
 | 
					        assert len(reslist) == 2
 | 
				
			||||||
 | 
					        # ensure reversed order 
 | 
				
			||||||
 | 
					        assert reslist == [23, 17]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_keyword_args(self):
 | 
				
			||||||
 | 
					        def f(x): 
 | 
				
			||||||
 | 
					            return x + 1
 | 
				
			||||||
 | 
					        class A:
 | 
				
			||||||
 | 
					            def f(self, x, y):
 | 
				
			||||||
 | 
					                return x + y
 | 
				
			||||||
 | 
					        multicall = MultiCall([f, A().f], dict(x=23, y=24))
 | 
				
			||||||
 | 
					        assert "'x': 23" in repr(multicall)
 | 
				
			||||||
 | 
					        assert "'y': 24" in repr(multicall)
 | 
				
			||||||
 | 
					        reslist = multicall.execute()
 | 
				
			||||||
 | 
					        assert reslist == [24+23, 24]
 | 
				
			||||||
 | 
					        assert "2 results" in repr(multicall)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_keywords_call_error(self):
 | 
				
			||||||
 | 
					        multicall = MultiCall([lambda x: x], {})
 | 
				
			||||||
 | 
					        py.test.raises(TypeError, "multicall.execute()")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_call_subexecute(self):
 | 
				
			||||||
 | 
					        def m(__multicall__):
 | 
				
			||||||
 | 
					            subresult = __multicall__.execute()
 | 
				
			||||||
 | 
					            return subresult + 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        def n():
 | 
				
			||||||
 | 
					            return 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        call = MultiCall([n, m], {}, firstresult=True)
 | 
				
			||||||
 | 
					        res = call.execute()
 | 
				
			||||||
 | 
					        assert res == 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_call_none_is_no_result(self):
 | 
				
			||||||
 | 
					        def m1():
 | 
				
			||||||
 | 
					            return 1
 | 
				
			||||||
 | 
					        def m2():
 | 
				
			||||||
 | 
					            return None
 | 
				
			||||||
 | 
					        res = MultiCall([m1, m2], {}, firstresult=True).execute()
 | 
				
			||||||
 | 
					        assert res == 1
 | 
				
			||||||
 | 
					        res = MultiCall([m1, m2], {}).execute()
 | 
				
			||||||
 | 
					        assert res == [1]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class TestRegistry:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_register(self):
 | 
				
			||||||
 | 
					        registry = Registry()
 | 
				
			||||||
 | 
					        class MyPlugin:
 | 
				
			||||||
 | 
					            pass
 | 
				
			||||||
 | 
					        my = MyPlugin()
 | 
				
			||||||
 | 
					        registry.register(my)
 | 
				
			||||||
 | 
					        assert list(registry) == [my]
 | 
				
			||||||
 | 
					        my2 = MyPlugin()
 | 
				
			||||||
 | 
					        registry.register(my2)
 | 
				
			||||||
 | 
					        assert list(registry) == [my, my2]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        assert registry.isregistered(my)
 | 
				
			||||||
 | 
					        assert registry.isregistered(my2)
 | 
				
			||||||
 | 
					        registry.unregister(my)
 | 
				
			||||||
 | 
					        assert not registry.isregistered(my)
 | 
				
			||||||
 | 
					        assert list(registry) == [my2]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_listattr(self):
 | 
				
			||||||
 | 
					        plugins = Registry()
 | 
				
			||||||
 | 
					        class api1:
 | 
				
			||||||
 | 
					            x = 41
 | 
				
			||||||
 | 
					        class api2:
 | 
				
			||||||
 | 
					            x = 42
 | 
				
			||||||
 | 
					        class api3:
 | 
				
			||||||
 | 
					            x = 43
 | 
				
			||||||
 | 
					        plugins.register(api1())
 | 
				
			||||||
 | 
					        plugins.register(api2())
 | 
				
			||||||
 | 
					        plugins.register(api3())
 | 
				
			||||||
 | 
					        l = list(plugins.listattr('x'))
 | 
				
			||||||
 | 
					        assert l == [41, 42, 43]
 | 
				
			||||||
 | 
					        l = list(plugins.listattr('x', reverse=True))
 | 
				
			||||||
 | 
					        assert l == [43, 42, 41]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        class api4: 
 | 
				
			||||||
 | 
					            x = 44
 | 
				
			||||||
 | 
					        l = list(plugins.listattr('x', extra=(api4,)))
 | 
				
			||||||
 | 
					        assert l == [41,42,43,44]
 | 
				
			||||||
 | 
					        assert len(list(plugins)) == 3  # otherwise extra added
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class TestHookRelay:
 | 
				
			||||||
 | 
					    def test_happypath(self):
 | 
				
			||||||
 | 
					        registry = Registry()
 | 
				
			||||||
 | 
					        class Api:
 | 
				
			||||||
 | 
					            def hello(self, arg):
 | 
				
			||||||
 | 
					                pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        mcm = HookRelay(hookspecs=Api, registry=registry)
 | 
				
			||||||
 | 
					        assert hasattr(mcm, 'hello')
 | 
				
			||||||
 | 
					        assert repr(mcm.hello).find("hello") != -1
 | 
				
			||||||
 | 
					        class Plugin:
 | 
				
			||||||
 | 
					            def hello(self, arg):
 | 
				
			||||||
 | 
					                return arg + 1
 | 
				
			||||||
 | 
					        registry.register(Plugin())
 | 
				
			||||||
 | 
					        l = mcm.hello(arg=3)
 | 
				
			||||||
 | 
					        assert l == [4]
 | 
				
			||||||
 | 
					        assert not hasattr(mcm, 'world')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_only_kwargs(self):
 | 
				
			||||||
 | 
					        registry = Registry()
 | 
				
			||||||
 | 
					        class Api:
 | 
				
			||||||
 | 
					            def hello(self, arg):
 | 
				
			||||||
 | 
					                pass
 | 
				
			||||||
 | 
					        mcm = HookRelay(hookspecs=Api, registry=registry)
 | 
				
			||||||
 | 
					        py.test.raises(TypeError, "mcm.hello(3)")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_firstresult_definition(self):
 | 
				
			||||||
 | 
					        registry = Registry()
 | 
				
			||||||
 | 
					        class Api:
 | 
				
			||||||
 | 
					            def hello(self, arg): pass
 | 
				
			||||||
 | 
					            hello.firstresult = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        mcm = HookRelay(hookspecs=Api, registry=registry)
 | 
				
			||||||
 | 
					        class Plugin:
 | 
				
			||||||
 | 
					            def hello(self, arg):
 | 
				
			||||||
 | 
					                return arg + 1
 | 
				
			||||||
 | 
					        registry.register(Plugin())
 | 
				
			||||||
 | 
					        res = mcm.hello(arg=3)
 | 
				
			||||||
 | 
					        assert res == 4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_hooks_extra_plugins(self):
 | 
				
			||||||
 | 
					        registry = Registry()
 | 
				
			||||||
 | 
					        class Api:
 | 
				
			||||||
 | 
					            def hello(self, arg):
 | 
				
			||||||
 | 
					                pass
 | 
				
			||||||
 | 
					        hookrelay = HookRelay(hookspecs=Api, registry=registry)
 | 
				
			||||||
 | 
					        hook_hello = hookrelay.hello
 | 
				
			||||||
 | 
					        class Plugin:
 | 
				
			||||||
 | 
					            def hello(self, arg):
 | 
				
			||||||
 | 
					                return arg + 1
 | 
				
			||||||
 | 
					        registry.register(Plugin())
 | 
				
			||||||
 | 
					        class Plugin2:
 | 
				
			||||||
 | 
					            def hello(self, arg):
 | 
				
			||||||
 | 
					                return arg + 2
 | 
				
			||||||
 | 
					        newhook = hookrelay._makecall("hello", extralookup=Plugin2())
 | 
				
			||||||
 | 
					        l = newhook(arg=3)
 | 
				
			||||||
 | 
					        assert l == [5, 4]
 | 
				
			||||||
 | 
					        l2 = hook_hello(arg=3)
 | 
				
			||||||
 | 
					        assert l2 == [4]
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,193 +1,3 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import py
 | 
					import py
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
from py.impl._com import Registry, MultiCall, HookRelay, varnames
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def test_varnames():
 | 
					 | 
				
			||||||
    def f(x):
 | 
					 | 
				
			||||||
        pass
 | 
					 | 
				
			||||||
    class A:
 | 
					 | 
				
			||||||
        def f(self, y):
 | 
					 | 
				
			||||||
            pass
 | 
					 | 
				
			||||||
    assert varnames(f) == ("x",)
 | 
					 | 
				
			||||||
    assert varnames(A().f) == ('y',)
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
class TestMultiCall:
 | 
					 | 
				
			||||||
    def test_uses_copy_of_methods(self):
 | 
					 | 
				
			||||||
        l = [lambda: 42]
 | 
					 | 
				
			||||||
        mc = MultiCall(l, {})
 | 
					 | 
				
			||||||
        repr(mc)
 | 
					 | 
				
			||||||
        l[:] = []
 | 
					 | 
				
			||||||
        res = mc.execute()
 | 
					 | 
				
			||||||
        return res == 42
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def test_call_passing(self):
 | 
					 | 
				
			||||||
        class P1:
 | 
					 | 
				
			||||||
            def m(self, __multicall__, x):
 | 
					 | 
				
			||||||
                assert len(__multicall__.results) == 1
 | 
					 | 
				
			||||||
                assert not __multicall__.methods
 | 
					 | 
				
			||||||
                return 17
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        class P2:
 | 
					 | 
				
			||||||
            def m(self, __multicall__, x):
 | 
					 | 
				
			||||||
                assert __multicall__.results == []
 | 
					 | 
				
			||||||
                assert __multicall__.methods
 | 
					 | 
				
			||||||
                return 23 
 | 
					 | 
				
			||||||
               
 | 
					 | 
				
			||||||
        p1 = P1() 
 | 
					 | 
				
			||||||
        p2 = P2() 
 | 
					 | 
				
			||||||
        multicall = MultiCall([p1.m, p2.m], {'x': 23})
 | 
					 | 
				
			||||||
        assert "23" in repr(multicall)
 | 
					 | 
				
			||||||
        reslist = multicall.execute()
 | 
					 | 
				
			||||||
        assert len(reslist) == 2
 | 
					 | 
				
			||||||
        # ensure reversed order 
 | 
					 | 
				
			||||||
        assert reslist == [23, 17]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def test_keyword_args(self):
 | 
					 | 
				
			||||||
        def f(x): 
 | 
					 | 
				
			||||||
            return x + 1
 | 
					 | 
				
			||||||
        class A:
 | 
					 | 
				
			||||||
            def f(self, x, y):
 | 
					 | 
				
			||||||
                return x + y
 | 
					 | 
				
			||||||
        multicall = MultiCall([f, A().f], dict(x=23, y=24))
 | 
					 | 
				
			||||||
        assert "'x': 23" in repr(multicall)
 | 
					 | 
				
			||||||
        assert "'y': 24" in repr(multicall)
 | 
					 | 
				
			||||||
        reslist = multicall.execute()
 | 
					 | 
				
			||||||
        assert reslist == [24+23, 24]
 | 
					 | 
				
			||||||
        assert "2 results" in repr(multicall)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def test_keywords_call_error(self):
 | 
					 | 
				
			||||||
        multicall = MultiCall([lambda x: x], {})
 | 
					 | 
				
			||||||
        py.test.raises(TypeError, "multicall.execute()")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def test_call_subexecute(self):
 | 
					 | 
				
			||||||
        def m(__multicall__):
 | 
					 | 
				
			||||||
            subresult = __multicall__.execute()
 | 
					 | 
				
			||||||
            return subresult + 1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        def n():
 | 
					 | 
				
			||||||
            return 1
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        call = MultiCall([n, m], {}, firstresult=True)
 | 
					 | 
				
			||||||
        res = call.execute()
 | 
					 | 
				
			||||||
        assert res == 2
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def test_call_none_is_no_result(self):
 | 
					 | 
				
			||||||
        def m1():
 | 
					 | 
				
			||||||
            return 1
 | 
					 | 
				
			||||||
        def m2():
 | 
					 | 
				
			||||||
            return None
 | 
					 | 
				
			||||||
        res = MultiCall([m1, m2], {}, firstresult=True).execute()
 | 
					 | 
				
			||||||
        assert res == 1
 | 
					 | 
				
			||||||
        res = MultiCall([m1, m2], {}).execute()
 | 
					 | 
				
			||||||
        assert res == [1]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class TestRegistry:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def test_register(self):
 | 
					 | 
				
			||||||
        registry = Registry()
 | 
					 | 
				
			||||||
        class MyPlugin:
 | 
					 | 
				
			||||||
            pass
 | 
					 | 
				
			||||||
        my = MyPlugin()
 | 
					 | 
				
			||||||
        registry.register(my)
 | 
					 | 
				
			||||||
        assert list(registry) == [my]
 | 
					 | 
				
			||||||
        my2 = MyPlugin()
 | 
					 | 
				
			||||||
        registry.register(my2)
 | 
					 | 
				
			||||||
        assert list(registry) == [my, my2]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        assert registry.isregistered(my)
 | 
					 | 
				
			||||||
        assert registry.isregistered(my2)
 | 
					 | 
				
			||||||
        registry.unregister(my)
 | 
					 | 
				
			||||||
        assert not registry.isregistered(my)
 | 
					 | 
				
			||||||
        assert list(registry) == [my2]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def test_listattr(self):
 | 
					 | 
				
			||||||
        plugins = Registry()
 | 
					 | 
				
			||||||
        class api1:
 | 
					 | 
				
			||||||
            x = 41
 | 
					 | 
				
			||||||
        class api2:
 | 
					 | 
				
			||||||
            x = 42
 | 
					 | 
				
			||||||
        class api3:
 | 
					 | 
				
			||||||
            x = 43
 | 
					 | 
				
			||||||
        plugins.register(api1())
 | 
					 | 
				
			||||||
        plugins.register(api2())
 | 
					 | 
				
			||||||
        plugins.register(api3())
 | 
					 | 
				
			||||||
        l = list(plugins.listattr('x'))
 | 
					 | 
				
			||||||
        assert l == [41, 42, 43]
 | 
					 | 
				
			||||||
        l = list(plugins.listattr('x', reverse=True))
 | 
					 | 
				
			||||||
        assert l == [43, 42, 41]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        class api4: 
 | 
					 | 
				
			||||||
            x = 44
 | 
					 | 
				
			||||||
        l = list(plugins.listattr('x', extra=(api4,)))
 | 
					 | 
				
			||||||
        assert l == [41,42,43,44]
 | 
					 | 
				
			||||||
        assert len(list(plugins)) == 3  # otherwise extra added
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
def test_api_and_defaults():
 | 
					 | 
				
			||||||
    assert isinstance(py._com.comregistry, Registry)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class TestHookRelay:
 | 
					 | 
				
			||||||
    def test_happypath(self):
 | 
					 | 
				
			||||||
        registry = Registry()
 | 
					 | 
				
			||||||
        class Api:
 | 
					 | 
				
			||||||
            def hello(self, arg):
 | 
					 | 
				
			||||||
                pass
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        mcm = HookRelay(hookspecs=Api, registry=registry)
 | 
					 | 
				
			||||||
        assert hasattr(mcm, 'hello')
 | 
					 | 
				
			||||||
        assert repr(mcm.hello).find("hello") != -1
 | 
					 | 
				
			||||||
        class Plugin:
 | 
					 | 
				
			||||||
            def hello(self, arg):
 | 
					 | 
				
			||||||
                return arg + 1
 | 
					 | 
				
			||||||
        registry.register(Plugin())
 | 
					 | 
				
			||||||
        l = mcm.hello(arg=3)
 | 
					 | 
				
			||||||
        assert l == [4]
 | 
					 | 
				
			||||||
        assert not hasattr(mcm, 'world')
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def test_only_kwargs(self):
 | 
					 | 
				
			||||||
        registry = Registry()
 | 
					 | 
				
			||||||
        class Api:
 | 
					 | 
				
			||||||
            def hello(self, arg):
 | 
					 | 
				
			||||||
                pass
 | 
					 | 
				
			||||||
        mcm = HookRelay(hookspecs=Api, registry=registry)
 | 
					 | 
				
			||||||
        py.test.raises(TypeError, "mcm.hello(3)")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def test_firstresult_definition(self):
 | 
					 | 
				
			||||||
        registry = Registry()
 | 
					 | 
				
			||||||
        class Api:
 | 
					 | 
				
			||||||
            def hello(self, arg): pass
 | 
					 | 
				
			||||||
            hello.firstresult = True
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        mcm = HookRelay(hookspecs=Api, registry=registry)
 | 
					 | 
				
			||||||
        class Plugin:
 | 
					 | 
				
			||||||
            def hello(self, arg):
 | 
					 | 
				
			||||||
                return arg + 1
 | 
					 | 
				
			||||||
        registry.register(Plugin())
 | 
					 | 
				
			||||||
        res = mcm.hello(arg=3)
 | 
					 | 
				
			||||||
        assert res == 4
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def test_default_plugins(self):
 | 
					 | 
				
			||||||
        class Api: pass 
 | 
					 | 
				
			||||||
        mcm = HookRelay(hookspecs=Api, registry=py._com.comregistry)
 | 
					 | 
				
			||||||
        assert mcm._registry == py._com.comregistry
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def test_hooks_extra_plugins(self):
 | 
					 | 
				
			||||||
        registry = Registry()
 | 
					 | 
				
			||||||
        class Api:
 | 
					 | 
				
			||||||
            def hello(self, arg):
 | 
					 | 
				
			||||||
                pass
 | 
					 | 
				
			||||||
        hookrelay = HookRelay(hookspecs=Api, registry=registry)
 | 
					 | 
				
			||||||
        hook_hello = hookrelay.hello
 | 
					 | 
				
			||||||
        class Plugin:
 | 
					 | 
				
			||||||
            def hello(self, arg):
 | 
					 | 
				
			||||||
                return arg + 1
 | 
					 | 
				
			||||||
        registry.register(Plugin())
 | 
					 | 
				
			||||||
        class Plugin2:
 | 
					 | 
				
			||||||
            def hello(self, arg):
 | 
					 | 
				
			||||||
                return arg + 2
 | 
					 | 
				
			||||||
        newhook = hookrelay._makecall("hello", extralookup=Plugin2())
 | 
					 | 
				
			||||||
        l = newhook(arg=3)
 | 
					 | 
				
			||||||
        assert l == [5, 4]
 | 
					 | 
				
			||||||
        l2 = hook_hello(arg=3)
 | 
					 | 
				
			||||||
        assert l2 == [4]
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue