Merge part of the trunk changes into the p3yk branch. This merges from 43030
(branch-creation time) up to 43067. 43068 and 43069 contain a little
swapping action between re.py and sre.py, and this mightily confuses svn
merge, so later changes are going in separately.

This merge should break no additional tests.

The last-merged revision is going in a 'last_merge' property on '.' (the
branch directory.) Arbitrarily chosen, really; if there's a BCP for this, I
couldn't find it, but we can easily change it afterwards ;)
diff --git a/Lib/runpy.py b/Lib/runpy.py
new file mode 100755
index 0000000..afb0098
--- /dev/null
+++ b/Lib/runpy.py
@@ -0,0 +1,431 @@
+"""runpy.py - locating and running Python code using the module namespace
+
+Provides support for locating and running Python scripts using the Python
+module namespace instead of the native filesystem.
+
+This allows Python code to play nicely with non-filesystem based PEP 302
+importers when locating support scripts as well as when importing modules.
+"""
+# Written by Nick Coghlan <ncoghlan at gmail.com>
+#    to implement PEP 338 (Executing Modules as Scripts)
+
+import sys
+import imp
+
+__all__ = [
+    "run_module",
+]
+
+try:
+    _get_loader = imp.get_loader
+except AttributeError:
+    # get_loader() is not provided by the imp module, so emulate it
+    # as best we can using the PEP 302 import machinery exposed since
+    # Python 2.3. The emulation isn't perfect, but the differences
+    # in the way names are shadowed shouldn't matter in practice.
+    import os.path
+    import marshal                           # Handle compiled Python files
+
+    # This helper is needed in order for the PEP 302 emulation to
+    # correctly handle compiled files
+    def _read_compiled_file(compiled_file):
+        magic = compiled_file.read(4)
+        if magic != imp.get_magic():
+            return None
+        try:
+            compiled_file.read(4) # Skip timestamp
+            return marshal.load(compiled_file)
+        except Exception:
+            return None
+
+    class _AbsoluteImporter(object):
+        """PEP 302 importer wrapper for top level import machinery"""
+        def find_module(self, mod_name, path=None):
+            if path is not None:
+                return None
+            try:
+                file, filename, mod_info = imp.find_module(mod_name)
+            except ImportError:
+                return None
+            suffix, mode, mod_type = mod_info
+            if mod_type == imp.PY_SOURCE:
+                loader = _SourceFileLoader(mod_name, file,
+                                           filename, mod_info)
+            elif mod_type == imp.PY_COMPILED:
+                loader = _CompiledFileLoader(mod_name, file,
+                                             filename, mod_info)
+            elif mod_type == imp.PKG_DIRECTORY:
+                loader = _PackageDirLoader(mod_name, file,
+                                           filename, mod_info)
+            elif mod_type == imp.C_EXTENSION:
+                loader = _FileSystemLoader(mod_name, file,
+                                           filename, mod_info)
+            else:
+                loader = _BasicLoader(mod_name, file,
+                                      filename, mod_info)
+            return loader
+
+
+    class _FileSystemImporter(object):
+        """PEP 302 importer wrapper for filesystem based imports"""
+        def __init__(self, path_item=None):
+            if path_item is not None:
+                if path_item != '' and not os.path.isdir(path_item):
+                    raise ImportError("%s is not a directory" % path_item)
+                self.path_dir = path_item
+            else:
+                raise ImportError("Filesystem importer requires "
+                                  "a directory name")
+
+        def find_module(self, mod_name, path=None):
+            if path is not None:
+                return None
+            path_dir = self.path_dir
+            if path_dir == '':
+                path_dir = os.getcwd()
+            sub_name = mod_name.rsplit(".", 1)[-1]
+            try:
+                file, filename, mod_info = imp.find_module(sub_name,
+                                                           [path_dir])
+            except ImportError:
+                return None
+            if not filename.startswith(path_dir):
+                return None
+            suffix, mode, mod_type = mod_info
+            if mod_type == imp.PY_SOURCE:
+                loader = _SourceFileLoader(mod_name, file,
+                                           filename, mod_info)
+            elif mod_type == imp.PY_COMPILED:
+                loader = _CompiledFileLoader(mod_name, file,
+                                             filename, mod_info)
+            elif mod_type == imp.PKG_DIRECTORY:
+                loader = _PackageDirLoader(mod_name, file,
+                                           filename, mod_info)
+            elif mod_type == imp.C_EXTENSION:
+                loader = _FileSystemLoader(mod_name, file,
+                                           filename, mod_info)
+            else:
+                loader = _BasicLoader(mod_name, file,
+                                      filename, mod_info)
+            return loader
+
+
+    class _BasicLoader(object):
+        """PEP 302 loader wrapper for top level import machinery"""
+        def __init__(self, mod_name, file, filename, mod_info):
+            self.mod_name = mod_name
+            self.file = file
+            self.filename = filename
+            self.mod_info = mod_info
+
+        def _fix_name(self, mod_name):
+            if mod_name is None:
+                mod_name = self.mod_name
+            elif mod_name != self.mod_name:
+                raise ImportError("Loader for module %s cannot handle "
+                                  "module %s" % (self.mod_name, mod_name))
+            return mod_name
+
+        def load_module(self, mod_name=None):
+            mod_name = self._fix_name(mod_name)
+            mod = imp.load_module(mod_name, self.file,
+                                  self.filename, self.mod_info)
+            mod.__loader__ = self  # for introspection
+            return mod
+
+        def get_code(self, mod_name=None):
+            return None
+
+        def get_source(self, mod_name=None):
+            return None
+
+        def is_package(self, mod_name=None):
+            return False
+
+        def close(self):
+            if self.file:
+                self.file.close()
+
+        def __del__(self):
+            self.close()
+
+
+    class _FileSystemLoader(_BasicLoader):
+        """PEP 302 loader wrapper for filesystem based imports"""
+        def get_code(self, mod_name=None):
+            mod_name = self._fix_name(mod_name)
+            return self._get_code(mod_name)
+
+        def get_data(self, pathname):
+            return open(pathname, "rb").read()
+
+        def get_filename(self, mod_name=None):
+            mod_name = self._fix_name(mod_name)
+            return self._get_filename(mod_name)
+
+        def get_source(self, mod_name=None):
+            mod_name = self._fix_name(mod_name)
+            return self._get_source(mod_name)
+
+        def is_package(self, mod_name=None):
+            mod_name = self._fix_name(mod_name)
+            return self._is_package(mod_name)
+
+        def _get_code(self, mod_name):
+            return None
+
+        def _get_filename(self, mod_name):
+            return self.filename
+
+        def _get_source(self, mod_name):
+            return None
+
+        def _is_package(self, mod_name):
+            return False
+
+    class _PackageDirLoader(_FileSystemLoader):
+        """PEP 302 loader wrapper for PKG_DIRECTORY directories"""
+        def _is_package(self, mod_name):
+            return True
+
+
+    class _SourceFileLoader(_FileSystemLoader):
+        """PEP 302 loader wrapper for PY_SOURCE modules"""
+        def _get_code(self, mod_name):
+            return compile(self._get_source(mod_name),
+                           self.filename, 'exec')
+
+        def _get_source(self, mod_name):
+            f = self.file
+            f.seek(0)
+            return f.read()
+
+
+    class _CompiledFileLoader(_FileSystemLoader):
+        """PEP 302 loader wrapper for PY_COMPILED modules"""
+        def _get_code(self, mod_name):
+            f = self.file
+            f.seek(0)
+            return _read_compiled_file(f)
+
+
+    def _get_importer(path_item):
+        """Retrieve a PEP 302 importer for the given path item
+
+        The returned importer is cached in sys.path_importer_cache
+        if it was newly created by a path hook.
+
+        If there is no importer, a wrapper around the basic import
+        machinery is returned. This wrapper is never inserted into
+        the importer cache (None is inserted instead).
+
+        The cache (or part of it) can be cleared manually if a
+        rescan of sys.path_hooks is necessary.
+        """
+        try:
+            importer = sys.path_importer_cache[path_item]
+        except KeyError:
+            for path_hook in sys.path_hooks:
+                try:
+                    importer = path_hook(path_item)
+                    break
+                except ImportError:
+                    pass
+            else:
+                importer = None
+            sys.path_importer_cache[path_item] = importer
+        if importer is None:
+            try:
+                importer = _FileSystemImporter(path_item)
+            except ImportError:
+                pass
+        return importer
+
+
+    def _get_path_loader(mod_name, path=None):
+        """Retrieve a PEP 302 loader using a path importer"""
+        if path is None:
+            path = sys.path
+            absolute_loader = _AbsoluteImporter().find_module(mod_name)
+            if isinstance(absolute_loader, _FileSystemLoader):
+                # Found in filesystem, so scan path hooks
+                # before accepting this one as the right one
+                loader = None
+            else:
+                # Not found in filesystem, so use top-level loader
+                loader = absolute_loader
+        else:
+            loader = absolute_loader = None
+        if loader is None:
+            for path_item in path:
+                importer = _get_importer(path_item)
+                if importer is not None:
+                    loader = importer.find_module(mod_name)
+                    if loader is not None:
+                        # Found a loader for our module
+                        break
+            else:
+                # No path hook found, so accept the top level loader
+                loader = absolute_loader
+        return loader
+
+    def _get_package(pkg_name):
+        """Retrieve a named package"""
+        pkg = __import__(pkg_name)
+        sub_pkg_names = pkg_name.split(".")
+        for sub_pkg in sub_pkg_names[1:]:
+            pkg = getattr(pkg, sub_pkg)
+        return pkg
+
+    def _get_loader(mod_name, path=None):
+        """Retrieve a PEP 302 loader for the given module or package
+
+        If the module or package is accessible via the normal import
+        mechanism, a wrapper around the relevant part of that machinery
+        is returned.
+
+        Non PEP 302 mechanisms (e.g. the Windows registry) used by the
+        standard import machinery to find files in alternative locations
+        are partially supported, but are searched AFTER sys.path. Normally,
+        these locations are searched BEFORE sys.path, preventing sys.path
+        entries from shadowing them.
+        For this to cause a visible difference in behaviour, there must
+        be a module or package name that is accessible via both sys.path
+        and one of the non PEP 302 file system mechanisms. In this case,
+        the emulation will find the former version, while the builtin
+        import mechanism will find the latter.
+        Items of the following types can be affected by this discrepancy:
+            imp.C_EXTENSION
+            imp.PY_SOURCE
+            imp.PY_COMPILED
+            imp.PKG_DIRECTORY
+        """
+        try:
+            loader = sys.modules[mod_name].__loader__
+        except (KeyError, AttributeError):
+            loader = None
+        if loader is None:
+            imp.acquire_lock()
+            try:
+                # Module not in sys.modules, or uses an unhooked loader
+                parts = mod_name.rsplit(".", 1)
+                if len(parts) == 2:
+                    # Sub package, so use parent package's path
+                    pkg_name, sub_name = parts
+                    if pkg_name and pkg_name[0] != '.':
+                        if path is not None:
+                            raise ImportError("Path argument must be None "
+                                            "for a dotted module name")
+                        pkg = _get_package(pkg_name)
+                        try:
+                            path = pkg.__path__
+                        except AttributeError:
+                            raise ImportError(pkg_name +
+                                            " is not a package")
+                    else:
+                        raise ImportError("Relative import syntax is not "
+                                          "supported by _get_loader()")
+                else:
+                    # Top level module, so stick with default path
+                    sub_name = mod_name
+
+                for importer in sys.meta_path:
+                    loader = importer.find_module(mod_name, path)
+                    if loader is not None:
+                        # Found a metahook to handle the module
+                        break
+                else:
+                    # Handling via the standard path mechanism
+                    loader = _get_path_loader(mod_name, path)
+            finally:
+                imp.release_lock()
+        return loader
+
+
+# This helper is needed due to a missing component in the PEP 302
+# loader protocol (specifically, "get_filename" is non-standard)
+def _get_filename(loader, mod_name):
+    try:
+        get_filename = loader.get_filename
+    except AttributeError:
+        return None
+    else:
+        return get_filename(mod_name)
+
+# ------------------------------------------------------------
+# Done with the import machinery emulation, on with the code!
+
+def _run_code(code, run_globals, init_globals,
+              mod_name, mod_fname, mod_loader):
+    """Helper for _run_module_code"""
+    if init_globals is not None:
+        run_globals.update(init_globals)
+    run_globals.update(__name__ = mod_name,
+                       __file__ = mod_fname,
+                       __loader__ = mod_loader)
+    exec code in run_globals
+    return run_globals
+
+def _run_module_code(code, init_globals=None,
+                    mod_name=None, mod_fname=None,
+                    mod_loader=None, alter_sys=False):
+    """Helper for run_module"""
+    # Set up the top level namespace dictionary
+    if alter_sys:
+        # Modify sys.argv[0] and sys.module[mod_name]
+        temp_module = imp.new_module(mod_name)
+        mod_globals = temp_module.__dict__
+        saved_argv0 = sys.argv[0]
+        restore_module = mod_name in sys.modules
+        if restore_module:
+            saved_module = sys.modules[mod_name]
+        imp.acquire_lock()
+        try:
+            sys.argv[0] = mod_fname
+            sys.modules[mod_name] = temp_module
+            try:
+                _run_code(code, mod_globals, init_globals,
+                          mod_name, mod_fname, mod_loader)
+            finally:
+                sys.argv[0] = saved_argv0
+                if restore_module:
+                    sys.modules[mod_name] = saved_module
+                else:
+                    del sys.modules[mod_name]
+        finally:
+            imp.release_lock()
+        # Copy the globals of the temporary module, as they
+        # may be cleared when the temporary module goes away
+        return mod_globals.copy()
+    else:
+        # Leave the sys module alone
+        return _run_code(code, {}, init_globals,
+                         mod_name, mod_fname, mod_loader)
+
+
+def run_module(mod_name, init_globals=None,
+                         run_name=None, alter_sys=False):
+    """Execute a module's code without importing it
+
+       Returns the resulting top level namespace dictionary
+    """
+    loader = _get_loader(mod_name)
+    if loader is None:
+        raise ImportError("No module named " + mod_name)
+    code = loader.get_code(mod_name)
+    if code is None:
+        raise ImportError("No code object available for " + mod_name)
+    filename = _get_filename(loader, mod_name)
+    if run_name is None:
+        run_name = mod_name
+    return _run_module_code(code, init_globals, run_name,
+                            filename, loader, alter_sys)
+
+
+if __name__ == "__main__":
+    # Run the module specified as the next command line argument
+    if len(sys.argv) < 2:
+        print >> sys.stderr, "No module specified for execution"
+    else:
+        del sys.argv[0] # Make the requested module sys.argv[0]
+        run_module(sys.argv[0], run_name="__main__", alter_sys=True)