PEP 302 + zipimport:
- new import hooks in import.c, exposed in the sys module - new module called 'zipimport' - various changes to allow bootstrapping from zip files I hope I didn't break the Windows build (or anything else for that matter), but then again, it's been sitting on sf long enough... Regarding the latest discussions on python-dev: zipimport sets pkg.__path__ as specified in PEP 273, and likewise, sys.path item such as /path/to/Archive.zip/subdir/ are supported again.
This commit is contained in:
parent
60087fb450
commit
52e14d640b
|
@ -99,6 +99,7 @@ PyAPI_FUNC(PyObject *) _PyBuiltin_Init(void);
|
||||||
PyAPI_FUNC(PyObject *) _PySys_Init(void);
|
PyAPI_FUNC(PyObject *) _PySys_Init(void);
|
||||||
PyAPI_FUNC(void) _PyImport_Init(void);
|
PyAPI_FUNC(void) _PyImport_Init(void);
|
||||||
PyAPI_FUNC(void) _PyExc_Init(void);
|
PyAPI_FUNC(void) _PyExc_Init(void);
|
||||||
|
PyAPI_FUNC(void) _PyImportHooks_Init(void);
|
||||||
|
|
||||||
/* Various internal finalizers */
|
/* Various internal finalizers */
|
||||||
PyAPI_FUNC(void) _PyExc_Fini(void);
|
PyAPI_FUNC(void) _PyExc_Fini(void);
|
||||||
|
|
13
Lib/site.py
13
Lib/site.py
|
@ -73,16 +73,11 @@ del m
|
||||||
# only absolute pathnames, even if we're running from the build directory.
|
# only absolute pathnames, even if we're running from the build directory.
|
||||||
L = []
|
L = []
|
||||||
_dirs_in_sys_path = {}
|
_dirs_in_sys_path = {}
|
||||||
|
dir = dircase = None # sys.path may be empty at this point
|
||||||
for dir in sys.path:
|
for dir in sys.path:
|
||||||
# Filter out paths that don't exist, but leave in the empty string
|
# Filter out duplicate paths (on case-insensitive file systems also
|
||||||
# since it's a special case. We also need to special-case the Mac,
|
# if they only differ in case); turn relative paths into absolute
|
||||||
# as file names are allowed on sys.path there.
|
# paths.
|
||||||
if sys.platform != 'mac':
|
|
||||||
if dir and not os.path.isdir(dir):
|
|
||||||
continue
|
|
||||||
else:
|
|
||||||
if dir and not os.path.exists(dir):
|
|
||||||
continue
|
|
||||||
dir, dircase = makepath(dir)
|
dir, dircase = makepath(dir)
|
||||||
if not dircase in _dirs_in_sys_path:
|
if not dircase in _dirs_in_sys_path:
|
||||||
L.append(dir)
|
L.append(dir)
|
||||||
|
|
|
@ -0,0 +1,204 @@
|
||||||
|
import sys
|
||||||
|
import imp
|
||||||
|
import os
|
||||||
|
import unittest
|
||||||
|
from test import test_support
|
||||||
|
|
||||||
|
|
||||||
|
test_src = """\
|
||||||
|
def get_name():
|
||||||
|
return __name__
|
||||||
|
def get_file():
|
||||||
|
return __file__
|
||||||
|
"""
|
||||||
|
|
||||||
|
test_co = compile(test_src, "<???>", "exec")
|
||||||
|
test_path = "!!!_test_!!!"
|
||||||
|
|
||||||
|
|
||||||
|
class ImportTracker:
|
||||||
|
"""Importer that only tracks attempted imports."""
|
||||||
|
def __init__(self):
|
||||||
|
self.imports = []
|
||||||
|
def find_module(self, fullname, path=None):
|
||||||
|
self.imports.append(fullname)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
class TestImporter:
|
||||||
|
|
||||||
|
modules = {
|
||||||
|
"hooktestmodule": (False, test_co),
|
||||||
|
"hooktestpackage": (True, test_co),
|
||||||
|
"hooktestpackage.sub": (True, test_co),
|
||||||
|
"hooktestpackage.sub.subber": (False, test_co),
|
||||||
|
}
|
||||||
|
|
||||||
|
def __init__(self, path=test_path):
|
||||||
|
if path != test_path:
|
||||||
|
# if out class is on sys.path_hooks, we must raise
|
||||||
|
# ImportError for any path item that we can't handle.
|
||||||
|
raise ImportError
|
||||||
|
self.path = path
|
||||||
|
|
||||||
|
def _get__path__(self):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
def find_module(self, fullname, path=None):
|
||||||
|
if fullname in self.modules:
|
||||||
|
return self
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def load_module(self, fullname):
|
||||||
|
ispkg, code = self.modules[fullname]
|
||||||
|
mod = imp.new_module(fullname)
|
||||||
|
sys.modules[fullname] = mod
|
||||||
|
mod.__file__ = "<%s>" % self.__class__.__name__
|
||||||
|
mod.__loader__ = self
|
||||||
|
if ispkg:
|
||||||
|
mod.__path__ = self._get__path__()
|
||||||
|
exec code in mod.__dict__
|
||||||
|
return mod
|
||||||
|
|
||||||
|
|
||||||
|
class MetaImporter(TestImporter):
|
||||||
|
def _get__path__(self):
|
||||||
|
return []
|
||||||
|
|
||||||
|
class PathImporter(TestImporter):
|
||||||
|
def _get__path__(self):
|
||||||
|
return [self.path]
|
||||||
|
|
||||||
|
|
||||||
|
class ImportBlocker:
|
||||||
|
"""Place an ImportBlocker instance on sys.meta_path and you
|
||||||
|
can be sure the modules you specified can't be imported, even
|
||||||
|
if it's a builtin."""
|
||||||
|
def __init__(self, *namestoblock):
|
||||||
|
self.namestoblock = dict.fromkeys(namestoblock)
|
||||||
|
def find_module(self, fullname, path=None):
|
||||||
|
if fullname in self.namestoblock:
|
||||||
|
return self
|
||||||
|
return None
|
||||||
|
def load_module(self, fullname):
|
||||||
|
raise ImportError, "I dare you"
|
||||||
|
|
||||||
|
|
||||||
|
class ImpWrapper:
|
||||||
|
|
||||||
|
def __init__(self, path=None):
|
||||||
|
if path is not None and not os.path.isdir(path):
|
||||||
|
raise ImportError
|
||||||
|
self.path = path
|
||||||
|
|
||||||
|
def find_module(self, fullname, path=None):
|
||||||
|
subname = fullname.split(".")[-1]
|
||||||
|
if subname != fullname and self.path is None:
|
||||||
|
return None
|
||||||
|
if self.path is None:
|
||||||
|
path = None
|
||||||
|
else:
|
||||||
|
path = [self.path]
|
||||||
|
try:
|
||||||
|
file, filename, stuff = imp.find_module(subname, path)
|
||||||
|
except ImportError:
|
||||||
|
return None
|
||||||
|
return ImpLoader(file, filename, stuff)
|
||||||
|
|
||||||
|
|
||||||
|
class ImpLoader:
|
||||||
|
|
||||||
|
def __init__(self, file, filename, stuff):
|
||||||
|
self.file = file
|
||||||
|
self.filename = filename
|
||||||
|
self.stuff = stuff
|
||||||
|
|
||||||
|
def load_module(self, fullname):
|
||||||
|
mod = imp.load_module(fullname, self.file, self.filename, self.stuff)
|
||||||
|
if self.file:
|
||||||
|
self.file.close()
|
||||||
|
mod.__loader__ = self # for introspection
|
||||||
|
return mod
|
||||||
|
|
||||||
|
|
||||||
|
class ImportHooksBaseTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
self.path = sys.path[:]
|
||||||
|
self.meta_path = sys.meta_path[:]
|
||||||
|
self.path_hooks = sys.path_hooks[:]
|
||||||
|
sys.path_importer_cache.clear()
|
||||||
|
self.tracker = ImportTracker()
|
||||||
|
sys.meta_path.insert(0, self.tracker)
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
sys.path[:] = self.path
|
||||||
|
sys.meta_path[:] = self.meta_path
|
||||||
|
sys.path_hooks[:] = self.path_hooks
|
||||||
|
sys.path_importer_cache.clear()
|
||||||
|
for fullname in self.tracker.imports:
|
||||||
|
if fullname in sys.modules:
|
||||||
|
del sys.modules[fullname]
|
||||||
|
|
||||||
|
|
||||||
|
class ImportHooksTestCase(ImportHooksBaseTestCase):
|
||||||
|
|
||||||
|
def doTestImports(self, importer=None):
|
||||||
|
import hooktestmodule
|
||||||
|
import hooktestpackage
|
||||||
|
import hooktestpackage.sub
|
||||||
|
import hooktestpackage.sub.subber
|
||||||
|
self.assertEqual(hooktestmodule.get_name(),
|
||||||
|
"hooktestmodule")
|
||||||
|
self.assertEqual(hooktestpackage.get_name(),
|
||||||
|
"hooktestpackage")
|
||||||
|
self.assertEqual(hooktestpackage.sub.get_name(),
|
||||||
|
"hooktestpackage.sub")
|
||||||
|
self.assertEqual(hooktestpackage.sub.subber.get_name(),
|
||||||
|
"hooktestpackage.sub.subber")
|
||||||
|
if importer:
|
||||||
|
self.assertEqual(hooktestmodule.__loader__, importer)
|
||||||
|
self.assertEqual(hooktestpackage.__loader__, importer)
|
||||||
|
self.assertEqual(hooktestpackage.sub.__loader__, importer)
|
||||||
|
self.assertEqual(hooktestpackage.sub.subber.__loader__, importer)
|
||||||
|
|
||||||
|
def testMetaPath(self):
|
||||||
|
i = MetaImporter()
|
||||||
|
sys.meta_path.append(i)
|
||||||
|
self.doTestImports(i)
|
||||||
|
|
||||||
|
def testPathHook(self):
|
||||||
|
sys.path_hooks.append(PathImporter)
|
||||||
|
sys.path.append(test_path)
|
||||||
|
self.doTestImports()
|
||||||
|
|
||||||
|
def testBlocker(self):
|
||||||
|
mname = "exceptions" # an arbitrary harmless builtin module
|
||||||
|
if mname in sys.modules:
|
||||||
|
del sys.modules[mname]
|
||||||
|
sys.meta_path.append(ImportBlocker(mname))
|
||||||
|
try:
|
||||||
|
__import__(mname)
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
self.fail("'%s' was not supposed to be importable" % mname)
|
||||||
|
|
||||||
|
def testImpWrapper(self):
|
||||||
|
i = ImpWrapper()
|
||||||
|
sys.meta_path.append(i)
|
||||||
|
sys.path_hooks.append(ImpWrapper)
|
||||||
|
mnames = ("colorsys", "urlparse", "distutils.core", "compiler.misc")
|
||||||
|
for mname in mnames:
|
||||||
|
parent = mname.split(".")[0]
|
||||||
|
for n in sys.modules.keys():
|
||||||
|
if n.startswith(parent):
|
||||||
|
del sys.modules[n]
|
||||||
|
for mname in mnames:
|
||||||
|
m = __import__(mname, globals(), locals(), ["__dummy__"])
|
||||||
|
m.__loader__ # to make sure we actually handled the import
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
test_support.run_unittest(ImportHooksTestCase)
|
|
@ -0,0 +1,180 @@
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import marshal
|
||||||
|
import imp
|
||||||
|
import struct
|
||||||
|
import time
|
||||||
|
|
||||||
|
import zlib # implied prerequisite
|
||||||
|
from zipfile import ZipFile, ZipInfo, ZIP_STORED, ZIP_DEFLATED
|
||||||
|
from test import test_support
|
||||||
|
from test.test_importhooks import ImportHooksBaseTestCase, test_src, test_co
|
||||||
|
|
||||||
|
import zipimport
|
||||||
|
|
||||||
|
|
||||||
|
def make_pyc(co, mtime):
|
||||||
|
data = marshal.dumps(co)
|
||||||
|
pyc = imp.get_magic() + struct.pack("<i", mtime) + data
|
||||||
|
return pyc
|
||||||
|
|
||||||
|
NOW = time.time()
|
||||||
|
test_pyc = make_pyc(test_co, NOW)
|
||||||
|
|
||||||
|
|
||||||
|
if __debug__:
|
||||||
|
pyc_ext = ".pyc"
|
||||||
|
else:
|
||||||
|
pyc_ext = ".pyo"
|
||||||
|
|
||||||
|
|
||||||
|
TESTMOD = "ziptestmodule"
|
||||||
|
TESTPACK = "ziptestpackage"
|
||||||
|
TEMP_ZIP = "junk95142.zip"
|
||||||
|
|
||||||
|
|
||||||
|
class UncompressedZipImportTestCase(ImportHooksBaseTestCase):
|
||||||
|
|
||||||
|
compression = ZIP_STORED
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
# We're reusing the zip archive path, so we must clear the
|
||||||
|
# cached directory info.
|
||||||
|
zipimport._zip_directory_cache.clear()
|
||||||
|
ImportHooksBaseTestCase.setUp(self)
|
||||||
|
|
||||||
|
def doTest(self, expected_ext, files, *modules):
|
||||||
|
z = ZipFile(TEMP_ZIP, "w")
|
||||||
|
try:
|
||||||
|
for name, (mtime, data) in files.items():
|
||||||
|
zinfo = ZipInfo(name, time.localtime(mtime))
|
||||||
|
zinfo.compress_type = self.compression
|
||||||
|
z.writestr(zinfo, data)
|
||||||
|
z.close()
|
||||||
|
sys.path.insert(0, TEMP_ZIP)
|
||||||
|
|
||||||
|
mod = __import__(".".join(modules), globals(), locals(),
|
||||||
|
["__dummy__"])
|
||||||
|
file = mod.get_file()
|
||||||
|
self.assertEquals(file, os.path.join(TEMP_ZIP,
|
||||||
|
os.sep.join(modules) + expected_ext))
|
||||||
|
finally:
|
||||||
|
z.close()
|
||||||
|
os.remove(TEMP_ZIP)
|
||||||
|
|
||||||
|
def testAFakeZlib(self):
|
||||||
|
#
|
||||||
|
# This could cause a stack overflow before: importing zlib.py
|
||||||
|
# from a compressed archive would cause zlib to be imported
|
||||||
|
# which would find zlib.py in the archive, which would... etc.
|
||||||
|
#
|
||||||
|
# This test *must* be executed first: it must be the first one
|
||||||
|
# to trigger zipimport to import zlib (zipimport caches the
|
||||||
|
# zlib.decompress function object, after which the problem being
|
||||||
|
# tested here wouldn't be a problem anymore...
|
||||||
|
# (Hence the 'A' in the test method name: to make it the first
|
||||||
|
# item in a list sorted by name, like unittest.makeSuite() does.)
|
||||||
|
#
|
||||||
|
if "zlib" in sys.modules:
|
||||||
|
del sys.modules["zlib"]
|
||||||
|
files = {"zlib.py": (NOW, test_src)}
|
||||||
|
try:
|
||||||
|
self.doTest(".py", files, "zlib")
|
||||||
|
except ImportError:
|
||||||
|
if self.compression != ZIP_DEFLATED:
|
||||||
|
self.fail("expected test to not raise ImportError")
|
||||||
|
else:
|
||||||
|
if self.compression != ZIP_STORED:
|
||||||
|
self.fail("expected test to raise ImportError")
|
||||||
|
|
||||||
|
def testPy(self):
|
||||||
|
files = {TESTMOD + ".py": (NOW, test_src)}
|
||||||
|
self.doTest(".py", files, TESTMOD)
|
||||||
|
|
||||||
|
def testPyc(self):
|
||||||
|
files = {TESTMOD + pyc_ext: (NOW, test_pyc)}
|
||||||
|
self.doTest(pyc_ext, files, TESTMOD)
|
||||||
|
|
||||||
|
def testBoth(self):
|
||||||
|
files = {TESTMOD + ".py": (NOW, test_src),
|
||||||
|
TESTMOD + pyc_ext: (NOW, test_pyc)}
|
||||||
|
self.doTest(pyc_ext, files, TESTMOD)
|
||||||
|
|
||||||
|
def testBadMagic(self):
|
||||||
|
# make pyc magic word invalid, forcing loading from .py
|
||||||
|
m0 = ord(test_pyc[0])
|
||||||
|
m0 ^= 0x04 # flip an arbitrary bit
|
||||||
|
badmagic_pyc = chr(m0) + test_pyc[1:]
|
||||||
|
files = {TESTMOD + ".py": (NOW, test_src),
|
||||||
|
TESTMOD + pyc_ext: (NOW, badmagic_pyc)}
|
||||||
|
self.doTest(".py", files, TESTMOD)
|
||||||
|
|
||||||
|
def testBadMagic2(self):
|
||||||
|
# make pyc magic word invalid, causing an ImportError
|
||||||
|
m0 = ord(test_pyc[0])
|
||||||
|
m0 ^= 0x04 # flip an arbitrary bit
|
||||||
|
badmagic_pyc = chr(m0) + test_pyc[1:]
|
||||||
|
files = {TESTMOD + pyc_ext: (NOW, badmagic_pyc)}
|
||||||
|
try:
|
||||||
|
self.doTest(".py", files, TESTMOD)
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
self.fail("expected ImportError; import from bad pyc")
|
||||||
|
|
||||||
|
def testBadMTime(self):
|
||||||
|
t3 = ord(test_pyc[7])
|
||||||
|
t3 ^= 0x02 # flip the second bit -- not the first as that one
|
||||||
|
# isn't stored in the .py's mtime in the zip archive.
|
||||||
|
badtime_pyc = test_pyc[:7] + chr(t3) + test_pyc[8:]
|
||||||
|
files = {TESTMOD + ".py": (NOW, test_src),
|
||||||
|
TESTMOD + pyc_ext: (NOW, badtime_pyc)}
|
||||||
|
self.doTest(".py", files, TESTMOD)
|
||||||
|
|
||||||
|
def testPackage(self):
|
||||||
|
packdir = TESTPACK + os.sep
|
||||||
|
files = {packdir + "__init__" + pyc_ext: (NOW, test_pyc),
|
||||||
|
packdir + TESTMOD + pyc_ext: (NOW, test_pyc)}
|
||||||
|
self.doTest(pyc_ext, files, TESTPACK, TESTMOD)
|
||||||
|
|
||||||
|
def testDeepPackage(self):
|
||||||
|
packdir = TESTPACK + os.sep
|
||||||
|
packdir2 = packdir + packdir
|
||||||
|
files = {packdir + "__init__" + pyc_ext: (NOW, test_pyc),
|
||||||
|
packdir2 + "__init__" + pyc_ext: (NOW, test_pyc),
|
||||||
|
packdir2 + TESTMOD + pyc_ext: (NOW, test_pyc)}
|
||||||
|
self.doTest(pyc_ext, files, TESTPACK, TESTPACK, TESTMOD)
|
||||||
|
|
||||||
|
def testGetData(self):
|
||||||
|
z = ZipFile(TEMP_ZIP, "w")
|
||||||
|
z.compression = self.compression
|
||||||
|
try:
|
||||||
|
name = "testdata.dat"
|
||||||
|
data = "".join([chr(x) for x in range(256)]) * 500
|
||||||
|
z.writestr(name, data)
|
||||||
|
z.close()
|
||||||
|
zi = zipimport.zipimporter(TEMP_ZIP)
|
||||||
|
self.assertEquals(data, zi.get_data(name))
|
||||||
|
finally:
|
||||||
|
z.close()
|
||||||
|
os.remove(TEMP_ZIP)
|
||||||
|
|
||||||
|
def testImporterAttr(self):
|
||||||
|
src = """if 1: # indent hack
|
||||||
|
def get_file():
|
||||||
|
return __file__
|
||||||
|
if __importer__.get_data("some.data") != "some data":
|
||||||
|
raise AssertionError, "bad data"\n"""
|
||||||
|
pyc = make_pyc(compile(src, "<???>", "exec"), NOW)
|
||||||
|
files = {TESTMOD + pyc_ext: (NOW, pyc),
|
||||||
|
"some.data": (NOW, "some data")}
|
||||||
|
self.doTest(pyc_ext, files, TESTMOD)
|
||||||
|
|
||||||
|
|
||||||
|
class CompressedZipImportTestCase(UncompressedZipImportTestCase):
|
||||||
|
compression = ZIP_DEFLATED
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
test_support.run_unittest(UncompressedZipImportTestCase)
|
||||||
|
test_support.run_unittest(CompressedZipImportTestCase)
|
|
@ -113,6 +113,10 @@ errno errnomodule.c # posix (UNIX) errno values
|
||||||
_sre _sre.c # Fredrik Lundh's new regular expressions
|
_sre _sre.c # Fredrik Lundh's new regular expressions
|
||||||
_codecs _codecsmodule.c # access to the builtin codecs and codec registry
|
_codecs _codecsmodule.c # access to the builtin codecs and codec registry
|
||||||
|
|
||||||
|
# The zipimport module is always imported at startup. Having it as a
|
||||||
|
# builtin module avoids some bootstrapping problems and reduces overhead.
|
||||||
|
zipimport zipimport.c
|
||||||
|
|
||||||
# The rest of the modules listed in this file are all commented out by
|
# The rest of the modules listed in this file are all commented out by
|
||||||
# default. Usually they can be detected and built as dynamically
|
# default. Usually they can be detected and built as dynamically
|
||||||
# loaded modules by the new setup.py script added in Python 2.1. If
|
# loaded modules by the new setup.py script added in Python 2.1. If
|
||||||
|
|
|
@ -365,6 +365,7 @@ calculate_path(void)
|
||||||
char *path = getenv("PATH");
|
char *path = getenv("PATH");
|
||||||
char *prog = Py_GetProgramName();
|
char *prog = Py_GetProgramName();
|
||||||
char argv0_path[MAXPATHLEN+1];
|
char argv0_path[MAXPATHLEN+1];
|
||||||
|
char zip_path[MAXPATHLEN+1];
|
||||||
int pfound, efound; /* 1 if found; -1 if found build directory */
|
int pfound, efound; /* 1 if found; -1 if found build directory */
|
||||||
char *buf;
|
char *buf;
|
||||||
size_t bufsz;
|
size_t bufsz;
|
||||||
|
@ -483,6 +484,18 @@ calculate_path(void)
|
||||||
else
|
else
|
||||||
reduce(prefix);
|
reduce(prefix);
|
||||||
|
|
||||||
|
strncpy(zip_path, prefix, MAXPATHLEN);
|
||||||
|
if (pfound > 0) { /* Use the reduced prefix returned by Py_GetPrefix() */
|
||||||
|
reduce(zip_path);
|
||||||
|
reduce(zip_path);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
strncpy(zip_path, PREFIX, MAXPATHLEN);
|
||||||
|
joinpath(zip_path, "lib/python00.zip");
|
||||||
|
bufsz = strlen(zip_path); /* Replace "00" with version */
|
||||||
|
zip_path[bufsz - 6] = VERSION[0];
|
||||||
|
zip_path[bufsz - 5] = VERSION[2];
|
||||||
|
|
||||||
if (!(efound = search_for_exec_prefix(argv0_path, home))) {
|
if (!(efound = search_for_exec_prefix(argv0_path, home))) {
|
||||||
if (!Py_FrozenFlag)
|
if (!Py_FrozenFlag)
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
|
@ -521,6 +534,7 @@ calculate_path(void)
|
||||||
defpath = delim + 1;
|
defpath = delim + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bufsz += strlen(zip_path) + 1;
|
||||||
bufsz += strlen(exec_prefix) + 1;
|
bufsz += strlen(exec_prefix) + 1;
|
||||||
|
|
||||||
/* This is the only malloc call in this file */
|
/* This is the only malloc call in this file */
|
||||||
|
@ -541,6 +555,10 @@ calculate_path(void)
|
||||||
else
|
else
|
||||||
buf[0] = '\0';
|
buf[0] = '\0';
|
||||||
|
|
||||||
|
/* Next is the default zip path */
|
||||||
|
strcat(buf, zip_path);
|
||||||
|
strcat(buf, delimiter);
|
||||||
|
|
||||||
/* Next goes merge of compile-time $PYTHONPATH with
|
/* Next goes merge of compile-time $PYTHONPATH with
|
||||||
* dynamically located prefix.
|
* dynamically located prefix.
|
||||||
*/
|
*/
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -43,6 +43,7 @@ extern void initxreadlines(void);
|
||||||
extern void init_weakref(void);
|
extern void init_weakref(void);
|
||||||
extern void init_hotshot(void);
|
extern void init_hotshot(void);
|
||||||
extern void initxxsubtype(void);
|
extern void initxxsubtype(void);
|
||||||
|
extern void initzipimport(void);
|
||||||
extern void init_random(void);
|
extern void init_random(void);
|
||||||
|
|
||||||
/* XXX tim: what's the purpose of ADDMODULE MARKER? */
|
/* XXX tim: what's the purpose of ADDMODULE MARKER? */
|
||||||
|
@ -98,6 +99,7 @@ struct _inittab _PyImport_Inittab[] = {
|
||||||
{"_random", init_random},
|
{"_random", init_random},
|
||||||
|
|
||||||
{"xxsubtype", initxxsubtype},
|
{"xxsubtype", initxxsubtype},
|
||||||
|
{"zipimport", initzipimport},
|
||||||
|
|
||||||
/* XXX tim: what's the purpose of ADDMODULE MARKER? */
|
/* XXX tim: what's the purpose of ADDMODULE MARKER? */
|
||||||
/* -- ADDMODULE MARKER 2 -- */
|
/* -- ADDMODULE MARKER 2 -- */
|
||||||
|
|
|
@ -81,6 +81,7 @@
|
||||||
|
|
||||||
static char prefix[MAXPATHLEN+1];
|
static char prefix[MAXPATHLEN+1];
|
||||||
static char progpath[MAXPATHLEN+1];
|
static char progpath[MAXPATHLEN+1];
|
||||||
|
static char dllpath[MAXPATHLEN+1];
|
||||||
static char *module_search_path = NULL;
|
static char *module_search_path = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
@ -350,6 +351,7 @@ get_progpath(void)
|
||||||
char *prog = Py_GetProgramName();
|
char *prog = Py_GetProgramName();
|
||||||
|
|
||||||
#ifdef MS_WINDOWS
|
#ifdef MS_WINDOWS
|
||||||
|
extern HANDLE PyWin_DLLhModule;
|
||||||
#ifdef UNICODE
|
#ifdef UNICODE
|
||||||
WCHAR wprogpath[MAXPATHLEN+1];
|
WCHAR wprogpath[MAXPATHLEN+1];
|
||||||
/* Windows documents that GetModuleFileName() will "truncate",
|
/* Windows documents that GetModuleFileName() will "truncate",
|
||||||
|
@ -357,6 +359,14 @@ get_progpath(void)
|
||||||
PLUS Windows itself defines MAX_PATH as the same, but anyway...
|
PLUS Windows itself defines MAX_PATH as the same, but anyway...
|
||||||
*/
|
*/
|
||||||
wprogpath[MAXPATHLEN]=_T('\0');
|
wprogpath[MAXPATHLEN]=_T('\0');
|
||||||
|
if (PyWin_DLLhModule &&
|
||||||
|
GetModuleFileName(PyWin_DLLhModule, wprogpath, MAXPATHLEN)) {
|
||||||
|
WideCharToMultiByte(CP_ACP, 0,
|
||||||
|
wprogpath, -1,
|
||||||
|
dllpath, MAXPATHLEN+1,
|
||||||
|
NULL, NULL);
|
||||||
|
}
|
||||||
|
wprogpath[MAXPATHLEN]=_T('\0')';
|
||||||
if (GetModuleFileName(NULL, wprogpath, MAXPATHLEN)) {
|
if (GetModuleFileName(NULL, wprogpath, MAXPATHLEN)) {
|
||||||
WideCharToMultiByte(CP_ACP, 0,
|
WideCharToMultiByte(CP_ACP, 0,
|
||||||
wprogpath, -1,
|
wprogpath, -1,
|
||||||
|
@ -366,6 +376,9 @@ get_progpath(void)
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
/* static init of progpath ensures final char remains \0 */
|
/* static init of progpath ensures final char remains \0 */
|
||||||
|
if (PyWin_DLLhModule)
|
||||||
|
if (!GetModuleFileName(PyWin_DLLhModule, dllpath, MAXPATHLEN))
|
||||||
|
dllpath[0] = 0;
|
||||||
if (GetModuleFileName(NULL, progpath, MAXPATHLEN))
|
if (GetModuleFileName(NULL, progpath, MAXPATHLEN))
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
|
@ -427,6 +440,8 @@ calculate_path(void)
|
||||||
int skiphome, skipdefault;
|
int skiphome, skipdefault;
|
||||||
char *machinepath = NULL;
|
char *machinepath = NULL;
|
||||||
char *userpath = NULL;
|
char *userpath = NULL;
|
||||||
|
char zip_path[MAXPATHLEN+1];
|
||||||
|
size_t len;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
get_progpath();
|
get_progpath();
|
||||||
|
@ -447,6 +462,21 @@ calculate_path(void)
|
||||||
|
|
||||||
|
|
||||||
#ifdef MS_WINDOWS
|
#ifdef MS_WINDOWS
|
||||||
|
/* Calculate zip archive path */
|
||||||
|
if (dllpath[0]) /* use name of python DLL */
|
||||||
|
strncpy(zip_path, dllpath, MAXPATHLEN);
|
||||||
|
else /* use name of executable program */
|
||||||
|
strncpy(zip_path, progpath, MAXPATHLEN);
|
||||||
|
len = strlen(zip_path);
|
||||||
|
if (len > 4) {
|
||||||
|
zip_path[len-3] = 'z'; /* change ending to "zip" */
|
||||||
|
zip_path[len-2] = 'i';
|
||||||
|
zip_path[len-1] = 'p';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
zip_path[0] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
skiphome = pythonhome==NULL ? 0 : 1;
|
skiphome = pythonhome==NULL ? 0 : 1;
|
||||||
machinepath = getpythonregpath(HKEY_LOCAL_MACHINE, skiphome);
|
machinepath = getpythonregpath(HKEY_LOCAL_MACHINE, skiphome);
|
||||||
userpath = getpythonregpath(HKEY_CURRENT_USER, skiphome);
|
userpath = getpythonregpath(HKEY_CURRENT_USER, skiphome);
|
||||||
|
@ -458,14 +488,15 @@ calculate_path(void)
|
||||||
|
|
||||||
/* We need to construct a path from the following parts.
|
/* We need to construct a path from the following parts.
|
||||||
(1) the PYTHONPATH environment variable, if set;
|
(1) the PYTHONPATH environment variable, if set;
|
||||||
(2) for Win32, the machinepath and userpath, if set;
|
(2) for Win32, the zip archive file path;
|
||||||
(3) the PYTHONPATH config macro, with the leading "."
|
(3) for Win32, the machinepath and userpath, if set;
|
||||||
|
(4) the PYTHONPATH config macro, with the leading "."
|
||||||
of each component replaced with pythonhome, if set;
|
of each component replaced with pythonhome, if set;
|
||||||
(4) the directory containing the executable (argv0_path).
|
(5) the directory containing the executable (argv0_path).
|
||||||
The length calculation calculates #3 first.
|
The length calculation calculates #4 first.
|
||||||
Extra rules:
|
Extra rules:
|
||||||
- If PYTHONHOME is set (in any way) item (2) is ignored.
|
- If PYTHONHOME is set (in any way) item (3) is ignored.
|
||||||
- If registry values are used, (3) and (4) are ignored.
|
- If registry values are used, (4) and (5) are ignored.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Calculate size of return buffer */
|
/* Calculate size of return buffer */
|
||||||
|
@ -487,6 +518,7 @@ calculate_path(void)
|
||||||
bufsz += strlen(userpath) + 1;
|
bufsz += strlen(userpath) + 1;
|
||||||
if (machinepath)
|
if (machinepath)
|
||||||
bufsz += strlen(machinepath) + 1;
|
bufsz += strlen(machinepath) + 1;
|
||||||
|
bufsz += strlen(zip_path) + 1;
|
||||||
#endif
|
#endif
|
||||||
if (envpath != NULL)
|
if (envpath != NULL)
|
||||||
bufsz += strlen(envpath) + 1;
|
bufsz += strlen(envpath) + 1;
|
||||||
|
@ -518,6 +550,11 @@ calculate_path(void)
|
||||||
*buf++ = DELIM;
|
*buf++ = DELIM;
|
||||||
}
|
}
|
||||||
#ifdef MS_WINDOWS
|
#ifdef MS_WINDOWS
|
||||||
|
if (zip_path[0]) {
|
||||||
|
strcpy(buf, zip_path);
|
||||||
|
buf = strchr(buf, '\0');
|
||||||
|
*buf++ = DELIM;
|
||||||
|
}
|
||||||
if (userpath) {
|
if (userpath) {
|
||||||
strcpy(buf, userpath);
|
strcpy(buf, userpath);
|
||||||
buf = strchr(buf, '\0');
|
buf = strchr(buf, '\0');
|
||||||
|
|
|
@ -549,5 +549,9 @@ SOURCE=..\Modules\xxsubtype.c
|
||||||
|
|
||||||
SOURCE=..\Modules\yuvconvert.c
|
SOURCE=..\Modules\yuvconvert.c
|
||||||
# End Source File
|
# End Source File
|
||||||
|
# Begin Source File
|
||||||
|
|
||||||
|
SOURCE=..\Modules\zipimport.c
|
||||||
|
# End Source File
|
||||||
# End Target
|
# End Target
|
||||||
# End Project
|
# End Project
|
||||||
|
|
255
Python/import.c
255
Python/import.c
|
@ -152,6 +152,72 @@ _PyImport_Init(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_PyImportHooks_Init(void)
|
||||||
|
{
|
||||||
|
PyObject *v, *path_hooks = NULL, *zimpimport;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
/* adding sys.path_hooks and sys.path_importer_cache, setting up
|
||||||
|
zipimport */
|
||||||
|
|
||||||
|
if (Py_VerboseFlag)
|
||||||
|
PySys_WriteStderr("# installing zipimport hook\n");
|
||||||
|
|
||||||
|
v = PyList_New(0);
|
||||||
|
if (v == NULL)
|
||||||
|
goto error;
|
||||||
|
err = PySys_SetObject("meta_path", v);
|
||||||
|
Py_DECREF(v);
|
||||||
|
if (err)
|
||||||
|
goto error;
|
||||||
|
v = PyDict_New();
|
||||||
|
if (v == NULL)
|
||||||
|
goto error;
|
||||||
|
err = PySys_SetObject("path_importer_cache", v);
|
||||||
|
Py_DECREF(v);
|
||||||
|
if (err)
|
||||||
|
goto error;
|
||||||
|
path_hooks = PyList_New(0);
|
||||||
|
if (path_hooks == NULL)
|
||||||
|
goto error;
|
||||||
|
err = PySys_SetObject("path_hooks", path_hooks);
|
||||||
|
if (err) {
|
||||||
|
error:
|
||||||
|
PyErr_Print();
|
||||||
|
Py_FatalError("initializing sys.meta_path, sys.path_hooks or "
|
||||||
|
"path_importer_cache failed");
|
||||||
|
}
|
||||||
|
zimpimport = PyImport_ImportModule("zipimport");
|
||||||
|
if (zimpimport == NULL) {
|
||||||
|
PyErr_Clear(); /* No zip import module -- okay */
|
||||||
|
if (Py_VerboseFlag)
|
||||||
|
PySys_WriteStderr("# can't import zipimport\n");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
PyObject *zipimporter = PyObject_GetAttrString(zimpimport,
|
||||||
|
"zipimporter");
|
||||||
|
Py_DECREF(zimpimport);
|
||||||
|
if (zipimporter == NULL) {
|
||||||
|
PyErr_Clear(); /* No zipimporter object -- okay */
|
||||||
|
if (Py_VerboseFlag)
|
||||||
|
PySys_WriteStderr(
|
||||||
|
"# can't import zipimport.zimimporter\n");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* sys.path_hooks.append(zipimporter) */
|
||||||
|
err = PyList_Append(path_hooks, zipimporter);
|
||||||
|
Py_DECREF(zipimporter);
|
||||||
|
if (err)
|
||||||
|
goto error;
|
||||||
|
if (Py_VerboseFlag)
|
||||||
|
PySys_WriteStderr(
|
||||||
|
"# installed zipimport hook\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Py_DECREF(path_hooks);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_PyImport_Fini(void)
|
_PyImport_Fini(void)
|
||||||
{
|
{
|
||||||
|
@ -246,6 +312,7 @@ static char* sys_deletes[] = {
|
||||||
"path", "argv", "ps1", "ps2", "exitfunc",
|
"path", "argv", "ps1", "ps2", "exitfunc",
|
||||||
"exc_type", "exc_value", "exc_traceback",
|
"exc_type", "exc_value", "exc_traceback",
|
||||||
"last_type", "last_value", "last_traceback",
|
"last_type", "last_value", "last_traceback",
|
||||||
|
"path_hooks", "path_importer_cache", "meta_path",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -808,9 +875,9 @@ load_source_module(char *name, char *pathname, FILE *fp)
|
||||||
|
|
||||||
|
|
||||||
/* Forward */
|
/* Forward */
|
||||||
static PyObject *load_module(char *, FILE *, char *, int);
|
static PyObject *load_module(char *, FILE *, char *, int, PyObject *);
|
||||||
static struct filedescr *find_module(char *, PyObject *,
|
static struct filedescr *find_module(char *, char *, PyObject *,
|
||||||
char *, size_t, FILE **);
|
char *, size_t, FILE **, PyObject **);
|
||||||
static struct _frozen *find_frozen(char *name);
|
static struct _frozen *find_frozen(char *name);
|
||||||
|
|
||||||
/* Load a package and return its module object WITH INCREMENTED
|
/* Load a package and return its module object WITH INCREMENTED
|
||||||
|
@ -848,7 +915,7 @@ load_package(char *name, char *pathname)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
buf[0] = '\0';
|
buf[0] = '\0';
|
||||||
fdp = find_module("__init__", path, buf, sizeof(buf), &fp);
|
fdp = find_module(name, "__init__", path, buf, sizeof(buf), &fp, NULL);
|
||||||
if (fdp == NULL) {
|
if (fdp == NULL) {
|
||||||
if (PyErr_ExceptionMatches(PyExc_ImportError)) {
|
if (PyErr_ExceptionMatches(PyExc_ImportError)) {
|
||||||
PyErr_Clear();
|
PyErr_Clear();
|
||||||
|
@ -857,7 +924,7 @@ load_package(char *name, char *pathname)
|
||||||
m = NULL;
|
m = NULL;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
m = load_module(name, fp, buf, fdp->type);
|
m = load_module(name, fp, buf, fdp->type, NULL);
|
||||||
if (fp != NULL)
|
if (fp != NULL)
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
cleanup:
|
cleanup:
|
||||||
|
@ -885,6 +952,61 @@ is_builtin(char *name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Return an importer object for a sys.path/pkg.__path__ item 'p',
|
||||||
|
possibly by fetching it from the path_importer_cache dict. If it
|
||||||
|
wasn't yet cached, traverse path_hooks until it a hook is found
|
||||||
|
that can handle the path item. Return None if no hook could;
|
||||||
|
this tells our caller it should fall back to the builtin
|
||||||
|
import mechanism. Cache the result in path_importer_cache.
|
||||||
|
Returns a borrowed reference. */
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
get_path_importer(PyObject *path_importer_cache, PyObject *path_hooks,
|
||||||
|
PyObject *p)
|
||||||
|
{
|
||||||
|
PyObject *importer;
|
||||||
|
int j, nhooks;
|
||||||
|
|
||||||
|
/* These conditions are the caller's responsibility: */
|
||||||
|
assert(PyList_Check(path_hooks));
|
||||||
|
assert(PyDict_Check(path_importer_cache));
|
||||||
|
|
||||||
|
nhooks = PyList_Size(path_hooks);
|
||||||
|
if (nhooks < 0)
|
||||||
|
return NULL; /* Shouldn't happen */
|
||||||
|
|
||||||
|
importer = PyDict_GetItem(path_importer_cache, p);
|
||||||
|
if (importer != NULL)
|
||||||
|
return importer;
|
||||||
|
|
||||||
|
/* set path_importer_cache[p] to None to avoid recursion */
|
||||||
|
if (PyDict_SetItem(path_importer_cache, p, Py_None) != 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (j = 0; j < nhooks; j++) {
|
||||||
|
PyObject *hook = PyList_GetItem(path_hooks, j);
|
||||||
|
if (hook == NULL)
|
||||||
|
return NULL;
|
||||||
|
importer = PyObject_CallFunction(hook, "O", p);
|
||||||
|
if (importer != NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!PyErr_ExceptionMatches(PyExc_ImportError)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
PyErr_Clear();
|
||||||
|
}
|
||||||
|
if (importer == NULL)
|
||||||
|
importer = Py_None;
|
||||||
|
else if (importer != Py_None) {
|
||||||
|
int err = PyDict_SetItem(path_importer_cache, p, importer);
|
||||||
|
Py_DECREF(importer);
|
||||||
|
if (err != 0)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return importer;
|
||||||
|
}
|
||||||
|
|
||||||
/* Search the path (default sys.path) for a module. Return the
|
/* Search the path (default sys.path) for a module. Return the
|
||||||
corresponding filedescr struct, and (via return arguments) the
|
corresponding filedescr struct, and (via return arguments) the
|
||||||
pathname and an open file. Return NULL if the module is not found. */
|
pathname and an open file. Return NULL if the module is not found. */
|
||||||
|
@ -896,16 +1018,18 @@ extern FILE *PyWin_FindRegisteredModule(const char *, struct filedescr **,
|
||||||
|
|
||||||
static int case_ok(char *, int, int, char *);
|
static int case_ok(char *, int, int, char *);
|
||||||
static int find_init_module(char *); /* Forward */
|
static int find_init_module(char *); /* Forward */
|
||||||
|
static struct filedescr importhookdescr = {"", "", IMP_HOOK};
|
||||||
|
|
||||||
static struct filedescr *
|
static struct filedescr *
|
||||||
find_module(char *realname, PyObject *path, char *buf, size_t buflen,
|
find_module(char *fullname, char *subname, PyObject *path, char *buf,
|
||||||
FILE **p_fp)
|
size_t buflen, FILE **p_fp, PyObject **p_loader)
|
||||||
{
|
{
|
||||||
int i, npath;
|
int i, npath;
|
||||||
size_t len, namelen;
|
size_t len, namelen;
|
||||||
struct filedescr *fdp = NULL;
|
struct filedescr *fdp = NULL;
|
||||||
char *filemode;
|
char *filemode;
|
||||||
FILE *fp = NULL;
|
FILE *fp = NULL;
|
||||||
|
PyObject *path_hooks, *path_importer_cache;
|
||||||
#ifndef RISCOS
|
#ifndef RISCOS
|
||||||
struct stat statbuf;
|
struct stat statbuf;
|
||||||
#endif
|
#endif
|
||||||
|
@ -918,13 +1042,50 @@ find_module(char *realname, PyObject *path, char *buf, size_t buflen,
|
||||||
size_t saved_namelen;
|
size_t saved_namelen;
|
||||||
char *saved_buf = NULL;
|
char *saved_buf = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
if (p_loader != NULL)
|
||||||
|
*p_loader = NULL;
|
||||||
|
|
||||||
if (strlen(realname) > MAXPATHLEN) {
|
if (strlen(subname) > MAXPATHLEN) {
|
||||||
PyErr_SetString(PyExc_OverflowError,
|
PyErr_SetString(PyExc_OverflowError,
|
||||||
"module name is too long");
|
"module name is too long");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
strcpy(name, realname);
|
strcpy(name, subname);
|
||||||
|
|
||||||
|
/* sys.meta_path import hook */
|
||||||
|
if (p_loader != NULL) {
|
||||||
|
PyObject *meta_path;
|
||||||
|
|
||||||
|
meta_path = PySys_GetObject("meta_path");
|
||||||
|
if (meta_path == NULL || !PyList_Check(meta_path)) {
|
||||||
|
PyErr_SetString(PyExc_ImportError,
|
||||||
|
"sys.meta_path must be a list of "
|
||||||
|
"import hooks");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
Py_INCREF(meta_path); /* zap guard */
|
||||||
|
npath = PyList_Size(meta_path);
|
||||||
|
for (i = 0; i < npath; i++) {
|
||||||
|
PyObject *loader;
|
||||||
|
PyObject *hook = PyList_GetItem(meta_path, i);
|
||||||
|
loader = PyObject_CallMethod(hook, "find_module",
|
||||||
|
"sO", fullname,
|
||||||
|
path != NULL ?
|
||||||
|
path : Py_None);
|
||||||
|
if (loader == NULL) {
|
||||||
|
Py_DECREF(meta_path);
|
||||||
|
return NULL; /* true error */
|
||||||
|
}
|
||||||
|
if (loader != Py_None) {
|
||||||
|
/* a loader was found */
|
||||||
|
*p_loader = loader;
|
||||||
|
Py_DECREF(meta_path);
|
||||||
|
return &importhookdescr;
|
||||||
|
}
|
||||||
|
Py_DECREF(loader);
|
||||||
|
}
|
||||||
|
Py_DECREF(meta_path);
|
||||||
|
}
|
||||||
|
|
||||||
if (path != NULL && PyString_Check(path)) {
|
if (path != NULL && PyString_Check(path)) {
|
||||||
/* The only type of submodule allowed inside a "frozen"
|
/* The only type of submodule allowed inside a "frozen"
|
||||||
|
@ -978,6 +1139,22 @@ find_module(char *realname, PyObject *path, char *buf, size_t buflen,
|
||||||
"sys.path must be a list of directory names");
|
"sys.path must be a list of directory names");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
path_hooks = PySys_GetObject("path_hooks");
|
||||||
|
if (path_hooks == NULL || !PyList_Check(path_hooks)) {
|
||||||
|
PyErr_SetString(PyExc_ImportError,
|
||||||
|
"sys.path_hooks must be a list of "
|
||||||
|
"import hooks");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
path_importer_cache = PySys_GetObject("path_importer_cache");
|
||||||
|
if (path_importer_cache == NULL ||
|
||||||
|
!PyDict_Check(path_importer_cache)) {
|
||||||
|
PyErr_SetString(PyExc_ImportError,
|
||||||
|
"sys.path_importer_cache must be a dict");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
npath = PyList_Size(path);
|
npath = PyList_Size(path);
|
||||||
namelen = strlen(name);
|
namelen = strlen(name);
|
||||||
for (i = 0; i < npath; i++) {
|
for (i = 0; i < npath; i++) {
|
||||||
|
@ -1005,6 +1182,33 @@ find_module(char *realname, PyObject *path, char *buf, size_t buflen,
|
||||||
Py_XDECREF(copy);
|
Py_XDECREF(copy);
|
||||||
continue; /* v contains '\0' */
|
continue; /* v contains '\0' */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* sys.path_hooks import hook */
|
||||||
|
if (p_loader != NULL) {
|
||||||
|
PyObject *importer;
|
||||||
|
|
||||||
|
importer = get_path_importer(path_importer_cache,
|
||||||
|
path_hooks, v);
|
||||||
|
if (importer == NULL)
|
||||||
|
return NULL;
|
||||||
|
/* Note: importer is a borrowed reference */
|
||||||
|
if (importer != Py_None) {
|
||||||
|
PyObject *loader;
|
||||||
|
loader = PyObject_CallMethod(importer,
|
||||||
|
"find_module",
|
||||||
|
"s", fullname);
|
||||||
|
if (loader == NULL)
|
||||||
|
return NULL; /* error */
|
||||||
|
if (loader != Py_None) {
|
||||||
|
/* a loader was found */
|
||||||
|
*p_loader = loader;
|
||||||
|
return &importhookdescr;
|
||||||
|
}
|
||||||
|
Py_DECREF(loader);
|
||||||
|
}
|
||||||
|
/* no hook was successful, use builtin import */
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef macintosh
|
#ifdef macintosh
|
||||||
/*
|
/*
|
||||||
** Speedup: each sys.path item is interned, and
|
** Speedup: each sys.path item is interned, and
|
||||||
|
@ -1079,7 +1283,7 @@ find_module(char *realname, PyObject *path, char *buf, size_t buflen,
|
||||||
* dynamically loaded module we're going to try,
|
* dynamically loaded module we're going to try,
|
||||||
* truncate the name before trying
|
* truncate the name before trying
|
||||||
*/
|
*/
|
||||||
if (strlen(realname) > 8) {
|
if (strlen(subname) > 8) {
|
||||||
/* is this an attempt to load a C extension? */
|
/* is this an attempt to load a C extension? */
|
||||||
const struct filedescr *scan;
|
const struct filedescr *scan;
|
||||||
scan = _PyImport_DynLoadFiletab;
|
scan = _PyImport_DynLoadFiletab;
|
||||||
|
@ -1092,7 +1296,7 @@ find_module(char *realname, PyObject *path, char *buf, size_t buflen,
|
||||||
if (scan->suffix != NULL) {
|
if (scan->suffix != NULL) {
|
||||||
/* yes, so truncate the name */
|
/* yes, so truncate the name */
|
||||||
namelen = 8;
|
namelen = 8;
|
||||||
len -= strlen(realname) - namelen;
|
len -= strlen(subname) - namelen;
|
||||||
buf[len] = '\0';
|
buf[len] = '\0';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1444,7 +1648,7 @@ static int init_builtin(char *); /* Forward */
|
||||||
its module object WITH INCREMENTED REFERENCE COUNT */
|
its module object WITH INCREMENTED REFERENCE COUNT */
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
load_module(char *name, FILE *fp, char *buf, int type)
|
load_module(char *name, FILE *fp, char *buf, int type, PyObject *loader)
|
||||||
{
|
{
|
||||||
PyObject *modules;
|
PyObject *modules;
|
||||||
PyObject *m;
|
PyObject *m;
|
||||||
|
@ -1523,6 +1727,16 @@ load_module(char *name, FILE *fp, char *buf, int type)
|
||||||
Py_INCREF(m);
|
Py_INCREF(m);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case IMP_HOOK: {
|
||||||
|
if (loader == NULL) {
|
||||||
|
PyErr_SetString(PyExc_ImportError,
|
||||||
|
"import hook without loader");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
m = PyObject_CallMethod(loader, "load_module", "s", name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
PyErr_Format(PyExc_ImportError,
|
PyErr_Format(PyExc_ImportError,
|
||||||
"Don't know how to import %.200s (type code %d)",
|
"Don't know how to import %.200s (type code %d)",
|
||||||
|
@ -1978,7 +2192,7 @@ import_submodule(PyObject *mod, char *subname, char *fullname)
|
||||||
Py_INCREF(m);
|
Py_INCREF(m);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
PyObject *path;
|
PyObject *path, *loader = NULL;
|
||||||
char buf[MAXPATHLEN+1];
|
char buf[MAXPATHLEN+1];
|
||||||
struct filedescr *fdp;
|
struct filedescr *fdp;
|
||||||
FILE *fp = NULL;
|
FILE *fp = NULL;
|
||||||
|
@ -1995,7 +2209,8 @@ import_submodule(PyObject *mod, char *subname, char *fullname)
|
||||||
}
|
}
|
||||||
|
|
||||||
buf[0] = '\0';
|
buf[0] = '\0';
|
||||||
fdp = find_module(subname, path, buf, MAXPATHLEN+1, &fp);
|
fdp = find_module(fullname, subname, path, buf, MAXPATHLEN+1,
|
||||||
|
&fp, &loader);
|
||||||
Py_XDECREF(path);
|
Py_XDECREF(path);
|
||||||
if (fdp == NULL) {
|
if (fdp == NULL) {
|
||||||
if (!PyErr_ExceptionMatches(PyExc_ImportError))
|
if (!PyErr_ExceptionMatches(PyExc_ImportError))
|
||||||
|
@ -2004,7 +2219,8 @@ import_submodule(PyObject *mod, char *subname, char *fullname)
|
||||||
Py_INCREF(Py_None);
|
Py_INCREF(Py_None);
|
||||||
return Py_None;
|
return Py_None;
|
||||||
}
|
}
|
||||||
m = load_module(fullname, fp, buf, fdp->type);
|
m = load_module(fullname, fp, buf, fdp->type, loader);
|
||||||
|
Py_XDECREF(loader);
|
||||||
if (fp)
|
if (fp)
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
if (mod != Py_None) {
|
if (mod != Py_None) {
|
||||||
|
@ -2080,11 +2296,11 @@ PyImport_ReloadModule(PyObject *m)
|
||||||
PyErr_Clear();
|
PyErr_Clear();
|
||||||
}
|
}
|
||||||
buf[0] = '\0';
|
buf[0] = '\0';
|
||||||
fdp = find_module(subname, path, buf, MAXPATHLEN+1, &fp);
|
fdp = find_module(name, subname, path, buf, MAXPATHLEN+1, &fp, NULL);
|
||||||
Py_XDECREF(path);
|
Py_XDECREF(path);
|
||||||
if (fdp == NULL)
|
if (fdp == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
m = load_module(name, fp, buf, fdp->type);
|
m = load_module(name, fp, buf, fdp->type, NULL);
|
||||||
if (fp)
|
if (fp)
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return m;
|
return m;
|
||||||
|
@ -2228,7 +2444,7 @@ call_find_module(char *name, PyObject *path)
|
||||||
pathname[0] = '\0';
|
pathname[0] = '\0';
|
||||||
if (path == Py_None)
|
if (path == Py_None)
|
||||||
path = NULL;
|
path = NULL;
|
||||||
fdp = find_module(name, path, pathname, MAXPATHLEN+1, &fp);
|
fdp = find_module(NULL, name, path, pathname, MAXPATHLEN+1, &fp, NULL);
|
||||||
if (fdp == NULL)
|
if (fdp == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (fp != NULL) {
|
if (fp != NULL) {
|
||||||
|
@ -2465,7 +2681,7 @@ imp_load_module(PyObject *self, PyObject *args)
|
||||||
if (fp == NULL)
|
if (fp == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return load_module(name, fp, pathname, type);
|
return load_module(name, fp, pathname, type, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
|
@ -2579,6 +2795,7 @@ initimp(void)
|
||||||
if (setint(d, "C_BUILTIN", C_BUILTIN) < 0) goto failure;
|
if (setint(d, "C_BUILTIN", C_BUILTIN) < 0) goto failure;
|
||||||
if (setint(d, "PY_FROZEN", PY_FROZEN) < 0) goto failure;
|
if (setint(d, "PY_FROZEN", PY_FROZEN) < 0) goto failure;
|
||||||
if (setint(d, "PY_CODERESOURCE", PY_CODERESOURCE) < 0) goto failure;
|
if (setint(d, "PY_CODERESOURCE", PY_CODERESOURCE) < 0) goto failure;
|
||||||
|
if (setint(d, "IMP_HOOK", IMP_HOOK) < 0) goto failure;
|
||||||
|
|
||||||
failure:
|
failure:
|
||||||
;
|
;
|
||||||
|
|
|
@ -16,7 +16,8 @@ enum filetype {
|
||||||
PKG_DIRECTORY,
|
PKG_DIRECTORY,
|
||||||
C_BUILTIN,
|
C_BUILTIN,
|
||||||
PY_FROZEN,
|
PY_FROZEN,
|
||||||
PY_CODERESOURCE /* Mac only */
|
PY_CODERESOURCE, /* Mac only */
|
||||||
|
IMP_HOOK
|
||||||
};
|
};
|
||||||
|
|
||||||
struct filedescr {
|
struct filedescr {
|
||||||
|
|
|
@ -161,6 +161,8 @@ Py_Initialize(void)
|
||||||
/* phase 2 of builtins */
|
/* phase 2 of builtins */
|
||||||
_PyImport_FixupExtension("__builtin__", "__builtin__");
|
_PyImport_FixupExtension("__builtin__", "__builtin__");
|
||||||
|
|
||||||
|
_PyImportHooks_Init();
|
||||||
|
|
||||||
initsigs(); /* Signal handling stuff, including initintr() */
|
initsigs(); /* Signal handling stuff, including initintr() */
|
||||||
|
|
||||||
initmain(); /* Module __main__ */
|
initmain(); /* Module __main__ */
|
||||||
|
|
Loading…
Reference in New Issue