Skip to content

Commit 8a5c80b

Browse files
committed
hooks: avoid mutating self in call_extra
call_extra previously worked by saving the exiting hookimpls, call self._add_hookimpl() with all the extras, doing the call then restoring the old hookimpls. This is mostly fine but prevents the fields from being made Final, and probably has some reentrancy issues, so I think it's much better to avoid such tricks.
1 parent 17fa868 commit 8a5c80b

File tree

1 file changed

+15
-13
lines changed

1 file changed

+15
-13
lines changed

src/pluggy/_hooks.py

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -407,22 +407,24 @@ def call_extra(
407407
not self.is_historic()
408408
), "Cannot directly call a historic hook - use call_historic instead."
409409
self._verify_all_args_are_provided(kwargs)
410-
old = list(self._nonwrappers), list(self._wrappers)
410+
opts: "_HookImplOpts" = {
411+
"hookwrapper": False,
412+
"optionalhook": False,
413+
"trylast": False,
414+
"tryfirst": False,
415+
"specname": None,
416+
}
417+
hookimpls = self.get_hookimpls()
411418
for method in methods:
412-
opts: "_HookImplOpts" = {
413-
"hookwrapper": False,
414-
"optionalhook": False,
415-
"trylast": False,
416-
"tryfirst": False,
417-
"specname": None,
418-
}
419419
hookimpl = HookImpl(None, "<temp>", method, opts)
420-
self._add_hookimpl(hookimpl)
420+
# Find last non-tryfirst nonwrapper method.
421+
i = len(hookimpls) - 1
422+
until = len(self._nonwrappers)
423+
while i >= until and hookimpls[i].tryfirst:
424+
i -= 1
425+
hookimpls.insert(i + 1, hookimpl)
421426
firstresult = self.spec.opts.get("firstresult", False) if self.spec else False
422-
try:
423-
return self._hookexec(self.name, self.get_hookimpls(), kwargs, firstresult)
424-
finally:
425-
self._nonwrappers, self._wrappers = old
427+
return self._hookexec(self.name, hookimpls, kwargs, firstresult)
426428

427429
def _maybe_apply_history(self, method: "HookImpl") -> None:
428430
"""Apply call history to a new hookimpl if it is marked as historic."""

0 commit comments

Comments
 (0)