From cc493866cdd21632f6baef2a78f82768db9c5ac6 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Mon, 24 Sep 2018 00:09:40 +0200 Subject: [PATCH] Try to introduce is_instance and is_function --- jedi/api/classes.py | 4 ++-- jedi/evaluate/analysis.py | 4 ++-- jedi/evaluate/base_context.py | 6 ++++++ jedi/evaluate/context/function.py | 7 ++++--- jedi/evaluate/context/instance.py | 8 ++++---- jedi/evaluate/finder.py | 5 ++--- 6 files changed, 20 insertions(+), 14 deletions(-) diff --git a/jedi/api/classes.py b/jedi/api/classes.py index 894a66a1..35fe8d09 100644 --- a/jedi/api/classes.py +++ b/jedi/api/classes.py @@ -326,8 +326,8 @@ class BaseDefinition(object): param_names = list(context.get_param_names()) if isinstance(context, instance.BoundMethod): param_names = param_names[1:] - elif isinstance(context, (instance.AbstractInstanceContext, ClassContext)): - if isinstance(context, ClassContext): + elif context.is_class() or context.is_instance(): + if context.is_class(): search = u'__init__' else: search = u'__call__' diff --git a/jedi/evaluate/analysis.py b/jedi/evaluate/analysis.py index 6261b5c8..5066b0a1 100644 --- a/jedi/evaluate/analysis.py +++ b/jedi/evaluate/analysis.py @@ -113,11 +113,11 @@ def _check_for_setattr(instance): def add_attribute_error(name_context, lookup_context, name): message = ('AttributeError: %s has no attribute %s.' % (lookup_context, name)) - from jedi.evaluate.context.instance import AbstractInstanceContext, CompiledInstanceName + from jedi.evaluate.context.instance import CompiledInstanceName # Check for __getattr__/__getattribute__ existance and issue a warning # instead of an error, if that happens. typ = Error - if isinstance(lookup_context, AbstractInstanceContext): + if lookup_context.is_instance(): slot_names = lookup_context.get_function_slot_names(u'__getattr__') + \ lookup_context.get_function_slot_names(u'__getattribute__') for n in slot_names: diff --git a/jedi/evaluate/base_context.py b/jedi/evaluate/base_context.py index 082f92e1..04a8a63c 100644 --- a/jedi/evaluate/base_context.py +++ b/jedi/evaluate/base_context.py @@ -132,6 +132,12 @@ class Context(HelperContextMixin, BaseContext): def is_class(self): return False + def is_instance(self): + return False + + def is_function(self): + return False + def py__bool__(self): """ Since Wrapper is a super class for classes, functions and modules, diff --git a/jedi/evaluate/context/function.py b/jedi/evaluate/context/function.py index cc666823..2f938b25 100644 --- a/jedi/evaluate/context/function.py +++ b/jedi/evaluate/context/function.py @@ -75,6 +75,9 @@ class FunctionContext(use_metaclass(CachedMetaClass, AbstractFunction)): """ Needed because of decorators. Decorators are evaluated here. """ + def is_function(self): + return True + @classmethod def from_context(cls, context, tree_node): def create(tree_node): @@ -92,12 +95,10 @@ class FunctionContext(use_metaclass(CachedMetaClass, AbstractFunction)): tree_node=tree_node ) - from jedi.evaluate.context import AbstractInstanceContext - overloaded_funcs = list(_find_overload_functions(context, tree_node)) parent_context = context - while parent_context.is_class() or isinstance(parent_context, AbstractInstanceContext): + while parent_context.is_class() or parent_context.is_instance(): parent_context = parent_context.parent_context function = create(tree_node) diff --git a/jedi/evaluate/context/instance.py b/jedi/evaluate/context/instance.py index a51f5821..16e7e011 100644 --- a/jedi/evaluate/context/instance.py +++ b/jedi/evaluate/context/instance.py @@ -68,8 +68,8 @@ class AbstractInstanceContext(Context): self.class_context = class_context self.var_args = var_args - def is_class(self): - return False + def is_instance(self): + return True def get_annotated_class_object(self): return self.class_context # This is the default. @@ -114,7 +114,7 @@ class AbstractInstanceContext(Context): # `method` is the new parent of the array, don't know if that's good. names = self.get_function_slot_names(u'__get__') if names: - if isinstance(obj, AbstractInstanceContext): + if obj.is_instance(): return self.execute_function_slots(names, obj, obj.class_context) else: none_obj = compiled.builtin_from_name(self.evaluator, u'None') @@ -156,7 +156,7 @@ class AbstractInstanceContext(Context): return for generator in self.execute_function_slots(iter_slot_names): - if isinstance(generator, AbstractInstanceContext): + if generator.is_instance(): # `__next__` logic. if self.evaluator.environment.version_info.major == 2: name = u'next' diff --git a/jedi/evaluate/finder.py b/jedi/evaluate/finder.py index 3872c149..22147970 100644 --- a/jedi/evaluate/finder.py +++ b/jedi/evaluate/finder.py @@ -19,7 +19,6 @@ from parso.python import tree from parso.tree import search_ancestor from jedi import debug from jedi import settings -from jedi.evaluate.context import AbstractInstanceContext from jedi.evaluate import compiled from jedi.evaluate import analysis from jedi.evaluate import flow_analysis @@ -178,13 +177,13 @@ class NameFinder(object): contexts = ContextSet.from_sets(name.infer() for name in names) debug.dbg('finder._names_to_types: %s -> %s', names, contexts) - if not names and isinstance(self._context, AbstractInstanceContext): + if not names and self._context.is_instance(): # handling __getattr__ / __getattribute__ return self._check_getattr(self._context) # Add isinstance and other if/assert knowledge. if not contexts and isinstance(self._name, tree.Name) and \ - not isinstance(self._name_context, AbstractInstanceContext): + not self._name_context.is_instance(): flow_scope = self._name base_node = self._name_context.tree_node if base_node.type == 'comp_for':