[Python-checkins] python/dist/src/Python import.c,2.214,2.215 importdl.h,2.18,2.19 pythonrun.c,2.171,2.172
jvr@users.sourceforge.net
jvr@users.sourceforge.net
Mon, 30 Dec 2002 14:08:07 -0800
Update of /cvsroot/python/python/dist/src/Python
In directory sc8-pr-cvs1:/tmp/cvs-serv32400/Python
Modified Files:
import.c importdl.h pythonrun.c
Log Message:
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.
Index: import.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/import.c,v
retrieving revision 2.214
retrieving revision 2.215
diff -C2 -d -r2.214 -r2.215
*** import.c 25 Dec 2002 23:13:34 -0000 2.214
--- import.c 30 Dec 2002 22:08:04 -0000 2.215
***************
*** 154,157 ****
--- 154,223 ----
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
_PyImport_Fini(void)
{
***************
*** 247,250 ****
--- 313,317 ----
"exc_type", "exc_value", "exc_traceback",
"last_type", "last_value", "last_traceback",
+ "path_hooks", "path_importer_cache", "meta_path",
NULL
};
***************
*** 809,815 ****
/* Forward */
! static PyObject *load_module(char *, FILE *, char *, int);
! static struct filedescr *find_module(char *, PyObject *,
! char *, size_t, FILE **);
static struct _frozen *find_frozen(char *name);
--- 876,882 ----
/* Forward */
! static PyObject *load_module(char *, FILE *, char *, int, PyObject *);
! static struct filedescr *find_module(char *, char *, PyObject *,
! char *, size_t, FILE **, PyObject **);
static struct _frozen *find_frozen(char *name);
***************
*** 849,853 ****
}
buf[0] = '\0';
! fdp = find_module("__init__", path, buf, sizeof(buf), &fp);
if (fdp == NULL) {
if (PyErr_ExceptionMatches(PyExc_ImportError)) {
--- 916,920 ----
}
buf[0] = '\0';
! fdp = find_module(name, "__init__", path, buf, sizeof(buf), &fp, NULL);
if (fdp == NULL) {
if (PyErr_ExceptionMatches(PyExc_ImportError)) {
***************
*** 858,862 ****
goto cleanup;
}
! m = load_module(name, fp, buf, fdp->type);
if (fp != NULL)
fclose(fp);
--- 925,929 ----
goto cleanup;
}
! m = load_module(name, fp, buf, fdp->type, NULL);
if (fp != NULL)
fclose(fp);
***************
*** 886,889 ****
--- 953,1011 ----
+ /* 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
corresponding filedescr struct, and (via return arguments) the
***************
*** 897,904 ****
static int case_ok(char *, int, int, char *);
static int find_init_module(char *); /* Forward */
static struct filedescr *
! find_module(char *realname, PyObject *path, char *buf, size_t buflen,
! FILE **p_fp)
{
int i, npath;
--- 1019,1027 ----
static int case_ok(char *, int, int, char *);
static int find_init_module(char *); /* Forward */
+ static struct filedescr importhookdescr = {"", "", IMP_HOOK};
static struct filedescr *
! find_module(char *fullname, char *subname, PyObject *path, char *buf,
! size_t buflen, FILE **p_fp, PyObject **p_loader)
{
int i, npath;
***************
*** 907,910 ****
--- 1030,1034 ----
char *filemode;
FILE *fp = NULL;
+ PyObject *path_hooks, *path_importer_cache;
#ifndef RISCOS
struct stat statbuf;
***************
*** 919,929 ****
char *saved_buf = NULL;
#endif
! if (strlen(realname) > MAXPATHLEN) {
PyErr_SetString(PyExc_OverflowError,
"module name is too long");
return NULL;
}
! strcpy(name, realname);
if (path != NULL && PyString_Check(path)) {
--- 1043,1090 ----
char *saved_buf = NULL;
#endif
+ if (p_loader != NULL)
+ *p_loader = NULL;
! if (strlen(subname) > MAXPATHLEN) {
PyErr_SetString(PyExc_OverflowError,
"module name is too long");
return NULL;
}
! 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)) {
***************
*** 979,982 ****
--- 1140,1159 ----
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);
namelen = strlen(name);
***************
*** 1006,1009 ****
--- 1183,1213 ----
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
/*
***************
*** 1080,1084 ****
* truncate the name before trying
*/
! if (strlen(realname) > 8) {
/* is this an attempt to load a C extension? */
const struct filedescr *scan;
--- 1284,1288 ----
* truncate the name before trying
*/
! if (strlen(subname) > 8) {
/* is this an attempt to load a C extension? */
const struct filedescr *scan;
***************
*** 1093,1097 ****
/* yes, so truncate the name */
namelen = 8;
! len -= strlen(realname) - namelen;
buf[len] = '\0';
}
--- 1297,1301 ----
/* yes, so truncate the name */
namelen = 8;
! len -= strlen(subname) - namelen;
buf[len] = '\0';
}
***************
*** 1445,1449 ****
static PyObject *
! load_module(char *name, FILE *fp, char *buf, int type)
{
PyObject *modules;
--- 1649,1653 ----
static PyObject *
! load_module(char *name, FILE *fp, char *buf, int type, PyObject *loader)
{
PyObject *modules;
***************
*** 1524,1527 ****
--- 1728,1741 ----
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:
PyErr_Format(PyExc_ImportError,
***************
*** 1979,1983 ****
}
else {
! PyObject *path;
char buf[MAXPATHLEN+1];
struct filedescr *fdp;
--- 2193,2197 ----
}
else {
! PyObject *path, *loader = NULL;
char buf[MAXPATHLEN+1];
struct filedescr *fdp;
***************
*** 1996,2000 ****
buf[0] = '\0';
! fdp = find_module(subname, path, buf, MAXPATHLEN+1, &fp);
Py_XDECREF(path);
if (fdp == NULL) {
--- 2210,2215 ----
buf[0] = '\0';
! fdp = find_module(fullname, subname, path, buf, MAXPATHLEN+1,
! &fp, &loader);
Py_XDECREF(path);
if (fdp == NULL) {
***************
*** 2005,2009 ****
return Py_None;
}
! m = load_module(fullname, fp, buf, fdp->type);
if (fp)
fclose(fp);
--- 2220,2225 ----
return Py_None;
}
! m = load_module(fullname, fp, buf, fdp->type, loader);
! Py_XDECREF(loader);
if (fp)
fclose(fp);
***************
*** 2081,2089 ****
}
buf[0] = '\0';
! fdp = find_module(subname, path, buf, MAXPATHLEN+1, &fp);
Py_XDECREF(path);
if (fdp == NULL)
return NULL;
! m = load_module(name, fp, buf, fdp->type);
if (fp)
fclose(fp);
--- 2297,2305 ----
}
buf[0] = '\0';
! fdp = find_module(name, subname, path, buf, MAXPATHLEN+1, &fp, NULL);
Py_XDECREF(path);
if (fdp == NULL)
return NULL;
! m = load_module(name, fp, buf, fdp->type, NULL);
if (fp)
fclose(fp);
***************
*** 2229,2233 ****
if (path == Py_None)
path = NULL;
! fdp = find_module(name, path, pathname, MAXPATHLEN+1, &fp);
if (fdp == NULL)
return NULL;
--- 2445,2449 ----
if (path == Py_None)
path = NULL;
! fdp = find_module(NULL, name, path, pathname, MAXPATHLEN+1, &fp, NULL);
if (fdp == NULL)
return NULL;
***************
*** 2466,2470 ****
return NULL;
}
! return load_module(name, fp, pathname, type);
}
--- 2682,2686 ----
return NULL;
}
! return load_module(name, fp, pathname, type, NULL);
}
***************
*** 2580,2583 ****
--- 2796,2800 ----
if (setint(d, "PY_FROZEN", PY_FROZEN) < 0) goto failure;
if (setint(d, "PY_CODERESOURCE", PY_CODERESOURCE) < 0) goto failure;
+ if (setint(d, "IMP_HOOK", IMP_HOOK) < 0) goto failure;
failure:
Index: importdl.h
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/importdl.h,v
retrieving revision 2.18
retrieving revision 2.19
diff -C2 -d -r2.18 -r2.19
*** importdl.h 26 Feb 2002 11:41:34 -0000 2.18
--- importdl.h 30 Dec 2002 22:08:05 -0000 2.19
***************
*** 17,21 ****
C_BUILTIN,
PY_FROZEN,
! PY_CODERESOURCE /* Mac only */
};
--- 17,22 ----
C_BUILTIN,
PY_FROZEN,
! PY_CODERESOURCE, /* Mac only */
! IMP_HOOK
};
Index: pythonrun.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/pythonrun.c,v
retrieving revision 2.171
retrieving revision 2.172
diff -C2 -d -r2.171 -r2.172
*** pythonrun.c 13 Dec 2002 15:23:00 -0000 2.171
--- pythonrun.c 30 Dec 2002 22:08:05 -0000 2.172
***************
*** 162,165 ****
--- 162,167 ----
_PyImport_FixupExtension("__builtin__", "__builtin__");
+ _PyImportHooks_Init();
+
initsigs(); /* Signal handling stuff, including initintr() */