Commit 13914715 authored by Dylan Trotter's avatar Dylan Trotter Committed by Dylan Trotter

Implement absolute_import.

parent c6c46bd7
...@@ -34,7 +34,7 @@ _NATIVE_MODULE_PREFIX = '__go__.' ...@@ -34,7 +34,7 @@ _NATIVE_MODULE_PREFIX = '__go__.'
class Path(object): class Path(object):
"""Resolves imported modules based on a search path of directories.""" """Resolves imported modules based on a search path of directories."""
def __init__(self, gopath, modname, script): def __init__(self, gopath, modname, script, absolute_import):
self.dirs = [] self.dirs = []
if gopath: if gopath:
self.dirs.extend(os.path.join(d, 'src', '__python__') self.dirs.extend(os.path.join(d, 'src', '__python__')
...@@ -50,6 +50,7 @@ class Path(object): ...@@ -50,6 +50,7 @@ class Path(object):
else: else:
self.package_dir = None self.package_dir = None
self.package_name = None self.package_name = None
self.absolute_import = absolute_import
def resolve_import(self, modname): def resolve_import(self, modname):
"""Find module on the path returning full module name and script path. """Find module on the path returning full module name and script path.
...@@ -61,7 +62,7 @@ class Path(object): ...@@ -61,7 +62,7 @@ class Path(object):
A pair (full_name, script), where full_name is the absolute module name A pair (full_name, script), where full_name is the absolute module name
and script is the filename of the associate .py file. and script is the filename of the associate .py file.
""" """
if self.package_dir: if not self.absolute_import and self.package_dir:
script = self._find_script(self.package_dir, modname) script = self._find_script(self.package_dir, modname)
if script: if script:
return '{}.{}'.format(self.package_name, modname), script return '{}.{}'.format(self.package_name, modname), script
...@@ -178,7 +179,7 @@ _FUTURE_FEATURES = ( ...@@ -178,7 +179,7 @@ _FUTURE_FEATURES = (
'unicode_literals', 'unicode_literals',
) )
_IMPLEMENTED_FUTURE_FEATURES = ('print_function',) _IMPLEMENTED_FUTURE_FEATURES = ('absolute_import', 'print_function',)
# These future features are already in the language proper as of 2.6, so # These future features are already in the language proper as of 2.6, so
# importing them via __future__ has no effect. # importing them via __future__ has no effect.
...@@ -188,8 +189,10 @@ _REDUNDANT_FUTURE_FEATURES = ('generators', 'with_statement', 'nested_scopes') ...@@ -188,8 +189,10 @@ _REDUNDANT_FUTURE_FEATURES = ('generators', 'with_statement', 'nested_scopes')
class FutureFeatures(object): class FutureFeatures(object):
def __init__(self): def __init__(self):
for name in _FUTURE_FEATURES: self.absolute_import = False
setattr(self, name, False) self.division = False
self.print_function = False
self.unicode_literals = False
def _make_future_features(node): def _make_future_features(node):
......
...@@ -72,18 +72,18 @@ class _MaterializedPathTree(object): ...@@ -72,18 +72,18 @@ class _MaterializedPathTree(object):
class PathTest(unittest.TestCase): class PathTest(unittest.TestCase):
def testResolveImportEmptyPath(self): def testResolveImportEmptyPath(self):
path = imputil.Path(None, 'foo', 'foo.py') path = imputil.Path(None, 'foo', 'foo.py', False)
self.assertEqual(path.resolve_import('bar'), (None, None)) self.assertEqual(path.resolve_import('bar'), (None, None))
def testResolveImportTopLevelModule(self): def testResolveImportTopLevelModule(self):
with _MaterializedPathTree({'bar.py': None}) as tree: with _MaterializedPathTree({'bar.py': None}) as tree:
path = imputil.Path(tree.rootdir, 'foo', 'foo.py') path = imputil.Path(tree.rootdir, 'foo', 'foo.py', False)
want = ('bar', os.path.join(tree.pydir, 'bar.py')) want = ('bar', os.path.join(tree.pydir, 'bar.py'))
self.assertEqual(path.resolve_import('bar'), want) self.assertEqual(path.resolve_import('bar'), want)
def testResolveImportTopLevelPackage(self): def testResolveImportTopLevelPackage(self):
with _MaterializedPathTree({'bar/': {'__init__.py': None}}) as tree: with _MaterializedPathTree({'bar/': {'__init__.py': None}}) as tree:
path = imputil.Path(tree.rootdir, 'foo', 'foo.py') path = imputil.Path(tree.rootdir, 'foo', 'foo.py', False)
want = ('bar', os.path.join(tree.pydir, 'bar', '__init__.py')) want = ('bar', os.path.join(tree.pydir, 'bar', '__init__.py'))
self.assertEqual(path.resolve_import('bar'), want) self.assertEqual(path.resolve_import('bar'), want)
...@@ -95,7 +95,7 @@ class PathTest(unittest.TestCase): ...@@ -95,7 +95,7 @@ class PathTest(unittest.TestCase):
} }
} }
with _MaterializedPathTree(spec) as tree: with _MaterializedPathTree(spec) as tree:
path = imputil.Path(tree.rootdir, 'foo', 'foo.py') path = imputil.Path(tree.rootdir, 'foo', 'foo.py', False)
want = ('bar.baz', os.path.join(tree.pydir, 'bar', 'baz.py')) want = ('bar.baz', os.path.join(tree.pydir, 'bar', 'baz.py'))
self.assertEqual(path.resolve_import('bar.baz'), want) self.assertEqual(path.resolve_import('bar.baz'), want)
...@@ -104,14 +104,29 @@ class PathTest(unittest.TestCase): ...@@ -104,14 +104,29 @@ class PathTest(unittest.TestCase):
'bar/': { 'bar/': {
'__init__.py': None, '__init__.py': None,
'baz.py': None, 'baz.py': None,
} },
'baz.py': None,
} }
with _MaterializedPathTree(spec) as tree: with _MaterializedPathTree(spec) as tree:
bar_script = os.path.join(tree.pydir, 'bar', '__init__.py') bar_script = os.path.join(tree.pydir, 'bar', '__init__.py')
path = imputil.Path(tree.rootdir, 'bar', bar_script) path = imputil.Path(tree.rootdir, 'bar', bar_script, False)
want = ('bar.baz', os.path.join(tree.pydir, 'bar', 'baz.py')) want = ('bar.baz', os.path.join(tree.pydir, 'bar', 'baz.py'))
self.assertEqual(path.resolve_import('baz'), want) self.assertEqual(path.resolve_import('baz'), want)
def testResolveImportPackageModuleAbsoluteImport(self):
spec = {
'bar/': {
'__init__.py': None,
'baz.py': None,
},
'baz.py': None,
}
with _MaterializedPathTree(spec) as tree:
bar_script = os.path.join(tree.pydir, 'bar', '__init__.py')
path = imputil.Path(tree.rootdir, 'bar', bar_script, True)
want = ('baz', os.path.join(tree.pydir, 'baz.py'))
self.assertEqual(path.resolve_import('baz'), want)
def testResolveImportPackageModuleRelativeFromSubModule(self): def testResolveImportPackageModuleRelativeFromSubModule(self):
spec = { spec = {
'bar/': { 'bar/': {
...@@ -122,7 +137,7 @@ class PathTest(unittest.TestCase): ...@@ -122,7 +137,7 @@ class PathTest(unittest.TestCase):
} }
with _MaterializedPathTree(spec) as tree: with _MaterializedPathTree(spec) as tree:
foo_script = os.path.join(tree.pydir, 'bar', 'foo.py') foo_script = os.path.join(tree.pydir, 'bar', 'foo.py')
path = imputil.Path(tree.rootdir, 'bar.foo', foo_script) path = imputil.Path(tree.rootdir, 'bar.foo', foo_script, False)
want = ('bar.baz', os.path.join(tree.pydir, 'bar', 'baz.py')) want = ('bar.baz', os.path.join(tree.pydir, 'bar', 'baz.py'))
self.assertEqual(path.resolve_import('baz'), want) self.assertEqual(path.resolve_import('baz'), want)
...@@ -278,8 +293,9 @@ class MakeFutureFeaturesTest(unittest.TestCase): ...@@ -278,8 +293,9 @@ class MakeFutureFeaturesTest(unittest.TestCase):
class ParseFutureFeaturesTest(unittest.TestCase): class ParseFutureFeaturesTest(unittest.TestCase):
def testFutureFeatures(self): def testFutureFeatures(self):
print_function_features = imputil.FutureFeatures() print_function_features = {'print_function': True}
print_function_features.print_function = True absolute_import_features = {'absolute_import': True}
all_features = {'print_function': True, 'absolute_import': True}
testcases = [ testcases = [
('from __future__ import print_function', ('from __future__ import print_function',
print_function_features), print_function_features),
...@@ -294,13 +310,17 @@ class ParseFutureFeaturesTest(unittest.TestCase): ...@@ -294,13 +310,17 @@ class ParseFutureFeaturesTest(unittest.TestCase):
from __future__ import print_function, with_statement from __future__ import print_function, with_statement
from __future__ import nested_scopes from __future__ import nested_scopes
""", print_function_features), """, print_function_features),
('from __future__ import absolute_import',
absolute_import_features),
('from __future__ import absolute_import, print_function',
all_features),
] ]
for tc in testcases: for tc in testcases:
source, want = tc source, want = tc
mod = pythonparser.parse(textwrap.dedent(source)) mod = pythonparser.parse(textwrap.dedent(source))
_, got = imputil.parse_future_features(mod) _, got = imputil.parse_future_features(mod)
self.assertEqual(want.__dict__, got.__dict__) self.assertEqual(want, got.__dict__)
def testFutureAfterAssignRaises(self): def testFutureAfterAssignRaises(self):
source = 'foo = 123\nfrom __future__ import print_function' source = 'foo = 123\nfrom __future__ import print_function'
......
...@@ -64,7 +64,8 @@ def main(args): ...@@ -64,7 +64,8 @@ def main(args):
print >> sys.stderr, str(e) print >> sys.stderr, str(e)
return 2 return 2
path = imputil.Path(gopath, args.modname, args.script) path = imputil.Path(gopath, args.modname, args.script,
future_features.absolute_import)
full_package_name = args.modname.replace('.', '/') full_package_name = args.modname.replace('.', '/')
mod_block = block.ModuleBlock(path, full_package_name, args.script, mod_block = block.ModuleBlock(path, full_package_name, args.script,
py_contents, future_features) py_contents, future_features)
......
...@@ -36,7 +36,6 @@ def main(args): ...@@ -36,7 +36,6 @@ def main(args):
if not gopath: if not gopath:
print >> sys.stderr, 'GOPATH not set' print >> sys.stderr, 'GOPATH not set'
return 1 return 1
path = imputil.Path(gopath, args.modname, args.script)
with open(args.script) as py_file: with open(args.script) as py_file:
py_contents = py_file.read() py_contents = py_file.read()
...@@ -48,11 +47,13 @@ def main(args): ...@@ -48,11 +47,13 @@ def main(args):
return 2 return 2
try: try:
future_node, _ = imputil.parse_future_features(mod) future_node, future_features = imputil.parse_future_features(mod)
except util.CompileError as e: except util.CompileError as e:
print >> sys.stderr, str(e) print >> sys.stderr, str(e)
return 2 return 2
path = imputil.Path(gopath, args.modname, args.script,
future_features.absolute_import)
visitor = imputil.ImportVisitor(path, future_node) visitor = imputil.ImportVisitor(path, future_node)
try: try:
visitor.visit(mod) visitor.visit(mod)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment