summaryrefslogtreecommitdiffstats
path: root/Modules/zipimport.c
diff options
context:
space:
mode:
authorBrett Cannon <brett@python.org>2016-01-15 19:22:19 (GMT)
committerBrett Cannon <brett@python.org>2016-01-15 19:22:19 (GMT)
commit56aae8f3043761853504193508d404280a3ec40b (patch)
treee47f204077b6723f54cf0da43a4fc33784844dfb /Modules/zipimport.c
parent07b954d1488c961cf8520f9bdb727925bd4b191e (diff)
downloadcpython-56aae8f3043761853504193508d404280a3ec40b.zip
cpython-56aae8f3043761853504193508d404280a3ec40b.tar.gz
cpython-56aae8f3043761853504193508d404280a3ec40b.tar.bz2
Issue #17633: Improve support for namespace packages with zipimport.
Previously zipimport mistakenly limited namespace support to only the top-level of the zipfile when it should have supported an arbitrary depth. Thanks to Phil Connel for the bug report and initial patch and Mike Romberg for the final patch.
Diffstat (limited to 'Modules/zipimport.c')
-rw-r--r--Modules/zipimport.c48
1 files changed, 32 insertions, 16 deletions
diff --git a/Modules/zipimport.c b/Modules/zipimport.c
index 7220faf..b978f26 100644
--- a/Modules/zipimport.c
+++ b/Modules/zipimport.c
@@ -324,17 +324,14 @@ get_module_info(ZipImporter *self, PyObject *fullname)
}
typedef enum {
- FL_ERROR,
- FL_NOT_FOUND,
- FL_MODULE_FOUND,
- FL_NS_FOUND
+ FL_ERROR = -1, /* error */
+ FL_NOT_FOUND, /* no loader or namespace portions found */
+ FL_MODULE_FOUND, /* module/package found */
+ FL_NS_FOUND /* namespace portion found: */
+ /* *namespace_portion will point to the name */
} find_loader_result;
-/* The guts of "find_loader" and "find_module". Return values:
- -1: error
- 0: no loader or namespace portions found
- 1: module/package found
- 2: namespace portion found: *namespace_portion will point to the name
+/* The guts of "find_loader" and "find_module".
*/
static find_loader_result
find_loader(ZipImporter *self, PyObject *fullname, PyObject **namespace_portion)
@@ -349,21 +346,34 @@ find_loader(ZipImporter *self, PyObject *fullname, PyObject **namespace_portion)
if (mi == MI_NOT_FOUND) {
/* Not a module or regular package. See if this is a directory, and
therefore possibly a portion of a namespace package. */
- int is_dir = check_is_directory(self, self->prefix, fullname);
+ find_loader_result result = FL_NOT_FOUND;
+ PyObject *subname;
+ int is_dir;
+
+ /* We're only interested in the last path component of fullname;
+ earlier components are recorded in self->prefix. */
+ subname = get_subname(fullname);
+ if (subname == NULL) {
+ return FL_ERROR;
+ }
+
+ is_dir = check_is_directory(self, self->prefix, subname);
if (is_dir < 0)
- return -1;
- if (is_dir) {
+ result = FL_ERROR;
+ else if (is_dir) {
/* This is possibly a portion of a namespace
package. Return the string representing its path,
without a trailing separator. */
*namespace_portion = PyUnicode_FromFormat("%U%c%U%U",
self->archive, SEP,
- self->prefix, fullname);
+ self->prefix, subname);
if (*namespace_portion == NULL)
- return FL_ERROR;
- return FL_NS_FOUND;
+ result = FL_ERROR;
+ else
+ result = FL_NS_FOUND;
}
- return FL_NOT_FOUND;
+ Py_DECREF(subname);
+ return result;
}
/* This is a module or package. */
return FL_MODULE_FOUND;
@@ -397,6 +407,9 @@ zipimporter_find_module(PyObject *obj, PyObject *args)
case FL_MODULE_FOUND:
result = (PyObject *)self;
break;
+ default:
+ PyErr_BadInternalCall();
+ return NULL;
}
Py_INCREF(result);
return result;
@@ -433,6 +446,9 @@ zipimporter_find_loader(PyObject *obj, PyObject *args)
result = Py_BuildValue("O[O]", Py_None, namespace_portion);
Py_DECREF(namespace_portion);
return result;
+ default:
+ PyErr_BadInternalCall();
+ return NULL;
}
return result;
}