16
16
Awaitable ,
17
17
Callable ,
18
18
Dict ,
19
+ Generator ,
19
20
Iterable ,
20
21
Iterator ,
21
22
List ,
22
23
Literal ,
24
+ Mapping ,
23
25
Optional ,
26
+ Sequence ,
24
27
Set ,
25
28
Type ,
26
29
TypeVar ,
47
50
StashKey ,
48
51
)
49
52
50
- _R = TypeVar ("_R" )
51
-
52
53
_ScopeName = Literal ["session" , "package" , "module" , "class" , "function" ]
53
54
_T = TypeVar ("_T" )
54
55
55
56
SimpleFixtureFunction = TypeVar (
56
- "SimpleFixtureFunction" , bound = Callable [..., Awaitable [_R ]]
57
+ "SimpleFixtureFunction" , bound = Callable [..., Awaitable [object ]]
57
58
)
58
59
FactoryFixtureFunction = TypeVar (
59
- "FactoryFixtureFunction" , bound = Callable [..., AsyncIterator [_R ]]
60
+ "FactoryFixtureFunction" , bound = Callable [..., AsyncIterator [object ]]
60
61
)
61
62
FixtureFunction = Union [SimpleFixtureFunction , FactoryFixtureFunction ]
62
63
FixtureFunctionMarker = Callable [[FixtureFunction ], FixtureFunction ]
@@ -204,6 +205,7 @@ def _preprocess_async_fixtures(
204
205
config = collector .config
205
206
asyncio_mode = _get_asyncio_mode (config )
206
207
fixturemanager = config .pluginmanager .get_plugin ("funcmanage" )
208
+ assert fixturemanager is not None
207
209
for fixtures in fixturemanager ._arg2fixturedefs .values ():
208
210
for fixturedef in fixtures :
209
211
func = fixturedef .func
@@ -217,11 +219,13 @@ def _preprocess_async_fixtures(
217
219
continue
218
220
scope = fixturedef .scope
219
221
if scope == "function" :
220
- event_loop_fixture_id = "event_loop"
222
+ event_loop_fixture_id : Optional [ str ] = "event_loop"
221
223
else :
222
224
event_loop_node = _retrieve_scope_root (collector , scope )
223
225
event_loop_fixture_id = event_loop_node .stash .get (
224
- _event_loop_fixture_id , None
226
+ # Type ignored because of non-optimal mypy inference.
227
+ _event_loop_fixture_id , # type: ignore[arg-type]
228
+ None ,
225
229
)
226
230
_make_asyncio_fixture_function (func )
227
231
function_signature = inspect .signature (func )
@@ -234,8 +238,15 @@ def _preprocess_async_fixtures(
234
238
f"instead."
235
239
)
236
240
)
237
- _inject_fixture_argnames (fixturedef , event_loop_fixture_id )
238
- _synchronize_async_fixture (fixturedef , event_loop_fixture_id )
241
+ # TODO: Fix type errors below.
242
+ _inject_fixture_argnames (
243
+ fixturedef ,
244
+ event_loop_fixture_id , # type: ignore[arg-type]
245
+ )
246
+ _synchronize_async_fixture (
247
+ fixturedef ,
248
+ event_loop_fixture_id , # type: ignore[arg-type]
249
+ )
239
250
assert _is_asyncio_fixture_function (fixturedef .func )
240
251
processed_fixturedefs .add (fixturedef )
241
252
@@ -517,20 +528,20 @@ def pytest_pycollect_makeitem_preprocess_async_fixtures(
517
528
@pytest .hookimpl (specname = "pytest_pycollect_makeitem" , hookwrapper = True )
518
529
def pytest_pycollect_makeitem_convert_async_functions_to_subclass (
519
530
collector : Union [pytest .Module , pytest .Class ], name : str , obj : object
520
- ) -> Union [
521
- pytest .Item , pytest .Collector , List [Union [pytest .Item , pytest .Collector ]], None
522
- ]:
531
+ ) -> Generator [None , Any , None ]:
523
532
"""
524
533
Converts coroutines and async generators collected as pytest.Functions
525
534
to AsyncFunction items.
526
535
"""
527
536
hook_result = yield
528
- node_or_list_of_nodes = hook_result .get_result ()
537
+ node_or_list_of_nodes : Union [
538
+ pytest .Item , pytest .Collector , List [Union [pytest .Item , pytest .Collector ]], None
539
+ ] = hook_result .get_result ()
529
540
if not node_or_list_of_nodes :
530
541
return
531
- try :
542
+ if isinstance ( node_or_list_of_nodes , Sequence ) :
532
543
node_iterator = iter (node_or_list_of_nodes )
533
- except TypeError :
544
+ else :
534
545
# Treat single node as a single-element iterable
535
546
node_iterator = iter ((node_or_list_of_nodes ,))
536
547
updated_node_collection = []
@@ -549,8 +560,8 @@ def pytest_pycollect_makeitem_convert_async_functions_to_subclass(
549
560
hook_result .force_result (updated_node_collection )
550
561
551
562
552
- _event_loop_fixture_id = StashKey [str ]
553
- _fixture_scope_by_collector_type = {
563
+ _event_loop_fixture_id = StashKey [str ]()
564
+ _fixture_scope_by_collector_type : Mapping [ Type [ pytest . Collector ], _ScopeName ] = {
554
565
Class : "class" ,
555
566
# Package is a subclass of module and the dict is used in isinstance checks
556
567
# Therefore, the order matters and Package needs to appear before Module
@@ -565,7 +576,7 @@ def pytest_pycollect_makeitem_convert_async_functions_to_subclass(
565
576
566
577
567
578
@pytest .hookimpl
568
- def pytest_collectstart (collector : pytest .Collector ):
579
+ def pytest_collectstart (collector : pytest .Collector ) -> None :
569
580
try :
570
581
collector_scope = next (
571
582
scope
@@ -639,8 +650,8 @@ def _patched_collect():
639
650
pass
640
651
return collector .__original_collect ()
641
652
642
- collector .__original_collect = collector .collect
643
- collector .collect = _patched_collect
653
+ collector .__original_collect = collector .collect # type: ignore[attr-defined]
654
+ collector .collect = _patched_collect # type: ignore[method-assign]
644
655
elif isinstance (collector , Class ):
645
656
collector .obj .__pytest_asyncio_scoped_event_loop = scoped_event_loop
646
657
@@ -708,6 +719,7 @@ def pytest_generate_tests(metafunc: Metafunc) -> None:
708
719
if event_loop_fixture_id in metafunc .fixturenames :
709
720
return
710
721
fixturemanager = metafunc .config .pluginmanager .get_plugin ("funcmanage" )
722
+ assert fixturemanager is not None
711
723
if "event_loop" in metafunc .fixturenames :
712
724
raise MultipleEventLoopsRequestedError (
713
725
_MULTIPLE_LOOPS_REQUESTED_ERROR .format (
@@ -728,8 +740,8 @@ def pytest_generate_tests(metafunc: Metafunc) -> None:
728
740
729
741
@pytest .hookimpl (hookwrapper = True )
730
742
def pytest_fixture_setup (
731
- fixturedef : FixtureDef , request : SubRequest
732
- ) -> Optional [ object ]:
743
+ fixturedef : FixtureDef ,
744
+ ) -> Generator [ None , Any , None ]:
733
745
"""Adjust the event loop policy when an event loop is produced."""
734
746
if fixturedef .argname == "event_loop" :
735
747
# The use of a fixture finalizer is preferred over the
@@ -744,7 +756,7 @@ def pytest_fixture_setup(
744
756
_provide_clean_event_loop ,
745
757
)
746
758
outcome = yield
747
- loop = outcome .get_result ()
759
+ loop : asyncio . AbstractEventLoop = outcome .get_result ()
748
760
# Weird behavior was observed when checking for an attribute of FixtureDef.func
749
761
# Instead, we now check for a special attribute of the returned event loop
750
762
fixture_filename = inspect .getsourcefile (fixturedef .func )
@@ -946,6 +958,7 @@ def _retrieve_scope_root(item: Union[Collector, Item], scope: str) -> Collector:
946
958
scope_root_type = node_type_by_scope [scope ]
947
959
for node in reversed (item .listchain ()):
948
960
if isinstance (node , scope_root_type ):
961
+ assert isinstance (node , pytest .Collector )
949
962
return node
950
963
error_message = (
951
964
f"{ item .name } is marked to be run in an event loop with scope { scope } , "
0 commit comments