diff -r 64ac8c36f413 Modules/zipimport.c --- a/Modules/zipimport.c Thu Aug 16 23:43:50 2012 +0200 +++ b/Modules/zipimport.c Thu Aug 16 23:51:04 2012 +0200 @@ -42,9 +42,46 @@ PyObject *files; /* dict with file info {path: toc_entry} */ }; -static PyObject *ZipImportError; +typedef struct { + PyObject *ZipImportError; + PyObject *zip_directory_cache; + PyObject *ZipImporter_Type; +} zipimportstate; + +#define zipimport_state(o) ((zipimportstate *)PyModule_GetState(o)) + +static int +zipimport_clear(PyObject *m) +{ + zipimportstate *state = zipimport_state(m); + Py_CLEAR(state->ZipImportError); + Py_CLEAR(state->zip_directory_cache); + Py_CLEAR(state->ZipImporter_Type); + return 0; +} + +static int +zipimport_traverse(PyObject *m, visitproc visit, void *arg) +{ + zipimportstate *state = zipimport_state(m); + Py_VISIT(state->ZipImportError); + Py_VISIT(state->zip_directory_cache); + Py_VISIT(state->ZipImporter_Type); + return 0; +} + +static void +zipimport_free(void *m) +{ + zipimport_clear((PyObject *)m); +} + +static PyModuleDef zipimportmodule; + +#define zipimportstate_global ((zipimportstate *)PyModule_GetState(PyState_FindModule(&zipimportmodule))) + /* read_directory() cache */ -static PyObject *zip_directory_cache = NULL; + /* forward decls */ static PyObject *read_directory(PyObject *archive); @@ -53,7 +90,7 @@ int *p_ispackage, PyObject **p_modpath); -#define ZipImporter_Check(op) PyObject_TypeCheck(op, &ZipImporter_Type) +#define ZipImporter_Check(op) PyObject_TypeCheck(op, zipimportstate_global->ZipImporter_Type) /* zipimporter.__init__ @@ -82,7 +119,7 @@ len = PyUnicode_GET_LENGTH(path); if (len == 0) { - PyErr_SetString(ZipImportError, "archive path is empty"); + PyErr_SetString(zipimportstate_global->ZipImportError, "archive path is empty"); goto error; } @@ -119,19 +156,19 @@ filename = PyUnicode_Substring(path, 0, flen); } if (filename == NULL) { - PyErr_SetString(ZipImportError, "not a Zip file"); + PyErr_SetString(zipimportstate_global->ZipImportError, "not a Zip file"); goto error; } if (PyUnicode_READY(filename) < 0) goto error; - files = PyDict_GetItem(zip_directory_cache, filename); + files = PyDict_GetItem(zipimportstate_global->zip_directory_cache, filename); if (files == NULL) { files = read_directory(filename); if (files == NULL) goto error; - if (PyDict_SetItem(zip_directory_cache, filename, files) != 0) + if (PyDict_SetItem(zipimportstate_global->zip_directory_cache, filename, files) != 0) goto error; } else @@ -181,11 +218,15 @@ static void zipimporter_dealloc(ZipImporter *self) { + PyTypeObject *type = Py_TYPE(self); PyObject_GC_UnTrack(self); Py_XDECREF(self->archive); Py_XDECREF(self->prefix); Py_XDECREF(self->files); - Py_TYPE(self)->tp_free((PyObject *)self); + type->tp_free((PyObject *)self); + if((void *)type->tp_dealloc == (void *)zipimporter_dealloc) { + Py_DECREF(type); + } } static PyObject * @@ -538,7 +579,7 @@ if (mi == MI_ERROR) return NULL; if (mi == MI_NOT_FOUND) { - PyErr_Format(ZipImportError, "can't find module %R", fullname); + PyErr_Format(zipimportstate_global->ZipImportError, "can't find module %R", fullname); return NULL; } return PyBool_FromLong(mi == MI_PACKAGE); @@ -622,7 +663,7 @@ if (mi == MI_ERROR) return NULL; if (mi == MI_NOT_FOUND) { - PyErr_Format(ZipImportError, "can't find module %R", fullname); + PyErr_Format(zipimportstate_global->ZipImportError, "can't find module %R", fullname); return NULL; } @@ -761,50 +802,34 @@ #define DEFERRED_ADDRESS(ADDR) 0 -static PyTypeObject ZipImporter_Type = { - PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0) + + +static PyType_Slot ZipImporter_Type_slots[] = { + {Py_tp_dealloc, (destructor)zipimporter_dealloc}, + {Py_tp_repr, (reprfunc)zipimporter_repr}, + {Py_tp_getattro, PyObject_GenericGetAttr}, + {Py_tp_doc, zipimporter_doc}, + {Py_tp_traverse, zipimporter_traverse}, + {Py_tp_methods, zipimporter_methods}, + {Py_tp_members, zipimporter_members}, + {Py_tp_init, (initproc)zipimporter_init}, + {Py_tp_alloc, PyType_GenericAlloc}, + {Py_tp_new, PyType_GenericNew}, + {Py_tp_free, PyObject_GC_Del}, + {0, 0} +}; + +static PyType_Spec ZipImporter_Type_spec = { "zipimport.zipimporter", sizeof(ZipImporter), - 0, /* tp_itemsize */ - (destructor)zipimporter_dealloc, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - (reprfunc)zipimporter_repr, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - 0, /* tp_setattro */ - 0, /* tp_as_buffer */ + 0, Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | - Py_TPFLAGS_HAVE_GC, /* tp_flags */ - zipimporter_doc, /* tp_doc */ - zipimporter_traverse, /* tp_traverse */ - 0, /* tp_clear */ - 0, /* tp_richcompare */ - 0, /* tp_weaklistoffset */ - 0, /* tp_iter */ - 0, /* tp_iternext */ - zipimporter_methods, /* tp_methods */ - zipimporter_members, /* tp_members */ - 0, /* tp_getset */ - 0, /* tp_base */ - 0, /* tp_dict */ - 0, /* tp_descr_get */ - 0, /* tp_descr_set */ - 0, /* tp_dictoffset */ - (initproc)zipimporter_init, /* tp_init */ - PyType_GenericAlloc, /* tp_alloc */ - PyType_GenericNew, /* tp_new */ - PyObject_GC_Del, /* tp_free */ + Py_TPFLAGS_HAVE_GC, + ZipImporter_Type_slots, }; + /* implementation */ /* Given a buffer, return the long that is represented by the first @@ -868,20 +893,20 @@ fp = _Py_fopen(archive, "rb"); if (fp == NULL) { if (!PyErr_Occurred()) - PyErr_Format(ZipImportError, "can't open Zip file: %R", archive); + PyErr_Format(zipimportstate_global->ZipImportError, "can't open Zip file: %R", archive); return NULL; } fseek(fp, -22, SEEK_END); header_position = ftell(fp); if (fread(endof_central_dir, 1, 22, fp) != 22) { fclose(fp); - PyErr_Format(ZipImportError, "can't read Zip file: %R", archive); + PyErr_Format(zipimportstate_global->ZipImportError, "can't read Zip file: %R", archive); return NULL; } if (get_long((unsigned char *)endof_central_dir) != 0x06054B50) { /* Bad: End of Central Dir signature */ fclose(fp); - PyErr_Format(ZipImportError, "not a Zip file: %R", archive); + PyErr_Format(zipimportstate_global->ZipImportError, "not a Zip file: %R", archive); return NULL; } @@ -1050,7 +1075,7 @@ l = PyMarshal_ReadLongFromFile(fp); if (l != 0x04034B50) { /* Bad: Local File Header */ - PyErr_Format(ZipImportError, + PyErr_Format(zipimportstate_global->ZipImportError, "bad local file header in %U", archive); fclose(fp); @@ -1098,7 +1123,7 @@ /* Decompress with zlib */ decompress = get_decompress_func(); if (decompress == NULL) { - PyErr_SetString(ZipImportError, + PyErr_SetString(zipimportstate_global->ZipImportError, "can't decompress data; " "zlib not available"); goto error; @@ -1136,7 +1161,7 @@ Py_ssize_t size = PyBytes_Size(data); if (size <= 9) { - PyErr_SetString(ZipImportError, + PyErr_SetString(zipimportstate_global->ZipImportError, "bad pyc data"); return NULL; } @@ -1376,7 +1401,7 @@ else Py_CLEAR(fullpath); } - PyErr_Format(ZipImportError, "can't find module %R", fullname); + PyErr_Format(zipimportstate_global->ZipImportError, "can't find module %R", fullname); exit: Py_DECREF(path); Py_XDECREF(fullpath); @@ -1404,20 +1429,29 @@ PyModuleDef_HEAD_INIT, "zipimport", zipimport_doc, - -1, + sizeof(zipimportstate), NULL, NULL, - NULL, - NULL, - NULL + zipimport_traverse, + zipimport_clear, + zipimport_free }; PyMODINIT_FUNC PyInit_zipimport(void) { PyObject *mod; + zipimportstate *state; - if (PyType_Ready(&ZipImporter_Type) < 0) + mod = PyModule_Create(&zipimportmodule); + if (mod == NULL) + return NULL; + + state = zipimport_state(mod); + + state->ZipImporter_Type = + PyType_FromSpec(&ZipImporter_Type_spec); + if (state->ZipImporter_Type == NULL) return NULL; /* Correct directory separator */ @@ -1435,31 +1469,27 @@ zip_searchorder[4] = tmp; } - mod = PyModule_Create(&zipimportmodule); - if (mod == NULL) + state->ZipImportError = PyErr_NewException("zipimport.ZipImportError", + PyExc_ImportError, NULL); + if (state->ZipImportError == NULL) return NULL; - ZipImportError = PyErr_NewException("zipimport.ZipImportError", - PyExc_ImportError, NULL); - if (ZipImportError == NULL) + Py_INCREF(state->ZipImportError); + if (PyModule_AddObject(mod, "ZipImportError", + state->ZipImportError) < 0) return NULL; - Py_INCREF(ZipImportError); - if (PyModule_AddObject(mod, "ZipImportError", - ZipImportError) < 0) + Py_INCREF(state->ZipImporter_Type); + if (PyModule_AddObject(mod, "zipimporter", + state->ZipImporter_Type) < 0) return NULL; - Py_INCREF(&ZipImporter_Type); - if (PyModule_AddObject(mod, "zipimporter", - (PyObject *)&ZipImporter_Type) < 0) + state->zip_directory_cache = PyDict_New(); + if (state->zip_directory_cache == NULL) return NULL; - - zip_directory_cache = PyDict_New(); - if (zip_directory_cache == NULL) - return NULL; - Py_INCREF(zip_directory_cache); + Py_INCREF(state->zip_directory_cache); if (PyModule_AddObject(mod, "_zip_directory_cache", - zip_directory_cache) < 0) + state->zip_directory_cache) < 0) return NULL; return mod; }