|
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