From 07ba6658dd3ecd539f344ad5cc7ad17c53ab5eb0 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Sat, 16 Mar 2013 20:37:12 +0100 Subject: [PATCH 1/3] Add test_no_duplicate_modules --- test/test_regression.py | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/test/test_regression.py b/test/test_regression.py index d71dec1a..201ca063 100755 --- a/test/test_regression.py +++ b/test/test_regression.py @@ -537,5 +537,41 @@ def test_settings_module(): assert cache.settings is settings +def test_no_duplicate_modules(): + """ + Make sure that import hack works as expected. + + Jedi does an import hack (see: jedi/__init__.py) to have submodules + with circular dependencies. The modules in this circular dependency + "loop" must be imported by ``import `` rather than normal + ``from jedi import `` (or ``from . jedi ...``). This test + make sure that this is satisfied. + + See also: + + - `#160 `_ + - `#161 `_ + """ + import sys + jedipath = os.path.dirname(os.path.abspath(jedi.__file__)) + + def is_submodule(m): + try: + filepath = m.__file__ + except AttributeError: + return False + return os.path.abspath(filepath).startswith(jedipath) + + modules = list(filter(is_submodule, sys.modules.values())) + top_modules = [m for m in modules if not m.__name__.startswith('jedi.')] + for m in modules: + for tm in top_modules: + try: + imported = getattr(m, tm.__name__) + except AttributeError: + continue + assert imported is tm + + if __name__ == '__main__': unittest.main() From f5fee5f0df1b7f869efe10cf95e138aae5dd1e46 Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Sat, 16 Mar 2013 21:03:34 +0100 Subject: [PATCH 2/3] Fix wrong imports - "from _compatibility import ..." (not in circular imports) - "from jedi import builtin" (one of circular imports) - "api_classes = api.api_classes" ("from jedi import api_classes" is not supported) --- jedi/evaluate.py | 2 +- jedi/evaluate_representation.py | 2 +- jedi/keywords.py | 2 +- jedi/modules.py | 3 +-- jedi/parsing.py | 2 +- test/test_regression.py | 2 +- 6 files changed, 6 insertions(+), 7 deletions(-) diff --git a/jedi/evaluate.py b/jedi/evaluate.py index 551852d7..c76bbb27 100644 --- a/jedi/evaluate.py +++ b/jedi/evaluate.py @@ -68,11 +68,11 @@ backtracking algorithm. .. todo:: nonlocal statement, needed or can be ignored? (py3k) """ -from _compatibility import next, hasattr, is_py3k, unicode, reraise import sys import itertools +from jedi._compatibility import next, hasattr, is_py3k, unicode, reraise from jedi import common from jedi import cache from jedi import parsing_representation as pr diff --git a/jedi/evaluate_representation.py b/jedi/evaluate_representation.py index 99fded99..f5c6e991 100644 --- a/jedi/evaluate_representation.py +++ b/jedi/evaluate_representation.py @@ -12,7 +12,7 @@ they change classes in Python 3. import copy import itertools -from _compatibility import property, use_metaclass, next, hasattr +from jedi._compatibility import property, use_metaclass, next, hasattr from jedi import parsing_representation as pr from jedi import cache from jedi import helpers diff --git a/jedi/keywords.py b/jedi/keywords.py index 07461bb7..5495ae32 100644 --- a/jedi/keywords.py +++ b/jedi/keywords.py @@ -2,7 +2,7 @@ import pydoc import keyword from jedi._compatibility import is_py3k -from jedi import builtin +import builtin try: from pydoc_data import topics as pydoc_topics diff --git a/jedi/modules.py b/jedi/modules.py index b6c8f1e8..9277e742 100644 --- a/jedi/modules.py +++ b/jedi/modules.py @@ -15,13 +15,12 @@ Apart from those classes there's a ``sys.path`` fetching function, as well as """ from __future__ import with_statement -from _compatibility import exec_function, unicode, is_py25, literal_eval - import re import tokenize import sys import os +from jedi._compatibility import exec_function, unicode, is_py25, literal_eval from jedi import cache from jedi import parsing from jedi import parsing_representation as pr diff --git a/jedi/parsing.py b/jedi/parsing.py index 17ca7d49..69607fec 100644 --- a/jedi/parsing.py +++ b/jedi/parsing.py @@ -15,11 +15,11 @@ within the statement. This lowers memory usage and cpu time and reduces the complexity of the ``Parser`` (there's another parser sitting inside ``Statement``, which produces ``Array`` and ``Call``). """ -from _compatibility import next, StringIO import tokenize import keyword +from jedi._compatibility import next, StringIO from jedi import debug from jedi import common from jedi import parsing_representation as pr diff --git a/test/test_regression.py b/test/test_regression.py index 201ca063..8c8209dc 100755 --- a/test/test_regression.py +++ b/test/test_regression.py @@ -18,7 +18,7 @@ from .base import TestBase, unittest, cwd_at import jedi from jedi._compatibility import is_py25, utf8, unicode from jedi import api -from jedi import api_classes +api_classes = api.api_classes #jedi.set_debug_function(jedi.debug.print_to_stdout) From febc65be6fa144723261a08d3d864abf47cc15fd Mon Sep 17 00:00:00 2001 From: Takafumi Arakaki Date: Sat, 16 Mar 2013 21:07:02 +0100 Subject: [PATCH 3/3] Skip test_no_duplicate_modules for jedi.__init__ --- test/test_regression.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/test_regression.py b/test/test_regression.py index 8c8209dc..e6027c9f 100755 --- a/test/test_regression.py +++ b/test/test_regression.py @@ -565,6 +565,10 @@ def test_no_duplicate_modules(): modules = list(filter(is_submodule, sys.modules.values())) top_modules = [m for m in modules if not m.__name__.startswith('jedi.')] for m in modules: + if m is jedi: + # py.test automatically improts `jedi.*` when --doctest-modules + # is given. So this test cannot succeeds. + continue for tm in top_modules: try: imported = getattr(m, tm.__name__)