#include "uwsgi_python.h" extern struct uwsgi_server uwsgi; extern struct uwsgi_python up; struct _symimporter { PyObject_HEAD; } uwsgi_symbol_importer_object; struct _symzipimporter { PyObject_HEAD; char *prefix; PyObject *zip; PyObject *items; } uwsgi_symbol_zip_importer_object; static char *symbolize(char *name) { char *base = uwsgi_concat2(name, ""); char *ptr = base; while(*ptr != 0) { if (*ptr == '.') { *ptr = '_'; } ptr++; } return base; } static char *name_to_py(char *prefix, char *name) { char *base; char *ptr; if (prefix) { if (prefix[strlen(prefix)-1] == '/') { base = uwsgi_concat3(prefix, name, ".py"); ptr = base + strlen(prefix); } else { base = uwsgi_concat4(prefix, "/", name, ".py"); ptr = base + strlen(prefix) + 1; } } else { base = uwsgi_concat2(name, ".py"); ptr = base; } while(*ptr != 0) { if (*ptr == '.') { *ptr = '/'; } ptr++; } // fix .py ptr-=3; *ptr = '.'; return base; } static char *name_to_init_py(char *prefix, char *name) { char *base; char *ptr; if (prefix) { if (prefix[strlen(prefix)-1] == '/') { base = uwsgi_concat3(prefix, name, "/__init__.py"); ptr = base + strlen(prefix); } else { base = uwsgi_concat4(prefix, "/", name, "/__init__.py"); ptr = base + strlen(prefix) + 1; } } else { base = uwsgi_concat2(name, "/__init__.py"); ptr = base; } while(*ptr != 0) { if (*ptr == '.') { *ptr = '/'; } ptr++; } // fix .py ptr-=3; *ptr = '.'; return base; } static char *name_to_symbol(char *name, char *what) { char *symbol = uwsgi_concat4("_binary_", name, "_", what); char *sym_ptr_start = dlsym(RTLD_DEFAULT, symbol); free(symbol); return sym_ptr_start; } static char *name_to_symbol_module(char *name, char *what) { char *symbol = uwsgi_concat4("_binary_", name, "_py_", what); char *sym_ptr_start = dlsym(RTLD_DEFAULT, symbol); free(symbol); return sym_ptr_start; } static char *name_to_symbol_pkg(char *name, char *what) { char *symbol = uwsgi_concat4("_binary_", name, "___init___py_", what); char *sym_ptr_start = dlsym(RTLD_DEFAULT, symbol); free(symbol); return sym_ptr_start; } int py_list_has_string(PyObject *obj, char *name) { Py_ssize_t i, len = PyList_Size(obj); int found = 0; for(i=0;iprefix, fullname); if (py_list_has_string(this->items, filename)) { free(filename); return self; } PyErr_Clear(); free(filename); filename = name_to_init_py(this->prefix, fullname); if (py_list_has_string(this->items, filename)) { free(filename); return self; } PyErr_Clear(); free(filename); Py_INCREF(Py_None); return Py_None; } static PyObject* symzipimporter_load_module(PyObject *self, PyObject *args) { char *fullname; char *modname; struct _symzipimporter *this = (struct _symzipimporter *) self; if (!PyArg_ParseTuple(args, "s:load_module", &fullname)) { return NULL; } char *filename = name_to_py(this->prefix, fullname); if (py_list_has_string(this->items, filename)) { PyObject *mod = PyImport_AddModule(fullname); if (!mod) goto clear; PyObject *dict = PyModule_GetDict(mod); if (!dict) goto clear; PyDict_SetItemString(dict, "__loader__", self); modname = uwsgi_concat2("symzip://", fullname); PyObject *source = PyObject_CallMethod(this->zip, "read", "(s)", filename); free(filename); PyObject *code = Py_CompileString(PyString_AsString(source), modname, Py_file_input); if (!code) { PyErr_Print(); goto shit; } mod = PyImport_ExecCodeModuleEx(fullname, code, modname); Py_DECREF(code); shit: Py_DECREF(source); free(modname); return mod; } PyErr_Clear(); free(filename); filename = name_to_init_py(this->prefix, fullname); if (py_list_has_string(this->items, filename)) { PyObject *mod = PyImport_AddModule(fullname); if (!mod) goto clear; PyObject *dict = PyModule_GetDict(mod); if (!dict) goto clear; modname = uwsgi_concat2("symzip://", fullname); PyObject *pkgpath = Py_BuildValue("[O]", PyString_FromString(modname)); PyDict_SetItemString(dict, "__path__", pkgpath); PyDict_SetItemString(dict, "__loader__", self); PyObject *source = PyObject_CallMethod(this->zip, "read", "(s)", filename); free(filename); PyObject *code = Py_CompileString(PyString_AsString(source), modname, Py_file_input); if (!code) { PyErr_Print(); goto shit2; } mod = PyImport_ExecCodeModuleEx(fullname, code, modname); Py_DECREF(code); shit2: Py_DECREF(source); free(modname); return mod; } clear: PyErr_Clear(); free(filename); Py_INCREF(Py_None); return Py_None; } static PyObject* symimporter_find_module(PyObject *self, PyObject *args) { char *fullname; PyObject *path = NULL; if (!PyArg_ParseTuple(args, "s|O:find_module", &fullname, &path)) { return NULL; } char *fullname2 = symbolize(fullname); char *code_start = name_to_symbol_module(fullname2, "start"); if (code_start) { free(fullname2); Py_INCREF(self); return self; } code_start = name_to_symbol_pkg(fullname2, "start"); if (code_start) { free(fullname2); Py_INCREF(self); return self; } free(fullname2); Py_INCREF(Py_None); return Py_None; } static PyObject* symimporter_load_module(PyObject *self, PyObject *args) { char *code_start; char *code_end; char *fullname; char *source; char *modname; PyObject *code; if (!PyArg_ParseTuple(args, "s:load_module", &fullname)) { return NULL; } char *fullname2 = symbolize(fullname); code_start = name_to_symbol_module(fullname2, "start"); if (code_start) { code_end = name_to_symbol_module(fullname2, "end"); if (code_end) { PyObject *mod = PyImport_AddModule(fullname); if (!mod) goto clear; PyObject *dict = PyModule_GetDict(mod); if (!dict) goto clear; PyDict_SetItemString(dict, "__loader__", self); source = uwsgi_concat2n(code_start, code_end-code_start, "", 0); modname = uwsgi_concat3("sym://", fullname2, "_py"); code = Py_CompileString(source, modname, Py_file_input); if (!code) { PyErr_Print(); goto shit; } mod = PyImport_ExecCodeModuleEx(fullname, code, modname); Py_DECREF(code); shit: free(source); free(modname); free(fullname2); return mod; } } code_start = name_to_symbol_pkg(fullname2, "start"); if (code_start) { code_end = name_to_symbol_pkg(fullname2, "end"); if (code_end) { char *symbolized; PyObject *mod = PyImport_AddModule(fullname); if (!mod) goto clear; PyObject *dict = PyModule_GetDict(mod); if (!dict) goto clear; source = uwsgi_concat2n(code_start, code_end-code_start, "", 0); symbolized = symbolize(fullname); modname = uwsgi_concat3("sym://", symbolized, "___init___py"); PyObject *pkgpath = Py_BuildValue("[O]", PyString_FromString(modname)); PyDict_SetItemString(dict, "__path__", pkgpath); PyDict_SetItemString(dict, "__loader__", self); code = Py_CompileString(source, modname, Py_file_input); if (!code) { PyErr_Print(); goto shit2; } mod = PyImport_ExecCodeModuleEx(fullname, code, modname); Py_DECREF(code); shit2: free(symbolized); free(source); free(modname); free(fullname2); return mod; } } clear: free(fullname2); Py_INCREF(Py_None); return Py_None; } static PyMethodDef symimporter_methods[] = { {"find_module", symimporter_find_module, METH_VARARGS}, {"load_module", symimporter_load_module, METH_VARARGS}, { NULL, NULL }, }; static PyMethodDef symzipimporter_methods[] = { {"find_module", symzipimporter_find_module, METH_VARARGS}, {"load_module", symzipimporter_load_module, METH_VARARGS}, { NULL, NULL }, }; static void uwsgi_symimporter_free(struct _symimporter *self) { PyObject_Del(self); } static PyTypeObject SymImporter_Type = { PyVarObject_HEAD_INIT(NULL, 0) "uwsgi.SymbolsImporter", sizeof(struct _symimporter), 0, /* tp_itemsize */ (destructor) uwsgi_symimporter_free, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, "uwsgi symbols importer", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ symimporter_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ 0, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ PyType_GenericNew, /* tp_new */ 0, /* tp_free */ }; static int zipimporter_init(struct _symzipimporter *self, PyObject *args, PyObject *kwds) { char *name; char *prefix = NULL; size_t len = 0; if (!PyArg_ParseTuple(args, "s", &name)) return -1; // avoid GC !!! name = uwsgi_concat2(name, ""); if (uwsgi_check_scheme(name)) { prefix = uwsgi_get_last_char(name, '/'); prefix = uwsgi_get_last_char(prefix, ':'); } else { prefix = uwsgi_get_last_char(name, ':'); } if (prefix) { prefix[0] = 0; } char *body = uwsgi_open_and_read(name, &len, 0, NULL); if (!body) { return -1; } PyObject *stringio = PyImport_ImportModule("StringIO"); if (!stringio) { free(body); return -1; } #ifdef PYTHREE PyObject *source_code = PyObject_CallMethodObjArgs(stringio, PyString_FromString("StringIO"), PyString_FromStringAndSize(body, len)); #else PyObject *stringio_dict = PyModule_GetDict(stringio); if (!stringio_dict) { return -1; } PyObject *stringio_stringio = PyDict_GetItemString(stringio_dict, "StringIO"); if (!stringio_stringio) { return -1; } PyObject *stringio_args = PyTuple_New(1); PyTuple_SetItem(stringio_args, 0, PyString_FromStringAndSize(body, len)); PyObject *source_code = PyInstance_New(stringio_stringio, stringio_args, NULL); #endif if (!source_code) { return -1; } PyObject *zipfile = PyImport_ImportModule("zipfile"); if (!zipfile) { PyErr_Print(); return -1; } #ifdef PYTHREE self->zip = PyObject_CallMethodObjArgs(zipfile, PyString_FromString("ZipFile"), source_code); #else PyObject *zipfile_dict = PyModule_GetDict(zipfile); if (!zipfile_dict) { return -1; } PyObject *zipfile_zipfile = PyDict_GetItemString(zipfile_dict, "ZipFile"); if (!zipfile_zipfile) { return -1; } PyObject *zipfile_args = PyTuple_New(1); PyTuple_SetItem(zipfile_args, 0, source_code); self->zip = PyInstance_New(zipfile_zipfile, zipfile_args, NULL); #endif if (!self->zip) { return -1; } Py_INCREF(self->zip); self->items = PyObject_CallMethod(self->zip, "namelist", NULL); if (!self->items) { return -1; } Py_INCREF(self->items); self->prefix = NULL; if (prefix) { self->prefix = prefix+1; prefix[0] = ':'; } return 0; } static int symzipimporter_init(struct _symzipimporter *self, PyObject *args, PyObject *kwds) { char *name; char *prefix = NULL; if (!PyArg_ParseTuple(args, "s", &name)) return -1; // avoid GC !!! name = uwsgi_concat2(name, ""); prefix = strchr(name, ':'); if (prefix) { prefix[0] = 0; } char *code_start = name_to_symbol(name, "start"); if (!code_start) { PyErr_Format(PyExc_ValueError, "unable to find symbol"); goto error; } char *code_end = name_to_symbol(name, "end"); if (!code_end) { PyErr_Format(PyExc_ValueError, "unable to find symbol"); goto error; } PyObject *stringio = PyImport_ImportModule("StringIO"); if (!stringio) { goto error; } #ifdef PYTHREE PyObject *source_code = PyObject_CallMethodObjArgs(stringio, PyString_FromString("StringIO"), PyString_FromStringAndSize(code_start, code_end-code_start)); #else PyObject *stringio_dict = PyModule_GetDict(stringio); if (!stringio_dict) { goto error; } PyObject *stringio_stringio = PyDict_GetItemString(stringio_dict, "StringIO"); if (!stringio_stringio) { goto error; } PyObject *stringio_args = PyTuple_New(1); PyTuple_SetItem(stringio_args, 0, PyString_FromStringAndSize(code_start, code_end-code_start)); PyObject *source_code = PyInstance_New(stringio_stringio, stringio_args, NULL); #endif if (!source_code) { goto error; } PyObject *zipfile = PyImport_ImportModule("zipfile"); if (!zipfile) { goto error; } #ifdef PYTHREE self->zip = PyObject_CallMethodObjArgs(zipfile, PyString_FromString("ZipFile"), source_code); #else PyObject *zipfile_dict = PyModule_GetDict(zipfile); if (!zipfile_dict) { goto error; } PyObject *zipfile_zipfile = PyDict_GetItemString(zipfile_dict, "ZipFile"); if (!zipfile_zipfile) { goto error; } PyObject *zipfile_args = PyTuple_New(1); PyTuple_SetItem(zipfile_args, 0, source_code); self->zip = PyInstance_New(zipfile_zipfile, zipfile_args, NULL); #endif if (!self->zip) { goto error; } Py_INCREF(self->zip); self->items = PyObject_CallMethod(self->zip, "namelist", NULL); if (!self->items) { goto error; } Py_INCREF(self->items); self->prefix = NULL; if (prefix) { self->prefix = prefix+1; prefix[0] = ':'; } return 0; error: free(name); return -1; } static PyTypeObject SymZipImporter_Type = { PyVarObject_HEAD_INIT(NULL, 0) "uwsgi.SymbolsZipImporter", sizeof(struct _symzipimporter), 0, /* tp_itemsize */ (destructor) uwsgi_symimporter_free, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, "uwsgi symbols zip importer", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ symzipimporter_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ (initproc) symzipimporter_init, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ PyType_GenericNew, /* tp_new */ 0, /* tp_free */ }; static PyTypeObject ZipImporter_Type = { PyVarObject_HEAD_INIT(NULL, 0) "uwsgi.ZipImporter", sizeof(struct _symzipimporter), 0, /* tp_itemsize */ (destructor) uwsgi_symimporter_free, /* tp_dealloc */ 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ 0, /* tp_getattro */ 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT, "uwsgi zip importer", /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ symzipimporter_methods, /* tp_methods */ 0, /* 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 */ 0, /* tp_free */ }; int uwsgi_init_symbol_import() { if (PyType_Ready(&SymImporter_Type) < 0) { PyErr_Print(); uwsgi_log("unable to initialize symbols importer module\n"); exit(1); } if (PyType_Ready(&ZipImporter_Type) < 0) { PyErr_Print(); uwsgi_log("unable to initialize zip importer module\n"); exit(1); } if (PyType_Ready(&SymZipImporter_Type) < 0) { PyErr_Print(); uwsgi_log("unable to initialize symbols zip importer module\n"); exit(1); } PyObject *uwsgi_em = PyImport_ImportModule("uwsgi"); if (!uwsgi_em) { PyErr_Print(); uwsgi_log("unable to get uwsgi module\n"); exit(1); } Py_INCREF((PyObject *)&SymImporter_Type); if (PyModule_AddObject(uwsgi_em, "SymbolsImporter", (PyObject *)&SymImporter_Type) < 0) { PyErr_Print(); uwsgi_log("unable to initialize symbols importer object\n"); exit(1); } Py_INCREF((PyObject *)&ZipImporter_Type); if (PyModule_AddObject(uwsgi_em, "ZipImporter", (PyObject *)&ZipImporter_Type) < 0) { PyErr_Print(); uwsgi_log("unable to initialize zip importer object\n"); exit(1); } Py_INCREF((PyObject *)&SymZipImporter_Type); if (PyModule_AddObject(uwsgi_em, "SymbolsZipImporter", (PyObject *)&SymZipImporter_Type) < 0) { PyErr_Print(); uwsgi_log("unable to initialize symbols zip importer object\n"); exit(1); } return 0; }