# HG changeset patch
# User Stephen Thorne
# Parent d9c98730e2e87b09096bc98e535e5683cb969ea4
Issue #14905: zipimport.c now does not require directory entries to exist in
the zipfile manifest in order to import modules within namespaces.
diff -r d9c98730e2e8 Lib/test/test_namespace_pkgs.py
--- a/Lib/test/test_namespace_pkgs.py Sat Jul 07 13:34:50 2012 +1000
+++ b/Lib/test/test_namespace_pkgs.py Sat Jul 07 16:45:39 2012 +0200
@@ -254,9 +254,8 @@
class ZipWithMissingDirectory(NamespacePackageTest):
paths = ['missing_directory.zip']
- @unittest.expectedFailure
def test_missing_directory(self):
- # This will fail because missing_directory.zip contains:
+ # missing_directory.zip contains:
# Length Date Time Name
# --------- ---------- ----- ----
# 29 2012-05-03 18:13 foo/one.py
@@ -265,8 +264,8 @@
# --------- -------
# 67 3 files
- # Because there is no 'foo/', the zipimporter currently doesn't
- # know that foo is a namespace package
+ # foo/ should be synthesised and added to zipimporter's internal state,
+ # allowing import foo.one to work.
import foo.one
diff -r d9c98730e2e8 Misc/NEWS
--- a/Misc/NEWS Sat Jul 07 13:34:50 2012 +1000
+++ b/Misc/NEWS Sat Jul 07 16:45:39 2012 +0200
@@ -54,6 +54,9 @@
- Issue #15194: Update libffi to the 3.0.11 release.
+- Issue #14905: zipimport.c now does not require directory entries to exist in
+ the zipfile manifest in order to import modules within namespaces.
+
Tools/Demos
-----------
diff -r d9c98730e2e8 Modules/zipimport.c
--- a/Modules/zipimport.c Sat Jul 07 13:34:50 2012 +1000
+++ b/Modules/zipimport.c Sat Jul 07 16:45:39 2012 +0200
@@ -859,6 +859,7 @@
Py_ssize_t i;
char name[MAXPATHLEN + 5];
PyObject *nameobj = NULL;
+ PyObject *dirnameobj = NULL;
char *p, endof_central_dir[22];
Py_ssize_t arc_offset; /* Absolute offset to start of the zip-archive. */
PyObject *path;
@@ -965,10 +966,40 @@
if (t == NULL)
goto error;
err = PyDict_SetItem(files, nameobj, t);
- Py_CLEAR(nameobj);
Py_DECREF(t);
if (err != 0)
goto error;
+
+ Py_UCS4 c;
+ for (i = 0; i < PyUnicode_GetLength(nameobj) - 1; i++) {
+ c = PyUnicode_READ_CHAR(nameobj, i);
+ if (c != SEP)
+ continue;
+
+ dirnameobj = PyUnicode_Substring(nameobj, 0, i+1);
+ if (dirnameobj == NULL)
+ goto error;
+ if (PyDict_Contains(files, dirnameobj)) {
+ Py_CLEAR(dirnameobj);
+ continue;
+ }
+
+ path = PyUnicode_FromFormat("%U%c%U", archive, SEP, dirnameobj);
+ if (path == NULL)
+ goto error;
+
+ t = Py_BuildValue("Nhllnhhl", path, 0, 0, 0, 0, 0, 0, 0);
+ if (t == NULL)
+ goto error;
+ err = PyDict_SetItem(files, dirnameobj, t);
+ Py_CLEAR(dirnameobj);
+ Py_DECREF(t);
+ if (err != 0) {
+ goto error;
+ }
+ count++;
+ }
+ Py_CLEAR(nameobj);
count++;
}
fclose(fp);
@@ -980,6 +1011,7 @@
fclose(fp);
Py_XDECREF(files);
Py_XDECREF(nameobj);
+ Py_XDECREF(dirnameobj);
return NULL;
}