Use the cwd when the empty string is found in sys.path. This leads to
authorBrett Cannon <brett@python.org>
Wed, 8 Feb 2012 23:52:56 +0000 (18:52 -0500)
committerBrett Cannon <brett@python.org>
Wed, 8 Feb 2012 23:52:56 +0000 (18:52 -0500)
__file__ being an absolute path when the module is found in the
current directory.

Lib/importlib/_bootstrap.py
Lib/importlib/test/import_/test_path.py
Misc/NEWS

index e5a9580a3b08da5d02f537650b8e796bf5cde524..25692847d68260c5dcbf4b56deea7234d1656a8a 100644 (file)
@@ -718,7 +718,7 @@ class PathFinder:
         try:
             finder = sys.path_importer_cache[path]
         except KeyError:
-            finder = cls._path_hooks(path)
+            finder = cls._path_hooks(path if path != '' else _os.getcwd())
             sys.path_importer_cache[path] = finder
         else:
             if finder is None and default:
@@ -1039,3 +1039,47 @@ def _setup(sys_module, imp_module):
     setattr(self_module, '_os', os_module)
     setattr(self_module, 'path_sep', path_sep)
 
+
+
+def _setup(sys_module, imp_module):
+    """Setup importlib by importing needed built-in modules and injecting them
+    into the global namespace.
+
+    As sys is needed for sys.modules access and imp is needed to load built-in
+    modules those two modules must be explicitly passed in.
+
+    """
+    global imp, sys
+    imp = imp_module
+    sys = sys_module
+
+    for module in (imp, sys):
+        if not hasattr(module, '__loader__'):
+            module.__loader__ = BuiltinImporter
+
+    self_module = sys.modules[__name__]
+    for builtin_name in ('_io', '_warnings', 'builtins', 'marshal'):
+        if builtin_name not in sys.modules:
+            builtin_module = BuiltinImporter.load_module(builtin_name)
+        else:
+            builtin_module = sys.modules[builtin_name]
+        setattr(self_module, builtin_name, builtin_module)
+
+    for builtin_os, path_sep in [('posix', '/'), ('nt', '\\'), ('os2', '\\')]:
+        if builtin_os in sys.modules:
+            os_module = sys.modules[builtin_os]
+            break
+        else:
+            try:
+                os_module = BuiltinImporter.load_module(builtin_os)
+                # TODO: rip out os2 code after 3.3 is released as per PEP 11
+                if builtin_os == 'os2' and 'EMX GCC' in sys.version:
+                    path_sep = '/'
+                break
+            except ImportError:
+                continue
+    else:
+        raise ImportError('importlib requires posix or nt')
+    setattr(self_module, '_os', os_module)
+    setattr(self_module, 'path_sep', path_sep)
+
index 2faa23174b334e75bfd807d9fdcdd616ad4fd9ac..b28f25df869e8a5d6d66874ff9d1e61749caefd3 100644 (file)
@@ -73,6 +73,16 @@ class FinderTests(unittest.TestCase):
             loader = machinery.PathFinder.find_module(module)
             self.assertTrue(loader is importer)
 
+    def test_path_importer_cache_empty_string(self):
+        # The empty string should create a finder using the cwd.
+        path = ''
+        module = '<test module>'
+        importer = util.mock_modules(module)
+        hook = import_util.mock_path_hook(os.getcwd(), importer=importer)
+        with util.import_state(path=[path], path_hooks=[hook]):
+            loader = machinery.PathFinder.find_module(module)
+            self.assertIs(loader, importer)
+            self.assertIn('', sys.path_importer_cache)
 
 
 class DefaultPathFinderTests(unittest.TestCase):
index 55940e564107dfb4a2a20f24313ed1521da96e8c..6ec3df8e0218216b1c84f331146be7060e8c31bc 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -466,6 +466,9 @@ Core and Builtins
 Library
 -------
 
+- When '' is a path (e.g. in sys.path), make sure __file__ uses the current
+  working directory instead of ''.
+
 - Issue #13609: Add two functions to query the terminal size:
   os.get_terminal_size (low level) and shutil.get_terminal_size (high level).
   Patch by Zbigniew Jędrzejewski-Szmek.