mirror of
https://github.com/davidhalter/jedi.git
synced 2026-05-08 01:30:09 +08:00
@@ -59,7 +59,7 @@ class HelperValueMixin:
|
||||
arguments = ValuesArguments([ValueSet([value]) for value in value_list])
|
||||
return self.inference_state.execute(self, arguments)
|
||||
|
||||
def execute_annotation(self):
|
||||
def execute_annotation(self, context):
|
||||
return self.execute_with_values()
|
||||
|
||||
def gather_annotation_classes(self):
|
||||
|
||||
@@ -54,7 +54,7 @@ class CompiledValue(Value):
|
||||
return create_from_access_path(
|
||||
self.inference_state,
|
||||
return_annotation
|
||||
).execute_annotation()
|
||||
).execute_annotation(arguments.context)
|
||||
|
||||
try:
|
||||
self.access_handle.getattr_paths('__call__')
|
||||
@@ -241,7 +241,7 @@ class CompiledValue(Value):
|
||||
except TypeError:
|
||||
return NO_VALUES
|
||||
|
||||
def execute_annotation(self):
|
||||
def execute_annotation(self, context):
|
||||
if self.access_handle.get_repr() == 'None':
|
||||
# None as an annotation doesn't need to be executed.
|
||||
return ValueSet([self])
|
||||
@@ -252,7 +252,9 @@ class CompiledValue(Value):
|
||||
for path in args
|
||||
]
|
||||
if name == 'Union':
|
||||
return ValueSet.from_sets(arg.execute_annotation() for arg in arguments)
|
||||
return ValueSet.from_sets(
|
||||
arg.execute_annotation(context)
|
||||
for arg in arguments)
|
||||
elif name:
|
||||
# While with_generics only exists on very specific objects, we
|
||||
# should probably be fine, because we control all the typing
|
||||
@@ -260,8 +262,8 @@ class CompiledValue(Value):
|
||||
return ValueSet([
|
||||
v.with_generics(arguments)
|
||||
for v in self.inference_state.typing_module.py__getattribute__(name)
|
||||
]).execute_annotation()
|
||||
return super().execute_annotation()
|
||||
]).execute_annotation(context)
|
||||
return super().execute_annotation(context)
|
||||
|
||||
def negate(self):
|
||||
return create_from_access_path(self.inference_state, self.access_handle.negate())
|
||||
@@ -459,7 +461,7 @@ class CompiledValueFilter(AbstractFilter):
|
||||
values = create_from_access_path(
|
||||
self._inference_state,
|
||||
property_return_annotation
|
||||
).execute_annotation()
|
||||
).execute_annotation(None)
|
||||
if values:
|
||||
return [CompiledValueName(v, name) for v in values]
|
||||
|
||||
|
||||
@@ -246,7 +246,7 @@ def _execute_array_values(inference_state, array):
|
||||
cls = FakeTuple if array.array_type == 'tuple' else FakeList
|
||||
return {cls(inference_state, values)}
|
||||
else:
|
||||
return array.execute_annotation()
|
||||
return array.execute_annotation(None)
|
||||
|
||||
|
||||
@inference_state_method_cache()
|
||||
|
||||
@@ -249,12 +249,12 @@ def infer_return_types(function, arguments):
|
||||
return _infer_annotation_string(
|
||||
context,
|
||||
match.group(1).strip()
|
||||
).execute_annotation()
|
||||
).execute_annotation(context)
|
||||
|
||||
unknown_type_vars = find_unknown_type_vars(context, annotation)
|
||||
annotation_values = infer_annotation(context, annotation)
|
||||
if not unknown_type_vars:
|
||||
return annotation_values.execute_annotation()
|
||||
return annotation_values.execute_annotation(context)
|
||||
|
||||
type_var_dict = infer_type_vars_for_execution(function, arguments, all_annotations)
|
||||
|
||||
@@ -262,7 +262,7 @@ def infer_return_types(function, arguments):
|
||||
ann.define_generics(type_var_dict)
|
||||
if isinstance(ann, (DefineGenericBaseClass, TypeVar)) else ValueSet({ann})
|
||||
for ann in annotation_values
|
||||
).execute_annotation()
|
||||
).execute_annotation(context)
|
||||
|
||||
|
||||
def infer_type_vars_for_execution(function, arguments, annotation_dict):
|
||||
@@ -315,7 +315,7 @@ def infer_return_for_callable(arguments, param_values, result_values):
|
||||
if isinstance(v, (DefineGenericBaseClass, TypeVar))
|
||||
else ValueSet({v})
|
||||
for v in result_values
|
||||
).execute_annotation()
|
||||
).execute_annotation(arguments.context)
|
||||
|
||||
|
||||
def _infer_type_vars_for_callable(arguments, lazy_params):
|
||||
@@ -391,7 +391,7 @@ def merge_pairwise_generics(annotation_value, annotated_argument_class):
|
||||
for annotation_generics_set, actual_generic_set in zip(annotation_generics, actual_generics):
|
||||
merge_type_var_dicts(
|
||||
type_var_dict,
|
||||
annotation_generics_set.infer_type_vars(actual_generic_set.execute_annotation()),
|
||||
annotation_generics_set.infer_type_vars(actual_generic_set.execute_annotation(None)),
|
||||
)
|
||||
|
||||
return type_var_dict
|
||||
@@ -438,7 +438,7 @@ def _find_type_from_comment_hint(context, node, varlist, name):
|
||||
return []
|
||||
return _infer_annotation_string(
|
||||
context, match.group(1).strip(), index
|
||||
).execute_annotation()
|
||||
).execute_annotation(context)
|
||||
|
||||
|
||||
def find_unknown_type_vars(context, node):
|
||||
|
||||
@@ -306,7 +306,7 @@ class _GenericInstanceWrapper(ValueWrapper):
|
||||
if cls.py__name__() == 'Generator':
|
||||
generics = cls.get_generics()
|
||||
try:
|
||||
return generics[2].execute_annotation()
|
||||
return generics[2].execute_annotation(None)
|
||||
except IndexError:
|
||||
pass
|
||||
elif cls.py__name__() == 'Iterator':
|
||||
@@ -427,7 +427,7 @@ class BaseTypingInstance(LazyValueWrapper):
|
||||
return ValueName(self, self._tree_name)
|
||||
|
||||
def _get_wrapped_value(self):
|
||||
object_, = builtin_from_name(self.inference_state, 'object').execute_annotation()
|
||||
object_, = builtin_from_name(self.inference_state, 'object').execute_annotation(None)
|
||||
return object_
|
||||
|
||||
def __repr__(self):
|
||||
|
||||
@@ -35,7 +35,7 @@ class _AbstractGenericManager:
|
||||
|
||||
def get_index_and_execute(self, index):
|
||||
try:
|
||||
return self[index].execute_annotation()
|
||||
return self[index].execute_annotation(None)
|
||||
except IndexError:
|
||||
debug.warning('No param #%s found for annotation %s', index, self)
|
||||
return NO_VALUES
|
||||
|
||||
@@ -100,8 +100,8 @@ class TypeVar(BaseTypingValue):
|
||||
return found
|
||||
return ValueSet({self})
|
||||
|
||||
def execute_annotation(self):
|
||||
return self._get_classes().execute_annotation()
|
||||
def execute_annotation(self, context):
|
||||
return self._get_classes().execute_annotation(context)
|
||||
|
||||
def infer_type_vars(self, value_set):
|
||||
def iterate():
|
||||
@@ -123,5 +123,5 @@ class TypeWrapper(ValueWrapper):
|
||||
super().__init__(wrapped_value)
|
||||
self._original_value = original_value
|
||||
|
||||
def execute_annotation(self):
|
||||
def execute_annotation(self, context):
|
||||
return ValueSet({self._original_value})
|
||||
|
||||
@@ -83,6 +83,9 @@ class TypingModuleName(NameWrapper):
|
||||
elif name == 'cast':
|
||||
cast_fn, = self._wrapped_name.infer()
|
||||
yield CastFunction.create_cached(inference_state, cast_fn)
|
||||
elif name == 'Self':
|
||||
yield SelfClass.create_cached(
|
||||
inference_state, self.parent_context, self.tree_name)
|
||||
elif name == 'TypedDict':
|
||||
# TODO doesn't even exist in typeshed/typing.py, yet. But will be
|
||||
# added soon.
|
||||
@@ -100,24 +103,24 @@ class TypingModuleFilterWrapper(FilterWrapper):
|
||||
|
||||
|
||||
class ProxyWithGenerics(BaseTypingClassWithGenerics):
|
||||
def execute_annotation(self):
|
||||
def execute_annotation(self, context):
|
||||
string_name = self._tree_name.value
|
||||
|
||||
if string_name == 'Union':
|
||||
# This is kind of a special case, because we have Unions (in Jedi
|
||||
# ValueSets).
|
||||
return self.gather_annotation_classes().execute_annotation()
|
||||
return self.gather_annotation_classes().execute_annotation(context)
|
||||
elif string_name == 'Optional':
|
||||
# Optional is basically just saying it's either None or the actual
|
||||
# type.
|
||||
return self.gather_annotation_classes().execute_annotation() \
|
||||
return self.gather_annotation_classes().execute_annotation(context) \
|
||||
| ValueSet([builtin_from_name(self.inference_state, 'None')])
|
||||
elif string_name == 'Type':
|
||||
# The type is actually already given in the index_value
|
||||
return self._generics_manager[0]
|
||||
elif string_name in IGNORE_ANNOTATION_PARTS:
|
||||
# For now don't do anything here, ClassVars are always used.
|
||||
return self._generics_manager[0].execute_annotation()
|
||||
return self._generics_manager[0].execute_annotation(context)
|
||||
|
||||
mapped = {
|
||||
'Tuple': Tuple,
|
||||
@@ -217,17 +220,17 @@ class TypingClassWithGenerics(ProxyWithGenerics, _TypingClassMixin):
|
||||
# This is basically a trick to avoid extra code: We execute the
|
||||
# incoming classes to be able to use the normal code for type
|
||||
# var inference.
|
||||
value_set.execute_annotation(),
|
||||
value_set.execute_annotation(None),
|
||||
)
|
||||
|
||||
elif annotation_name == 'Callable':
|
||||
if len(annotation_generics) == 2:
|
||||
return annotation_generics[1].infer_type_vars(
|
||||
value_set.execute_annotation(),
|
||||
value_set.execute_annotation(None),
|
||||
)
|
||||
|
||||
elif annotation_name == 'Tuple':
|
||||
tuple_annotation, = self.execute_annotation()
|
||||
tuple_annotation, = self.execute_annotation(None)
|
||||
return tuple_annotation.infer_type_vars(value_set)
|
||||
|
||||
return type_var_dict
|
||||
@@ -323,7 +326,7 @@ class Tuple(BaseTypingInstance):
|
||||
yield LazyKnownValues(self._generics_manager.get_index_and_execute(0))
|
||||
else:
|
||||
for v in self._generics_manager.to_tuple():
|
||||
yield LazyKnownValues(v.execute_annotation())
|
||||
yield LazyKnownValues(v.execute_annotation(None))
|
||||
|
||||
def py__getitem__(self, index_value_set, contextualized_node):
|
||||
if self._is_homogenous():
|
||||
@@ -331,11 +334,11 @@ class Tuple(BaseTypingInstance):
|
||||
|
||||
return ValueSet.from_sets(
|
||||
self._generics_manager.to_tuple()
|
||||
).execute_annotation()
|
||||
).execute_annotation(None)
|
||||
|
||||
def _get_wrapped_value(self):
|
||||
tuple_, = self.inference_state.builtins_module \
|
||||
.py__getattribute__('tuple').execute_annotation()
|
||||
.py__getattribute__('tuple').execute_annotation(None)
|
||||
return tuple_
|
||||
|
||||
@property
|
||||
@@ -392,11 +395,20 @@ class Protocol(BaseTypingInstance):
|
||||
|
||||
|
||||
class AnyClass(BaseTypingValue):
|
||||
def execute_annotation(self):
|
||||
def execute_annotation(self, context):
|
||||
debug.warning('Used Any - returned no results')
|
||||
return NO_VALUES
|
||||
|
||||
|
||||
class SelfClass(BaseTypingValue):
|
||||
def execute_annotation(self, context):
|
||||
debug.warning('Used Self')
|
||||
if context is not None:
|
||||
# Execute the class of Self
|
||||
return context.get_value().execute_annotation(None)
|
||||
return NO_VALUES
|
||||
|
||||
|
||||
class OverloadFunction(BaseTypingValue):
|
||||
@repack_with_argument_clinic('func, /')
|
||||
def py__call__(self, func_value_set):
|
||||
@@ -431,7 +443,7 @@ class NewType(Value):
|
||||
return c
|
||||
|
||||
def py__call__(self, arguments):
|
||||
return self._type_value_set.execute_annotation()
|
||||
return self._type_value_set.execute_annotation(arguments.context)
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
@@ -445,7 +457,7 @@ class NewType(Value):
|
||||
class CastFunction(ValueWrapper):
|
||||
@repack_with_argument_clinic('type, object, /')
|
||||
def py__call__(self, type_value_set, object_value_set):
|
||||
return type_value_set.execute_annotation()
|
||||
return type_value_set.execute_annotation(None)
|
||||
|
||||
|
||||
class TypedDictClass(BaseTypingValue):
|
||||
|
||||
@@ -466,7 +466,7 @@ class _ActualTreeParamName(BaseTreeParamName):
|
||||
self.function_value, self._get_param_node(),
|
||||
ignore_stars=ignore_stars)
|
||||
if execute_annotation:
|
||||
values = values.execute_annotation()
|
||||
values = values.execute_annotation(self.function_value.get_default_param_context())
|
||||
return values
|
||||
|
||||
def infer_default(self):
|
||||
|
||||
@@ -239,7 +239,7 @@ def _infer_node(context, element):
|
||||
return context.infer_node(element.children[0])
|
||||
elif typ == 'annassign':
|
||||
return annotation.infer_annotation(context, element.children[1]) \
|
||||
.execute_annotation()
|
||||
.execute_annotation(context)
|
||||
elif typ == 'yield_expr':
|
||||
if len(element.children) and element.children[1].type == 'yield_arg':
|
||||
# Implies that it's a yield from.
|
||||
@@ -497,7 +497,7 @@ def infer_factor(value_set, operator):
|
||||
b = value.py__bool__()
|
||||
if b is None: # Uncertainty.
|
||||
yield list(value.inference_state.builtins_module.py__getattribute__('bool')
|
||||
.execute_annotation()).pop()
|
||||
.execute_annotation(None)).pop()
|
||||
else:
|
||||
yield compiled.create_simple_object(value.inference_state, not b)
|
||||
else:
|
||||
@@ -650,7 +650,9 @@ def _infer_comparison_part(inference_state, context, left, operator, right):
|
||||
_bool_to_value(inference_state, False)
|
||||
])
|
||||
elif str_operator in ('in', 'not in'):
|
||||
return inference_state.builtins_module.py__getattribute__('bool').execute_annotation()
|
||||
return inference_state.builtins_module.py__getattribute__('bool').execute_annotation(
|
||||
context
|
||||
)
|
||||
|
||||
def check(obj):
|
||||
"""Checks if a Jedi object is either a float or an int."""
|
||||
@@ -719,7 +721,7 @@ def tree_name_to_values(inference_state, context, tree_name):
|
||||
and first.name.string_name in IGNORE_ANNOTATION_PARTS
|
||||
)
|
||||
found_annotation = set_found_annotation
|
||||
value_set |= found.execute_annotation()
|
||||
value_set |= found.execute_annotation(context)
|
||||
if found_annotation:
|
||||
return value_set
|
||||
|
||||
|
||||
@@ -338,7 +338,7 @@ class BaseFunctionExecutionContext(ValueContext, TreeContextMixin):
|
||||
return ValueSet(
|
||||
GenericClass(c, TupleGenericManager(generics))
|
||||
for c in async_generator_classes
|
||||
).execute_annotation()
|
||||
).execute_annotation(None)
|
||||
else:
|
||||
async_classes = inference_state.typing_module.py__getattribute__('Coroutine')
|
||||
return_values = self.get_return_values()
|
||||
@@ -346,7 +346,7 @@ class BaseFunctionExecutionContext(ValueContext, TreeContextMixin):
|
||||
generics = (return_values.py__class__(), NO_VALUES, NO_VALUES)
|
||||
return ValueSet(
|
||||
GenericClass(c, TupleGenericManager(generics)) for c in async_classes
|
||||
).execute_annotation()
|
||||
).execute_annotation(None)
|
||||
else:
|
||||
# If there are annotations, prefer them over anything else.
|
||||
if self.is_generator() and not self.infer_annotations():
|
||||
|
||||
@@ -506,7 +506,7 @@ class SelfName(TreeNameDefinition):
|
||||
from jedi.inference.gradual.annotation import infer_annotation
|
||||
values = infer_annotation(
|
||||
self.parent_context, stmt.children[1].children[1]
|
||||
).execute_annotation()
|
||||
).execute_annotation(None)
|
||||
if values:
|
||||
return values
|
||||
return super().infer()
|
||||
|
||||
@@ -44,7 +44,7 @@ class GeneratorBase(LazyAttributeOverwrite, IterableMixin):
|
||||
array_type = None
|
||||
|
||||
def _get_wrapped_value(self):
|
||||
instance, = self._get_cls().execute_annotation()
|
||||
instance, = self._get_cls().execute_annotation(None)
|
||||
return instance
|
||||
|
||||
def _get_cls(self):
|
||||
@@ -214,7 +214,7 @@ class Sequence(LazyAttributeOverwrite, IterableMixin):
|
||||
c, = GenericClass(
|
||||
klass,
|
||||
TupleGenericManager(self._cached_generics())
|
||||
).execute_annotation()
|
||||
).execute_annotation(None)
|
||||
return c
|
||||
|
||||
def py__bool__(self):
|
||||
|
||||
@@ -46,7 +46,7 @@ _FILTER_LIKE_METHODS = ('create', 'filter', 'exclude', 'update', 'get',
|
||||
def _get_deferred_attributes(inference_state):
|
||||
return inference_state.import_module(
|
||||
('django', 'db', 'models', 'query_utils')
|
||||
).py__getattribute__('DeferredAttribute').execute_annotation()
|
||||
).py__getattribute__('DeferredAttribute').execute_annotation(None)
|
||||
|
||||
|
||||
def _infer_scalar_field(inference_state, field_name, field_tree_instance, is_instance):
|
||||
@@ -130,7 +130,7 @@ def _create_manager_for(cls, manager_cls='BaseManager'):
|
||||
for m in managers:
|
||||
if m.is_class_mixin():
|
||||
generics_manager = TupleGenericManager((ValueSet([cls]),))
|
||||
for c in GenericClass(m, generics_manager).execute_annotation():
|
||||
for c in GenericClass(m, generics_manager).execute_annotation(None):
|
||||
return c
|
||||
return None
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ def infer_anonymous_param(func):
|
||||
== ('typing', 'Generator')
|
||||
for v in result):
|
||||
return ValueSet.from_sets(
|
||||
v.py__getattribute__('__next__').execute_annotation()
|
||||
v.py__getattribute__('__next__').execute_annotation(None)
|
||||
for v in result
|
||||
)
|
||||
return result
|
||||
|
||||
@@ -3,7 +3,7 @@ Test the typing library, with docstrings and annotations
|
||||
"""
|
||||
import typing
|
||||
from typing import Sequence, MutableSequence, List, Iterable, Iterator, \
|
||||
AbstractSet, Tuple, Mapping, Dict, Union, Optional, Final
|
||||
AbstractSet, Tuple, Mapping, Dict, Union, Optional, Final, Self
|
||||
|
||||
class B:
|
||||
pass
|
||||
@@ -555,3 +555,32 @@ def typed_dict_test_foo(arg: Bar):
|
||||
arg['an_int']
|
||||
#? int()
|
||||
arg['another_variable']
|
||||
|
||||
# -----------------
|
||||
# Self
|
||||
# -----------------
|
||||
|
||||
# From #2023, #2068
|
||||
class Builder:
|
||||
def __init__(self):
|
||||
self.x = 0
|
||||
self.y = 0
|
||||
|
||||
def add_x(self: Self, x: int) -> Self:
|
||||
self.x = x
|
||||
return self
|
||||
|
||||
def add_y(self: Self, y: int) -> Self:
|
||||
self.y = y
|
||||
return self
|
||||
|
||||
def add_not_implemented(self: Self, y: int) -> Self:
|
||||
raise NotImplementedError
|
||||
|
||||
b = Builder()
|
||||
#? Builder()
|
||||
b.add_x(2)
|
||||
#? Builder()
|
||||
b.add_x(2).add_y(5)
|
||||
#? Builder()
|
||||
b.add_x(2).add_not_implemented(5)
|
||||
|
||||
Reference in New Issue
Block a user