[Python-checkins] r51982 - in python/branches/theller_modulefinder/Lib: modulefinder.py test/test_modulefinder.py
thomas.heller
python-checkins at python.org
Fri Sep 22 16:41:31 CEST 2006
Author: thomas.heller
Date: Fri Sep 22 16:41:30 2006
New Revision: 51982
Modified:
python/branches/theller_modulefinder/Lib/modulefinder.py
python/branches/theller_modulefinder/Lib/test/test_modulefinder.py
Log:
Partial progress with relative imports.
'from ...x import y' seems to work, 'from ... import z' does not.
Modified: python/branches/theller_modulefinder/Lib/modulefinder.py
==============================================================================
--- python/branches/theller_modulefinder/Lib/modulefinder.py (original)
+++ python/branches/theller_modulefinder/Lib/modulefinder.py Fri Sep 22 16:41:30 2006
@@ -122,10 +122,7 @@
def import_hook(self, name, caller=None, fromlist=None, level=-1):
self.msg(3, "import_hook", name, caller, fromlist, level)
- if level == 0: # absolute import
- parent = None
- else:
- parent = self.determine_parent(caller)
+ parent = self.determine_parent(caller, level=level)
q, tail = self.find_head_package(parent, name)
m = self.load_tail(q, tail)
if not fromlist:
@@ -134,12 +131,21 @@
self.ensure_fromlist(m, fromlist)
return None
- def determine_parent(self, caller):
- self.msgin(4, "determine_parent", caller)
- if not caller:
+ def determine_parent(self, caller, level=-1):
+ self.msgin(4, "determine_parent", caller, level)
+ if not caller or level == 0:
self.msgout(4, "determine_parent -> None")
return None
pname = caller.__name__
+ if level >= 1:
+ if caller.__path__:
+ level -= 1
+ if pname.count(".") < level:
+ raise ImportError, "relative importpath too deep"
+ pname = ".".join(pname.split(".")[:-level])
+ parent = self.modules[pname]
+ self.msgout(4, "determine_parent ->", parent)
+ return parent
if caller.__path__:
parent = self.modules[pname]
assert caller is parent
@@ -325,6 +331,7 @@
def scan_opcodes(self, co,
unpack = struct.unpack):
# Scan the code, and yield 'interesting' opcode combinations
+ # Version for Python 2.4 and older
code = co.co_code
names = co.co_names
consts = co.co_consts
@@ -348,6 +355,7 @@
def scan_opcodes_25(self, co,
unpack = struct.unpack):
# Scan the code, and yield 'interesting' opcode combinations
+ # Python 2.5 version (has absolute and relative imports)
code = co.co_code
names = co.co_names
consts = co.co_consts
@@ -418,7 +426,9 @@
self._safe_import_hook(name, m, fromlist, level=0)
# XXX code missing, see above
elif what == "relative_import":
- raise NotImplementedError("relative import not yet implemented")
+ level, fromlist, name = args
+ # XXX code missing, see above
+ self._safe_import_hook(name, m, fromlist, level=level)
else:
# We don't expect anything else from the generator.
raise RuntimeError(what)
Modified: python/branches/theller_modulefinder/Lib/test/test_modulefinder.py
==============================================================================
--- python/branches/theller_modulefinder/Lib/test/test_modulefinder.py (original)
+++ python/branches/theller_modulefinder/Lib/test/test_modulefinder.py Fri Sep 22 16:41:30 2006
@@ -55,20 +55,20 @@
"a.module",
["a", "a.module",
"b", "b.x", "b.y", "b.z",
- "__future__", "sys", "time"],
+ "__future__", "sys", "exceptions"],
["blahblah"],
"""\
mymodule.py
a/__init__.py
a/module.py
from __future__ import absolute_import
- import sys # this is a.sys
+ import sys # sys
import blahblah # fails
- import time # this is NOT a.time
- import b.x # this is NOT a.b.x
- from b import y
- from b.z import *
-a/time.py
+ import exceptions # exceptions
+ import b.x # b.x
+ from b import y # b.y
+ from b.z import * # b.z.*
+a/exceptions.py
a/sys.py
import mymodule
a/b/__init__.py
@@ -85,33 +85,41 @@
relative_import_test = [
"a.module",
- ["a", "a.module",
- "b", "b.x", "b.y", "b.z",
- "__future__", "sys", "time"],
- ["blahblah"],
+ ["__future__",
+ "a", "a.module",
+ "a.b", "a.b.y", "a.b.z",
+ "a.b.c", "a.b.c.moduleC",
+ "a.b.c.d", "a.b.c.e",
+ "exceptions"],
+ [],
+# The 'from ... import name' constructs stil fail'
"""\
mymodule.py
a/__init__.py
+ ##from . import sys # a.sys
a/module.py
- from __future__ import absolute_import
- import sys # this is a.sys
- import blahblah # fails
- import time # this is NOT a.time
- from . import x # this is a.b.x
+ from __future__ import absolute_import # __future__
+ import exceptions # exceptions
+ #from . import x # a.x
from .b import y, z
-a/time.py
+ #from . import sys # a.sys
+a/exceptions.py
a/sys.py
- import mymodule
a/b/__init__.py
+ #from .c import moduleC
+ from a.b.c import moduleC
a/b/x.py
a/b/y.py
a/b/z.py
-b/__init__.py
- import z
-b/unused.py
-b/x.py
-b/y.py
-b/z.py
+a/b/c/__init__.py
+ from ..c import e # a.b.c.e
+a/b/c/moduleC.py
+ #
+ #from .. import c
+ #from .. import x # a.b.x
+ from ..c import d # a.b.c.d
+a/b/c/d.py
+a/b/c/e.py
"""]
def open_file(path):
@@ -129,13 +137,23 @@
ofi = open_file(os.path.join(TEST_DIR, line.strip()))
class ModuleFinderTest(unittest.TestCase):
- def _do_test(self, info):
+ def _do_test(self, info, report=False):
import_this, modules, missing, source = info
create_package(source)
try:
mf = modulefinder.ModuleFinder(path=TEST_PATH)
mf.import_hook(import_this)
-## mf.report()
+ if report:
+ mf.report()
+
+ opath = sys.path[:]
+ sys.path = TEST_PATH
+ try:
+ __import__(import_this)
+ except:
+ import traceback; traceback.print_exc()
+ sys.path = opath
+
modules = set(modules)
found = set(mf.modules.keys())
more = list(found - modules)
@@ -158,14 +176,7 @@
self._do_test(absolute_import_test)
def test_relative_imports(self):
- import_this, modules, missing, source = relative_import_test
- create_package(source)
- try:
- mf = modulefinder.ModuleFinder(path=TEST_PATH)
- self.assertRaises(NotImplementedError,
- lambda: mf.import_hook(import_this))
- finally:
- distutils.dir_util.remove_tree(TEST_DIR)
+ self._do_test(relative_import_test)
def test_main():
test_support.run_unittest(ModuleFinderTest)
More information about the Python-checkins
mailing list