simplify addition of method and scanning of plugins
--HG-- branch : more_plugin
This commit is contained in:
parent
1e883f5979
commit
1c0582eaa7
|
@ -257,8 +257,23 @@ class PluginManager(object):
|
||||||
raise ValueError("Plugin already registered: %s=%s\n%s" %(
|
raise ValueError("Plugin already registered: %s=%s\n%s" %(
|
||||||
name, plugin, self._name2plugin))
|
name, plugin, self._name2plugin))
|
||||||
self._name2plugin[name] = plugin
|
self._name2plugin[name] = plugin
|
||||||
self._scan_plugin(plugin)
|
|
||||||
self._plugins.append(plugin)
|
self._plugins.append(plugin)
|
||||||
|
|
||||||
|
# register prefix-matching hooks of the plugin
|
||||||
|
self._plugin2hookcallers[plugin] = hookcallers = []
|
||||||
|
for name in dir(plugin):
|
||||||
|
if name.startswith(self._prefix):
|
||||||
|
hook = getattr(self.hook, name, None)
|
||||||
|
if hook is None:
|
||||||
|
if self._excludefunc is not None and self._excludefunc(name):
|
||||||
|
continue
|
||||||
|
hook = HookCaller(name, self._hookexec)
|
||||||
|
setattr(self.hook, name, hook)
|
||||||
|
elif hook.has_spec():
|
||||||
|
self._verify_hook(hook, plugin)
|
||||||
|
hook._maybe_apply_history(getattr(plugin, name))
|
||||||
|
hookcallers.append(hook)
|
||||||
|
hook._add_plugin(plugin)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def unregister(self, plugin):
|
def unregister(self, plugin):
|
||||||
|
@ -311,29 +326,16 @@ class PluginManager(object):
|
||||||
""" Return a plugin or None for the given name. """
|
""" Return a plugin or None for the given name. """
|
||||||
return self._name2plugin.get(name)
|
return self._name2plugin.get(name)
|
||||||
|
|
||||||
def _scan_plugin(self, plugin):
|
|
||||||
self._plugin2hookcallers[plugin] = hookcallers = []
|
|
||||||
for name in dir(plugin):
|
|
||||||
if name[0] == "_" or not name.startswith(self._prefix):
|
|
||||||
continue
|
|
||||||
hook = getattr(self.hook, name, None)
|
|
||||||
method = getattr(plugin, name)
|
|
||||||
if hook is None:
|
|
||||||
if self._excludefunc is not None and self._excludefunc(name):
|
|
||||||
continue
|
|
||||||
hook = HookCaller(name, self._hookexec)
|
|
||||||
setattr(self.hook, name, hook)
|
|
||||||
elif hook.has_spec():
|
|
||||||
self._verify_hook(hook, plugin)
|
|
||||||
hook._apply_history(method)
|
|
||||||
hookcallers.append(hook)
|
|
||||||
hook._add_plugin(plugin)
|
|
||||||
|
|
||||||
def _verify_hook(self, hook, plugin):
|
def _verify_hook(self, hook, plugin):
|
||||||
method = getattr(plugin, hook.name)
|
method = getattr(plugin, hook.name)
|
||||||
|
pluginname = self._get_canonical_name(plugin)
|
||||||
|
if hook.is_historic() and hasattr(method, "hookwrapper"):
|
||||||
|
raise PluginValidationError(
|
||||||
|
"Plugin %r\nhook %r\nhistoric incompatible to hookwrapper" %(
|
||||||
|
pluginname, hook.name))
|
||||||
|
|
||||||
for arg in varnames(method):
|
for arg in varnames(method):
|
||||||
if arg not in hook.argnames:
|
if arg not in hook.argnames:
|
||||||
pluginname = self._get_canonical_name(plugin)
|
|
||||||
raise PluginValidationError(
|
raise PluginValidationError(
|
||||||
"Plugin %r\nhook %r\nargument %r not available\n"
|
"Plugin %r\nhook %r\nargument %r not available\n"
|
||||||
"plugin definition: %s\n"
|
"plugin definition: %s\n"
|
||||||
|
@ -369,6 +371,8 @@ class MultiCall:
|
||||||
def execute(self):
|
def execute(self):
|
||||||
all_kwargs = self.kwargs
|
all_kwargs = self.kwargs
|
||||||
self.results = results = []
|
self.results = results = []
|
||||||
|
firstresult = self.firstresult
|
||||||
|
|
||||||
while self.methods:
|
while self.methods:
|
||||||
method = self.methods.pop()
|
method = self.methods.pop()
|
||||||
args = [all_kwargs[argname] for argname in varnames(method)]
|
args = [all_kwargs[argname] for argname in varnames(method)]
|
||||||
|
@ -376,10 +380,11 @@ class MultiCall:
|
||||||
return wrapped_call(method(*args), self.execute)
|
return wrapped_call(method(*args), self.execute)
|
||||||
res = method(*args)
|
res = method(*args)
|
||||||
if res is not None:
|
if res is not None:
|
||||||
if self.firstresult:
|
if firstresult:
|
||||||
return res
|
return res
|
||||||
results.append(res)
|
results.append(res)
|
||||||
if not self.firstresult:
|
|
||||||
|
if not firstresult:
|
||||||
return results
|
return results
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
|
@ -476,24 +481,19 @@ class HookCaller(object):
|
||||||
|
|
||||||
def _add_method(self, meth):
|
def _add_method(self, meth):
|
||||||
if hasattr(meth, 'hookwrapper'):
|
if hasattr(meth, 'hookwrapper'):
|
||||||
assert not self.is_historic()
|
|
||||||
self._wrappers.append(meth)
|
self._wrappers.append(meth)
|
||||||
elif hasattr(meth, 'trylast'):
|
elif hasattr(meth, 'trylast'):
|
||||||
self._nonwrappers.insert(0, meth)
|
self._nonwrappers.insert(0, meth)
|
||||||
elif hasattr(meth, 'tryfirst'):
|
elif hasattr(meth, 'tryfirst'):
|
||||||
self._nonwrappers.append(meth)
|
self._nonwrappers.append(meth)
|
||||||
else:
|
else:
|
||||||
|
# find the last nonwrapper which is not tryfirst marked
|
||||||
nonwrappers = self._nonwrappers
|
nonwrappers = self._nonwrappers
|
||||||
if not nonwrappers or not hasattr(nonwrappers[-1], "tryfirst"):
|
i = len(nonwrappers) - 1
|
||||||
nonwrappers.append(meth)
|
while i >= 0 and hasattr(nonwrappers[i], "tryfirst"):
|
||||||
else:
|
i -= 1
|
||||||
for i in reversed(range(len(nonwrappers)-1)):
|
# and insert right in front of the tryfirst ones
|
||||||
if hasattr(nonwrappers[i], "tryfirst"):
|
nonwrappers.insert(i+1, meth)
|
||||||
continue
|
|
||||||
nonwrappers.insert(i+1, meth)
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
nonwrappers.insert(0, meth)
|
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "<HookCaller %r>" %(self.name,)
|
return "<HookCaller %r>" %(self.name,)
|
||||||
|
@ -518,7 +518,7 @@ class HookCaller(object):
|
||||||
finally:
|
finally:
|
||||||
self._nonwrappers, self._wrappers = old
|
self._nonwrappers, self._wrappers = old
|
||||||
|
|
||||||
def _apply_history(self, method):
|
def _maybe_apply_history(self, method):
|
||||||
if self.is_historic():
|
if self.is_historic():
|
||||||
for kwargs, proc in self._call_history:
|
for kwargs, proc in self._call_history:
|
||||||
res = self._hookexec(self, [method], kwargs)
|
res = self._hookexec(self, [method], kwargs)
|
||||||
|
|
|
@ -131,6 +131,22 @@ class TestPluginManager:
|
||||||
pm.register(Plugin())
|
pm.register(Plugin())
|
||||||
assert l == [10]
|
assert l == [10]
|
||||||
|
|
||||||
|
def test_register_historic_incompat_hookwrapper(self, pm):
|
||||||
|
class Hooks:
|
||||||
|
@hookspec_opts(historic=True)
|
||||||
|
def he_method1(self, arg):
|
||||||
|
pass
|
||||||
|
pm.addhooks(Hooks)
|
||||||
|
|
||||||
|
l = []
|
||||||
|
class Plugin:
|
||||||
|
@hookimpl_opts(hookwrapper=True)
|
||||||
|
def he_method1(self, arg):
|
||||||
|
l.append(arg)
|
||||||
|
|
||||||
|
with pytest.raises(PluginValidationError):
|
||||||
|
pm.register(Plugin())
|
||||||
|
|
||||||
def test_call_extra(self, pm):
|
def test_call_extra(self, pm):
|
||||||
class Hooks:
|
class Hooks:
|
||||||
def he_method1(self, arg):
|
def he_method1(self, arg):
|
||||||
|
|
Loading…
Reference in New Issue