[Python-checkins] cpython (3.3): - Issue #16514: Fix regression causing a traceback when sys.path[0] is None

barry.warsaw python-checkins at python.org
Tue Nov 20 21:35:38 CET 2012


http://hg.python.org/cpython/rev/291406748217
changeset:   80529:291406748217
branch:      3.3
parent:      80527:4537dd27b2dc
user:        Barry Warsaw <barry at python.org>
date:        Tue Nov 20 15:22:51 2012 -0500
summary:
  - Issue #16514: Fix regression causing a traceback when sys.path[0] is None
  (actually, any non-string or non-bytes type).

files:
  Doc/library/sys.rst                          |    4 +-
  Doc/reference/import.rst                     |   24 +-
  Lib/importlib/_bootstrap.py                  |    2 +
  Lib/test/test_importlib/import_/test_path.py |   25 +-
  Misc/NEWS                                    |    3 +
  Python/importlib.h                           |  130 +++++----
  6 files changed, 111 insertions(+), 77 deletions(-)


diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst
--- a/Doc/library/sys.rst
+++ b/Doc/library/sys.rst
@@ -783,7 +783,9 @@
    current directory first.  Notice that the script directory is inserted *before*
    the entries inserted as a result of :envvar:`PYTHONPATH`.
 
-   A program is free to modify this list for its own purposes.
+   A program is free to modify this list for its own purposes.  Only strings
+   and bytes should be added to :data:`sys.path`; all other data types are
+   ignored during import.
 
 
    .. seealso::
diff --git a/Doc/reference/import.rst b/Doc/reference/import.rst
--- a/Doc/reference/import.rst
+++ b/Doc/reference/import.rst
@@ -540,7 +540,10 @@
 implementation-specific defaults.  Entries in :data:`sys.path` can name
 directories on the file system, zip files, and potentially other "locations"
 (see the :mod:`site` module) that should be searched for modules, such as
-URLs, or database queries.
+URLs, or database queries.  Only strings and bytes should be present on
+:data:`sys.path`; all other data types are ignored.  The encoding of bytes
+entries is determined by the individual :term:`path entry finders <path entry
+finder>`.
 
 The :term:`path based finder` is a :term:`meta path finder`, so the import
 machinery begins the :term:`import path` search by calling the path
@@ -563,14 +566,17 @@
 the path based finder to perform the path entry search again [#fnpic]_.
 
 If the path entry is not present in the cache, the path based finder iterates
-over every callable in :data:`sys.path_hooks`.  Each of the
-:term:`path entry hooks <path entry hook>` in this list is called with a
-single argument, the path entry to be searched.  This callable may either
-return a :term:`path entry finder` that can handle the path entry, or it may
-raise :exc:`ImportError`.
-An :exc:`ImportError` is used by the path based finder to signal that the hook
-cannot find a :term:`path entry finder` for that :term:`path entry`.  The
-exception is ignored and :term:`import path` iteration continues.
+over every callable in :data:`sys.path_hooks`.  Each of the :term:`path entry
+hooks <path entry hook>` in this list is called with a single argument, the
+path entry to be searched.  This callable may either return a :term:`path
+entry finder` that can handle the path entry, or it may raise
+:exc:`ImportError`.  An :exc:`ImportError` is used by the path based finder to
+signal that the hook cannot find a :term:`path entry finder` for that
+:term:`path entry`.  The exception is ignored and :term:`import path`
+iteration continues.  The hook should expect either a string or bytes object;
+the encoding of bytes objects is up to the hook (e.g. it may be a file system
+encoding, UTF-8, or something else), and if the hook cannot decode the
+argument, it should raise :exc:`ImportError`.
 
 If :data:`sys.path_hooks` iteration ends with no :term:`path entry finder`
 being returned, then the path based finder's :meth:`find_module()` method
diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py
--- a/Lib/importlib/_bootstrap.py
+++ b/Lib/importlib/_bootstrap.py
@@ -1281,6 +1281,8 @@
         #  the list of paths that will become its __path__
         namespace_path = []
         for entry in path:
+            if not isinstance(entry, (str, bytes)):
+                continue
             finder = cls._path_importer_cache(entry)
             if finder is not None:
                 if hasattr(finder, 'find_loader'):
diff --git a/Lib/test/test_importlib/import_/test_path.py b/Lib/test/test_importlib/import_/test_path.py
--- a/Lib/test/test_importlib/import_/test_path.py
+++ b/Lib/test/test_importlib/import_/test_path.py
@@ -1,15 +1,14 @@
 from importlib import _bootstrap
 from importlib import machinery
+from importlib import import_module
 from .. import util
 from . import util as import_util
-import imp
 import os
 import sys
-import tempfile
-from test import support
-from types import MethodType
+from types import ModuleType
 import unittest
 import warnings
+import zipimport
 
 
 class FinderTests(unittest.TestCase):
@@ -89,6 +88,24 @@
             self.assertIs(loader, importer)
             self.assertIn(os.curdir, sys.path_importer_cache)
 
+    def test_None_on_sys_path(self):
+        # Putting None in sys.path[0] caused an import regression from Python
+        # 3.2: http://bugs.python.org/issue16514
+        new_path = sys.path[:]
+        new_path.insert(0, None)
+        new_path_importer_cache = sys.path_importer_cache.copy()
+        new_path_importer_cache.pop(None, None)
+        new_path_hooks = [zipimport.zipimporter,
+                          _bootstrap.FileFinder.path_hook(
+                              *_bootstrap._get_supported_file_loaders())]
+        with util.uncache('email'):
+            with util.import_state(meta_path=sys.meta_path[:],
+                                   path=new_path,
+                                   path_importer_cache=new_path_importer_cache,
+                                   path_hooks=new_path_hooks):
+                module = import_module('email')
+                self.assertIsInstance(module, ModuleType)
+
 
 def test_main():
     from test.support import run_unittest
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,9 @@
 Core and Builtins
 -----------------
 
+- Issue #16514: Fix regression causing a traceback when sys.path[0] is None
+  (actually, any non-string or non-bytes type).
+
 - Issue #16306: Fix multiple error messages when unknown command line
   parameters where passed to the interpreter.  Patch by Hieu Nguyen.
 
diff --git a/Python/importlib.h b/Python/importlib.h
--- a/Python/importlib.h
+++ b/Python/importlib.h
[stripped]

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list