1
0
forked from VimPlug/jedi

Remove the old instance.

This commit is contained in:
Dave Halter
2016-11-24 19:59:26 +01:00
parent 7ed1c95737
commit 75e412dbc5
2 changed files with 2 additions and 320 deletions

View File

@@ -73,324 +73,6 @@ class Executed(context.TreeContext):
return True
class Instance(use_metaclass(CachedMetaClass, Executed)):
"""
This class is used to evaluate instances.
"""
def __init__(self, evaluator, parent_context, class_context, var_args, is_generated=False):
raise DeprecationWarning
super(Instance, self).__init__(evaluator, parent_context, var_args)
# Generated instances are classes that are just generated by self
# (No var_args) used.
self.is_generated = is_generated
self._class_context = class_context
self._init_execution = None
if class_context.name.string_name in ['list', 'set'] \
and evaluator.BUILTINS == parent_context.get_root_context():
# compare the module path with the builtin name.
self.var_args = iterable.check_array_instances(evaluator, self)
elif not is_generated:
# Need to execute the __init__ function, because the dynamic param
# searching needs it.
try:
method = self.get_subscope_by_name('__init__')
except KeyError:
pass
else:
self._init_execution = evaluator.execute(method, self.var_args)
def is_class(self):
return False
@property
def py__call__(self):
def actual(params):
return self.evaluator.execute(method, params)
try:
method = self.get_subscope_by_name('__call__')
except KeyError:
# Means the Instance is not callable.
raise AttributeError
return actual
def py__class__(self):
return self.class_context
def py__bool__(self):
# Signalize that we don't know about the bool type.
return None
@memoize_default()
def _get_init_execution(self):
try:
func = self.get_subscope_by_name('__init__')
except KeyError:
return None
return FunctionExecutionContext(self.evaluator, self, func, self.var_args)
def _get_func_self_name(self, func):
"""
Returns the name of the first param in a class method (which is
normally self.
"""
try:
return str(func.params[0].name)
except IndexError:
return None
def _self_names_dict(self, add_mro=True):
names = {}
# This loop adds the names of the self object, copies them and removes
# the self.
for sub in self.base.subscopes:
if isinstance(sub, tree.ClassContext):
continue
# Get the self name, if there's one.
self_name = self._get_func_self_name(sub)
if self_name is None:
continue
if sub.name.value == '__init__' and not self.is_generated:
# ``__init__`` is special because the params need are injected
# this way. Therefore an execution is necessary.
if not sub.get_decorators():
# __init__ decorators should generally just be ignored,
# because to follow them and their self variables is too
# complicated.
sub = self._get_init_execution()
for name_list in sub.names_dict.values():
for name in name_list:
if name.value == self_name and name.get_previous_sibling() is None:
trailer = name.get_next_sibling()
if tree.is_node(trailer, 'trailer') \
and len(trailer.children) == 2 \
and trailer.children[0] == '.':
name = trailer.children[1] # After dot.
if name.is_definition():
arr = names.setdefault(name.value, [])
arr.append(get_instance_el(self.evaluator, self, name))
return names
def get_subscope_by_name(self, name):
sub = self._class_context.get_subscope_by_name(name)
return get_instance_el(self.evaluator, self, sub, True)
def execute_subscope_by_name(self, name, *args):
method = self.get_subscope_by_name(name)
return self.evaluator.execute_evaluated(method, *args)
def get_descriptor_returns(self, obj):
""" Throws a KeyError if there's no method. """
# Arguments in __get__ descriptors are obj, class.
# `method` is the new parent of the array, don't know if that's good.
none_obj = compiled.create(self.evaluator, None)
args = [obj, obj.base] if isinstance(obj, Instance) else [none_obj, obj]
try:
return self.execute_subscope_by_name('__get__', *args)
except KeyError:
return set([self])
@memoize_default()
def names_dicts(self, search_global):
yield self._self_names_dict()
for s in self._class_context.py__mro__()[1:]:
if not isinstance(s, compiled.CompiledObject):
# Compiled objects don't have `self.` names.
for inst in self.evaluator.execute(s):
yield inst._self_names_dict(add_mro=False)
for names_dict in self.base.names_dicts(search_global=False, is_instance=True):
yield LazyInstanceDict(self.evaluator, self, names_dict)
def get_filters(self, search_global, until_position=None, origin_scope=None):
for cls in self._class_context.py__mro__():
if isinstance(cls, compiled.CompiledObject):
yield SelfNameFilter(self.evaluator, self, cls, origin_scope)
else:
yield SelfNameFilter(self.evaluator, self, cls.base, origin_scope)
for cls in self._class_context.py__mro__():
if isinstance(cls, compiled.CompiledObject):
yield CompiledInstanceClassFilter(self.evaluator, self, cls)
else:
yield InstanceClassFilter(self.evaluator, self, cls.base, origin_scope)
def py__getitem__(self, index):
try:
method = self.get_subscope_by_name('__getitem__')
except KeyError:
debug.warning('No __getitem__, cannot access the array.')
return set()
else:
index_obj = compiled.create(self.evaluator, index)
return self.evaluator.execute_evaluated(method, index_obj)
def py__iter__(self):
try:
method = self.get_subscope_by_name('__iter__')
except KeyError:
debug.warning('No __iter__ on %s.' % self)
return
else:
iters = self.evaluator.execute(method)
for generator in iters:
if isinstance(generator, Instance):
# `__next__` logic.
name = '__next__' if is_py3 else 'next'
try:
yield generator.execute_subscope_by_name(name)
except KeyError:
debug.warning('Instance has no __next__ function in %s.', generator)
else:
for typ in generator.py__iter__():
yield typ
@property
@underscore_memoization
def name(self):
return ContextName(self, self._class_context.name.string_name)
def __repr__(self):
return "<%s of %s(%s)>" % (self.__class__.__name__, self._class_context,
self.var_args)
class LazyInstanceDict(object):
def __init__(self, evaluator, instance, dct):
self._evaluator = evaluator
self._instance = instance
self._dct = dct
def __getitem__(self, name):
return [get_instance_el(self._evaluator, self._instance, var, True)
for var in self._dct[name]]
def values(self):
return [self[key] for key in self._dct]
class InstanceName(tree.Name):
def __init__(self, origin_name, parent):
super(InstanceName, self).__init__(origin_name.value,
origin_name.start_pos)
self._origin_name = origin_name
self.parent = parent
def is_definition(self):
return self._origin_name.is_definition()
def get_instance_el(evaluator, instance, var, is_class_var=False):
"""
Returns an InstanceElement if it makes sense, otherwise leaves the object
untouched.
Basically having an InstanceElement is context information. That is needed
in quite a lot of cases, which includes Nodes like ``power``, that need to
know where a self name comes from for example.
"""
return var
if isinstance(var, tree.Name):
parent = get_instance_el(evaluator, instance, var.parent, is_class_var)
return InstanceName(var, parent)
elif var.type != 'funcdef' \
and isinstance(var, (Instance, compiled.CompiledObject, tree.Leaf,
tree.Module, FunctionExecutionContext)):
return var
var = evaluator.wrap(var)
return InstanceElement(evaluator, instance, var, is_class_var)
class InstanceElement(use_metaclass(CachedMetaClass, tree.Base)):
"""
InstanceElement is a wrapper for any object, that is used as an instance
variable (e.g. self.variable or class methods).
"""
def __init__(self, evaluator, instance, var, is_class_var):
self.evaluator = evaluator
self.instance = instance
self.var = var
self.is_class_var = is_class_var
@common.safe_property
@memoize_default()
def parent(self):
par = self.var.parent
if isinstance(par, ClassContext) and par == self.instance.base \
or not isinstance(self.instance.base, (tree.Class, ClassContext)) \
or isinstance(par, tree.Class) \
and par == self.instance.base.base:
par = self.instance
else:
par = get_instance_el(self.evaluator, self.instance, par,
self.is_class_var)
return par
def get_parent_until(self, *args, **kwargs):
return tree.BaseNode.get_parent_until(self, *args, **kwargs)
def get_definition(self):
return self.get_parent_until((tree.ExprStmt, tree.IsScope, tree.Import))
def get_decorated_func(self):
""" Needed because the InstanceElement should not be stripped """
func = self.var.get_decorated_func()
func = get_instance_el(self.evaluator, self.instance, func)
return func
def get_rhs(self):
return get_instance_el(self.evaluator, self.instance,
self.var.get_rhs(), self.is_class_var)
def is_definition(self):
return self.var.is_definition()
@property
def children(self):
# Copy and modify the array.
return [get_instance_el(self.evaluator, self.instance, command, self.is_class_var)
for command in self.var.children]
@property
@memoize_default()
def name(self):
return ContextName(self.var.name, self)
def __iter__(self):
for el in self.var.__iter__():
yield get_instance_el(self.evaluator, self.instance, el,
self.is_class_var)
def __getitem__(self, index):
return get_instance_el(self.evaluator, self.instance, self.var[index],
self.is_class_var)
def isinstance(self, *cls):
return isinstance(self.var, cls)
def is_scope(self):
"""
Since we inherit from Base, it would overwrite the action we want here.
"""
return self.var.is_scope()
def py__call__(self, params):
if isinstance(self.var, compiled.CompiledObject):
# This check is a bit strange, but CompiledObject itself is a bit
# more complicated than we would it actually like to be.
return self.var.py__call__(params)
else:
return FunctionContext.py__call__(self, params)
def __repr__(self):
return "<%s of %s>" % (self.__class__.__name__, self.var)
class Wrapper(tree.Base):
def is_scope(self):
return True

View File

@@ -16,7 +16,7 @@ from jedi._compatibility import unicode
from jedi.common import unite
from jedi.evaluate import compiled
from jedi.evaluate import representation as er
from jedi.evaluate.instance import InstanceFunctionExecution
from jedi.evaluate.instance import InstanceFunctionExecution, AbstractInstanceContext
from jedi.evaluate import iterable
from jedi.parser import ParserWithRecovery
from jedi import debug
@@ -127,7 +127,7 @@ def builtins_type(evaluator, objects, bases, dicts):
return set([o.py__class__() for o in objects])
class SuperInstance(er.Instance):
class SuperInstance(AbstractInstanceContext):
"""To be used like the object ``super`` returns."""
def __init__(self, evaluator, cls):
su = cls.py_mro()[1]