diff --git a/jedi/api/__init__.py b/jedi/api/__init__.py index d88b3422..3f8f4c60 100644 --- a/jedi/api/__init__.py +++ b/jedi/api/__init__.py @@ -433,7 +433,7 @@ class Script(object): and d.start_pos == (0, 0): i = imports.ImportWrapper(self._evaluator, d.parent).follow(is_goto=True) definitions.remove(d) - definitions |= follow_inexistent_imports(i.names[-1]) + definitions |= follow_inexistent_imports(i) return definitions goto_path = self._user_context.get_path_under_cursor() @@ -468,7 +468,7 @@ class Script(object): if add_import_name: import_name = user_stmt.get_defined_names() # imports have only one name - np = import_name[0].names[-1] + np = import_name[0] if not user_stmt.star and unicode(name_part) == unicode(np): definitions.append(np) else: @@ -573,7 +573,7 @@ class Script(object): key_name = unicode(detail[0][0].name) except (IndexError, AttributeError): pass - return [classes.CallSignature(self._evaluator, o.name.names[-1], call, index, key_name) + return [classes.CallSignature(self._evaluator, o.name, call, index, key_name) for o in origins if hasattr(o, 'py__call__')] def _analysis(self): @@ -584,7 +584,7 @@ class Script(object): iw = imports.ImportWrapper(self._evaluator, i, nested_resolve=True).follow() if i.is_nested() and any(not isinstance(i, pr.Module) for i in iw): - analysis.add(self._evaluator, 'import-error', i.namespace.names[-1]) + analysis.add(self._evaluator, 'import-error', i.namespace_names[-1]) for stmt in sorted(stmts, key=lambda obj: obj.start_pos): if not (isinstance(stmt.parent, pr.ForFlow) and stmt.parent.set_stmt == stmt): diff --git a/jedi/api/classes.py b/jedi/api/classes.py index e5007d45..d2d1a0cf 100644 --- a/jedi/api/classes.py +++ b/jedi/api/classes.py @@ -37,7 +37,7 @@ def defined_names(evaluator, scope): include_builtin=False), None) names = pair[1] if pair else [] names = [n for n in names if isinstance(n, pr.Import) or (len(n) == 1)] - return [Definition(evaluator, d.names[-1]) for d in sorted(names, key=lambda s: s.start_pos)] + return [Definition(evaluator, d) for d in sorted(names, key=lambda s: s.start_pos)] class BaseDefinition(object): @@ -176,8 +176,8 @@ class BaseDefinition(object): par = self._definition while par is not None: if isinstance(par, pr.Import): - insert_nonnone(par.namespace) - insert_nonnone(par.from_ns) + insert_nonnone(par.namespace_names) + insert_nonnone(par.from_names) if par.relative_count == 0: break with common.ignored(AttributeError): @@ -376,12 +376,12 @@ class BaseDefinition(object): params = sub.params[1:] # ignore self except KeyError: return [] - return [_Param(self._evaluator, p.get_name().names[-1]) for p in params] + return [_Param(self._evaluator, p.get_name()) for p in params] def parent(self): scope = self._definition.get_parent_scope() non_flow = scope.get_parent_until(pr.Flow, reverse=True) - return Definition(self._evaluator, non_flow.name.names[-1]) + return Definition(self._evaluator, non_flow.name) def __repr__(self): return "<%s %s>" % (type(self).__name__, self.description) @@ -539,7 +539,7 @@ class Completion(BaseDefinition): it's just PITA-slow. """ defs = self._follow_statements_imports() - return [Definition(self._evaluator, d.name.names[-1]) for d in defs] + return [Definition(self._evaluator, d.name) for d in defs] class Definition(use_metaclass(CachedMetaClass, BaseDefinition)): diff --git a/jedi/evaluate/__init__.py b/jedi/evaluate/__init__.py index ca01d8af..c89c4ba6 100644 --- a/jedi/evaluate/__init__.py +++ b/jedi/evaluate/__init__.py @@ -357,7 +357,7 @@ class Evaluator(object): params = typ.params for param in params: if unicode(param.get_name()) == unicode(named_param_name): - param_names.append(param.get_name().names[-1]) + param_names.append(param.get_name()) return param_names return [call_path[0]] diff --git a/jedi/evaluate/finder.py b/jedi/evaluate/finder.py index d91798f6..7abf7f0e 100644 --- a/jedi/evaluate/finder.py +++ b/jedi/evaluate/finder.py @@ -287,7 +287,7 @@ class NameFinder(object): if isinstance(p, pr.Flow) and p.command == 'except' and p.inputs: as_names = p.inputs[0].as_names try: - if as_names[0].names[-1] == name: + if as_names[0] == name: # TODO check for types that are not classes and add it to # the static analysis report. types = list(chain.from_iterable( @@ -589,7 +589,7 @@ def find_assignments(lhs, results, seek_name): """ if isinstance(lhs, pr.Array): return _assign_tuples(lhs, results, seek_name) - elif unicode(lhs.name.names[-1]) == seek_name: + elif unicode(lhs.name) == seek_name: return results else: return [] diff --git a/jedi/evaluate/helpers.py b/jedi/evaluate/helpers.py index fde6c1b2..3864d590 100644 --- a/jedi/evaluate/helpers.py +++ b/jedi/evaluate/helpers.py @@ -217,7 +217,7 @@ def get_module_name_parts(module): def scope_name_parts(scope): for s in scope.subscopes: # Yield the name parts, not names. - yield s.name.names[0] + yield s.name for need_yield_from in scope_name_parts(s): yield need_yield_from @@ -237,8 +237,8 @@ def get_module_name_parts(module): # token_list anymore, but for now this is the easiest way to get # all the name_parts. for tok in stmt_or_import._token_list: - if isinstance(tok, pr.Name): - name_parts.update(tok.names) + if isinstance(tok, pr.NamePart): + name_parts.add(tok) return name_parts diff --git a/jedi/evaluate/imports.py b/jedi/evaluate/imports.py index aac70a15..a2cc56b9 100644 --- a/jedi/evaluate/imports.py +++ b/jedi/evaluate/imports.py @@ -67,13 +67,13 @@ class ImportWrapper(pr.Base): # rest is import_path resolution import_path = [] - if import_stmt.from_ns: - import_path += import_stmt.from_ns.names - if import_stmt.namespace: + if import_stmt.from_names: + import_path += import_stmt.from_names + if import_stmt.namespace_names: if self.import_stmt.is_nested() and not nested_resolve: - import_path.append(import_stmt.namespace.names[0]) + import_path.append(import_stmt.namespace_names[0]) else: - import_path += import_stmt.namespace.names + import_path += import_stmt.namespace_names for i in range(kill_count + int(is_like_search)): if import_path: @@ -140,9 +140,9 @@ class ImportWrapper(pr.Base): for s, scope_names in finder.get_names_of_scope(self._evaluator, scope, include_builtin=False): for n in scope_names: - if self.import_stmt.from_ns is None \ + if self.import_stmt.from_names is None \ or self.is_partial_import: - # from_ns must be defined to access module + # from_names must be defined to access module # values plus a partial import means that there # is something after the import, which # automatically implies that there must not be @@ -198,7 +198,7 @@ class ImportWrapper(pr.Base): # goto only accepts Names or NameParts if is_goto and not rest: - scopes = [s.name.names[-1] for s in scopes] + scopes = [s.name for s in scopes] # follow the rest of the import (not FS -> classes, functions) if len(rest) > 1 or rest and self.is_like_search: @@ -243,12 +243,12 @@ class NestedImportModule(pr.Module): # This is not an existing Import statement. Therefore, set position to # 0 (0 is not a valid line number). zero = (0, 0) - names = [unicode(name_part) for name_part in i.namespace.names[1:]] + names = [unicode(name_part) for name_part in i.namespace_names[1:]] name = helpers.FakeName(names, self._nested_import) new = pr.Import(i._sub_module, zero, zero, name) new.parent = self._module debug.dbg('Generated a nested import: %s', new) - return helpers.FakeName(str(i.namespace.names[1]), new) + return helpers.FakeName(str(i.namespace_names[1]), new) def _get_defined_names(self): """ diff --git a/jedi/evaluate/iterable.py b/jedi/evaluate/iterable.py index 1d6d5765..7773e657 100644 --- a/jedi/evaluate/iterable.py +++ b/jedi/evaluate/iterable.py @@ -224,6 +224,7 @@ class Array(use_metaclass(CachedMetaClass, IterableWrapper)): return "" % (type(self).__name__, self._array) +# TODO REMOVE, not used. class ArrayMethod(IterableWrapper): """ A name, e.g. `list.append`, it is used to access the original array diff --git a/jedi/evaluate/param.py b/jedi/evaluate/param.py index f5ef8f50..64711a19 100644 --- a/jedi/evaluate/param.py +++ b/jedi/evaluate/param.py @@ -359,8 +359,6 @@ def _gen_param_name_copy(func, var_args, param, keys=(), values=(), array_type=N new_param.set_expression_list([arr]) name = copy.copy(param.get_name()) - name.names = [copy.copy(name.names[0])] - name.names[0].parent = name name.parent = new_param return name diff --git a/jedi/evaluate/representation.py b/jedi/evaluate/representation.py index f510a340..abf0c12a 100644 --- a/jedi/evaluate/representation.py +++ b/jedi/evaluate/representation.py @@ -303,12 +303,6 @@ class InstanceElement(use_metaclass(CachedMetaClass, pr.Base)): return [get_instance_el(self._evaluator, self.instance, command, self.is_class_var) for command in self.var.expression_list()] - @property - @underscore_memoization - def names(self): - return [pr.NamePart(helpers.FakeSubModule, unicode(n), self, n.start_pos) - for n in self.var.names] - @property @underscore_memoization def name(self): diff --git a/jedi/parser/__init__.py b/jedi/parser/__init__.py index 6e2ad210..1c65f043 100644 --- a/jedi/parser/__init__.py +++ b/jedi/parser/__init__.py @@ -354,6 +354,7 @@ class Parser(object): elif in_lambda_param and tok.string == ':': in_lambda_param = False elif tok.type == tokenize.NAME and not is_kw: + tok_list[-1], tok = self._parse_name(tok) continue elif tok.string in opening_brackets: level += 1 @@ -456,7 +457,7 @@ class Parser(object): elif tok_str == 'import': imports = self._parse_import_list() for count, (names, alias, defunct) in enumerate(imports): - e = (alias or m or self._gen.previous).end_pos + e = (alias or names and names[-1] or self._gen.previous).end_pos end_pos = self._gen.previous.end_pos if count + 1 == len(imports) else e i = pr.Import(self.module, first_pos, end_pos, names, alias, defunct=defunct) diff --git a/jedi/parser/representation.py b/jedi/parser/representation.py index 02ede1f3..598c8893 100644 --- a/jedi/parser/representation.py +++ b/jedi/parser/representation.py @@ -477,10 +477,10 @@ class SubModule(Scope, Module): is a ``__future__`` import. """ for imp in self.imports: - if imp.from_ns is None or imp.namespace is None: + if imp.from_ns is None or imp.namespace_names is None: continue - namespace, feature = imp.from_ns.names[0], imp.namespace.names[0] + namespace, feature = imp.from_names[0], imp.namespace_names[0] if unicode(namespace) == "__future__" and unicode(feature) == "absolute_import": return True @@ -528,9 +528,9 @@ class Class(Scope): if self._doc_token is not None: docstr = self.raw_doc for sub in self.subscopes: - if unicode(sub.name.names[-1]) == '__init__': + if unicode(sub.name) == '__init__': return '%s\n\n%s' % ( - sub.get_call_signature(funcname=self.name.names[-1]), docstr) + sub.get_call_signature(funcname=self.name), docstr) return docstr def scope_names_generator(self, position=None): @@ -596,7 +596,7 @@ class Function(Scope): :rtype: str """ - l = unicode(funcname or self.name.names[-1]) + '(' + l = unicode(funcname or self.name) + '(' lines = [] for (i, p) in enumerate(self.params): code = p.get_code(False) @@ -780,15 +780,16 @@ class Import(Simple): :type defunct: bool """ def __init__(self, module, start_pos, end_pos, namespace_names, alias=None, - from_names=None, star=False, relative_count=0, defunct=False): + from_names=(), star=False, relative_count=0, defunct=False): super(Import, self).__init__(module, start_pos, end_pos) self.namespace_names = namespace_names self.alias = alias + if self.alias: + alias.parent = self self.from_names = from_names - for n in namespace_names, alias, from_names: - if n: - n.parent = self.use_as_parent + for n in namespace_names + list(from_names): + n.parent = self.use_as_parent self.star = star self.relative_count = relative_count @@ -841,7 +842,7 @@ class Import(Simple): TODO refactor and dont use this method, because NamePart will not exist in the future. """ - return self.alias.names[0] if self.alias else None + return self.alias def is_nested(self): """ @@ -850,8 +851,8 @@ class Import(Simple): import foo.bar """ - return not self.alias and not self.from_names and self.namespace is not None \ - and len(self.namespace.names) > 1 + return not self.alias and not self.from_names \ + and len(self.namespace_names) > 1 class KeywordStatement(Base): @@ -1193,7 +1194,7 @@ class Statement(Simple, DocstringMixin): continue is_literal = token_type in (tokenize.STRING, tokenize.NUMBER) - if isinstance(tok_str, Name) or is_literal: + if is_literal or isinstance(tok, NamePart): cls = Literal if is_literal else Call call = cls(self._sub_module, tok_str, tok.start_pos, tok.end_pos, self) @@ -1311,8 +1312,7 @@ class StatementElement(Simple): def generate_call_path(self): """ Helps to get the order in which statements are executed. """ try: - for name_part in self.name.names: - yield name_part + yield self.name except AttributeError: yield self if self.next is not None: