|
1 | 1 | import inspect |
2 | 2 | import warnings |
3 | | -from .callers import _multicall, HookCallError, _Result, _legacymulticall |
| 3 | +from .callers import ( |
| 4 | + _multicall, _itercall, HookCallError, _Result, _legacymulticall) |
4 | 5 |
|
5 | 6 | __version__ = '0.5.3.dev' |
6 | 7 |
|
@@ -209,6 +210,8 @@ def __init__(self, project_name, implprefix=None): |
209 | 210 | self._plugin_distinfo = [] |
210 | 211 | self.trace = _TagTracer().get("pluginmanage") |
211 | 212 | self.hook = _HookRelay(self.trace.root.get("hook")) |
| 213 | + # alternative set of lazily executed hook calls |
| 214 | + self.ihook = _HookRelay(self.trace.root.get("hook")) |
212 | 215 | self._implprefix = implprefix |
213 | 216 | self._inner_hookexec = lambda hook, methods, kwargs: \ |
214 | 217 | hook.multicall( |
@@ -245,14 +248,25 @@ def register(self, plugin, name=None): |
245 | 248 | method = getattr(plugin, name) |
246 | 249 | hookimpl = HookImpl(plugin, plugin_name, method, hookimpl_opts) |
247 | 250 | hook = getattr(self.hook, name, None) |
| 251 | + ihook = getattr(self.ihook, name, None) |
| 252 | + |
248 | 253 | if hook is None: |
249 | 254 | hook = _HookCaller(name, self._hookexec) |
| 255 | + ihook = _HookCaller(name, self._hookexec, iterate=True) |
250 | 256 | setattr(self.hook, name, hook) |
| 257 | + setattr(self.ihook, name, ihook) |
| 258 | + |
251 | 259 | elif hook.has_spec(): |
252 | 260 | self._verify_hook(hook, hookimpl) |
253 | 261 | hook._maybe_apply_history(hookimpl) |
| 262 | + |
| 263 | + self._verify_hook(ihook, hookimpl) |
| 264 | + ihook._maybe_apply_history(hookimpl) |
| 265 | + |
254 | 266 | hook._add_hookimpl(hookimpl) |
| 267 | + ihook._add_hookimpl(hookimpl) |
255 | 268 | hookcallers.append(hook) |
| 269 | + hookcallers.append(ihook) |
256 | 270 | return plugin_name |
257 | 271 |
|
258 | 272 | def parse_hookimpl_opts(self, plugin, name): |
@@ -306,14 +320,19 @@ def add_hookspecs(self, module_or_class): |
306 | 320 | spec_opts = self.parse_hookspec_opts(module_or_class, name) |
307 | 321 | if spec_opts is not None: |
308 | 322 | hc = getattr(self.hook, name, None) |
| 323 | + hi = getattr(self.ihook, name, None) |
309 | 324 | if hc is None: |
310 | 325 | hc = _HookCaller(name, self._hookexec, module_or_class, spec_opts) |
311 | 326 | setattr(self.hook, name, hc) |
| 327 | + hi = _HookCaller(name, self._hookexec, module_or_class, |
| 328 | + spec_opts, iterate=True) |
| 329 | + setattr(self.ihook, name, hi) |
312 | 330 | else: |
313 | 331 | # plugins registered this hook without knowing the spec |
314 | | - hc.set_specification(module_or_class, spec_opts) |
315 | | - for hookfunction in (hc._wrappers + hc._nonwrappers): |
316 | | - self._verify_hook(hc, hookfunction) |
| 332 | + for h in [hc, hi]: |
| 333 | + h.set_specification(module_or_class, spec_opts) |
| 334 | + for hookfunction in (h._wrappers + h._nonwrappers): |
| 335 | + self._verify_hook(h, hookfunction) |
317 | 336 | names.append(name) |
318 | 337 |
|
319 | 338 | if not names: |
@@ -528,14 +547,15 @@ def __init__(self, trace): |
528 | 547 |
|
529 | 548 |
|
530 | 549 | class _HookCaller(object): |
531 | | - def __init__(self, name, hook_execute, specmodule_or_class=None, spec_opts=None): |
| 550 | + def __init__(self, name, hook_execute, specmodule_or_class=None, spec_opts=None, |
| 551 | + iterate=False): |
532 | 552 | self.name = name |
533 | 553 | self._wrappers = [] |
534 | 554 | self._nonwrappers = [] |
535 | 555 | self._hookexec = hook_execute |
536 | 556 | self.argnames = None |
537 | 557 | self.kwargnames = None |
538 | | - self.multicall = _multicall |
| 558 | + self.multicall = _multicall if not iterate else _itercall |
539 | 559 | if specmodule_or_class is not None: |
540 | 560 | assert spec_opts is not None |
541 | 561 | self.set_specification(specmodule_or_class, spec_opts) |
|
0 commit comments