1
0
forked from VimPlug/jedi

Start creating access objects in a different way

This commit is contained in:
Dave Halter
2017-12-03 19:37:03 +01:00
parent 3c78aad8b1
commit 15d9e64281
4 changed files with 64 additions and 34 deletions

View File

@@ -5,8 +5,8 @@ import re
from jedi._compatibility import builtins as _builtins from jedi._compatibility import builtins as _builtins
from jedi.evaluate.compiled.context import CompiledObject, CompiledName, \ from jedi.evaluate.compiled.context import CompiledObject, CompiledName, \
CompiledObjectFilter, CompiledContextName, create_from_access CompiledObjectFilter, CompiledContextName, create_from_access_path
from jedi.evaluate.compiled.access import create_access from jedi.evaluate.compiled.access import create_access_path
from jedi import debug from jedi import debug
@@ -32,8 +32,8 @@ def create_simple_object(evaluator, obj):
def create(evaluator, obj): def create(evaluator, obj):
return create_from_access( return create_from_access_path(
evaluator, create_access(evaluator, obj) evaluator, create_access_path(evaluator, obj)
) )

View File

@@ -109,6 +109,16 @@ def create_access(evaluator, obj):
return DirectObjectAccess(evaluator, obj) return DirectObjectAccess(evaluator, obj)
class AccessPath(object):
def __init__(self, accesses):
self.accesses = accesses
def create_access_path(evaluator, obj):
access = create_access(evaluator, obj)
return AccessPath(access.get_access_path_tuples())
class DirectObjectAccess(object): class DirectObjectAccess(object):
def __init__(self, evaluator, obj): def __init__(self, evaluator, obj):
self._evaluator = evaluator self._evaluator = evaluator
@@ -120,6 +130,9 @@ class DirectObjectAccess(object):
def _create_access(self, obj): def _create_access(self, obj):
return create_access(self._evaluator, obj) return create_access(self._evaluator, obj)
def _create_access_path(self, obj):
return create_access_path(self._evaluator, obj)
def py__bool__(self): def py__bool__(self):
return bool(self._obj) return bool(self._obj)
@@ -150,14 +163,14 @@ class DirectObjectAccess(object):
return None return None
def py__mro__accesses(self): def py__mro__accesses(self):
return tuple(self._create_access(cls) for cls in self._obj.__mro__[1:]) return tuple(self._create_access_path(cls) for cls in self._obj.__mro__[1:])
def py__getitem__(self, index): def py__getitem__(self, index):
if type(self._obj) not in (str, list, tuple, unicode, bytes, bytearray, dict): if type(self._obj) not in (str, list, tuple, unicode, bytes, bytearray, dict):
# Get rid of side effects, we won't call custom `__getitem__`s. # Get rid of side effects, we won't call custom `__getitem__`s.
return None return None
return self._create_access(self._obj[index]) return self._create_access_path(self._obj[index])
def py__iter__list(self): def py__iter__list(self):
if type(self._obj) not in (str, list, tuple, unicode, bytes, bytearray, dict): if type(self._obj) not in (str, list, tuple, unicode, bytes, bytearray, dict):
@@ -169,14 +182,14 @@ class DirectObjectAccess(object):
if i > 20: if i > 20:
# Should not go crazy with large iterators # Should not go crazy with large iterators
break break
lst.append(self._create_access(part)) lst.append(self._create_access_path(part))
return lst return lst
def py__class__(self): def py__class__(self):
return self._create_access(self._obj.__class__) return self._create_access_path(self._obj.__class__)
def py__bases__(self): def py__bases__(self):
return [self._create_access(base) for base in self._obj.__bases__] return [self._create_access_path(base) for base in self._obj.__bases__]
def get_repr(self): def get_repr(self):
return repr(self._obj) return repr(self._obj)
@@ -239,14 +252,10 @@ class DirectObjectAccess(object):
return 'instance' return 'instance'
def get_access_path_tuples(self): def get_access_path_tuples(self):
path = self._get_objects_path() return [
try: (getattr(o, '__name__', None), create_access(self._evaluator, o))
# Just provoke an AttributeError. for o in self._get_objects_path()
result = [(o.__name__, o) for o in path] ]
except AttributeError:
return []
else:
return [(name, self._create_access(o)) for name, o in result]
def _get_objects_path(self): def _get_objects_path(self):
def get(): def get():
@@ -272,6 +281,7 @@ class DirectObjectAccess(object):
yield builtins yield builtins
else: else:
try: try:
# TODO use sys.modules, __module__ can be faked.
yield __import__(imp_plz) yield __import__(imp_plz)
except ImportError: except ImportError:
# __module__ can be something arbitrary that doesn't exist. # __module__ can be something arbitrary that doesn't exist.
@@ -281,7 +291,7 @@ class DirectObjectAccess(object):
def execute_operation(self, other, operator): def execute_operation(self, other, operator):
op = _OPERATORS[operator] op = _OPERATORS[operator]
return self._create_access(op(self._obj, other._obj)) return self._create_access_path(op(self._obj, other._obj))
def needs_type_completions(self): def needs_type_completions(self):
return inspect.isclass(self._obj) and self._obj != type return inspect.isclass(self._obj) and self._obj != type
@@ -311,17 +321,17 @@ class DirectObjectAccess(object):
SignatureParam( SignatureParam(
name=p.name, name=p.name,
has_default=p.default is not p.empty, has_default=p.default is not p.empty,
default=self._create_access(p.default), default=self._create_access_path(p.default),
has_annotation=p.annotation is not p.empty, has_annotation=p.annotation is not p.empty,
annotation=self._create_access(p.annotation), annotation=self._create_access_path(p.annotation),
) for p in signature.parameters.values() ) for p in signature.parameters.values()
] ]
def negate(self): def negate(self):
return self._create_access(-self._obj) return self._create_access_path(-self._obj)
def dict_values(self): def dict_values(self):
return [self._create_access(v) for v in self._obj.values()] return [self._create_access_path(v) for v in self._obj.values()]
def is_super_class(self, exception): def is_super_class(self, exception):
return issubclass(exception, self._obj) return issubclass(exception, self._obj)

View File

@@ -63,18 +63,18 @@ class CompiledObject(Context):
@CheckAttribute @CheckAttribute
def py__class__(self): def py__class__(self):
return create_from_access(self.evaluator, self.access.py__class__()) return create_from_access_path(self.evaluator, self.access.py__class__())
@CheckAttribute @CheckAttribute
def py__mro__(self): def py__mro__(self):
return (self,) + tuple( return (self,) + tuple(
create_from_access(self.evaluator, access) for access in self.access.py__mro__accesses() create_from_access_path(self.evaluator, access) for access in self.access.py__mro__accesses()
) )
@CheckAttribute @CheckAttribute
def py__bases__(self): def py__bases__(self):
return tuple( return tuple(
create_from_access(self.evaluator, access) create_from_access_path(self.evaluator, access)
for access in self.access.py__bases__() for access in self.access.py__bases__()
) )
@@ -147,12 +147,12 @@ class CompiledObject(Context):
if access is None: if access is None:
return ContextSet() return ContextSet()
return ContextSet(create_from_access(self.evaluator, access)) return ContextSet(create_from_access_path(self.evaluator, access))
@CheckAttribute @CheckAttribute
def py__iter__(self): def py__iter__(self):
for access in self.access.py__iter__list(): for access in self.access.py__iter__list():
yield LazyKnownContext(create_from_access(self.evaluator, access)) yield LazyKnownContext(create_from_access_path(self.evaluator, access))
def py__name__(self): def py__name__(self):
return self.access.py__name__() return self.access.py__name__()
@@ -187,7 +187,7 @@ class CompiledObject(Context):
def dict_values(self): def dict_values(self):
return ContextSet.from_iterable( return ContextSet.from_iterable(
create_from_access(self.evaluator, access) for access in self.access.dict_values() create_from_access_path(self.evaluator, access) for access in self.access.dict_values()
) )
def get_safe_value(self, default=_sentinel): def get_safe_value(self, default=_sentinel):
@@ -199,13 +199,13 @@ class CompiledObject(Context):
return default return default
def execute_operation(self, other, operator): def execute_operation(self, other, operator):
return create_from_access( return create_from_access_path(
self.evaluator, self.evaluator,
self.access.execute_operation(other.access, operator) self.access.execute_operation(other.access, operator)
) )
def negate(self): def negate(self):
return create_from_access(self.evaluator, self.access.negate()) return create_from_access_path(self.evaluator, self.access.negate())
def is_super_class(self, exception): def is_super_class(self, exception):
return self.access.is_super_class(exception) return self.access.is_super_class(exception)
@@ -251,9 +251,9 @@ class SignatureParamName(AbstractNameDefinition):
evaluator = self.parent_context.evaluator evaluator = self.parent_context.evaluator
contexts = ContextSet() contexts = ContextSet()
if p.has_default: if p.has_default:
contexts = ContextSet(create_from_access(evaluator, p.default)) contexts = ContextSet(create_from_access_path(evaluator, p.default))
if p.has_annotation: if p.has_annotation:
annotation = create_from_access(evaluator, p.annotation) annotation = create_from_access_path(evaluator, p.annotation)
contexts |= annotation.execute_evaluated() contexts |= annotation.execute_evaluated()
return contexts return contexts
@@ -416,6 +416,21 @@ def _normalize_create_args(func):
return wrapper return wrapper
def create_from_access_path(evaluator, access_path):
parent_context = None
for name, access in access_path.accesses:
try:
if parent_context is None:
faked = fake.get_faked_module(evaluator.latest_grammar, access_path.accesses[0][0])
else:
faked = fake.get_faked_with_parent_context(parent_context, name)
except fake.FakeDoesNotExist:
faked = None
parent_context = create_cached_compiled_object(evaluator, access, parent_context, faked)
return parent_context
@evaluator_function_cache() @evaluator_function_cache()
def create_from_access(evaluator, access): def create_from_access(evaluator, access):
""" """

View File

@@ -74,10 +74,15 @@ def get_faked_with_parent_context(parent_context, name):
raise FakeDoesNotExist raise FakeDoesNotExist
def get_faked_tree_nodes(grammar, string_names): def get_faked_module(grammar, string_name):
module = base = _load_faked_module(grammar, string_names[0]) module = _load_faked_module(grammar, string_name)
if module is None: if module is None:
raise FakeDoesNotExist raise FakeDoesNotExist
return module
def get_faked_tree_nodes(grammar, string_names):
module = base = get_faked_module(grammar, string_names[0])
tree_nodes = [module] tree_nodes = [module]
for name in string_names[1:]: for name in string_names[1:]: