mirror of
https://github.com/davidhalter/jedi.git
synced 2026-10-17 16:31:26 +08:00
Merge pull request #2119 from abdull-ah-med/codex/async-pytest-fixtures
Recognize asynchronous pytest fixtures
This commit is contained in:
4 files changed
+76
-1
No files matched your search
@@ -71,6 +71,8 @@ Code Contributors
|
|||||||
- Dhanraj E (@Dhanu-dynamic) <dhanraj@labs.digiscrypt.com>
|
- Dhanraj E (@Dhanu-dynamic) <dhanraj@labs.digiscrypt.com>
|
||||||
- Charan Rathore (@charan-rathore)
|
- Charan Rathore (@charan-rathore)
|
||||||
|
|
||||||
|
- Abdullah Ahmed (@abdull-ah-med)
|
||||||
|
|
||||||
And a few more "anonymous" contributors.
|
And a few more "anonymous" contributors.
|
||||||
|
|
||||||
Note: (@user) means a github user name.
|
Note: (@user) means a github user name.
|
||||||
@@ -6,6 +6,7 @@ Changelog
|
|||||||
Unreleased
|
Unreleased
|
||||||
++++++++++
|
++++++++++
|
||||||
|
|
||||||
|
- Complete, infer and navigate to asynchronous pytest fixtures
|
||||||
- Avoid changing the global recursion limit
|
- Avoid changing the global recursion limit
|
||||||
|
|
||||||
0.20.0 (2026-05-02)
|
0.20.0 (2026-05-02)
|
||||||
|
|||||||
@@ -2,7 +2,9 @@ import sys
|
|||||||
from typing import List
|
from typing import List
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
from jedi.inference.arguments import ValuesArguments
|
||||||
from jedi.inference.cache import inference_state_method_cache
|
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.imports import goto_import, load_module_from_path
|
||||||
from jedi.inference.filters import ParserTreeFilter
|
from jedi.inference.filters import ParserTreeFilter
|
||||||
from jedi.inference.base_value import NO_VALUES, ValueSet
|
from jedi.inference.base_value import NO_VALUES, ValueSet
|
||||||
@@ -32,6 +34,19 @@ def execute(callback):
|
|||||||
def infer_anonymous_param(func):
|
def infer_anonymous_param(func):
|
||||||
def get_returns(value):
|
def get_returns(value):
|
||||||
if value.tree_node.annotation is not None:
|
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()
|
result = value.execute_with_values()
|
||||||
if any(v.name.get_qualified_names(include_module_names=True)
|
if any(v.name.get_qualified_names(include_module_names=True)
|
||||||
== ('typing', 'Generator')
|
== ('typing', 'Generator')
|
||||||
@@ -223,6 +238,8 @@ class FixtureFilter(ParserTreeFilter):
|
|||||||
if funcdef.type != "funcdef":
|
if funcdef.type != "funcdef":
|
||||||
return False
|
return False
|
||||||
decorated = funcdef.parent
|
decorated = funcdef.parent
|
||||||
|
if decorated.type == "async_funcdef":
|
||||||
|
decorated = decorated.parent
|
||||||
if decorated.type != "decorated":
|
if decorated.type != "decorated":
|
||||||
return False
|
return False
|
||||||
decorators = decorated.children[0]
|
decorators = decorated.children[0]
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from typing import Generator
|
from typing import AsyncGenerator, Generator
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from pytest import fixture
|
from pytest import fixture
|
||||||
@@ -208,3 +208,58 @@ def bla(admin_u
|
|||||||
def bla(admin_user):
|
def bla(admin_user):
|
||||||
pass
|
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
|
||||||
Reference in new issue
Block a user