forked from VimPlug/jedi
Refactor some things regarding Python 2 support
This commit is contained in:
@@ -45,18 +45,6 @@ WrapperDescriptorType = type(set.__iter__)
|
|||||||
object_class_dict = type.__dict__["__dict__"].__get__(object)
|
object_class_dict = type.__dict__["__dict__"].__get__(object)
|
||||||
ClassMethodDescriptorType = type(object_class_dict['__subclasshook__'])
|
ClassMethodDescriptorType = type(object_class_dict['__subclasshook__'])
|
||||||
|
|
||||||
ALLOWED_DESCRIPTOR_ACCESS = (
|
|
||||||
types.FunctionType,
|
|
||||||
types.GetSetDescriptorType,
|
|
||||||
types.MemberDescriptorType,
|
|
||||||
MethodDescriptorType,
|
|
||||||
WrapperDescriptorType,
|
|
||||||
ClassMethodDescriptorType,
|
|
||||||
staticmethod,
|
|
||||||
classmethod,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def _a_generator(foo):
|
def _a_generator(foo):
|
||||||
"""Used to have an object to return for generators."""
|
"""Used to have an object to return for generators."""
|
||||||
yield 42
|
yield 42
|
||||||
@@ -83,6 +71,32 @@ _OPERATORS = {
|
|||||||
}
|
}
|
||||||
_OPERATORS.update(COMPARISON_OPERATORS)
|
_OPERATORS.update(COMPARISON_OPERATORS)
|
||||||
|
|
||||||
|
ALLOWED_DESCRIPTOR_ACCESS = (
|
||||||
|
types.FunctionType,
|
||||||
|
types.GetSetDescriptorType,
|
||||||
|
types.MemberDescriptorType,
|
||||||
|
MethodDescriptorType,
|
||||||
|
WrapperDescriptorType,
|
||||||
|
ClassMethodDescriptorType,
|
||||||
|
staticmethod,
|
||||||
|
classmethod,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def safe_getattr(obj, name, default=_sentinel):
|
||||||
|
try:
|
||||||
|
attr, is_get_descriptor = getattr_static(obj, name)
|
||||||
|
except AttributeError:
|
||||||
|
if default is _sentinel:
|
||||||
|
raise
|
||||||
|
return default
|
||||||
|
else:
|
||||||
|
if is_get_descriptor and type(attr) in ALLOWED_DESCRIPTOR_ACCESS:
|
||||||
|
# In case of descriptors that have get methods we cannot return
|
||||||
|
# it's value, because that would mean code execution.
|
||||||
|
return getattr(obj, name)
|
||||||
|
return attr
|
||||||
|
|
||||||
|
|
||||||
SignatureParam = namedtuple('SignatureParam', 'name has_default default has_annotation annotation')
|
SignatureParam = namedtuple('SignatureParam', 'name has_default default has_annotation annotation')
|
||||||
|
|
||||||
@@ -247,13 +261,19 @@ class DirectObjectAccess(object):
|
|||||||
|
|
||||||
@_force_unicode_decorator
|
@_force_unicode_decorator
|
||||||
def get_repr(self):
|
def get_repr(self):
|
||||||
|
builtins = 'builtins', '__builtin__'
|
||||||
|
|
||||||
|
if inspect.ismodule(self._obj):
|
||||||
|
return repr(self._obj)
|
||||||
# Try to avoid execution of the property.
|
# Try to avoid execution of the property.
|
||||||
|
if safe_getattr(self._obj, '__module__', default='') in builtins:
|
||||||
|
return repr(self._obj)
|
||||||
|
|
||||||
type_ = type(self._obj)
|
type_ = type(self._obj)
|
||||||
if type_ == type:
|
if type_ == type:
|
||||||
return type.__repr__(self._obj)
|
return type.__repr__(self._obj)
|
||||||
|
|
||||||
builtins = 'builtins', '__builtin__'
|
if safe_getattr(type_, '__module__', default='') in builtins:
|
||||||
if getattr_static(type_, '__module__', default='') in builtins:
|
|
||||||
# Allow direct execution of repr for builtins.
|
# Allow direct execution of repr for builtins.
|
||||||
return repr(self._obj)
|
return repr(self._obj)
|
||||||
return object.__repr__(self._obj)
|
return object.__repr__(self._obj)
|
||||||
@@ -281,8 +301,7 @@ class DirectObjectAccess(object):
|
|||||||
except AttributeError:
|
except AttributeError:
|
||||||
return False, False
|
return False, False
|
||||||
else:
|
else:
|
||||||
if is_get_descriptor \
|
if is_get_descriptor and type(attr) not in ALLOWED_DESCRIPTOR_ACCESS:
|
||||||
and not type(attr) in ALLOWED_DESCRIPTOR_ACCESS:
|
|
||||||
# In case of descriptors that have get methods we cannot return
|
# In case of descriptors that have get methods we cannot return
|
||||||
# it's value, because that would mean code execution.
|
# it's value, because that would mean code execution.
|
||||||
return True, True
|
return True, True
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import re
|
|||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
from jedi import debug
|
from jedi import debug
|
||||||
|
from jedi._compatibility import force_unicode
|
||||||
from jedi.cache import underscore_memoization, memoize_method
|
from jedi.cache import underscore_memoization, memoize_method
|
||||||
from jedi.evaluate.filters import AbstractFilter, AbstractNameDefinition, \
|
from jedi.evaluate.filters import AbstractFilter, AbstractNameDefinition, \
|
||||||
ContextNameMixin
|
ContextNameMixin
|
||||||
@@ -313,6 +314,9 @@ class CompiledObjectFilter(AbstractFilter):
|
|||||||
if not has_attribute:
|
if not has_attribute:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
# Always use unicode objects in Python 2 from here.
|
||||||
|
name = force_unicode(name)
|
||||||
|
|
||||||
if is_descriptor:
|
if is_descriptor:
|
||||||
return [self._get_cached_name(name, is_empty=True)]
|
return [self._get_cached_name(name, is_empty=True)]
|
||||||
|
|
||||||
@@ -442,7 +446,7 @@ def create_from_access_path(evaluator, access_path):
|
|||||||
for name, access in access_path.accesses:
|
for name, access in access_path.accesses:
|
||||||
try:
|
try:
|
||||||
if parent_context is None:
|
if parent_context is None:
|
||||||
faked = fake.get_faked_module(evaluator.latest_grammar, access_path.accesses[0][0])
|
faked = fake.get_faked_module(evaluator, access_path.accesses[0][0])
|
||||||
else:
|
else:
|
||||||
faked = fake.get_faked_with_parent_context(parent_context, name)
|
faked = fake.get_faked_with_parent_context(parent_context, name)
|
||||||
except fake.FakeDoesNotExist:
|
except fake.FakeDoesNotExist:
|
||||||
|
|||||||
@@ -29,17 +29,18 @@ class FakeDoesNotExist(Exception):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def _load_faked_module(grammar, module_name):
|
def _load_faked_module(evaluator, module_name):
|
||||||
if module_name == '__builtin__' and not is_py3:
|
|
||||||
module_name = 'builtins'
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return fake_modules[module_name]
|
return fake_modules[module_name]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
check_module_name = module_name
|
||||||
|
if module_name == '__builtin__' and evaluator.environment.version_info.major == 2:
|
||||||
|
check_module_name = 'builtins'
|
||||||
|
|
||||||
try:
|
try:
|
||||||
path = _path_dict[module_name]
|
path = _path_dict[check_module_name]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
fake_modules[module_name] = None
|
fake_modules[module_name] = None
|
||||||
return
|
return
|
||||||
@@ -47,9 +48,9 @@ def _load_faked_module(grammar, module_name):
|
|||||||
with open(path) as f:
|
with open(path) as f:
|
||||||
source = f.read()
|
source = f.read()
|
||||||
|
|
||||||
fake_modules[module_name] = m = grammar.parse(unicode(source))
|
fake_modules[module_name] = m = evaluator.latest_grammar.parse(unicode(source))
|
||||||
|
|
||||||
if module_name == 'builtins' and not is_py3:
|
if check_module_name != module_name:
|
||||||
# There are two implementations of `open` for either python 2/3.
|
# There are two implementations of `open` for either python 2/3.
|
||||||
# -> Rename the python2 version (`look at fake/builtins.pym`).
|
# -> Rename the python2 version (`look at fake/builtins.pym`).
|
||||||
open_func = _search_scope(m, 'open')
|
open_func = _search_scope(m, 'open')
|
||||||
@@ -74,8 +75,8 @@ def get_faked_with_parent_context(parent_context, name):
|
|||||||
raise FakeDoesNotExist
|
raise FakeDoesNotExist
|
||||||
|
|
||||||
|
|
||||||
def get_faked_module(grammar, string_name):
|
def get_faked_module(evaluator, string_name):
|
||||||
module = _load_faked_module(grammar, string_name)
|
module = _load_faked_module(evaluator, string_name)
|
||||||
if module is None:
|
if module is None:
|
||||||
raise FakeDoesNotExist
|
raise FakeDoesNotExist
|
||||||
return module
|
return module
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ def _fix_forward_reference(context, node):
|
|||||||
if is_string(evaled_node):
|
if is_string(evaled_node):
|
||||||
try:
|
try:
|
||||||
new_node = context.evaluator.grammar.parse(
|
new_node = context.evaluator.grammar.parse(
|
||||||
_compatibility.unicode(evaled_node.get_safe_value()),
|
_compatibility.force_unicode(evaled_node.get_safe_value()),
|
||||||
start_symbol='eval_input',
|
start_symbol='eval_input',
|
||||||
error_recovery=False
|
error_recovery=False
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user