1
0
forked from VimPlug/jedi

Use unicode in way more cases

This commit is contained in:
Dave Halter
2017-12-28 23:07:53 +01:00
parent 5755d5a4ee
commit ba81aa16a2
8 changed files with 35 additions and 30 deletions

View File

@@ -324,9 +324,9 @@ class BaseDefinition(object):
param_names = param_names[1:]
elif isinstance(context, (instance.AbstractInstanceContext, ClassContext)):
if isinstance(context, ClassContext):
search = '__init__'
search = u'__init__'
else:
search = '__call__'
search = u'__call__'
names = context.get_function_slot_names(search)
if not names:
return []

View File

@@ -117,8 +117,8 @@ def add_attribute_error(name_context, lookup_context, name):
# instead of an error, if that happens.
typ = Error
if isinstance(lookup_context, AbstractInstanceContext):
slot_names = lookup_context.get_function_slot_names('__getattr__') + \
lookup_context.get_function_slot_names('__getattribute__')
slot_names = lookup_context.get_function_slot_names(u'__getattr__') + \
lookup_context.get_function_slot_names(u'__getattribute__')
for n in slot_names:
# TODO do we even get here?
if isinstance(name, CompiledInstanceName) and \

View File

@@ -21,7 +21,7 @@ class CheckAttribute(object):
def __init__(self, func):
self.func = func
# Remove the py in front of e.g. py__call__.
self.check_name = func.__name__[2:]
self.check_name = force_unicode(func.__name__[2:])
def __get__(self, instance, owner):
if instance is None:

View File

@@ -14,7 +14,7 @@ import weakref
import pickle
from functools import partial
from jedi._compatibility import queue, is_py3
from jedi._compatibility import queue, is_py3, force_unicode
from jedi.cache import memoize_method
from jedi.evaluate.compiled.subprocess import functions
from jedi.evaluate.compiled.access import DirectObjectAccess, AccessPath, \
@@ -286,7 +286,7 @@ class AccessHandle(object):
#if not is_py3: print >> sys.stderr, name
#print('getattr', name, file=sys.stderr)
return partial(self._workaround, name)
return partial(self._workaround, force_unicode(name))
def _workaround(self, name, *args, **kwargs):
"""
@@ -294,6 +294,9 @@ class AccessHandle(object):
happen. They are also the only unhashable objects that we're passing
around.
"""
# Python 2 compatibility
kwargs = {force_unicode(key): value for key, value in kwargs.items()}
if args and isinstance(args[0], slice):
return self._subprocess.get_compiled_method_return(self.id, name, *args, **kwargs)
return self._cached_results(name, *args, **kwargs)

View File

@@ -53,7 +53,7 @@ class AbstractInstanceContext(Context):
@property
def py__call__(self):
names = self.get_function_slot_names('__call__')
names = self.get_function_slot_names(u'__call__')
if not names:
# Means the Instance is not callable.
raise AttributeError
@@ -89,7 +89,7 @@ class AbstractInstanceContext(Context):
def py__get__(self, obj):
# Arguments in __get__ descriptors are obj, class.
# `method` is the new parent of the array, don't know if that's good.
names = self.get_function_slot_names('__get__')
names = self.get_function_slot_names(u'__get__')
if names:
if isinstance(obj, AbstractInstanceContext):
return self.execute_function_slots(names, obj, obj.class_context)
@@ -118,7 +118,7 @@ class AbstractInstanceContext(Context):
def py__getitem__(self, index):
try:
names = self.get_function_slot_names('__getitem__')
names = self.get_function_slot_names(u'__getitem__')
except KeyError:
debug.warning('No __getitem__, cannot access the array.')
return NO_CONTEXTS
@@ -127,7 +127,7 @@ class AbstractInstanceContext(Context):
return self.execute_function_slots(names, index_obj)
def py__iter__(self):
iter_slot_names = self.get_function_slot_names('__iter__')
iter_slot_names = self.get_function_slot_names(u'__iter__')
if not iter_slot_names:
debug.warning('No __iter__ on %s.' % self)
return
@@ -136,9 +136,9 @@ class AbstractInstanceContext(Context):
if isinstance(generator, AbstractInstanceContext):
# `__next__` logic.
if self.evaluator.environment.version_info.major == 2:
name = 'next'
name = u'next'
else:
name = '__next__'
name = u'__next__'
iter_slot_names = generator.get_function_slot_names(name)
if iter_slot_names:
yield LazyKnownContexts(
@@ -166,7 +166,7 @@ class AbstractInstanceContext(Context):
)
def create_init_executions(self):
for name in self.get_function_slot_names('__init__'):
for name in self.get_function_slot_names(u'__init__'):
if isinstance(name, SelfName):
yield self._create_init_execution(name.class_context, name.tree_name.parent)

View File

@@ -139,7 +139,7 @@ class ClassContext(use_metaclass(CachedMetaClass, TreeContext)):
args = arguments.TreeArguments(self.evaluator, self, arglist)
return [value for key, value in args.unpack() if key is None]
else:
return [LazyKnownContext(compiled.builtin_from_name(self.evaluator, 'object'))]
return [LazyKnownContext(compiled.builtin_from_name(self.evaluator, u'object'))]
def py__call__(self, params):
from jedi.evaluate.context import TreeInstance
@@ -182,7 +182,7 @@ class ClassContext(use_metaclass(CachedMetaClass, TreeContext)):
return []
def get_param_names(self):
for name in self.get_function_slot_names('__init__'):
for name in self.get_function_slot_names(u'__init__'):
for context_ in name.infer():
try:
method = context_.get_param_names

View File

@@ -149,8 +149,8 @@ class NameFinder(object):
# We are inversing this, because a hand-crafted `__getattribute__`
# could still call another hand-crafted `__getattr__`, but not the
# other way around.
names = (inst.get_function_slot_names('__getattr__') or
inst.get_function_slot_names('__getattribute__'))
names = (inst.get_function_slot_names(u'__getattr__') or
inst.get_function_slot_names(u'__getattribute__'))
return inst.execute_function_slots(names, name)
def _names_to_types(self, names, attribute_lookup):

View File

@@ -5,6 +5,7 @@ import copy
from parso.python import tree
from jedi._compatibility import force_unicode
from jedi import debug
from jedi import parser_utils
from jedi.evaluate.base_context import ContextSet, NO_CONTEXTS, ContextualizedNode, \
@@ -367,40 +368,41 @@ def _bool_to_context(evaluator, bool_):
def _eval_comparison_part(evaluator, context, left, operator, right):
l_is_num = is_number(left)
r_is_num = is_number(right)
if operator == '*':
str_operator = force_unicode(str(operator.value))
if str_operator == '*':
# for iterables, ignore * operations
if isinstance(left, iterable.AbstractIterable) or is_string(left):
return ContextSet(left)
elif isinstance(right, iterable.AbstractIterable) or is_string(right):
return ContextSet(right)
elif operator == '+':
elif str_operator == '+':
if l_is_num and r_is_num or is_string(left) and is_string(right):
return ContextSet(left.execute_operation(right, operator))
return ContextSet(left.execute_operation(right, str_operator))
elif _is_tuple(left) and _is_tuple(right) or _is_list(left) and _is_list(right):
return ContextSet(iterable.MergedArray(evaluator, (left, right)))
elif operator == '-':
elif str_operator == '-':
if l_is_num and r_is_num:
return ContextSet(left.execute_operation(right, operator))
elif operator == '%':
return ContextSet(left.execute_operation(right, str_operator))
elif str_operator == '%':
# With strings and numbers the left type typically remains. Except for
# `int() % float()`.
return ContextSet(left)
elif operator in COMPARISON_OPERATORS:
elif str_operator in COMPARISON_OPERATORS:
if is_compiled(left) and is_compiled(right):
# Possible, because the return is not an option. Just compare.
try:
return ContextSet(left.execute_operation(right, operator))
return ContextSet(left.execute_operation(right, str_operator))
except TypeError:
# Could be True or False.
pass
else:
if operator in ('is', '!=', '==', 'is not'):
operation = COMPARISON_OPERATORS[operator]
if str_operator in ('is', '!=', '==', 'is not'):
operation = COMPARISON_OPERATORS[str_operator]
bool_ = operation(left, right)
return ContextSet(_bool_to_context(evaluator, bool_))
return ContextSet(_bool_to_context(evaluator, True), _bool_to_context(evaluator, False))
elif operator == 'in':
elif str_operator == 'in':
return NO_CONTEXTS
def check(obj):
@@ -409,7 +411,7 @@ def _eval_comparison_part(evaluator, context, left, operator, right):
obj.name.string_name in ('int', 'float')
# Static analysis, one is a number, the other one is not.
if operator in ('+', '-') and l_is_num != r_is_num \
if str_operator in ('+', '-') and l_is_num != r_is_num \
and not (check(left) or check(right)):
message = "TypeError: unsupported operand type(s) for +: %s and %s"
analysis.add(context, 'type-error-operation', operator,