diff --git a/jedi/api/__init__.py b/jedi/api/__init__.py index 5ee560f3..d306c26a 100644 --- a/jedi/api/__init__.py +++ b/jedi/api/__init__.py @@ -148,7 +148,7 @@ class Script(object): comps = [] comp_dct = {} for c, s in set(completions): - n = c.names[-1] + n = str(c.names[-1]) if settings.case_insensitive_completion \ and n.lower().startswith(like.lower()) \ or n.startswith(like): diff --git a/jedi/api/classes.py b/jedi/api/classes.py index 5e1d386c..96c296fb 100644 --- a/jedi/api/classes.py +++ b/jedi/api/classes.py @@ -323,7 +323,7 @@ class Completion(BaseDefinition): if isinstance(self._base, pr.Param): append += '=' - name = self._name.names[-1] + name = str(self._name.names[-1]) if like_name: name = name[self._like_name_length:] return dot + name + append diff --git a/jedi/api/interpreter.py b/jedi/api/interpreter.py index 374c4797..cf38dff5 100644 --- a/jedi/api/interpreter.py +++ b/jedi/api/interpreter.py @@ -44,14 +44,14 @@ class LazyName(helpers.FakeName): else: try: o = obj.__objclass__ - parser_path.append(pr.NamePart(obj.__name__, None, None)) + parser_path.append(pr.NamePart(obj.__name__, None, (None, None))) obj = o except AttributeError: pass try: module_name = obj.__module__ - parser_path.insert(0, pr.NamePart(obj.__name__, None, None)) + parser_path.insert(0, pr.NamePart(obj.__name__, None, (None, None))) except AttributeError: # Unfortunately in some cases like `int` there's no __module__ module = builtins diff --git a/jedi/api/usages.py b/jedi/api/usages.py index ea976298..bc2be942 100644 --- a/jedi/api/usages.py +++ b/jedi/api/usages.py @@ -71,7 +71,7 @@ def usages(evaluator, definitions, search_name, mods): compare_definitions = compare_array(definitions) mods |= set([d.get_parent_until() for d in definitions]) names = [] - for m in imports.get_modules_containing_name(mods, search_name): + for m in imports.get_modules_containing_name(mods, str(search_name)): try: stmts = m.used_names[search_name] except KeyError: diff --git a/jedi/evaluate/__init__.py b/jedi/evaluate/__init__.py index 7a3afcb7..548ba34e 100644 --- a/jedi/evaluate/__init__.py +++ b/jedi/evaluate/__init__.py @@ -348,6 +348,7 @@ class Evaluator(object): def filter_private_variable(scope, call_scope, var_name): """private variables begin with a double underline `__`""" + var_name = str(var_name) # var_name could be a NamePart if isinstance(var_name, (str, unicode)) and isinstance(scope, er.Instance)\ and var_name.startswith('__') and not var_name.endswith('__'): s = call_scope.get_parent_until((pr.Class, er.Instance, compiled.CompiledObject)) diff --git a/jedi/evaluate/imports.py b/jedi/evaluate/imports.py index ad5727ce..ef02f556 100644 --- a/jedi/evaluate/imports.py +++ b/jedi/evaluate/imports.py @@ -63,6 +63,7 @@ class ImportPath(pr.Base): self.import_path.append(import_stmt.namespace.names[0]) else: self.import_path += import_stmt.namespace.names + self.import_path = [str(name_part) for name_part in self.import_path] for i in range(kill_count + int(is_like_search)): self.import_path.pop() diff --git a/jedi/parser/representation.py b/jedi/parser/representation.py index 55ad20ab..7399aa22 100644 --- a/jedi/parser/representation.py +++ b/jedi/parser/representation.py @@ -538,7 +538,7 @@ class Function(Scope): :rtype: str """ - l = (funcname or self.name.names[-1]) + '(' + l = str(funcname or self.name.names[-1]) + '(' lines = [] for (i, p) in enumerate(self.params): code = p.get_code(False) @@ -1386,31 +1386,45 @@ class Array(StatementElement): return "<%s: %s%s>" % (type(self).__name__, typ, self.values) -class NamePart(str): +class NamePart(object): """ A string. Sometimes it is important to know if the string belongs to a name or not. """ # Unfortunately there's no way to use slots for str (non-zero __itemsize__) # -> http://utcc.utoronto.ca/~cks/space/blog/python/IntSlotsPython3k - #__slots__ = ('_start_pos', 'parent') - def __new__(cls, s, parent, start_pos): - self = super(NamePart, cls).__new__(cls, s) - self._start_pos = start_pos + # Therefore don't subclass `str`. + __slots__ = ('parent', 'string', '_line', '_column') + + def __init__(self, string, parent, start_pos): + if isinstance(string, NamePart): + # may happen, because this class used to be a `str`. + string = string.string + self.string = string self.parent = parent - return self + self._line = start_pos[0] + self._column = start_pos[1] + + def __str__(self): + return self.string + + def __repr__(self): + return "<%s: %s>" % (type(self).__name__, self.string) + + def __eq__(self, other): + return self.string == other + + def __hash__(self): + return hash(self.string) @property def start_pos(self): offset = self.parent._sub_module.line_offset - return offset + self._start_pos[0], self._start_pos[1] + return offset + self._line, self._column @property def end_pos(self): - return self.start_pos[0], self.start_pos[1] + len(self) - - def __getnewargs__(self): - return str(self), self.parent, self._start_pos + return self.start_pos[0], self.start_pos[1] + len(self.string) class Name(Simple): @@ -1431,7 +1445,7 @@ class Name(Simple): def get_code(self): """ Returns the names in a full string format """ - return ".".join(self.names) + return ".".join(str(n) for n in self.names) @property def docstr(self):