1
0
forked from VimPlug/jedi

Add an access abstraction (only array tests work, yet)

The access abstraction will be the new way of accessing builtin objects. This way it will be easier to move that to another process
This commit is contained in:
Dave Halter
2017-11-25 19:47:49 +01:00
parent 52bc1be84e
commit 7263d8565b
10 changed files with 408 additions and 235 deletions
+50 -89
View File
@@ -6,72 +6,60 @@ mixing in Python code, the autocompletion should work much better for builtins.
import os
import inspect
import types
from itertools import chain
from parso.python import tree
from jedi._compatibility import is_py3, builtins, unicode, is_py34
from jedi._compatibility import is_py3, builtins, unicode
modules = {}
fake_modules = {}
MethodDescriptorType = type(str.replace)
# These are not considered classes and access is granted even though they have
# a __class__ attribute.
NOT_CLASS_TYPES = (
types.BuiltinFunctionType,
types.CodeType,
types.FrameType,
types.FunctionType,
types.GeneratorType,
types.GetSetDescriptorType,
types.LambdaType,
types.MemberDescriptorType,
types.MethodType,
types.ModuleType,
types.TracebackType,
MethodDescriptorType
)
def _get_path_dict():
path = os.path.dirname(os.path.abspath(__file__))
base_path = os.path.join(path, 'fake')
dct = {}
for file_name in os.listdir(base_path):
if file_name.endswith('.pym'):
dct[file_name[:-4]] = os.path.join(base_path, file_name)
return dct
if is_py3:
NOT_CLASS_TYPES += (
types.MappingProxyType,
types.SimpleNamespace
)
if is_py34:
NOT_CLASS_TYPES += (types.DynamicClassAttribute,)
_path_dict = _get_path_dict()
class FakeDoesNotExist(Exception):
pass
def _load_faked_module(grammar, module):
module_name = module.__name__
def _load_faked_module(grammar, module_name):
if module_name == '__builtin__' and not is_py3:
module_name = 'builtins'
try:
return modules[module_name]
return fake_modules[module_name]
except KeyError:
path = os.path.dirname(os.path.abspath(__file__))
try:
with open(os.path.join(path, 'fake', module_name) + '.pym') as f:
source = f.read()
except IOError:
modules[module_name] = None
return
modules[module_name] = m = grammar.parse(unicode(source))
pass
if module_name == 'builtins' and not is_py3:
# There are two implementations of `open` for either python 2/3.
# -> Rename the python2 version (`look at fake/builtins.pym`).
open_func = _search_scope(m, 'open')
open_func.children[1].value = 'open_python3'
open_func = _search_scope(m, 'open_python2')
open_func.children[1].value = 'open'
return m
try:
path = _path_dict[module_name]
except KeyError:
fake_modules[module_name] = None
return
with open(path) as f:
source = f.read()
fake_modules[module_name] = m = grammar.parse(unicode(source))
if module_name == 'builtins' and not is_py3:
# There are two implementations of `open` for either python 2/3.
# -> Rename the python2 version (`look at fake/builtins.pym`).
open_func = _search_scope(m, 'open')
open_func.children[1].value = 'open_python3'
open_func = _search_scope(m, 'open_python2')
open_func.children[1].value = 'open'
return m
def _search_scope(scope, obj_name):
@@ -80,31 +68,6 @@ def _search_scope(scope, obj_name):
return s
def _get_module(obj):
if inspect.ismodule(obj):
return obj
try:
obj = obj.__objclass__
except AttributeError:
pass
try:
imp_plz = obj.__module__
except AttributeError:
# Unfortunately in some cases like `int` there's no __module__
return builtins
else:
if imp_plz is None:
# Happens for example in `(_ for _ in []).send.__module__`.
return builtins
else:
try:
return __import__(imp_plz)
except ImportError:
# __module__ can be something arbitrary that doesn't exist.
return builtins
def _faked(grammar, module, obj, name):
# Crazy underscore actions to try to escape all the internal madness.
if module is None:
@@ -188,26 +151,24 @@ def _get_faked(grammar, module, obj, name=None):
return result, fake_module
def get_faked(evaluator, module, obj, name=None, parent_context=None):
if parent_context and parent_context.tree_node is not None:
def get_faked_with_parent_context(parent_context, name):
if parent_context.tree_node is not None:
# Try to search in already clearly defined stuff.
found = _search_scope(parent_context.tree_node, name)
if found is not None:
return found
else:
raise FakeDoesNotExist
def get_faked_tree_nodes(grammar, string_names):
module = base = _load_faked_module(grammar, string_names[0])
if module is None:
raise FakeDoesNotExist
tree_nodes = [module]
for name in string_names[1:]:
base = _search_scope(base, name)
if base is None:
raise FakeDoesNotExist
faked, fake_module = _get_faked(evaluator.latest_grammar, module and module.obj, obj, name)
if module is not None:
module.get_used_names = fake_module.get_used_names
return faked
def is_class_instance(obj):
"""Like inspect.* methods."""
try:
cls = obj.__class__
except AttributeError:
return False
else:
return cls != type and not issubclass(cls, NOT_CLASS_TYPES)
tree_nodes.append(base)
return tree_nodes