|
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,
|
@@ -1009,18 +1010,26 @@ def _retrieve_scope_root(item: Union[Collector, Item], scope: str) -> Collector:
|
1009 | 1010 | "package": Package,
|
1010 | 1011 | "session": Session,
|
1011 | 1012 | }
|
| 1013 | + collectors = _iter_collectors(item) |
1012 | 1014 | scope_root_type = node_type_by_scope[scope]
|
1013 |
| - for node in reversed(item.listchain()): |
1014 |
| - if isinstance(node, scope_root_type): |
1015 |
| - assert isinstance(node, pytest.Collector) |
1016 |
| - return node |
| 1015 | + collector_with_specified_scope = next( |
| 1016 | + dropwhile(lambda c: not isinstance(c, scope_root_type), collectors), None |
| 1017 | + ) |
| 1018 | + if collector_with_specified_scope: |
| 1019 | + return collector_with_specified_scope |
1017 | 1020 | error_message = (
|
1018 | 1021 | f"{item.name} is marked to be run in an event loop with scope {scope}, "
|
1019 | 1022 | f"but is not part of any {scope}."
|
1020 | 1023 | )
|
1021 | 1024 | raise pytest.UsageError(error_message)
|
1022 | 1025 |
|
1023 | 1026 |
|
| 1027 | +def _iter_collectors(item: Union[Collector, Item]) -> Iterable[Collector]: |
| 1028 | + for node in reversed(item.listchain()): |
| 1029 | + if isinstance(node, pytest.Collector): |
| 1030 | + yield node |
| 1031 | + |
| 1032 | + |
1024 | 1033 | @pytest.fixture
|
1025 | 1034 | def event_loop(request: FixtureRequest) -> Iterator[asyncio.AbstractEventLoop]:
|
1026 | 1035 | """Create an instance of the default event loop for each test case."""
|
|
0 commit comments