Skip to content

Address internal pytest error during collection of doctests #685

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions pytest_asyncio/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -544,25 +544,33 @@ def pytest_pycollect_makeitem_convert_async_functions_to_subclass(
_event_loop_fixture_id = StashKey[str]
_fixture_scope_by_collector_type = {
Class: "class",
Module: "module",
# Package is a subclass of module and the dict is used in isinstance checks
# Therefore, the order matters and Package needs to appear before Module
Package: "package",
Module: "module",
Session: "session",
}


@pytest.hookimpl
def pytest_collectstart(collector: pytest.Collector):
try:
collector_scope = next(
scope
for cls, scope in _fixture_scope_by_collector_type.items()
if isinstance(collector, cls)
)
except StopIteration:
return
# Session is not a PyCollector type, so it doesn't have a corresponding
# "obj" attribute to attach a dynamic fixture function to.
# However, there's only one session per pytest run, so there's no need to
# create the fixture dynamically. We can simply define a session-scoped
# event loop fixture once in the plugin code.
if isinstance(collector, Session):
if collector_scope == "session":
event_loop_fixture_id = _session_event_loop.__name__
collector.stash[_event_loop_fixture_id] = event_loop_fixture_id
return
if not isinstance(collector, (Class, Module, Package)):
return
# There seem to be issues when a fixture is shadowed by another fixture
# and both differ in their params.
# https://github.com/pytest-dev/pytest/issues/2043
Expand All @@ -574,7 +582,7 @@ def pytest_collectstart(collector: pytest.Collector):
collector.stash[_event_loop_fixture_id] = event_loop_fixture_id

@pytest.fixture(
scope=_fixture_scope_by_collector_type[type(collector)],
scope=collector_scope,
name=event_loop_fixture_id,
)
def scoped_event_loop(
Expand Down
19 changes: 19 additions & 0 deletions tests/test_doctest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
from textwrap import dedent

from pytest import Pytester


def test_plugin_does_not_interfere_with_doctest_collection(pytester: Pytester):
pytester.makepyfile(
dedent(
'''\
def any_function():
"""
>>> 42
42
"""
'''
),
)
result = pytester.runpytest("--asyncio-mode=strict", "--doctest-modules")
result.assert_outcomes(passed=1)