forked from VimPlug/jedi
A lot of small improvements.
This commit is contained in:
@@ -56,38 +56,17 @@ from jedi.evaluate import param
|
||||
from jedi.evaluate import flow_analysis
|
||||
from jedi.evaluate import imports
|
||||
from jedi.evaluate.filters import ParserTreeFilter, FunctionExecutionFilter, \
|
||||
GlobalNameFilter, DictFilter
|
||||
GlobalNameFilter, DictFilter, ContextName
|
||||
from jedi.evaluate.context import Context
|
||||
|
||||
|
||||
class Context(object):
|
||||
def __init__(self, evaluator, parent_context=None):
|
||||
self._evaluator = evaluator
|
||||
self.parent_context = parent_context
|
||||
|
||||
def get_parent_flow_context(self):
|
||||
return self.parent_context
|
||||
|
||||
def get_root_context(self):
|
||||
context = self
|
||||
while True:
|
||||
if context.parent_context is None:
|
||||
return context
|
||||
context = context.parent_context
|
||||
|
||||
|
||||
class FlowContext(Context):
|
||||
def get_parent_flow_context(self):
|
||||
if 1:
|
||||
return self.parent_context
|
||||
|
||||
|
||||
class Executed(Context, tree.Base):
|
||||
class Executed(Context):
|
||||
"""
|
||||
An instance is also an executable - because __init__ is called
|
||||
:param var_args: The param input array, consist of a parser node or a list.
|
||||
"""
|
||||
def __init__(self, evaluator, base, var_args=()):
|
||||
self._evaluator = evaluator
|
||||
def __init__(self, evaluator, parent_context, base, var_args):
|
||||
super(Executed, self).__init__(evaluator, parent_context=parent_context)
|
||||
self.base = base
|
||||
self.var_args = var_args
|
||||
|
||||
@@ -97,25 +76,21 @@ class Executed(Context, tree.Base):
|
||||
def get_parent_until(self, *args, **kwargs):
|
||||
return tree.Base.get_parent_until(self, *args, **kwargs)
|
||||
|
||||
@common.safe_property
|
||||
def parent(self):
|
||||
return self.base.parent
|
||||
|
||||
|
||||
class Instance(use_metaclass(CachedMetaClass, Executed)):
|
||||
"""
|
||||
This class is used to evaluate instances.
|
||||
"""
|
||||
def __init__(self, evaluator, base, var_args, is_generated=False):
|
||||
super(Instance, self).__init__(evaluator, base, var_args)
|
||||
def __init__(self, evaluator, parent_context, base, var_args, is_generated=False):
|
||||
super(Instance, self).__init__(evaluator, parent_context, base, var_args)
|
||||
self.decorates = None
|
||||
# Generated instances are classes that are just generated by self
|
||||
# (No var_args) used.
|
||||
self.is_generated = is_generated
|
||||
|
||||
self._init_execution = None
|
||||
if base.name.get_code() in ['list', 'set'] \
|
||||
and evaluator.BUILTINS == base.get_parent_until():
|
||||
if base.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:
|
||||
@@ -157,7 +132,7 @@ class Instance(use_metaclass(CachedMetaClass, Executed)):
|
||||
func = self.get_subscope_by_name('__init__')
|
||||
except KeyError:
|
||||
return None
|
||||
return FunctionExecution(self._evaluator, func, self.var_args)
|
||||
return FunctionExecution(self._evaluator, self, func, self.var_args)
|
||||
|
||||
def _get_func_self_name(self, func):
|
||||
"""
|
||||
@@ -280,8 +255,7 @@ class Instance(use_metaclass(CachedMetaClass, Executed)):
|
||||
@property
|
||||
@underscore_memoization
|
||||
def name(self):
|
||||
name = self.base.name
|
||||
return helpers.FakeName(unicode(name), self, name.start_pos)
|
||||
return ContextName(self, self.base.name)
|
||||
|
||||
def __getattr__(self, name):
|
||||
if name not in ['start_pos', 'end_pos', 'get_imports', 'type',
|
||||
@@ -400,6 +374,7 @@ def get_instance_el(evaluator, instance, var, is_class_var=False):
|
||||
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)
|
||||
@@ -465,8 +440,7 @@ class InstanceElement(use_metaclass(CachedMetaClass, tree.Base)):
|
||||
@property
|
||||
@memoize_default()
|
||||
def name(self):
|
||||
name = self.var.name
|
||||
return helpers.FakeName(unicode(name), self, name.start_pos)
|
||||
return ContextName(self.var.name, self)
|
||||
|
||||
def __iter__(self):
|
||||
for el in self.var.__iter__():
|
||||
@@ -519,7 +493,7 @@ class Wrapper(tree.Base):
|
||||
@underscore_memoization
|
||||
def name(self):
|
||||
name = self.base.name
|
||||
return helpers.FakeName(unicode(name), self, name.start_pos)
|
||||
return ContextName(self, name)
|
||||
|
||||
|
||||
class ClassContext(use_metaclass(CachedMetaClass, Context, Wrapper)):
|
||||
@@ -574,7 +548,7 @@ class ClassContext(use_metaclass(CachedMetaClass, Context, Wrapper)):
|
||||
return [compiled.create(self._evaluator, object)]
|
||||
|
||||
def py__call__(self, params):
|
||||
return set([Instance(self._evaluator, self, params)])
|
||||
return set([Instance(self._evaluator, self.parent_context, self, params)])
|
||||
|
||||
def py__class__(self):
|
||||
return compiled.create(self._evaluator, type)
|
||||
@@ -628,13 +602,13 @@ class ClassContext(use_metaclass(CachedMetaClass, Context, Wrapper)):
|
||||
return "<e%s of %s>" % (type(self).__name__, self.base)
|
||||
|
||||
|
||||
class Function(use_metaclass(CachedMetaClass, Wrapper)):
|
||||
class Function(use_metaclass(CachedMetaClass, Context, Wrapper)):
|
||||
"""
|
||||
Needed because of decorators. Decorators are evaluated here.
|
||||
"""
|
||||
def __init__(self, evaluator, func, is_decorated=False):
|
||||
def __init__(self, evaluator, parent_context, func, is_decorated=False):
|
||||
""" This should not be called directly """
|
||||
self._evaluator = evaluator
|
||||
super(Function, self).__init__(evaluator, parent_context)
|
||||
self.base = self.base_func = func
|
||||
self.is_decorated = is_decorated
|
||||
# A property that is set by the decorator resolution.
|
||||
@@ -716,7 +690,7 @@ class Function(use_metaclass(CachedMetaClass, Wrapper)):
|
||||
if self.base.is_generator():
|
||||
return set([iterable.Generator(self._evaluator, self, params)])
|
||||
else:
|
||||
return FunctionExecution(self._evaluator, self, params).get_return_types()
|
||||
return FunctionExecution(self._evaluator, self.parent_context, self, params).get_return_types()
|
||||
|
||||
@memoize_default()
|
||||
def py__annotations__(self):
|
||||
@@ -767,24 +741,24 @@ class FunctionExecution(Executed):
|
||||
"""
|
||||
type = 'funcdef'
|
||||
|
||||
def __init__(self, evaluator, base, *args, **kwargs):
|
||||
super(FunctionExecution, self).__init__(evaluator, base, *args, **kwargs)
|
||||
def __init__(self, evaluator, parent_context, base, var_args):
|
||||
super(FunctionExecution, self).__init__(evaluator, parent_context, base, var_args)
|
||||
self._copy_dict = {}
|
||||
self._original_function = funcdef = base.base_func
|
||||
self._original_function = funcdef = base
|
||||
if isinstance(funcdef, mixed.MixedObject):
|
||||
# The extra information in mixed is not needed anymore. We can just
|
||||
# unpack it and give it the tree object.
|
||||
funcdef = funcdef.definition
|
||||
|
||||
# Just overwrite the old version. We don't need it anymore.
|
||||
funcdef = helpers.deep_ast_copy(funcdef, new_elements=self._copy_dict)
|
||||
for child in funcdef.children:
|
||||
if child.type not in ('operator', 'keyword'):
|
||||
#funcdef = helpers.deep_ast_copy(funcdef, new_elements=self._copy_dict)
|
||||
#for child in funcdef.children:
|
||||
#if child.type not in ('operator', 'keyword'):
|
||||
# Not all nodes are properly copied by deep_ast_copy.
|
||||
child.parent = self
|
||||
self.children = funcdef.children
|
||||
self.names_dict = funcdef.names_dict
|
||||
self._copied_funcdef = funcdef
|
||||
#child.parent = self
|
||||
#self.children = funcdef.children
|
||||
#self.names_dict = funcdef.names_dict
|
||||
#self._copied_funcdef = funcdef
|
||||
|
||||
@memoize_default(default=set())
|
||||
@recursion.execution_recursion_decorator
|
||||
@@ -940,6 +914,7 @@ class GlobalName(helpers.FakeName):
|
||||
We need to mark global names somehow. Otherwise they are just normal
|
||||
names that are not definitions.
|
||||
"""
|
||||
raise NotImplementedError
|
||||
super(GlobalName, self).__init__(name.value, name.parent,
|
||||
name.start_pos, is_definition=True)
|
||||
|
||||
@@ -1010,7 +985,7 @@ class ModuleContext(use_metaclass(CachedMetaClass, tree.Module, Wrapper)):
|
||||
@property
|
||||
@memoize_default()
|
||||
def name(self):
|
||||
return helpers.FakeName(unicode(self.base.name), self, (1, 0))
|
||||
return ContextName(self, self.base.name)
|
||||
|
||||
def _get_init_directory(self):
|
||||
"""
|
||||
@@ -1101,6 +1076,7 @@ class ModuleContext(use_metaclass(CachedMetaClass, tree.Module, Wrapper)):
|
||||
if path is not None and path.endswith(os.path.sep + '__init__.py'):
|
||||
mods = pkgutil.iter_modules([os.path.dirname(path)])
|
||||
for module_loader, name, is_pkg in mods:
|
||||
raise NotImplementedError
|
||||
fake_n = helpers.FakeName(name)
|
||||
# It's obviously a relative import to the current module.
|
||||
imp = helpers.FakeImport(fake_n, self, level=1)
|
||||
|
||||
Reference in New Issue
Block a user