Make yield pytest fixtures work

This commit is contained in:
Dave Halter
2019-12-27 01:50:17 +01:00
parent c45c8ec8ef
commit 148fffae28
3 changed files with 37 additions and 7 deletions

View File

@@ -277,17 +277,19 @@ class BaseFunctionExecutionContext(ValueContext, TreeContextMixin):
for lazy_value in self.get_yield_lazy_values() for lazy_value in self.get_yield_lazy_values()
) )
def is_generator(self):
return bool(get_yield_exprs(self.inference_state, self.tree_node))
def infer(self): def infer(self):
""" """
Created to be used by inheritance. Created to be used by inheritance.
""" """
inference_state = self.inference_state inference_state = self.inference_state
is_coroutine = self.tree_node.parent.type in ('async_stmt', 'async_funcdef') is_coroutine = self.tree_node.parent.type in ('async_stmt', 'async_funcdef')
is_generator = bool(get_yield_exprs(inference_state, self.tree_node))
from jedi.inference.gradual.base import GenericClass from jedi.inference.gradual.base import GenericClass
if is_coroutine: if is_coroutine:
if is_generator: if self.is_generator():
if inference_state.environment.version_info < (3, 6): if inference_state.environment.version_info < (3, 6):
return NO_VALUES return NO_VALUES
async_generator_classes = inference_state.typing_module \ async_generator_classes = inference_state.typing_module \
@@ -312,7 +314,7 @@ class BaseFunctionExecutionContext(ValueContext, TreeContextMixin):
GenericClass(c, TupleGenericManager(generics)) for c in async_classes GenericClass(c, TupleGenericManager(generics)) for c in async_classes
).execute_annotation() ).execute_annotation()
else: else:
if is_generator: if self.is_generator():
return ValueSet([iterable.Generator(inference_state, self)]) return ValueSet([iterable.Generator(inference_state, self)])
else: else:
return self.get_return_values() return self.get_return_values()

View File

@@ -17,8 +17,17 @@ 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:
return value.execute_with_values()
# In pytest we need to differentiate between generators and normal
# returns.
# Parameters still need to be anonymous, .as_context() ensures that.
function_context = value.as_context() function_context = value.as_context()
return function_context.get_return_values() if function_context.is_generator():
return function_context.merge_yield_values()
else:
return function_context.get_return_values()
def wrapper(param): def wrapper(param):
module = param.get_root_context() module = param.get_root_context()
@@ -59,4 +68,6 @@ def _iter_pytest_modules(module_context):
class FixtureFilter(ParserTreeFilter): class FixtureFilter(ParserTreeFilter):
def _filter(self, names): def _filter(self, names):
for name in super(FixtureFilter, self)._filter(names): for name in super(FixtureFilter, self)._filter(names):
yield name if name.parent.type == 'funcdef':
# Class fixtures are not supported
yield name

View File

@@ -13,14 +13,25 @@ def my_simple_fixture():
return 1 return 1
@fixture
def my_yield_fixture():
yield 1
@fixture
class MyClassFixture():
pass
# ----------------- # -----------------
# goto/infer # goto/infer
# ----------------- # -----------------
#! 18 'def my_conftest_fixture' #! 18 ['def my_conftest_fixture']
def test_x(my_conftest_fixture, my_fixture, my_not_existing_fixture): def test_x(my_conftest_fixture, my_fixture, my_not_existing_fixture, my_yield_fixture):
#? str() #? str()
my_fixture my_fixture
#? int()
my_yield_fixture
#? #?
my_not_existing_fixture my_not_existing_fixture
#? float() #? float()
@@ -30,6 +41,12 @@ def test_x(my_conftest_fixture, my_fixture, my_not_existing_fixture):
def test_x(my_conftest_fixture, my_fixture): def test_x(my_conftest_fixture, my_fixture):
pass pass
#! 18 ['param MyClassFixture']
def test_x(MyClassFixture):
#?
MyClassFixture
# ----------------- # -----------------
# completion # completion
# ----------------- # -----------------