[Python-checkins] r84013 - python/branches/py3k/Modules/zipimport.c

victor.stinner python-checkins at python.org
Sat Aug 14 16:54:10 CEST 2010


Author: victor.stinner
Date: Sat Aug 14 16:54:10 2010
New Revision: 84013

Log:
Issue #9425: zipimporter_init() is fully unicode compliant


Modified:
   python/branches/py3k/Modules/zipimport.c

Modified: python/branches/py3k/Modules/zipimport.c
==============================================================================
--- python/branches/py3k/Modules/zipimport.c	(original)
+++ python/branches/py3k/Modules/zipimport.c	Sat Aug 14 16:54:10 2010
@@ -60,26 +60,29 @@
 static int
 zipimporter_init(ZipImporter *self, PyObject *args, PyObject *kwds)
 {
-    char *path, *p, *prefix, buf[MAXPATHLEN+2];
-    size_t len;
+    PyObject *pathobj, *path_bytes, *files;
+    Py_UNICODE *path, *p, *prefix, buf[MAXPATHLEN+2];
+    Py_ssize_t len;
 
     if (!_PyArg_NoKeywords("zipimporter()", kwds))
         return -1;
 
-    if (!PyArg_ParseTuple(args, "s:zipimporter", &path))
+    if (!PyArg_ParseTuple(args, "O&:zipimporter",
+        PyUnicode_FSDecoder, &pathobj))
         return -1;
 
-    len = strlen(path);
+    /* copy path to buf */
+    len = PyUnicode_GET_SIZE(pathobj);
     if (len == 0) {
         PyErr_SetString(ZipImportError, "archive path is empty");
-        return -1;
+        goto error;
     }
     if (len >= MAXPATHLEN) {
         PyErr_SetString(ZipImportError,
                         "archive path too long");
-        return -1;
+        goto error;
     }
-    strcpy(buf, path);
+    Py_UNICODE_strcpy(buf, PyUnicode_AS_UNICODE(pathobj));
 
 #ifdef ALTSEP
     for (p = buf; *p; p++) {
@@ -94,7 +97,12 @@
         struct stat statbuf;
         int rv;
 
-        rv = stat(buf, &statbuf);
+        if (pathobj == NULL) {
+            pathobj = PyUnicode_FromUnicode(buf, len);
+            if (pathobj == NULL)
+                goto error;
+        }
+        rv = _Py_stat(pathobj, &statbuf);
         if (rv == 0) {
             /* it exists */
             if (S_ISREG(statbuf.st_mode))
@@ -102,56 +110,64 @@
                 path = buf;
             break;
         }
+        else if (PyErr_Occurred())
+            goto error;
         /* back up one path element */
-        p = strrchr(buf, SEP);
+        p = Py_UNICODE_strrchr(buf, SEP);
         if (prefix != NULL)
             *prefix = SEP;
         if (p == NULL)
             break;
         *p = '\0';
+        len = p - buf;
         prefix = p;
+        Py_CLEAR(pathobj);
     }
-    if (path != NULL) {
-        PyObject *files;
-        files = PyDict_GetItemString(zip_directory_cache, path);
-        if (files == NULL) {
-            files = read_directory(buf);
-            if (files == NULL)
-                return -1;
-            if (PyDict_SetItemString(zip_directory_cache, path,
-                                     files) != 0)
-                return -1;
-        }
-        else
-            Py_INCREF(files);
-        self->files = files;
-    }
-    else {
+    if (path == NULL) {
         PyErr_SetString(ZipImportError, "not a Zip file");
-        return -1;
+        goto error;
     }
 
-    if (prefix == NULL)
-        prefix = "";
-    else {
+    files = PyDict_GetItem(zip_directory_cache, pathobj);
+    if (files == NULL) {
+        path_bytes = PyUnicode_EncodeFSDefault(pathobj);
+        if (path_bytes == NULL)
+            goto error;
+        files = read_directory(PyBytes_AS_STRING(path_bytes));
+        Py_DECREF(path_bytes);
+        if (files == NULL)
+            goto error;
+        if (PyDict_SetItem(zip_directory_cache, pathobj, files) != 0)
+            goto error;
+    }
+    else
+        Py_INCREF(files);
+    self->files = files;
+
+    self->archive = pathobj;
+    pathobj = NULL;
+
+    if (prefix != NULL) {
         prefix++;
-        len = strlen(prefix);
+        len = Py_UNICODE_strlen(prefix);
         if (prefix[len-1] != SEP) {
             /* add trailing SEP */
             prefix[len] = SEP;
             prefix[len + 1] = '\0';
+            len++;
         }
     }
-
-    self->archive = PyUnicode_FromString(buf);
-    if (self->archive == NULL)
-        return -1;
-
-    self->prefix = PyUnicode_FromString(prefix);
+    else
+        len = 0;
+    self->prefix = PyUnicode_FromUnicode(prefix, len);
     if (self->prefix == NULL)
-        return -1;
+        goto error;
 
     return 0;
+
+error:
+    Py_XDECREF(pathobj);
+    return -1;
 }
 
 /* GC support. */


More information about the Python-checkins mailing list