symbol based python importer in C

This commit is contained in:
roberto@debian32
2011-07-18 18:24:01 +02:00
parent 140a1b1587
commit 9761153ab0
7 changed files with 277 additions and 40 deletions
+219
View File
@@ -0,0 +1,219 @@
#include "uwsgi_python.h"
extern struct uwsgi_server uwsgi;
extern struct uwsgi_python up;
struct _symimporter {
PyObject_HEAD;
} uwsgi_symbol_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_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;
}
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);
mod = PyImport_ExecCodeModuleEx(fullname, code, modname);
Py_DECREF(code);
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) {
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);
modname = uwsgi_concat3("sym://", symbolize(fullname), "___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);
mod = PyImport_ExecCodeModuleEx(fullname, code, modname);
Py_DECREF(code);
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},
};
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 */
PyObject_GC_Del, /* tp_free */
};
int uwsgi_init_symbol_import() {
if (PyType_Ready(&SymImporter_Type) < 0) {
uwsgi_log("unable to initialize symbols importer module\n");
exit(1);
}
PyObject *uwsgi_em = PyImport_ImportModule("uwsgi");
if (!uwsgi_em) {
uwsgi_log("unable to get uwsgi module\n");
exit(1);
}
if (PyModule_AddObject(uwsgi_em, "SymbolsImporter",
(PyObject *)&SymImporter_Type) < 0) {
uwsgi_log("unable to initialize symbols importer module\n");
exit(1);
}
return 0;
}