From 04fba28d35537673c50780332d307b585bfa68f2 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Thu, 25 Jan 2018 20:35:54 +0100 Subject: [PATCH] Differentiate between namespace and module as a type Also fixed a bug related to implicit namespace contexts, fixes #1033. --- jedi/api/classes.py | 6 +++--- jedi/evaluate/context/namespace.py | 6 +++--- jedi/evaluate/imports.py | 2 +- test/test_evaluate/test_implicit_namespace_package.py | 7 +++++-- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/jedi/api/classes.py b/jedi/api/classes.py index 1952f045..f02430e8 100644 --- a/jedi/api/classes.py +++ b/jedi/api/classes.py @@ -153,13 +153,13 @@ class BaseDefinition(object): """The path to a module/class/function definition.""" def to_reverse(): name = self._name - if name.api_type == 'module': + if name.api_type in ('module', 'namespace'): try: name = list(name.infer())[0].name except IndexError: pass - if name.api_type == 'module': + if name.api_type in ('module', 'namespace'): module_contexts = name.infer() if module_contexts: module_context, = module_contexts @@ -521,7 +521,7 @@ class Definition(BaseDefinition): """ typ = self.type tree_name = self._name.tree_name - if typ in ('function', 'class', 'module', 'instance') or tree_name is None: + if typ in ('function', 'class', 'module', 'instance', 'namespace') or tree_name is None: if typ == 'function': # For the description we want a short and a pythonic way. typ = 'def' diff --git a/jedi/evaluate/context/namespace.py b/jedi/evaluate/context/namespace.py index ba615e1b..469ea79e 100644 --- a/jedi/evaluate/context/namespace.py +++ b/jedi/evaluate/context/namespace.py @@ -13,21 +13,21 @@ class ImplicitNSName(AbstractNameDefinition): This object will prevent Jedi from raising exceptions """ def __init__(self, implicit_ns_context, string_name): - self.implicit_ns_context = implicit_ns_context + self.parent_context = implicit_ns_context self.string_name = string_name def infer(self): return NO_CONTEXTS def get_root_context(self): - return self.implicit_ns_context + return self.parent_context class ImplicitNamespaceContext(TreeContext): """ Provides support for implicit namespace packages """ - api_type = u'module' + api_type = u'namespace' parent_context = None def __init__(self, evaluator, fullname, paths): diff --git a/jedi/evaluate/imports.py b/jedi/evaluate/imports.py index 98768a47..9320c0e8 100644 --- a/jedi/evaluate/imports.py +++ b/jedi/evaluate/imports.py @@ -419,7 +419,7 @@ class Importer(object): for context in self.follow(): # Non-modules are not completable. - if context.api_type != 'module': # not a module + if context.api_type not in ('namespace', 'module'): # not a module continue # namespace packages if isinstance(context, ModuleContext) and context.py__file__().endswith('__init__.py'): diff --git a/test/test_evaluate/test_implicit_namespace_package.py b/test/test_evaluate/test_implicit_namespace_package.py index 60f37036..8c17ce09 100644 --- a/test/test_evaluate/test_implicit_namespace_package.py +++ b/test/test_evaluate/test_implicit_namespace_package.py @@ -51,12 +51,15 @@ def test_implicit_nested_namespace_package(Script, environment): if environment.version_info < (3, 4): pytest.skip() - CODE = 'from implicit_nested_namespaces.namespace.pkg.module import CONST' + code = 'from implicit_nested_namespaces.namespace.pkg.module import CONST' sys_path = [dirname(__file__)] - script = Script(sys_path=sys_path, source=CODE, line=1, column=61) + script = Script(sys_path=sys_path, source=code, line=1, column=61) result = script.goto_definitions() assert len(result) == 1 + + implicit_pkg, = Script(code, column=10, sys_path=sys_path).goto_definitions() + assert implicit_pkg.type == 'namespace'