##// END OF EJS Templates
cleared cached signature hash to avoid dangling pointers...
cleared cached signature hash to avoid dangling pointers git-svn-id: svn://svn.code.sf.net/p/pythonqt/code/trunk@244 ea8d5007-eb21-0410-b261-ccb3ea6e24a9

File last commit:

r173:7f1e2590af31
r203:64a9f70b03c9
Show More
PythonQtImporter.cpp
828 lines | 24.4 KiB | text/x-c | CppLexer
/ src / PythonQtImporter.cpp
ezust
reorganized SVN tree into branches, tags and trunk...
r0 /*
*
florianlink
updated old license information and current date...
r133 * Copyright (C) 2010 MeVis Medical Solutions AG All Rights Reserved.
ezust
reorganized SVN tree into branches, tags and trunk...
r0 *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* Further, this software is distributed without any warranty that it is
* free of the rightful claim of any third person regarding infringement
* or the like. Any license provided herein, whether implied or
* otherwise, applies only to this software file. Patent licenses, if
* any, provided herein do not apply to combinations of this program with
* other software, or any other product whatsoever.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
florianlink
updated old license information and current date...
r133 * Contact information: MeVis Medical Solutions AG, Universitaetsallee 29,
ezust
reorganized SVN tree into branches, tags and trunk...
r0 * 28359 Bremen, Germany or:
*
* http://www.mevis.de
*
*/
//----------------------------------------------------------------------------------
/*!
// \file PythonQtImporter.h
// \author Florian Link
// \author Last changed by $Author: florian $
// \date 2006-05
*/
// This module was inspired by the zipimport.c module of the original
// Python distribution. Most of the functions are identical or slightly
// modified to do all the loading of Python files via an external file interface.
// In contrast to zipimport.c, this module also writes *.pyc files
// automatically if it has write access/is not inside of a zip file.
//----------------------------------------------------------------------------------
#include "PythonQtImporter.h"
#include "PythonQtImportFileInterface.h"
#include "PythonQt.h"
florianlink
added support for shared library loading in custom importer by using imp.find_module and imp.load_module...
r83 #include "PythonQtConversion.h"
ezust
reorganized SVN tree into branches, tags and trunk...
r0 #include <QFile>
#include <QFileInfo>
#define IS_SOURCE 0x0
#define IS_BYTECODE 0x1
#define IS_PACKAGE 0x2
struct st_mlab_searchorder {
char suffix[14];
int type;
};
/* mlab_searchorder defines how we search for a module in the Zip
archive: we first search for a package __init__, then for
non-package .pyc, .pyo and .py entries. The .pyc and .pyo entries
are swapped by initmlabimport() if we run in optimized mode. Also,
'/' is replaced by SEP there. */
struct st_mlab_searchorder mlab_searchorder[] = {
{"/__init__.pyc", IS_PACKAGE | IS_BYTECODE},
{"/__init__.pyo", IS_PACKAGE | IS_BYTECODE},
{"/__init__.py", IS_PACKAGE | IS_SOURCE},
{".pyc", IS_BYTECODE},
{".pyo", IS_BYTECODE},
{".py", IS_SOURCE},
{"", 0}
};
extern PyTypeObject PythonQtImporter_Type;
PyObject *PythonQtImportError;
QString PythonQtImport::getSubName(const QString& str)
{
int idx = str.lastIndexOf('.');
if (idx!=-1) {
return str.mid(idx+1);
} else {
return str;
}
}
florianlink
added support for shared library loading in custom importer by using imp.find_module and imp.load_module...
r83 PythonQtImport::ModuleInfo PythonQtImport::getModuleInfo(PythonQtImporter* self, const QString& fullname)
ezust
reorganized SVN tree into branches, tags and trunk...
r0 {
florianlink
added support for shared library loading in custom importer by using imp.find_module and imp.load_module...
r83 ModuleInfo info;
ezust
reorganized SVN tree into branches, tags and trunk...
r0 QString subname;
struct st_mlab_searchorder *zso;
subname = getSubName(fullname);
QString path = *self->_path + "/" + subname;
QString test;
for (zso = mlab_searchorder; *zso->suffix; zso++) {
test = path + zso->suffix;
if (PythonQt::importInterface()->exists(test)) {
florianlink
added support for shared library loading in custom importer by using imp.find_module and imp.load_module...
r83 info.fullPath = test;
info.moduleName = subname;
info.type = (zso->type & IS_PACKAGE)?MI_PACKAGE:MI_MODULE;
return info;
ezust
reorganized SVN tree into branches, tags and trunk...
r0 }
}
florianlink
added support for shared library loading in custom importer by using imp.find_module and imp.load_module...
r83 // test if it is a shared library
foreach(const QString& suffix, PythonQt::priv()->sharedLibrarySuffixes()) {
test = path+suffix;
if (PythonQt::importInterface()->exists(test)) {
info.fullPath = test;
info.moduleName = subname;
info.type = MI_SHAREDLIBRARY;
florianlink
updated to upstream state in MeVisLab repository...
r157 return info;
florianlink
added support for shared library loading in custom importer by using imp.find_module and imp.load_module...
r83 }
florianlink
syncing with my current work, updating to 1.2, see changelog...
r10 }
florianlink
added support for shared library loading in custom importer by using imp.find_module and imp.load_module...
r83 return info;
ezust
reorganized SVN tree into branches, tags and trunk...
r0 }
/* PythonQtImporter.__init__
florianlink
changed so that paths are ignored when they startWith() an ignore path instead of matching the ignore path...
r40 Just store the path argument (or reject if it is in the ignorePaths list
ezust
reorganized SVN tree into branches, tags and trunk...
r0 */
florianlink
- removed warnings...
r8 int PythonQtImporter_init(PythonQtImporter *self, PyObject *args, PyObject * /*kwds*/)
ezust
reorganized SVN tree into branches, tags and trunk...
r0 {
self->_path = NULL;
florianlink
changed so that paths are ignored when they startWith() an ignore path instead of matching the ignore path...
r40 const char* cpath;
ezust
reorganized SVN tree into branches, tags and trunk...
r0 if (!PyArg_ParseTuple(args, "s",
florianlink
changed so that paths are ignored when they startWith() an ignore path instead of matching the ignore path...
r40 &cpath))
ezust
reorganized SVN tree into branches, tags and trunk...
r0 return -1;
florianlink
changed so that paths are ignored when they startWith() an ignore path instead of matching the ignore path...
r40 QString path(cpath);
ezust
reorganized SVN tree into branches, tags and trunk...
r0 if (PythonQt::importInterface()->exists(path)) {
const QStringList& ignorePaths = PythonQt::self()->getImporterIgnorePaths();
florianlink
changed so that paths are ignored when they startWith() an ignore path instead of matching the ignore path...
r40 foreach(QString ignorePath, ignorePaths) {
if (path.startsWith(ignorePath)) {
ezust
reorganized SVN tree into branches, tags and trunk...
r0 PyErr_SetString(PythonQtImportError,
"path ignored");
return -1;
}
}
florianlink
changed so that paths are ignored when they startWith() an ignore path instead of matching the ignore path...
r40 self->_path = new QString(path);
ezust
reorganized SVN tree into branches, tags and trunk...
r0 return 0;
} else {
PyErr_SetString(PythonQtImportError,
"path does not exist error");
return -1;
}
}
void
PythonQtImporter_dealloc(PythonQtImporter *self)
{
// free the stored path
if (self->_path) delete self->_path;
// free ourself
self->ob_type->tp_free((PyObject *)self);
}
/* Check whether we can satisfy the import of the module named by
'fullname'. Return self if we can, None if we can't. */
PyObject *
PythonQtImporter_find_module(PyObject *obj, PyObject *args)
{
PythonQtImporter *self = (PythonQtImporter *)obj;
PyObject *path = NULL;
char *fullname;
if (!PyArg_ParseTuple(args, "s|O:PythonQtImporter.find_module",
&fullname, &path))
return NULL;
florianlink
added support for shared library loading in custom importer by using imp.find_module and imp.load_module...
r83 //qDebug() << "looking for " << fullname << " at " << *self->_path;
florianlink
syncing with my current work, updating to 1.2, see changelog...
r10
florianlink
added support for shared library loading in custom importer by using imp.find_module and imp.load_module...
r83 PythonQtImport::ModuleInfo info = PythonQtImport::getModuleInfo(self, fullname);
if (info.type != PythonQtImport::MI_NOT_FOUND) {
ezust
reorganized SVN tree into branches, tags and trunk...
r0 Py_INCREF(self);
return (PyObject *)self;
} else {
Py_INCREF(Py_None);
return Py_None;
}
}
/* Load and return the module named by 'fullname'. */
PyObject *
PythonQtImporter_load_module(PyObject *obj, PyObject *args)
{
PythonQtImporter *self = (PythonQtImporter *)obj;
florianlink
added support for shared library loading in custom importer by using imp.find_module and imp.load_module...
r83 PyObject *code = NULL, *mod = NULL, *dict = NULL;
ezust
reorganized SVN tree into branches, tags and trunk...
r0 char *fullname;
if (!PyArg_ParseTuple(args, "s:PythonQtImporter.load_module",
&fullname))
return NULL;
florianlink
added support for shared library loading in custom importer by using imp.find_module and imp.load_module...
r83 PythonQtImport::ModuleInfo info = PythonQtImport::getModuleInfo(self, fullname);
if (info.type == PythonQtImport::MI_NOT_FOUND) {
ezust
reorganized SVN tree into branches, tags and trunk...
r0 return NULL;
}
florianlink
added support for shared library loading in custom importer by using imp.find_module and imp.load_module...
r83 if (info.type == PythonQtImport::MI_PACKAGE || info.type == PythonQtImport::MI_MODULE) {
QString fullPath;
code = PythonQtImport::getModuleCode(self, fullname, fullPath);
if (code == NULL) {
florianlink
- removed warnings...
r8 return NULL;
}
ezust
reorganized SVN tree into branches, tags and trunk...
r0
florianlink
added support for shared library loading in custom importer by using imp.find_module and imp.load_module...
r83 mod = PyImport_AddModule(fullname);
if (mod == NULL) {
florianlink
- removed warnings...
r8 Py_DECREF(code);
return NULL;
}
florianlink
added support for shared library loading in custom importer by using imp.find_module and imp.load_module...
r83 dict = PyModule_GetDict(mod);
if (PyDict_SetItemString(dict, "__loader__", (PyObject *)self) != 0) {
florianlink
- removed warnings...
r8 Py_DECREF(code);
Py_DECREF(mod);
return NULL;
}
florianlink
added support for shared library loading in custom importer by using imp.find_module and imp.load_module...
r83
if (info.type == PythonQtImport::MI_PACKAGE) {
PyObject *pkgpath, *fullpath;
QString subname = info.moduleName;
int err;
fullpath = PyString_FromFormat("%s%c%s",
self->_path->toLatin1().constData(),
SEP,
subname.toLatin1().constData());
if (fullpath == NULL) {
Py_DECREF(code);
Py_DECREF(mod);
return NULL;
}
pkgpath = Py_BuildValue("[O]", fullpath);
Py_DECREF(fullpath);
if (pkgpath == NULL) {
Py_DECREF(code);
Py_DECREF(mod);
return NULL;
}
err = PyDict_SetItemString(dict, "__path__", pkgpath);
Py_DECREF(pkgpath);
if (err != 0) {
Py_DECREF(code);
Py_DECREF(mod);
return NULL;
}
}
florianlink
Updated from current MeVisLab development...
r173
florianlink
added support for shared library loading in custom importer by using imp.find_module and imp.load_module...
r83 mod = PyImport_ExecCodeModuleEx(fullname, code, fullPath.toLatin1().data());
florianlink
Updated from current MeVisLab development...
r173
if (PythonQt::importInterface()) {
PythonQt::importInterface()->importedModule(fullname);
}
florianlink
added support for shared library loading in custom importer by using imp.find_module and imp.load_module...
r83 Py_DECREF(code);
if (Py_VerboseFlag) {
PySys_WriteStderr("import %s # loaded from %s\n",
fullname, fullPath.toLatin1().constData());
}
} else {
PythonQtObjectPtr imp;
imp.setNewRef(PyImport_ImportModule("imp"));
florianlink
updated to upstream state in MeVisLab repository...
r157
florianlink
added support for shared library loading in custom importer by using imp.find_module and imp.load_module...
r83 // Create a PyList with the current path as its single element,
// which is required for find_module (it won't accept a tuple...)
PythonQtObjectPtr pathList;
pathList.setNewRef(PythonQtConv::QStringListToPyList(QStringList() << *self->_path));
QVariantList args;
// Pass the module name without the package prefix
args.append(info.moduleName);
// And the path where we know that the shared library is
args.append(QVariant::fromValue(pathList));
QVariant result = imp.call("find_module", args);
if (result.isValid()) {
florianlink
updated to upstream state in MeVisLab repository...
r157 // This will return a tuple with (file, pathname, description=(suffix,mode,type))
florianlink
added support for shared library loading in custom importer by using imp.find_module and imp.load_module...
r83 QVariantList list = result.toList();
if (list.count()==3) {
// We prepend the full module name (including package prefix)
list.prepend(fullname);
florianlink
updated to upstream state in MeVisLab repository...
r157 #ifdef __linux
#ifdef _DEBUG
// imp_find_module() does not respect the debug suffix '_d' on Linux,
// so it does not return the correct file path and we correct it now
// find_module opened a file to the release library, but that file handle is
// ignored on Linux and Windows, maybe on MacOS also.
list[2] = info.fullPath;
#endif
#endif
// And call "load_module" with (fullname, file, pathname, description=(suffix,mode,type))
florianlink
added support for shared library loading in custom importer by using imp.find_module and imp.load_module...
r83 PythonQtObjectPtr module = imp.call("load_module", list);
mod = module.object();
if (mod) {
Py_INCREF(mod);
}
// Finally, we need to close the file again, which find_module opened for us
PythonQtObjectPtr file = list.at(1);
file.call("close");
}
}
florianlink
syncing with my current work, updating to 1.2, see changelog...
r10 }
ezust
reorganized SVN tree into branches, tags and trunk...
r0 return mod;
}
PyObject *
florianlink
- removed warnings...
r8 PythonQtImporter_get_data(PyObject* /*obj*/, PyObject* /*args*/)
ezust
reorganized SVN tree into branches, tags and trunk...
r0 {
// EXTRA, NOT YET IMPLEMENTED
return NULL;
}
PyObject *
PythonQtImporter_get_code(PyObject *obj, PyObject *args)
{
PythonQtImporter *self = (PythonQtImporter *)obj;
char *fullname;
if (!PyArg_ParseTuple(args, "s:PythonQtImporter.get_code", &fullname))
return NULL;
QString notused;
florianlink
added support for shared library loading in custom importer by using imp.find_module and imp.load_module...
r83 return PythonQtImport::getModuleCode(self, fullname, notused);
ezust
reorganized SVN tree into branches, tags and trunk...
r0 }
PyObject *
florianlink
- removed warnings...
r8 PythonQtImporter_get_source(PyObject * /*obj*/, PyObject * /*args*/)
ezust
reorganized SVN tree into branches, tags and trunk...
r0 {
// EXTRA, NOT YET IMPLEMENTED
return NULL;
}
PyDoc_STRVAR(doc_find_module,
"find_module(fullname, path=None) -> self or None.\n\
\n\
Search for a module specified by 'fullname'. 'fullname' must be the\n\
fully qualified (dotted) module name. It returns the PythonQtImporter\n\
instance itself if the module was found, or None if it wasn't.\n\
The optional 'path' argument is ignored -- it's there for compatibility\n\
with the importer protocol.");
PyDoc_STRVAR(doc_load_module,
"load_module(fullname) -> module.\n\
\n\
Load the module specified by 'fullname'. 'fullname' must be the\n\
fully qualified (dotted) module name. It returns the imported\n\
module, or raises PythonQtImportError if it wasn't found.");
PyDoc_STRVAR(doc_get_data,
"get_data(pathname) -> string with file data.\n\
\n\
Return the data associated with 'pathname'. Raise IOError if\n\
the file wasn't found.");
PyDoc_STRVAR(doc_get_code,
"get_code(fullname) -> code object.\n\
\n\
Return the code object for the specified module. Raise PythonQtImportError\n\
is the module couldn't be found.");
PyDoc_STRVAR(doc_get_source,
"get_source(fullname) -> source string.\n\
\n\
Return the source code for the specified module. Raise PythonQtImportError\n\
is the module couldn't be found, return None if the archive does\n\
contain the module, but has no source for it.");
PyMethodDef PythonQtImporter_methods[] = {
{"find_module", PythonQtImporter_find_module, METH_VARARGS,
doc_find_module},
{"load_module", PythonQtImporter_load_module, METH_VARARGS,
doc_load_module},
{"get_data", PythonQtImporter_get_data, METH_VARARGS,
doc_get_data},
{"get_code", PythonQtImporter_get_code, METH_VARARGS,
doc_get_code},
{"get_source", PythonQtImporter_get_source, METH_VARARGS,
doc_get_source},
florianlink
- removed warnings...
r8 {NULL, NULL, 0 , NULL} /* sentinel */
ezust
reorganized SVN tree into branches, tags and trunk...
r0 };
PyDoc_STRVAR(PythonQtImporter_doc,
"PythonQtImporter(path) -> PythonQtImporter object\n\
\n\
Create a new PythonQtImporter instance. 'path' must be a valid path on disk/or inside of a zip file known to MeVisLab\n\
. Every path is accepted.");
#define DEFERRED_ADDRESS(ADDR) 0
PyTypeObject PythonQtImporter_Type = {
PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
0,
"PythonQtImport.PythonQtImporter",
sizeof(PythonQtImporter),
0, /* tp_itemsize */
(destructor)PythonQtImporter_dealloc, /* 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 */
PyObject_GenericGetAttr, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE , /* tp_flags */
PythonQtImporter_doc, /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
PythonQtImporter_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)PythonQtImporter_init, /* tp_init */
PyType_GenericAlloc, /* tp_alloc */
PyType_GenericNew, /* tp_new */
PyObject_Del, /* tp_free */
};
/* Given a buffer, return the long that is represented by the first
4 bytes, encoded as little endian. This partially reimplements
marshal.c:r_long() */
long
PythonQtImport::getLong(unsigned char *buf)
{
long x;
x = buf[0];
x |= (long)buf[1] << 8;
x |= (long)buf[2] << 16;
x |= (long)buf[3] << 24;
#if SIZEOF_LONG > 4
/* Sign extension for 64-bit machines */
x |= -(x & 0x80000000L);
#endif
return x;
}
FILE *
open_exclusive(const QString& filename)
{
#if defined(O_EXCL)&&defined(O_CREAT)&&defined(O_WRONLY)&&defined(O_TRUNC)
/* Use O_EXCL to avoid a race condition when another process tries to
write the same file. When that happens, our open() call fails,
which is just fine (since it's only a cache).
XXX If the file exists and is writable but the directory is not
writable, the file will never be written. Oh well.
*/
QFile::remove(filename);
int fd;
int flags = O_EXCL|O_CREAT|O_WRONLY|O_TRUNC;
#ifdef O_BINARY
flags |= O_BINARY; /* necessary for Windows */
#endif
#ifdef WIN32
fd = _wopen(filename.ucs2(), flags, 0666);
#else
fd = open(filename.local8Bit(), flags, 0666);
#endif
if (fd < 0)
return NULL;
return fdopen(fd, "wb");
#else
/* Best we can do -- on Windows this can't happen anyway */
return fopen(filename.toLocal8Bit().constData(), "wb");
#endif
}
void PythonQtImport::writeCompiledModule(PyCodeObject *co, const QString& filename, long mtime)
{
FILE *fp;
florianlink
syncing with my current work, updating to 1.2, see changelog...
r10 // we do not want to write Qt resources to disk, do we?
if (filename.startsWith(":")) {
return;
}
ezust
reorganized SVN tree into branches, tags and trunk...
r0 fp = open_exclusive(filename);
if (fp == NULL) {
if (Py_VerboseFlag)
PySys_WriteStderr(
"# can't create %s\n", filename.toLatin1().constData());
return;
}
#if PY_VERSION_HEX < 0x02040000
PyMarshal_WriteLongToFile(PyImport_GetMagicNumber(), fp);
#else
PyMarshal_WriteLongToFile(PyImport_GetMagicNumber(), fp, Py_MARSHAL_VERSION);
#endif
/* First write a 0 for mtime */
#if PY_VERSION_HEX < 0x02040000
PyMarshal_WriteLongToFile(0L, fp);
#else
PyMarshal_WriteLongToFile(0L, fp, Py_MARSHAL_VERSION);
#endif
#if PY_VERSION_HEX < 0x02040000
PyMarshal_WriteObjectToFile((PyObject *)co, fp);
#else
PyMarshal_WriteObjectToFile((PyObject *)co, fp, Py_MARSHAL_VERSION);
#endif
if (ferror(fp)) {
if (Py_VerboseFlag)
PySys_WriteStderr("# can't write %s\n", filename.toLatin1().constData());
/* Don't keep partial file */
fclose(fp);
QFile::remove(filename);
return;
}
/* Now write the true mtime */
fseek(fp, 4L, 0);
#if PY_VERSION_HEX < 0x02040000
PyMarshal_WriteLongToFile(mtime, fp);
#else
PyMarshal_WriteLongToFile(mtime, fp, Py_MARSHAL_VERSION);
#endif
fflush(fp);
fclose(fp);
if (Py_VerboseFlag)
PySys_WriteStderr("# wrote %s\n", filename.toLatin1().constData());
//#ifdef macintosh
// PyMac_setfiletype(cpathname, 'Pyth', 'PYC ');
//#endif
}
/* Given the contents of a .py[co] file in a buffer, unmarshal the data
and return the code object. Return None if it the magic word doesn't
match (we do this instead of raising an exception as we fall back
to .py if available and we don't want to mask other errors).
Returns a new reference. */
PyObject *
PythonQtImport::unmarshalCode(const QString& path, const QByteArray& data, time_t mtime)
{
PyObject *code;
// ugly cast, but Python API is not const safe
char *buf = (char*) data.constData();
int size = data.size();
if (size <= 9) {
PySys_WriteStderr("# %s has bad pyc data\n",
path.toLatin1().constData());
Py_INCREF(Py_None);
return Py_None;
}
if (getLong((unsigned char *)buf) != PyImport_GetMagicNumber()) {
if (Py_VerboseFlag)
PySys_WriteStderr("# %s has bad magic\n",
path.toLatin1().constData());
Py_INCREF(Py_None);
return Py_None;
}
florianlink
updated to upstream state in MeVisLab repository...
r157 if (mtime != 0) {
time_t timeDiff = getLong((unsigned char *)buf + 4) - mtime;
if (timeDiff<0) { timeDiff = -timeDiff; }
if (timeDiff > 1) {
if (Py_VerboseFlag)
PySys_WriteStderr("# %s has bad mtime\n",
path.toLatin1().constData());
Py_INCREF(Py_None);
return Py_None;
}
ezust
reorganized SVN tree into branches, tags and trunk...
r0 }
code = PyMarshal_ReadObjectFromString(buf + 8, size - 8);
if (code == NULL)
return NULL;
if (!PyCode_Check(code)) {
Py_DECREF(code);
PyErr_Format(PyExc_TypeError,
"compiled module %.200s is not a code object",
path.toLatin1().constData());
return NULL;
}
return code;
}
/* Given a string buffer containing Python source code, compile it
return and return a code object as a new reference. */
PyObject *
PythonQtImport::compileSource(const QString& path, const QByteArray& data)
{
PyObject *code;
QByteArray data1 = data;
// in qt4, data is null terminated
// data1.resize(data.size()+1);
// data1.data()[data.size()-1] = 0;
code = Py_CompileString(data.data(), path.toLatin1().constData(),
Py_file_input);
return code;
}
/* Return the code object for the module named by 'fullname' from the
Zip archive as a new reference. */
PyObject *
florianlink
- removed warnings...
r8 PythonQtImport::getCodeFromData(const QString& path, int isbytecode,int /*ispackage*/, time_t mtime)
ezust
reorganized SVN tree into branches, tags and trunk...
r0 {
PyObject *code;
QByteArray qdata;
if (!isbytecode) {
// mlabDebugConst("MLABPython", "reading source " << path);
bool ok;
qdata = PythonQt::importInterface()->readSourceFile(path, ok);
if (!ok) {
// mlabErrorConst("PythonQtImporter","File could not be verified" << path);
return NULL;
}
if (qdata == " ") {
qdata.clear();
}
} else {
qdata = PythonQt::importInterface()->readFileAsBytes(path);
}
if (isbytecode) {
// mlabDebugConst("MLABPython", "reading bytecode " << path);
code = unmarshalCode(path, qdata, mtime);
}
else {
// mlabDebugConst("MLABPython", "compiling source " << path);
code = compileSource(path, qdata);
florianlink
merged in features from the MeVisLab repository...
r4 if (code) {
// save a pyc file if possible
QDateTime time;
florianlink
- removed warnings...
r8 time = PythonQt::importInterface()->lastModifiedDate(path);
florianlink
merged in features from the MeVisLab repository...
r4 writeCompiledModule((PyCodeObject*)code, path+"c", time.toTime_t());
}
ezust
reorganized SVN tree into branches, tags and trunk...
r0 }
return code;
}
time_t
PythonQtImport::getMTimeOfSource(const QString& path)
{
time_t mtime = 0;
QString path2 = path;
path2.truncate(path.length()-1);
florianlink
- removed warnings...
r8 if (PythonQt::importInterface()->exists(path2)) {
florianlink
updated to upstream state in MeVisLab repository...
r157 QDateTime t = PythonQt::importInterface()->lastModifiedDate(path2);
if (t.isValid()) {
mtime = t.toTime_t();
}
ezust
reorganized SVN tree into branches, tags and trunk...
r0 }
florianlink
- removed warnings...
r8
ezust
reorganized SVN tree into branches, tags and trunk...
r0 return mtime;
}
/* Get the code object associated with the module specified by
'fullname'. */
PyObject *
florianlink
added support for shared library loading in custom importer by using imp.find_module and imp.load_module...
r83 PythonQtImport::getModuleCode(PythonQtImporter *self, const char* fullname, QString& modpath)
ezust
reorganized SVN tree into branches, tags and trunk...
r0 {
QString subname;
struct st_mlab_searchorder *zso;
subname = getSubName(fullname);
QString path = *self->_path + "/" + subname;
QString test;
for (zso = mlab_searchorder; *zso->suffix; zso++) {
PyObject *code = NULL;
test = path + zso->suffix;
if (Py_VerboseFlag > 1)
PySys_WriteStderr("# trying %s\n",
test.toLatin1().constData());
if (PythonQt::importInterface()->exists(test)) {
time_t mtime = 0;
int ispackage = zso->type & IS_PACKAGE;
int isbytecode = zso->type & IS_BYTECODE;
florianlink
updated to upstream state in MeVisLab repository...
r157 // if ignoreUpdatedPythonSourceFiles() returns true, then mtime stays 0
// and unmarshalCode() in getCodeFromData() will always read an existing *.pyc file,
// even if a newer *.py file exists. This is a release optimization where
// typically only *.pyc files are delivered without *.py files and reading file
// modification time is slow.
if (isbytecode && !PythonQt::importInterface()->ignoreUpdatedPythonSourceFiles()) {
ezust
reorganized SVN tree into branches, tags and trunk...
r0 mtime = getMTimeOfSource(test);
florianlink
added support for shared library loading in custom importer by using imp.find_module and imp.load_module...
r83 }
ezust
reorganized SVN tree into branches, tags and trunk...
r0 code = getCodeFromData(test, isbytecode, ispackage, mtime);
if (code == Py_None) {
Py_DECREF(code);
continue;
}
florianlink
added support for shared library loading in custom importer by using imp.find_module and imp.load_module...
r83 if (code != NULL) {
ezust
reorganized SVN tree into branches, tags and trunk...
r0 modpath = test;
florianlink
added support for shared library loading in custom importer by using imp.find_module and imp.load_module...
r83 }
ezust
reorganized SVN tree into branches, tags and trunk...
r0 return code;
}
}
PyErr_Format(PythonQtImportError, "can't find module '%.200s'", fullname);
return NULL;
}
QString PythonQtImport::replaceExtension(const QString& str, const QString& ext)
{
QString r;
int i = str.lastIndexOf('.');
if (i!=-1) {
r = str.mid(0,i) + "." + ext;
} else {
r = str + "." + ext;
}
return r;
}
PyObject* PythonQtImport::getCodeFromPyc(const QString& file)
{
PyObject* code;
const static QString pycStr("pyc");
QString pyc = replaceExtension(file, pycStr);
florianlink
- removed warnings...
r8 if (PythonQt::importInterface()->exists(pyc)) {
ezust
reorganized SVN tree into branches, tags and trunk...
r0 time_t mtime = 0;
florianlink
updated to upstream state in MeVisLab repository...
r157 // if ignoreUpdatedPythonSourceFiles() returns true, then mtime stays 0
// and unmarshalCode() in getCodeFromData() will always read an existing *.pyc file,
// even if a newer *.py file exists. This is a release optimization where
// typically only *.pyc files are delivered without *.py files and reading file
// modification time is slow.
if (!PythonQt::importInterface()->ignoreUpdatedPythonSourceFiles()) {
mtime = getMTimeOfSource(pyc);
}
ezust
reorganized SVN tree into branches, tags and trunk...
r0 code = getCodeFromData(pyc, true, false, mtime);
if (code != Py_None && code != NULL) {
return code;
}
if (code) {
Py_DECREF(code);
}
}
code = getCodeFromData(file,false,false,0);
return code;
}
/* Module init */
PyDoc_STRVAR(mlabimport_doc,
florianlink
- removed warnings...
r8 "Imports python files into PythonQt, completely replaces internal python import");
ezust
reorganized SVN tree into branches, tags and trunk...
r0
void PythonQtImport::init()
{
florianlink
- removed warnings...
r8 static bool first = true;
if (!first) {
return;
}
first = false;
ezust
reorganized SVN tree into branches, tags and trunk...
r0 PyObject *mod;
if (PyType_Ready(&PythonQtImporter_Type) < 0)
return;
/* Correct directory separator */
mlab_searchorder[0].suffix[0] = SEP;
mlab_searchorder[1].suffix[0] = SEP;
mlab_searchorder[2].suffix[0] = SEP;
if (Py_OptimizeFlag) {
/* Reverse *.pyc and *.pyo */
struct st_mlab_searchorder tmp;
tmp = mlab_searchorder[0];
mlab_searchorder[0] = mlab_searchorder[1];
mlab_searchorder[1] = tmp;
tmp = mlab_searchorder[3];
mlab_searchorder[3] = mlab_searchorder[4];
mlab_searchorder[4] = tmp;
}
mod = Py_InitModule4("PythonQtImport", NULL, mlabimport_doc,
NULL, PYTHON_API_VERSION);
florianlink
merged contributions from https://github.com/commontk/PythonQt/compare/svn-mirror...patched...
r161 PythonQtImportError = PyErr_NewException(const_cast<char*>("PythonQtImport.PythonQtImportError"),
ezust
reorganized SVN tree into branches, tags and trunk...
r0 PyExc_ImportError, NULL);
if (PythonQtImportError == NULL)
return;
Py_INCREF(PythonQtImportError);
if (PyModule_AddObject(mod, "PythonQtImportError",
PythonQtImportError) < 0)
return;
Py_INCREF(&PythonQtImporter_Type);
if (PyModule_AddObject(mod, "PythonQtImporter",
(PyObject *)&PythonQtImporter_Type) < 0)
return;
// set our importer into the path_hooks to handle all path on sys.path
PyObject* classobj = PyDict_GetItemString(PyModule_GetDict(mod), "PythonQtImporter");
florianlink
merged contributions from https://github.com/commontk/PythonQt/compare/svn-mirror...patched...
r161 PyObject* path_hooks = PySys_GetObject(const_cast<char*>("path_hooks"));
ezust
reorganized SVN tree into branches, tags and trunk...
r0 PyList_Append(path_hooks, classobj);
florianlink
- removed warnings...
r8
ezust
reorganized SVN tree into branches, tags and trunk...
r0 #ifndef WIN32
// reload the encodings module, because it might fail to custom import requirements (e.g. encryption).
PyObject* modules = PyImport_GetModuleDict();
PyObject* encodingsModule = PyDict_GetItemString(modules, "encodings");
if (encodingsModule != NULL) {
PyImport_ReloadModule(encodingsModule);
}
#endif
}