Merge pull request #2119 from abdull-ah-med/codex/async-pytest-fixtures

Recognize asynchronous pytest fixtures
This commit is contained in:
Dave Halter authored and GitHub committed 2026-10-12 11:05:00 +00:00
commit 79d9764bce
4 files changed
+76 -1

No files matched your search

+2
View File
@@ -71,6 +71,8 @@ Code Contributors
- Dhanraj E (@Dhanu-dynamic) <dhanraj@labs.digiscrypt.com>
- Charan Rathore (@charan-rathore)
- Abdullah Ahmed (@abdull-ah-med)
And a few more "anonymous" contributors.
Note: (@user) means a github user name.
+1
View File
@@ -6,6 +6,7 @@ Changelog
Unreleased
++++++++++
- Complete, infer and navigate to asynchronous pytest fixtures
- Avoid changing the global recursion limit
0.20.0 (2026-05-02)
+17
View File
@@ -2,7 +2,9 @@ import sys
from typing import List
from pathlib import Path
from jedi.inference.arguments import ValuesArguments
from jedi.inference.cache import inference_state_method_cache
from jedi.inference.gradual.annotation import infer_return_types
from jedi.inference.imports import goto_import, load_module_from_path
from jedi.inference.filters import ParserTreeFilter
from jedi.inference.base_value import NO_VALUES, ValueSet
@@ -32,6 +34,19 @@ def execute(callback):
def infer_anonymous_param(func):
def get_returns(value):
if value.tree_node.annotation is not None:
if value.tree_node.parent.type == 'async_funcdef':
# Async fixtures provide the awaited value, rather than a
# coroutine. The annotation of an async generator describes
# the iterator, so the value is what that iterator yields.
result = infer_return_types(value, ValuesArguments([]))
if value.as_context().is_generator():
return ValueSet.from_sets(
lazy_value.infer()
for v in result
for lazy_value in v.iterate(is_async=True)
)
return result
result = value.execute_with_values()
if any(v.name.get_qualified_names(include_module_names=True)
== ('typing', 'Generator')
@@ -223,6 +238,8 @@ class FixtureFilter(ParserTreeFilter):
if funcdef.type != "funcdef":
return False
decorated = funcdef.parent
if decorated.type == "async_funcdef":
decorated = decorated.parent
if decorated.type != "decorated":
return False
decorators = decorated.children[0]
+56 -1
View File
@@ -1,4 +1,4 @@
from typing import Generator
from typing import AsyncGenerator, Generator
import pytest
from pytest import fixture
@@ -208,3 +208,58 @@ def bla(admin_u
def bla(admin_user):
pass
# -----------------
# asynchronous fixtures
# -----------------
@pytest.fixture
async def async_fixture():
return 1
@pytest.fixture(scope='module')
async def async_annotated_fixture() -> str:
return ''
@fixture
async def async_yield_fixture():
yield 1.0
@pytest.fixture
async def async_annotated_opaque() -> int:
return opaque_value
@pytest.fixture
async def async_generator_annotated() -> AsyncGenerator[str, None]:
yield opaque_value
#? ['async_fixture']
def test_async_fixture_completion(async_fixt
pass
def test_async_fixture_inference(async_fixture, async_annotated_fixture, async_yield_fixture):
#? int()
async_fixture
#? str()
async_annotated_fixture
#? float()
async_yield_fixture
def test_async_fixture_annotation(async_annotated_opaque, async_generator_annotated):
#? int()
async_annotated_opaque
#? str()
async_generator_annotated
#! 30 ['def async_fixture']
def test_async_fixture_goto(async_fixture):
pass