Skip to content

Commit a3efb24

Browse files
committed
pytest v9.0.0
1 parent 03dd96a commit a3efb24

File tree

3 files changed

+43
-49
lines changed

3 files changed

+43
-49
lines changed

pyproject.toml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,13 @@ maintainers = [
2020
authors = [
2121
{ name = "Tin Tvrtković", email = "[email protected]" },
2222
]
23-
requires-python = ">=3.9"
23+
requires-python = ">=3.10"
2424
classifiers = [
2525
"Development Status :: 5 - Production/Stable",
2626
"Framework :: AsyncIO",
2727
"Framework :: Pytest",
2828
"Intended Audience :: Developers",
2929
"Programming Language :: Python :: 3 :: Only",
30-
"Programming Language :: Python :: 3.9",
3130
"Programming Language :: Python :: 3.10",
3231
"Programming Language :: Python :: 3.11",
3332
"Programming Language :: Python :: 3.12",
@@ -42,7 +41,7 @@ dynamic = [
4241

4342
dependencies = [
4443
"backports-asyncio-runner>=1.1,<2; python_version<'3.11'",
45-
"pytest>=8.2,<9",
44+
"pytest>=9.0.0,<10.0.0",
4645
"typing-extensions>=4.12; python_version<'3.13'",
4746
]
4847
optional-dependencies.docs = [

pytest_asyncio/plugin.py

Lines changed: 25 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from collections.abc import (
1717
AsyncIterator,
1818
Awaitable,
19+
Callable,
1920
Generator,
2021
Iterable,
2122
Iterator,
@@ -24,10 +25,9 @@
2425
from types import AsyncGeneratorType, CoroutineType
2526
from typing import (
2627
Any,
27-
Callable,
2828
Literal,
29+
ParamSpec,
2930
TypeVar,
30-
Union,
3131
overload,
3232
)
3333

@@ -49,11 +49,6 @@
4949
PytestPluginManager,
5050
)
5151

52-
if sys.version_info >= (3, 10):
53-
from typing import ParamSpec
54-
else:
55-
from typing_extensions import ParamSpec
56-
5752
if sys.version_info >= (3, 11):
5853
from asyncio import Runner
5954
else:
@@ -65,7 +60,7 @@
6560
from typing_extensions import TypeIs
6661

6762
_ScopeName = Literal["session", "package", "module", "class", "function"]
68-
_R = TypeVar("_R", bound=Union[Awaitable[Any], AsyncIterator[Any]])
63+
_R = TypeVar("_R", bound=Awaitable[Any] | AsyncIterator[Any])
6964
_P = ParamSpec("_P")
7065
FixtureFunction = Callable[_P, _R]
7166

@@ -209,7 +204,7 @@ def _get_asyncio_mode(config: Config) -> Mode:
209204
except ValueError as e:
210205
modes = ", ".join(m.value for m in Mode)
211206
raise pytest.UsageError(
212-
f"{val!r} is not a valid asyncio_mode. Valid modes: {modes}."
207+
f"{val!r} is not a valid asyncio_mode. Valid modes: {modes}.",
213208
) from e
214209

215210

@@ -241,7 +236,7 @@ def _validate_scope(scope: str | None, option_name: str) -> None:
241236
if scope not in valid_scopes:
242237
raise pytest.UsageError(
243238
f"{scope!r} is not a valid {option_name}. "
244-
f"Valid scopes are: {', '.join(valid_scopes)}."
239+
f"Valid scopes are: {', '.join(valid_scopes)}.",
245240
)
246241

247242

@@ -280,7 +275,7 @@ def pytest_report_header(config: Config) -> list[str]:
280275

281276

282277
def _fixture_synchronizer(
283-
fixturedef: FixtureDef, runner: Runner, request: FixtureRequest
278+
fixturedef: FixtureDef, runner: Runner, request: FixtureRequest,
284279
) -> Callable:
285280
"""Returns a synchronous function evaluating the specified fixture."""
286281
fixture_function = resolve_fixture_function(fixturedef, request)
@@ -298,7 +293,7 @@ def _fixture_synchronizer(
298293

299294
def _wrap_asyncgen_fixture(
300295
fixture_function: Callable[
301-
AsyncGenFixtureParams, AsyncGeneratorType[AsyncGenFixtureYieldType, Any]
296+
AsyncGenFixtureParams, AsyncGeneratorType[AsyncGenFixtureYieldType, Any],
302297
],
303298
runner: Runner,
304299
request: FixtureRequest,
@@ -348,7 +343,7 @@ async def async_finalizer() -> None:
348343

349344
def _wrap_async_fixture(
350345
fixture_function: Callable[
351-
AsyncFixtureParams, CoroutineType[Any, Any, AsyncFixtureReturnType]
346+
AsyncFixtureParams, CoroutineType[Any, Any, AsyncFixtureReturnType],
352347
],
353348
runner: Runner,
354349
request: FixtureRequest,
@@ -454,7 +449,7 @@ def _from_function(cls, function: Function, /) -> Function:
454449
@staticmethod
455450
def _can_substitute(item: Function) -> bool:
456451
"""Returns whether the specified function can be replaced by this class"""
457-
raise NotImplementedError()
452+
raise NotImplementedError
458453

459454
def setup(self) -> None:
460455
runner_fixture_id = f"_{self._loop_scope}_scoped_runner"
@@ -467,7 +462,7 @@ def runtest(self) -> None:
467462
runner = self._request.getfixturevalue(runner_fixture_id)
468463
context = contextvars.copy_context()
469464
synchronized_obj = _synchronize_coroutine(
470-
getattr(*self._synchronization_target_attr), runner, context
465+
getattr(*self._synchronization_target_attr), runner, context,
471466
)
472467
with MonkeyPatch.context() as c:
473468
c.setattr(*self._synchronization_target_attr, synchronized_obj)
@@ -478,9 +473,9 @@ def _loop_scope(self) -> _ScopeName:
478473
"""
479474
Return the scope of the asyncio event loop this item is run in.
480475
481-
The effective scope is determined lazily. It is identical to to the
476+
The effective scope is determined lazily. It is identical to the
482477
`loop_scope` value of the closest `asyncio` pytest marker. If no such
483-
marker is present, the the loop scope is determined by the configuration
478+
marker is present, the loop scope is determined by the configuration
484479
value of `asyncio_default_test_loop_scope`, instead.
485480
"""
486481
marker = self.get_closest_marker("asyncio")
@@ -526,7 +521,7 @@ def _from_function(cls, function: Function, /) -> Function:
526521
)
527522
async_gen_item.warn(PytestCollectionWarning(unsupported_item_type_message))
528523
async_gen_item.add_marker(
529-
pytest.mark.xfail(run=False, reason=unsupported_item_type_message)
524+
pytest.mark.xfail(run=False, reason=unsupported_item_type_message),
530525
)
531526
return async_gen_item
532527

@@ -541,7 +536,7 @@ class AsyncStaticMethod(PytestAsyncioFunction):
541536
def _can_substitute(item: Function) -> bool:
542537
func = item.obj
543538
return isinstance(func, staticmethod) and _is_coroutine_or_asyncgen(
544-
func.__func__
539+
func.__func__,
545540
)
546541

547542

@@ -553,11 +548,11 @@ class AsyncHypothesisTest(PytestAsyncioFunction):
553548

554549
def setup(self) -> None:
555550
if not getattr(self.obj, "hypothesis", False) and getattr(
556-
self.obj, "is_hypothesis_test", False
551+
self.obj, "is_hypothesis_test", False,
557552
):
558553
pytest.fail(
559554
f"test function `{self!r}` is using Hypothesis, but pytest-asyncio "
560-
"only works with Hypothesis 3.64.0 or later."
555+
"only works with Hypothesis 3.64.0 or later.",
561556
)
562557
return super().setup()
563558

@@ -579,7 +574,7 @@ def _synchronization_target_attr(self) -> tuple[object, str]:
579574
# see https://github.com/pytest-dev/pytest/issues/11307
580575
@pytest.hookimpl(specname="pytest_pycollect_makeitem", hookwrapper=True)
581576
def pytest_pycollect_makeitem_convert_async_functions_to_subclass(
582-
collector: pytest.Module | pytest.Class, name: str, obj: object
577+
collector: pytest.Module | pytest.Class, name: str, obj: object,
583578
) -> Generator[None, pluggy.Result, None]:
584579
"""
585580
Converts coroutines and async generators collected as pytest.Functions
@@ -607,7 +602,7 @@ def pytest_pycollect_makeitem_convert_async_functions_to_subclass(
607602
specialized_item_class = PytestAsyncioFunction.item_subclass_for(node)
608603
if specialized_item_class:
609604
if _get_asyncio_mode(
610-
node.config
605+
node.config,
611606
) == Mode.AUTO and not node.get_closest_marker("asyncio"):
612607
node.add_marker("asyncio")
613608
if node.get_closest_marker("asyncio"):
@@ -683,7 +678,7 @@ def pytest_pyfunc_call(pyfuncitem: Function) -> object | None:
683678
"You might want to use @pytest_asyncio.fixture or switch "
684679
"to auto mode. "
685680
"This will become an error in future versions of "
686-
"pytest-asyncio."
681+
"pytest-asyncio.",
687682
),
688683
stacklevel=1,
689684
)
@@ -698,8 +693,8 @@ def pytest_pyfunc_call(pyfuncitem: Function) -> object | None:
698693
"but it is not an async function. "
699694
"Please remove the asyncio mark. "
700695
"If the test is not marked explicitly, "
701-
"check for global marks applied via 'pytestmark'."
702-
)
696+
"check for global marks applied via 'pytestmark'.",
697+
),
703698
)
704699
yield
705700
return None
@@ -761,7 +756,7 @@ def pytest_fixture_setup(fixturedef: FixtureDef, request) -> object | None:
761756

762757

763758
def _get_marked_loop_scope(
764-
asyncio_marker: Mark, default_loop_scope: _ScopeName
759+
asyncio_marker: Mark, default_loop_scope: _ScopeName,
765760
) -> _ScopeName:
766761
assert asyncio_marker.name == "asyncio"
767762
if asyncio_marker.args or (
@@ -773,7 +768,7 @@ def _get_marked_loop_scope(
773768
raise pytest.UsageError(_DUPLICATE_LOOP_SCOPE_DEFINITION_ERROR)
774769
warnings.warn(PytestDeprecationWarning(_MARKER_SCOPE_KWARG_DEPRECATION_WARNING))
775770
scope = asyncio_marker.kwargs.get("loop_scope") or asyncio_marker.kwargs.get(
776-
"scope"
771+
"scope",
777772
)
778773
if scope is None:
779774
scope = default_loop_scope
@@ -816,7 +811,7 @@ def _scoped_runner(
816811
else:
817812
with warnings.catch_warnings():
818813
warnings.filterwarnings(
819-
"ignore", ".*BaseEventLoop.shutdown_asyncgens.*", RuntimeWarning
814+
"ignore", ".*BaseEventLoop.shutdown_asyncgens.*", RuntimeWarning,
820815
)
821816
try:
822817
runner.__exit__(None, None, None)
@@ -831,7 +826,7 @@ def _scoped_runner(
831826

832827
for scope in Scope:
833828
globals()[f"_{scope.value}_scoped_runner"] = _create_scoped_runner_fixture(
834-
scope.value
829+
scope.value,
835830
)
836831

837832

tests/test_event_loop_fixture.py

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ def new_event_loop(self):
2222
2323
# This statement represents a code which sets a custom event loop policy
2424
asyncio.set_event_loop_policy(TestEventLoopPolicy())
25-
"""
26-
)
25+
""",
26+
),
2727
)
2828
pytester.makepyfile(
2929
dedent(
@@ -48,8 +48,8 @@ async def test_custom_policy_is_not_overwritten():
4848
across test cases.
4949
'''
5050
assert type(asyncio.get_event_loop()).__name__ == "TestEventLoop"
51-
"""
52-
)
51+
""",
52+
),
5353
)
5454
result = pytester.runpytest_subprocess("--asyncio-mode=strict")
5555
result.assert_outcomes(passed=2)
@@ -75,11 +75,11 @@ async def generator_fn():
7575
7676
gen = generator_fn()
7777
await gen.__anext__()
78-
"""
79-
)
78+
""",
79+
),
8080
)
8181
result = pytester.runpytest_subprocess("--asyncio-mode=strict", "-W", "default")
82-
result.assert_outcomes(passed=1, warnings=0)
82+
result.assert_outcomes(passed=1)
8383

8484

8585
def test_closing_event_loop_in_sync_fixture_teardown_raises_warning(
@@ -107,14 +107,14 @@ def close_event_loop(_event_loop):
107107
@pytest.mark.asyncio
108108
async def test_something(close_event_loop):
109109
await asyncio.sleep(0.01)
110-
"""
111-
)
110+
""",
111+
),
112112
)
113113
result = pytester.runpytest_subprocess("--asyncio-mode=strict")
114-
result.assert_outcomes(passed=1, warnings=1)
115-
result.stdout.fnmatch_lines(
116-
["*An exception occurred during teardown of an asyncio.Runner*"]
117-
)
114+
result.assert_outcomes(passed=1)
115+
result.stdout.fnmatch_lines([
116+
"*An exception occurred during teardown of an asyncio.Runner*",
117+
])
118118

119119

120120
def test_event_loop_fixture_asyncgen_error(
@@ -136,8 +136,8 @@ async def test_something():
136136
async def fail():
137137
raise RuntimeError("mock error cleaning up...")
138138
loop.shutdown_asyncgens = fail
139-
"""
140-
)
139+
""",
140+
),
141141
)
142142
result = pytester.runpytest_subprocess("--asyncio-mode=strict", "-W", "default")
143-
result.assert_outcomes(passed=1, warnings=1)
143+
result.assert_outcomes(passed=1)

0 commit comments

Comments
 (0)