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