forked from VimPlug/jedi
Use unicode in way more cases
This commit is contained in:
@@ -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 []
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user