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)
|
||||
ClassMethodDescriptorType = type(object_class_dict['__subclasshook__'])
|
||||
|
||||
ALLOWED_DESCRIPTOR_ACCESS = (
|
||||
types.FunctionType,
|
||||
types.GetSetDescriptorType,
|
||||
types.MemberDescriptorType,
|
||||
MethodDescriptorType,
|
||||
WrapperDescriptorType,
|
||||
ClassMethodDescriptorType,
|
||||
staticmethod,
|
||||
classmethod,
|
||||
)
|
||||
|
||||
|
||||
def _a_generator(foo):
|
||||
"""Used to have an object to return for generators."""
|
||||
yield 42
|
||||
@@ -83,6 +71,32 @@ _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')
|
||||
|
||||
@@ -247,13 +261,19 @@ class DirectObjectAccess(object):
|
||||
|
||||
@_force_unicode_decorator
|
||||
def get_repr(self):
|
||||
builtins = 'builtins', '__builtin__'
|
||||
|
||||
if inspect.ismodule(self._obj):
|
||||
return repr(self._obj)
|
||||
# Try to avoid execution of the property.
|
||||
if safe_getattr(self._obj, '__module__', default='') in builtins:
|
||||
return repr(self._obj)
|
||||
|
||||
type_ = type(self._obj)
|
||||
if type_ == type:
|
||||
return type.__repr__(self._obj)
|
||||
|
||||
builtins = 'builtins', '__builtin__'
|
||||
if getattr_static(type_, '__module__', default='') in builtins:
|
||||
if safe_getattr(type_, '__module__', default='') in builtins:
|
||||
# Allow direct execution of repr for builtins.
|
||||
return repr(self._obj)
|
||||
return object.__repr__(self._obj)
|
||||
@@ -281,8 +301,7 @@ class DirectObjectAccess(object):
|
||||
except AttributeError:
|
||||
return False, False
|
||||
else:
|
||||
if is_get_descriptor \
|
||||
and not type(attr) in ALLOWED_DESCRIPTOR_ACCESS:
|
||||
if is_get_descriptor and type(attr) not 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 True, True
|
||||
|
||||
@@ -5,6 +5,7 @@ import re
|
||||
from functools import partial
|
||||
|
||||
from jedi import debug
|
||||
from jedi._compatibility import force_unicode
|
||||
from jedi.cache import underscore_memoization, memoize_method
|
||||
from jedi.evaluate.filters import AbstractFilter, AbstractNameDefinition, \
|
||||
ContextNameMixin
|
||||
@@ -313,6 +314,9 @@ class CompiledObjectFilter(AbstractFilter):
|
||||
if not has_attribute:
|
||||
return []
|
||||
|
||||
# Always use unicode objects in Python 2 from here.
|
||||
name = force_unicode(name)
|
||||
|
||||
if is_descriptor:
|
||||
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:
|
||||
try:
|
||||
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:
|
||||
faked = fake.get_faked_with_parent_context(parent_context, name)
|
||||
except fake.FakeDoesNotExist:
|
||||
|
||||
@@ -29,17 +29,18 @@ class FakeDoesNotExist(Exception):
|
||||
pass
|
||||
|
||||
|
||||
def _load_faked_module(grammar, module_name):
|
||||
if module_name == '__builtin__' and not is_py3:
|
||||
module_name = 'builtins'
|
||||
|
||||
def _load_faked_module(evaluator, module_name):
|
||||
try:
|
||||
return fake_modules[module_name]
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
check_module_name = module_name
|
||||
if module_name == '__builtin__' and evaluator.environment.version_info.major == 2:
|
||||
check_module_name = 'builtins'
|
||||
|
||||
try:
|
||||
path = _path_dict[module_name]
|
||||
path = _path_dict[check_module_name]
|
||||
except KeyError:
|
||||
fake_modules[module_name] = None
|
||||
return
|
||||
@@ -47,9 +48,9 @@ def _load_faked_module(grammar, module_name):
|
||||
with open(path) as f:
|
||||
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.
|
||||
# -> Rename the python2 version (`look at fake/builtins.pym`).
|
||||
open_func = _search_scope(m, 'open')
|
||||
@@ -74,8 +75,8 @@ def get_faked_with_parent_context(parent_context, name):
|
||||
raise FakeDoesNotExist
|
||||
|
||||
|
||||
def get_faked_module(grammar, string_name):
|
||||
module = _load_faked_module(grammar, string_name)
|
||||
def get_faked_module(evaluator, string_name):
|
||||
module = _load_faked_module(evaluator, string_name)
|
||||
if module is None:
|
||||
raise FakeDoesNotExist
|
||||
return module
|
||||
|
||||
@@ -64,7 +64,7 @@ def _fix_forward_reference(context, node):
|
||||
if is_string(evaled_node):
|
||||
try:
|
||||
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',
|
||||
error_recovery=False
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user