Add absolute import detection

This commit is contained in:
Laurens Van Houtven
2013-06-21 17:02:17 +02:00
parent fd87e8af2a
commit 5701ac1a10
3 changed files with 59 additions and 0 deletions

View File

@@ -294,6 +294,27 @@ class Scope(Simple, IsScope):
if p: if p:
return p return p
@property
def absolute_imports(self):
"""
Checks if imports in this scope are absolute.
In Python 3, this is always true. In Python 2, this is true if there
is a ``absolute_import`` ``__future__`` import.
The result of this property is cached; the first time it is called on
Python 2 will cause it to walk through all the imports in the parse
tree.
"""
if self._absolute_imports is not None:
return self._absolute_imports
has_import = any(_enables_absolute_import(i) for i in self.imports)
self._absolute_imports = has_import
return has_import
_absolute_imports = True if is_py3k else None
def __repr__(self): def __repr__(self):
try: try:
name = self.path name = self.path
@@ -306,6 +327,13 @@ class Scope(Simple, IsScope):
return "<%s: %s@%s-%s>" % (type(self).__name__, name, return "<%s: %s@%s-%s>" % (type(self).__name__, name,
self.start_pos[0], self.end_pos[0]) self.start_pos[0], self.end_pos[0])
def _enables_absolute_import(imp):
"""
Checks if the import is a ``__future__`` import that enables the
``absolute_import`` feature.
"""
namespace, feature = imp.from_ns.names[0], imp.namespace.names[0]
return namespace == "__future__" and feature == "absolute_import"
class Module(IsScope): class Module(IsScope):
""" For isinstance checks. fast_parser.Module also inherits from this. """ """ For isinstance checks. fast_parser.Module also inherits from this. """

View File

@@ -6,6 +6,7 @@ else:
import os import os
from os.path import abspath, dirname from os.path import abspath, dirname
import functools import functools
import pytest
import jedi import jedi
@@ -60,3 +61,6 @@ def cwd_at(path):
os.chdir(oldcwd) os.chdir(oldcwd)
return wrapper return wrapper
return decorator return decorator
py3_only = pytest.mark.skipif("not is_py3k")
py2_only = pytest.mark.skipif("is_py3k")

View File

@@ -0,0 +1,27 @@
from jedi.parsing import Parser
from jedi._compatibility import is_py3k; is_py3k # shut up pyflakes
from . import base
@base.py3_only
def test_py3k_imports_are_always_absolute():
"""
By default, imports in Python 3 are absolute.
"""
parser = Parser("1", "test.py")
assert parser.scope.absolute_imports
@base.py2_only
def test_py2_imports_are_not_always_absolute():
"""
By default, imports in Python 2 are not absolute.
"""
parser = Parser("1", "test.py")
assert not parser.scope.absolute_imports
def test_imports_are_absolute_in_modules_with_future_import():
"""
In any module with the ``absolute_import`` ``__future__`` import, all
imports are absolute.
"""
parser = Parser("from __future__ import absolute_import", "test.py")
assert parser.scope.absolute_imports