|
8 | 8 | import socket
|
9 | 9 | import warnings
|
10 | 10 | from asyncio import AbstractEventLoopPolicy
|
| 11 | +from itertools import dropwhile |
11 | 12 | from textwrap import dedent
|
12 | 13 | from typing import (
|
13 | 14 | Any,
|
@@ -958,18 +959,26 @@ def _retrieve_scope_root(item: Union[Collector, Item], scope: str) -> Collector:
|
958 | 959 | "package": Package,
|
959 | 960 | "session": Session,
|
960 | 961 | }
|
| 962 | + collectors = _iter_collectors(item) |
961 | 963 | scope_root_type = node_type_by_scope[scope]
|
962 |
| - for node in reversed(item.listchain()): |
963 |
| - if isinstance(node, scope_root_type): |
964 |
| - assert isinstance(node, pytest.Collector) |
965 |
| - return node |
| 964 | + collector_with_specified_scope = next( |
| 965 | + dropwhile(lambda c: not isinstance(c, scope_root_type), collectors), None |
| 966 | + ) |
| 967 | + if collector_with_specified_scope: |
| 968 | + return collector_with_specified_scope |
966 | 969 | error_message = (
|
967 | 970 | f"{item.name} is marked to be run in an event loop with scope {scope}, "
|
968 | 971 | f"but is not part of any {scope}."
|
969 | 972 | )
|
970 | 973 | raise pytest.UsageError(error_message)
|
971 | 974 |
|
972 | 975 |
|
| 976 | +def _iter_collectors(item: Union[Collector, Item]) -> Iterable[Collector]: |
| 977 | + for node in reversed(item.listchain()): |
| 978 | + if isinstance(node, pytest.Collector): |
| 979 | + yield node |
| 980 | + |
| 981 | + |
973 | 982 | @pytest.fixture
|
974 | 983 | def event_loop(request: FixtureRequest) -> Iterator[asyncio.AbstractEventLoop]:
|
975 | 984 | """Create an instance of the default event loop for each test case."""
|
|
0 commit comments