Skip to content

Commit a6f2828

Browse files
committed
[refactor] Fix typing and update to mypy 1.8.0
1 parent e92efad commit a6f2828

File tree

2 files changed

+38
-23
lines changed

2 files changed

+38
-23
lines changed

.pre-commit-config.yaml

+3-1
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,12 @@ repos:
3737
- id: check-yaml
3838
- id: debug-statements
3939
- repo: https://github.com/pre-commit/mirrors-mypy
40-
rev: v0.991
40+
rev: v1.8.0
4141
hooks:
4242
- id: mypy
4343
exclude: ^(docs|tests)/.*
44+
additional_dependencies:
45+
- pytest
4446
- repo: https://github.com/pycqa/flake8
4547
rev: 6.1.0
4648
hooks:

pytest_asyncio/plugin.py

+35-22
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,14 @@
1616
Awaitable,
1717
Callable,
1818
Dict,
19+
Generator,
1920
Iterable,
2021
Iterator,
2122
List,
2223
Literal,
24+
Mapping,
2325
Optional,
26+
Sequence,
2427
Set,
2528
Type,
2629
TypeVar,
@@ -47,16 +50,14 @@
4750
StashKey,
4851
)
4952

50-
_R = TypeVar("_R")
51-
5253
_ScopeName = Literal["session", "package", "module", "class", "function"]
5354
_T = TypeVar("_T")
5455

5556
SimpleFixtureFunction = TypeVar(
56-
"SimpleFixtureFunction", bound=Callable[..., Awaitable[_R]]
57+
"SimpleFixtureFunction", bound=Callable[..., Awaitable[object]]
5758
)
5859
FactoryFixtureFunction = TypeVar(
59-
"FactoryFixtureFunction", bound=Callable[..., AsyncIterator[_R]]
60+
"FactoryFixtureFunction", bound=Callable[..., AsyncIterator[object]]
6061
)
6162
FixtureFunction = Union[SimpleFixtureFunction, FactoryFixtureFunction]
6263
FixtureFunctionMarker = Callable[[FixtureFunction], FixtureFunction]
@@ -204,6 +205,7 @@ def _preprocess_async_fixtures(
204205
config = collector.config
205206
asyncio_mode = _get_asyncio_mode(config)
206207
fixturemanager = config.pluginmanager.get_plugin("funcmanage")
208+
assert fixturemanager is not None
207209
for fixtures in fixturemanager._arg2fixturedefs.values():
208210
for fixturedef in fixtures:
209211
func = fixturedef.func
@@ -217,11 +219,13 @@ def _preprocess_async_fixtures(
217219
continue
218220
scope = fixturedef.scope
219221
if scope == "function":
220-
event_loop_fixture_id = "event_loop"
222+
event_loop_fixture_id: Optional[str] = "event_loop"
221223
else:
222224
event_loop_node = _retrieve_scope_root(collector, scope)
223225
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,
225229
)
226230
_make_asyncio_fixture_function(func)
227231
function_signature = inspect.signature(func)
@@ -234,8 +238,15 @@ def _preprocess_async_fixtures(
234238
f"instead."
235239
)
236240
)
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+
)
239250
assert _is_asyncio_fixture_function(fixturedef.func)
240251
processed_fixturedefs.add(fixturedef)
241252

@@ -517,20 +528,20 @@ def pytest_pycollect_makeitem_preprocess_async_fixtures(
517528
@pytest.hookimpl(specname="pytest_pycollect_makeitem", hookwrapper=True)
518529
def pytest_pycollect_makeitem_convert_async_functions_to_subclass(
519530
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]:
523532
"""
524533
Converts coroutines and async generators collected as pytest.Functions
525534
to AsyncFunction items.
526535
"""
527536
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()
529540
if not node_or_list_of_nodes:
530541
return
531-
try:
542+
if isinstance(node_or_list_of_nodes, Sequence):
532543
node_iterator = iter(node_or_list_of_nodes)
533-
except TypeError:
544+
else:
534545
# Treat single node as a single-element iterable
535546
node_iterator = iter((node_or_list_of_nodes,))
536547
updated_node_collection = []
@@ -549,8 +560,8 @@ def pytest_pycollect_makeitem_convert_async_functions_to_subclass(
549560
hook_result.force_result(updated_node_collection)
550561

551562

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] = {
554565
Class: "class",
555566
# Package is a subclass of module and the dict is used in isinstance checks
556567
# Therefore, the order matters and Package needs to appear before Module
@@ -565,7 +576,7 @@ def pytest_pycollect_makeitem_convert_async_functions_to_subclass(
565576

566577

567578
@pytest.hookimpl
568-
def pytest_collectstart(collector: pytest.Collector):
579+
def pytest_collectstart(collector: pytest.Collector) -> None:
569580
try:
570581
collector_scope = next(
571582
scope
@@ -639,8 +650,8 @@ def _patched_collect():
639650
pass
640651
return collector.__original_collect()
641652

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]
644655
elif isinstance(collector, Class):
645656
collector.obj.__pytest_asyncio_scoped_event_loop = scoped_event_loop
646657

@@ -708,6 +719,7 @@ def pytest_generate_tests(metafunc: Metafunc) -> None:
708719
if event_loop_fixture_id in metafunc.fixturenames:
709720
return
710721
fixturemanager = metafunc.config.pluginmanager.get_plugin("funcmanage")
722+
assert fixturemanager is not None
711723
if "event_loop" in metafunc.fixturenames:
712724
raise MultipleEventLoopsRequestedError(
713725
_MULTIPLE_LOOPS_REQUESTED_ERROR.format(
@@ -728,8 +740,8 @@ def pytest_generate_tests(metafunc: Metafunc) -> None:
728740

729741
@pytest.hookimpl(hookwrapper=True)
730742
def pytest_fixture_setup(
731-
fixturedef: FixtureDef, request: SubRequest
732-
) -> Optional[object]:
743+
fixturedef: FixtureDef,
744+
) -> Generator[None, Any, None]:
733745
"""Adjust the event loop policy when an event loop is produced."""
734746
if fixturedef.argname == "event_loop":
735747
# The use of a fixture finalizer is preferred over the
@@ -744,7 +756,7 @@ def pytest_fixture_setup(
744756
_provide_clean_event_loop,
745757
)
746758
outcome = yield
747-
loop = outcome.get_result()
759+
loop: asyncio.AbstractEventLoop = outcome.get_result()
748760
# Weird behavior was observed when checking for an attribute of FixtureDef.func
749761
# Instead, we now check for a special attribute of the returned event loop
750762
fixture_filename = inspect.getsourcefile(fixturedef.func)
@@ -946,6 +958,7 @@ def _retrieve_scope_root(item: Union[Collector, Item], scope: str) -> Collector:
946958
scope_root_type = node_type_by_scope[scope]
947959
for node in reversed(item.listchain()):
948960
if isinstance(node, scope_root_type):
961+
assert isinstance(node, pytest.Collector)
949962
return node
950963
error_message = (
951964
f"{item.name} is marked to be run in an event loop with scope {scope}, "

0 commit comments

Comments
 (0)