Fix class tests

This commit is contained in:
Dave Halter
2019-08-17 23:52:52 +02:00
parent 895e774962
commit 0c419a5094
11 changed files with 55 additions and 38 deletions

View File

@@ -284,7 +284,7 @@ class Completion:
cls = tree.search_ancestor(leaf, 'classdef')
if isinstance(cls, (tree.Class, tree.Function)):
# Complete the methods that are defined in the super classes.
random_value = self._module_context.create_context(
random_context = self._module_context.create_context(
cls,
node_is_value=True
)
@@ -294,7 +294,8 @@ class Completion:
if cls.start_pos[1] >= leaf.start_pos[1]:
return
filters = random_value.get_filters(is_instance=True)
# TODO _value private access!
filters = random_context._value.get_filters(is_instance=True)
# The first dict is the dictionary of class itself.
next(filters)
for filter in filters:

View File

@@ -349,13 +349,13 @@ class InferenceState(object):
new_dotted.children[index - 1:] = []
values = context.infer_node(new_dotted)
return unite(
value.py__getattribute__(name, name_value=value, is_goto=True)
value.goto(name, name_value=value)
for value in values
)
if node_type == 'trailer' and par.children[0] == '.':
values = helpers.infer_call_of_leaf(context, name, cut_own_trailer=True)
return values.py__getattribute__(name, name_context=context, is_goto=True)
return values.goto(name, name_context=context)
else:
stmt = tree.search_ancestor(
name, 'expr_stmt', 'lambdef'
@@ -391,8 +391,9 @@ class InferenceState(object):
if is_funcdef:
func = FunctionValue.from_context(parent_context, scope_node)
if parent_context.is_class():
# TODO _value private access!
instance = AnonymousInstance(
self, parent_context.parent_context, parent_context)
self, parent_context.parent_context, parent_context._value)
func = BoundMethod(
instance=instance,
function=func
@@ -402,7 +403,7 @@ class InferenceState(object):
return func.get_function_execution()
return func
elif scope_node.type == 'classdef':
return ClassValue(self, parent_context, scope_node)
return ClassValue(self, parent_context, scope_node).as_context()
elif scope_node.type in ('comp_for', 'sync_comp_for'):
if node.start_pos >= scope_node.children[-1].start_pos:
return parent_context

View File

@@ -71,6 +71,18 @@ class HelperValueMixin(object):
filters = f.get_value_filters()
return f.find(filters, attribute_lookup=True)
def goto(self, name_or_str, name_context=None, analysis_errors=True):
"""
:param position: Position of the last statement -> tuple of line, column
"""
if name_context is None:
name_context = self
from jedi.inference import finder
f = finder.NameFinder(self.inference_state, self, name_context, name_or_str,
analysis_errors=analysis_errors)
filters = f.get_value_filters()
return f.filter_name(filters)
def py__await__(self):
await_value_set = self.py__getattribute__(u"__await__")
if not await_value_set:
@@ -403,9 +415,10 @@ class ValueSet(BaseValueSet):
def execute_with_values(self, *args, **kwargs):
return ValueSet.from_sets(c.execute_with_values(*args, **kwargs) for c in self._set)
def goto(self, *args, **kwargs):
return reduce(add, [c.goto(*args, **kwargs) for c in self._set], [])
def py__getattribute__(self, *args, **kwargs):
if kwargs.get('is_goto'):
return reduce(add, [c.py__getattribute__(*args, **kwargs) for c in self._set], [])
return ValueSet.from_sets(c.py__getattribute__(*args, **kwargs) for c in self._set)
def get_item(self, *args, **kwargs):
@@ -422,9 +435,6 @@ class ValueSet(BaseValueSet):
value_set |= method()
return value_set
def as_context(self):
return [v.as_context() for v in self._set]
def gather_annotation_classes(self):
return ValueSet.from_sets([c.gather_annotation_classes() for c in self._set])

View File

@@ -72,6 +72,9 @@ class AbstractContext(object):
def py__name__(self):
return self._value.py__name__()
def get_qualified_names(self):
return self._value.get_qualified_names()
def py__doc__(self):
return self._value.py__doc__()
@@ -103,6 +106,7 @@ class ModuleContext(AbstractContext):
def get_filters(self, until_position=None, origin_scope=None):
filters = self._value.get_filters(origin_scope)
# Skip the first filter and replace it.
next(filters)
yield MergedFilter(
ParserTreeFilter(
context=self,

View File

@@ -169,11 +169,11 @@ def _infer_param(execution_context, param):
param_comment = params_comments[index]
return _infer_annotation_string(
execution_context.function_value.get_default_param_value(),
execution_context.function_value.get_default_param_context(),
param_comment
)
# Annotations are like default params and resolve in the same way.
value = execution_context.function_value.get_default_param_value()
value = execution_context.function_value.get_default_param_context()
return infer_annotation(value, annotation)
@@ -210,13 +210,13 @@ def infer_return_types(function_execution_context):
return NO_VALUES
return _infer_annotation_string(
function_execution_context.function_value.get_default_param_value(),
function_execution_context.function_value.get_default_param_context(),
match.group(1).strip()
).execute_annotation()
if annotation is None:
return NO_VALUES
value = function_execution_context.function_value.get_default_param_value()
value = function_execution_context.function_value.get_default_param_context()
unknown_type_vars = list(find_unknown_type_vars(value, annotation))
annotation_values = infer_annotation(value, annotation)
if not unknown_type_vars:
@@ -241,7 +241,7 @@ def infer_type_vars_for_execution(execution_context, annotation_dict):
2. Infer type vars with the execution state we have.
3. Return the union of all type vars that have been found.
"""
value = execution_context.function_value.get_default_param_value()
value = execution_context.function_value.get_default_param_context()
annotation_variable_results = {}
executed_params, _ = execution_context.get_executed_params_and_issues()

View File

@@ -69,7 +69,7 @@ def _try_stub_to_python_names(names, prefer_stub_to_compiled=False):
ignore_compiled=prefer_stub_to_compiled,
)
if values and name_list:
new_names = values.py__getattribute__(name_list[-1], is_goto=True)
new_names = values.goto(name_list[-1])
for new_name in new_names:
yield new_name
if new_names:
@@ -121,7 +121,7 @@ def _python_to_stub_names(names, fallback_to_python=False):
for name in name_list[:-1]:
stubs = stubs.py__getattribute__(name)
if stubs and name_list:
new_names = stubs.py__getattribute__(name_list[-1], is_goto=True)
new_names = stubs.goto(name_list[-1])
for new_name in new_names:
yield new_name
if new_names:

View File

@@ -89,7 +89,7 @@ def get_executed_params_and_issues(execution_context, arguments):
# Default params are part of the value where the function was defined.
# This means that they might have access on class variables that the
# function itself doesn't have.
default_param_value = execution_context.function_value.get_default_param_value()
default_param_context = execution_context.function_value.get_default_param_context()
for param in funcdef.get_params():
param_dict[param.name.value] = param
@@ -172,7 +172,7 @@ def get_executed_params_and_issues(execution_context, arguments):
)
)
else:
result_arg = LazyTreeValue(default_param_value, param.default)
result_arg = LazyTreeValue(default_param_context, param.default)
is_default = True
else:
result_arg = argument

View File

@@ -93,6 +93,9 @@ class FunctionMixin(object):
return FunctionExecutionContext(self, arguments)
def as_context(self):
return self.get_function_execution()
def get_signatures(self):
return [TreeSignature(f) for f in self.get_signature_functions()]
@@ -137,7 +140,7 @@ class FunctionValue(use_metaclass(CachedMetaClass, FunctionMixin, FunctionAndCla
c, = values_from_qualified_names(self.inference_state, u'types', u'FunctionType')
return c
def get_default_param_value(self):
def get_default_param_context(self):
return self.parent_context
def get_signature_functions(self):
@@ -145,17 +148,17 @@ class FunctionValue(use_metaclass(CachedMetaClass, FunctionMixin, FunctionAndCla
class MethodValue(FunctionValue):
def __init__(self, inference_state, class_value, *args, **kwargs):
def __init__(self, inference_state, class_context, *args, **kwargs):
super(MethodValue, self).__init__(inference_state, *args, **kwargs)
self.class_value = class_value
self.class_context = class_context
def get_default_param_value(self):
return self.class_value
def get_default_param_context(self):
return self.class_context
def get_qualified_names(self):
# Need to implement this, because the parent value of a method
# value is not the class value but the module.
names = self.class_value.get_qualified_names()
names = self.class_context.get_qualified_names()
if names is None:
return None
return names + (self.py__name__(),)

View File

@@ -106,7 +106,7 @@ class ClassFilter(ParserTreeFilter):
def _equals_origin_scope(self):
node = self._origin_scope
while node is not None:
if node == self._parser_scope or node == self.value:
if node == self._parser_scope or node == self.context:
return True
node = get_cached_parent_scope(self._used_names, node)
return False

View File

@@ -158,7 +158,7 @@ def _follow_param(inference_state, arguments, index):
return lazy_value.infer()
def argument_clinic(string, want_obj=False, want_value=False,
def argument_clinic(string, want_obj=False, want_context=False,
want_arguments=False, want_inference_state=False,
want_callback=False):
"""
@@ -174,8 +174,8 @@ def argument_clinic(string, want_obj=False, want_value=False,
assert not kwargs # Python 2...
debug.dbg('builtin start %s' % obj, color='MAGENTA')
result = NO_VALUES
if want_value:
kwargs['value'] = arguments.value
if want_context:
kwargs['context'] = arguments.context
if want_obj:
kwargs['obj'] = obj
if want_inference_state:
@@ -268,11 +268,11 @@ class SuperInstance(LazyValueWrapper):
yield f
@argument_clinic('[type[, obj]], /', want_value=True)
def builtins_super(types, objects, value):
if isinstance(value, FunctionExecutionContext):
if isinstance(value.var_args, InstanceArguments):
instance = value.var_args.instance
@argument_clinic('[type[, obj]], /', want_context=True)
def builtins_super(types, objects, context):
if isinstance(context, FunctionExecutionContext):
if isinstance(context.var_args, InstanceArguments):
instance = context.var_args.instance
# TODO if a class is given it doesn't have to be the direct super
# class, it can be an anecestor from long ago.
return ValueSet({SuperInstance(instance.inference_state, instance)})

View File

@@ -231,9 +231,7 @@ class IntegrationTestCase(object):
#if user_context._value.api_type == 'function':
# user_context = user_context.get_function_execution()
node.parent = user_context.tree_node
results = convert_values(
user_context.infer_node(node),
)
results = convert_values(user_context.infer_node(node))
if not results:
raise Exception('Could not resolve %s on line %s'
% (match.string, self.line_nr - 1))