[py-svn] r7202 - in py/dist/py: magic path path/test

arigo at codespeak.net arigo at codespeak.net
Tue Nov 9 17:57:57 CET 2004


Author: arigo
Date: Tue Nov  9 17:57:56 2004
New Revision: 7202

Modified:
   py/dist/py/magic/autopath.py
   py/dist/py/path/common.py
   py/dist/py/path/test/fscommon.py
Log:
The getpymodule() logic discussed on py-dev, with tests.


Modified: py/dist/py/magic/autopath.py
==============================================================================
--- py/dist/py/magic/autopath.py	(original)
+++ py/dist/py/magic/autopath.py	Tue Nov  9 17:57:56 2004
@@ -1,5 +1,6 @@
 import os, sys
-from py.path import local 
+from py.path import local
+from py.__impl__.path.common import PathStr
 
 def autopath(globs=None, basefile='__init__.py'):
     """ return the (local) path of the "current" file pointed to by globals 
@@ -19,9 +20,13 @@
             raise ValueError, "cannot compute autopath in interactive mode"
         __file__ = os.path.abspath(sys.argv[0]) 
 
-    ret = local(__file__) 
-    if ret.ext in ('.pyc', '.pyo'):
-        ret = ret.new(ext='.py')
+    custom__file__ = isinstance(__file__, PathStr)
+    if custom__file__:
+        ret = __file__.__path__
+    else:
+        ret = local(__file__) 
+        if ret.ext in ('.pyc', '.pyo'):
+            ret = ret.new(ext='.py')
     current = pkgdir = ret.dirpath()
     while 1: 
         if basefile in current:
@@ -29,7 +34,7 @@
             current = current.dirpath()
             if pkgdir != current:
                 continue
-        elif str(current) not in sys.path:
+        elif not custom__file__ and str(current) not in sys.path:
             sys.path.insert(0, str(current))
         break 
     ret.pkgdir = pkgdir 

Modified: py/dist/py/path/common.py
==============================================================================
--- py/dist/py/path/common.py	(original)
+++ py/dist/py/path/common.py	Tue Nov  9 17:57:56 2004
@@ -292,8 +292,7 @@
         except KeyError:
             co = self.getpycodeobj()
             mod = py.std.new.module(modname)
-            mod.__file__ = str(self)
-            #mod.__path__ = [str(self.get('dirname'))]
+            mod.__file__ = PathStr(self)
             sys.modules[modname] = mod
             exec co in mod.__dict__
             return mod
@@ -303,3 +302,64 @@
         # XXX str(self) should show up somewhere in the code's filename
         return py.magic.dyncode.compile2(s)
 
+
+class PathStr(str):
+    def __init__(self, path):
+        global old_import_hook
+        self.__path__ = path
+        if old_import_hook is None:
+            import __builtin__
+            old_import_hook = __builtin__.__import__
+            __builtin__.__import__ = custom_import_hook
+
+def relativeimport(p, name, parent=None):
+    names = name.split('.')
+    last_list = [False] * (len(names)-1) + [True]
+    modules = []
+    for name, is_last in zip(names, last_list):
+        if hasattr(parent, name):
+            # shortcut if there is already the correct name
+            # in the parent package
+            submodule = getattr(parent, name)
+        else:
+            if is_last and p.new(basename=name+'.py').check():
+                p = p.new(basename=name+'.py')
+            else:
+                p = p.new(basename=name).join('__init__.py')
+                if not p.check():
+                    return None   # not found
+            submodule = p.getpymodule()
+            if parent is not None:
+                setattr(parent, name, submodule)
+        modules.append(submodule)
+        parent = submodule
+    return modules   # success
+
+
+old_import_hook = None
+
+def custom_import_hook(name, glob=None, loc=None, fromlist=None):
+    __file__ = glob and glob.get('__file__')
+    if isinstance(__file__, PathStr):
+        # try to perform a relative import
+        # for cooperation with py.magic.autopath, first look in the pkgdir
+        modules = None
+        if hasattr(__file__.__path__, 'pkgdir'):
+            modules = relativeimport(__file__.__path__.pkgdir, name)
+        if not modules:
+            modules = relativeimport(__file__.__path__, name)
+        if modules:
+            if fromlist:
+                submodule = modules[-1]  # innermost submodule
+                # try to import submodules named in the 'fromlist' if the
+                # 'submodule' is a package
+                p = submodule.__file__.__path__
+                if p.check(basename='__init__.py'):
+                    for name in fromlist:
+                        relativeimport(p, name, parent=submodule)
+                        # failures are fine
+                return submodule
+            else:
+                return modules[0]   # outermost package
+    # fall-back
+    return old_import_hook(name, glob, loc, fromlist)

Modified: py/dist/py/path/test/fscommon.py
==============================================================================
--- py/dist/py/path/test/fscommon.py	(original)
+++ py/dist/py/path/test/fscommon.py	Tue Nov  9 17:57:56 2004
@@ -22,6 +22,21 @@
     otherdir = path.ensure('otherdir', dir=1)
     otherdir.ensure('__init__.py')
 
+    module_a = otherdir.ensure('a.py')
+    module_a.write('from b import stuff as result\n')
+    module_b = otherdir.ensure('b.py')
+    module_b.write('stuff="got it"\n')
+    module_c = otherdir.ensure('c.py')
+    module_c.write('''import py; py.magic.autopath()
+import otherdir.a
+value = otherdir.a.result
+''')
+    module_d = otherdir.ensure('d.py')
+    module_d.write('''import py; py.magic.autopath()
+from otherdir import a
+value2 = a.result
+''')
+
 class CommonFSTests(common.CommonPathTests):
     root = None  # subclasses have to provide a current 'root' attribute 
 
@@ -193,3 +208,22 @@
         # py.path.extpy
         assert not hasattr(self.root, 'resolve')
 
+    def test_getpymodule_a(self):
+        otherdir = self.root.join('otherdir')
+        mod = otherdir.join('a.py').getpymodule()
+        assert mod.result == "got it"
+
+    def test_getpymodule_b(self):
+        otherdir = self.root.join('otherdir')
+        mod = otherdir.join('b.py').getpymodule()
+        assert mod.stuff == "got it"
+
+    def test_getpymodule_c(self):
+        otherdir = self.root.join('otherdir')
+        mod = otherdir.join('c.py').getpymodule()
+        assert mod.value == "got it"
+
+    def test_getpymodule_d(self):
+        otherdir = self.root.join('otherdir')
+        mod = otherdir.join('d.py').getpymodule()
+        assert mod.value2 == "got it"



More information about the pytest-commit mailing list