Skip to content

Commit

Permalink
hooks: fix call_extra extra methods getting ordered before everythi…
Browse files Browse the repository at this point in the history
…ng else

when there is at least one wrapper impl.

Fix pytest-dev#441.
Regressed in 63b7e90 - pluggy 1.1.0.

[ran: reworked]
  • Loading branch information
Vishu Tupili authored and bluetech committed Jan 20, 2024
1 parent 4577b45 commit d6bccae
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 4 deletions.
9 changes: 5 additions & 4 deletions src/pluggy/_hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -548,10 +548,11 @@ def call_extra(
hookimpl = HookImpl(None, "<temp>", method, opts)
# Find last non-tryfirst nonwrapper method.
i = len(hookimpls) - 1
while (
i >= 0
and hookimpls[i].tryfirst
and not (hookimpls[i].hookwrapper or hookimpls[i].wrapper)
while i >= 0 and (
# Skip wrappers.
(hookimpls[i].hookwrapper or hookimpls[i].wrapper)
# Skip tryfirst nonwrappers.
or hookimpls[i].tryfirst
):
i -= 1
hookimpls.insert(i + 1, hookimpl)
Expand Down
71 changes: 71 additions & 0 deletions testing/test_hookcaller.py
Original file line number Diff line number Diff line change
Expand Up @@ -448,3 +448,74 @@ def conflict(self) -> None:
"Hook 'conflict' is already registered within namespace "
"<class 'test_hookcaller.test_hook_conflict.<locals>.Api1'>"
)


def test_call_extra_hook_order(hc: HookCaller, addmeth: AddMeth) -> None:
"""Ensure that call_extra is calling hooks in the right order."""
order = []

@addmeth(tryfirst=True)
def method1() -> str:
order.append("1")
return "1"

@addmeth()
def method2() -> str:
order.append("2")
return "2"

@addmeth(trylast=True)
def method3() -> str:
order.append("3")
return "3"

@addmeth(wrapper=True, tryfirst=True)
def method4() -> str:
order.append("4pre")
result = yield
order.append("4post")
return result

@addmeth(wrapper=True)
def method5() -> str:
order.append("5pre")
result = yield
order.append("5post")
return result

@addmeth(wrapper=True, trylast=True)
def method6() -> str:
order.append("6pre")
result = yield
order.append("6post")
return result

def extra1() -> str:
order.append("extra1")
return "extra1"

def extra2() -> str:
order.append("extra2")
return "extra2"

result = hc.call_extra([extra1, extra2], {"arg": "test"})
assert order == [
"4pre",
"5pre",
"6pre",
"1",
"extra2",
"extra1",
"2",
"3",
"6post",
"5post",
"4post",
]
assert result == [
"1",
"extra2",
"extra1",
"2",
"3",
]

0 comments on commit d6bccae

Please sign in to comment.