##// END OF EJS Templates
changed so that paths are ignored when they startWith() an ignore path instead of matching the ignore path...
florianlink -
r40:054959ca17a1
parent child
Show More
@@ -1,792 +1,788
1 /*
1 /*
2 *
2 *
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
3 * Copyright (C) 2006 MeVis Research GmbH All Rights Reserved.
4 *
4 *
5 * This library is free software; you can redistribute it and/or
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
8 * version 2.1 of the License, or (at your option) any later version.
9 *
9 *
10 * This library is distributed in the hope that it will be useful,
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
13 * Lesser General Public License for more details.
14 *
14 *
15 * Further, this software is distributed without any warranty that it is
15 * Further, this software is distributed without any warranty that it is
16 * free of the rightful claim of any third person regarding infringement
16 * free of the rightful claim of any third person regarding infringement
17 * or the like. Any license provided herein, whether implied or
17 * or the like. Any license provided herein, whether implied or
18 * otherwise, applies only to this software file. Patent licenses, if
18 * otherwise, applies only to this software file. Patent licenses, if
19 * any, provided herein do not apply to combinations of this program with
19 * any, provided herein do not apply to combinations of this program with
20 * other software, or any other product whatsoever.
20 * other software, or any other product whatsoever.
21 *
21 *
22 * You should have received a copy of the GNU Lesser General Public
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 *
25 *
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
26 * Contact information: MeVis Research GmbH, Universitaetsallee 29,
27 * 28359 Bremen, Germany or:
27 * 28359 Bremen, Germany or:
28 *
28 *
29 * http://www.mevis.de
29 * http://www.mevis.de
30 *
30 *
31 */
31 */
32
32
33 //----------------------------------------------------------------------------------
33 //----------------------------------------------------------------------------------
34 /*!
34 /*!
35 // \file PythonQtImporter.h
35 // \file PythonQtImporter.h
36 // \author Florian Link
36 // \author Florian Link
37 // \author Last changed by $Author: florian $
37 // \author Last changed by $Author: florian $
38 // \date 2006-05
38 // \date 2006-05
39 */
39 */
40 // This module was inspired by the zipimport.c module of the original
40 // This module was inspired by the zipimport.c module of the original
41 // Python distribution. Most of the functions are identical or slightly
41 // Python distribution. Most of the functions are identical or slightly
42 // modified to do all the loading of Python files via an external file interface.
42 // modified to do all the loading of Python files via an external file interface.
43 // In contrast to zipimport.c, this module also writes *.pyc files
43 // In contrast to zipimport.c, this module also writes *.pyc files
44 // automatically if it has write access/is not inside of a zip file.
44 // automatically if it has write access/is not inside of a zip file.
45 //----------------------------------------------------------------------------------
45 //----------------------------------------------------------------------------------
46
46
47 #include "PythonQtImporter.h"
47 #include "PythonQtImporter.h"
48 #include "PythonQtImportFileInterface.h"
48 #include "PythonQtImportFileInterface.h"
49 #include "PythonQt.h"
49 #include "PythonQt.h"
50 #include <QFile>
50 #include <QFile>
51 #include <QFileInfo>
51 #include <QFileInfo>
52
52
53 #define IS_SOURCE 0x0
53 #define IS_SOURCE 0x0
54 #define IS_BYTECODE 0x1
54 #define IS_BYTECODE 0x1
55 #define IS_PACKAGE 0x2
55 #define IS_PACKAGE 0x2
56
56
57 struct st_mlab_searchorder {
57 struct st_mlab_searchorder {
58 char suffix[14];
58 char suffix[14];
59 int type;
59 int type;
60 };
60 };
61
61
62 /* mlab_searchorder defines how we search for a module in the Zip
62 /* mlab_searchorder defines how we search for a module in the Zip
63 archive: we first search for a package __init__, then for
63 archive: we first search for a package __init__, then for
64 non-package .pyc, .pyo and .py entries. The .pyc and .pyo entries
64 non-package .pyc, .pyo and .py entries. The .pyc and .pyo entries
65 are swapped by initmlabimport() if we run in optimized mode. Also,
65 are swapped by initmlabimport() if we run in optimized mode. Also,
66 '/' is replaced by SEP there. */
66 '/' is replaced by SEP there. */
67 struct st_mlab_searchorder mlab_searchorder[] = {
67 struct st_mlab_searchorder mlab_searchorder[] = {
68 {"/__init__.pyc", IS_PACKAGE | IS_BYTECODE},
68 {"/__init__.pyc", IS_PACKAGE | IS_BYTECODE},
69 {"/__init__.pyo", IS_PACKAGE | IS_BYTECODE},
69 {"/__init__.pyo", IS_PACKAGE | IS_BYTECODE},
70 {"/__init__.py", IS_PACKAGE | IS_SOURCE},
70 {"/__init__.py", IS_PACKAGE | IS_SOURCE},
71 {".pyc", IS_BYTECODE},
71 {".pyc", IS_BYTECODE},
72 {".pyo", IS_BYTECODE},
72 {".pyo", IS_BYTECODE},
73 {".py", IS_SOURCE},
73 {".py", IS_SOURCE},
74 {"", 0}
74 {"", 0}
75 };
75 };
76
76
77 extern PyTypeObject PythonQtImporter_Type;
77 extern PyTypeObject PythonQtImporter_Type;
78 PyObject *PythonQtImportError;
78 PyObject *PythonQtImportError;
79
79
80 QString PythonQtImport::getSubName(const QString& str)
80 QString PythonQtImport::getSubName(const QString& str)
81 {
81 {
82 int idx = str.lastIndexOf('.');
82 int idx = str.lastIndexOf('.');
83 if (idx!=-1) {
83 if (idx!=-1) {
84 return str.mid(idx+1);
84 return str.mid(idx+1);
85 } else {
85 } else {
86 return str;
86 return str;
87 }
87 }
88 }
88 }
89
89
90 PythonQtImport::module_info PythonQtImport::getModuleInfo(PythonQtImporter* self, const QString& fullname)
90 PythonQtImport::module_info PythonQtImport::getModuleInfo(PythonQtImporter* self, const QString& fullname)
91 {
91 {
92 QString subname;
92 QString subname;
93 struct st_mlab_searchorder *zso;
93 struct st_mlab_searchorder *zso;
94
94
95 subname = getSubName(fullname);
95 subname = getSubName(fullname);
96 QString path = *self->_path + "/" + subname;
96 QString path = *self->_path + "/" + subname;
97
97
98 QString test;
98 QString test;
99 for (zso = mlab_searchorder; *zso->suffix; zso++) {
99 for (zso = mlab_searchorder; *zso->suffix; zso++) {
100 test = path + zso->suffix;
100 test = path + zso->suffix;
101 if (PythonQt::importInterface()->exists(test)) {
101 if (PythonQt::importInterface()->exists(test)) {
102 if (zso->type & IS_PACKAGE)
102 if (zso->type & IS_PACKAGE)
103 return MI_PACKAGE;
103 return MI_PACKAGE;
104 else
104 else
105 return MI_MODULE;
105 return MI_MODULE;
106 }
106 }
107 }
107 }
108 if (PythonQt::importInterface()->exists(path+".so")) {
108 if (PythonQt::importInterface()->exists(path+".so")) {
109 return MI_SHAREDLIBRARY;
109 return MI_SHAREDLIBRARY;
110 }
110 }
111 return MI_NOT_FOUND;
111 return MI_NOT_FOUND;
112 }
112 }
113
113
114
114
115 /* PythonQtImporter.__init__
115 /* PythonQtImporter.__init__
116 Just store the path argument
116 Just store the path argument (or reject if it is in the ignorePaths list
117 */
117 */
118 int PythonQtImporter_init(PythonQtImporter *self, PyObject *args, PyObject * /*kwds*/)
118 int PythonQtImporter_init(PythonQtImporter *self, PyObject *args, PyObject * /*kwds*/)
119 {
119 {
120 self->_path = NULL;
120 self->_path = NULL;
121
121
122 const char* path;
122 const char* cpath;
123 if (!PyArg_ParseTuple(args, "s",
123 if (!PyArg_ParseTuple(args, "s",
124 &path))
124 &cpath))
125 return -1;
125 return -1;
126
126
127 QString path(cpath);
127 if (PythonQt::importInterface()->exists(path)) {
128 if (PythonQt::importInterface()->exists(path)) {
128 //qDebug("path %s", path);
129 QString p(path);
130 const QStringList& ignorePaths = PythonQt::self()->getImporterIgnorePaths();
129 const QStringList& ignorePaths = PythonQt::self()->getImporterIgnorePaths();
131 foreach(QString a, ignorePaths) {
130 foreach(QString ignorePath, ignorePaths) {
132 if (a==p) {
131 if (path.startsWith(ignorePath)) {
133 PyErr_SetString(PythonQtImportError,
132 PyErr_SetString(PythonQtImportError,
134 "path ignored");
133 "path ignored");
135 return -1;
134 return -1;
136 }
135 }
137 }
136 }
138
137
139 self->_path = new QString(p);
138 self->_path = new QString(path);
140
141 //mlabDebugConst("MLABPython", "PythonQtImporter init: " << *self->_path);
142
143 return 0;
139 return 0;
144 } else {
140 } else {
145 PyErr_SetString(PythonQtImportError,
141 PyErr_SetString(PythonQtImportError,
146 "path does not exist error");
142 "path does not exist error");
147 return -1;
143 return -1;
148 }
144 }
149 }
145 }
150
146
151 void
147 void
152 PythonQtImporter_dealloc(PythonQtImporter *self)
148 PythonQtImporter_dealloc(PythonQtImporter *self)
153 {
149 {
154 // free the stored path
150 // free the stored path
155 if (self->_path) delete self->_path;
151 if (self->_path) delete self->_path;
156 // free ourself
152 // free ourself
157 self->ob_type->tp_free((PyObject *)self);
153 self->ob_type->tp_free((PyObject *)self);
158 }
154 }
159
155
160
156
161 /* Check whether we can satisfy the import of the module named by
157 /* Check whether we can satisfy the import of the module named by
162 'fullname'. Return self if we can, None if we can't. */
158 'fullname'. Return self if we can, None if we can't. */
163 PyObject *
159 PyObject *
164 PythonQtImporter_find_module(PyObject *obj, PyObject *args)
160 PythonQtImporter_find_module(PyObject *obj, PyObject *args)
165 {
161 {
166 PythonQtImporter *self = (PythonQtImporter *)obj;
162 PythonQtImporter *self = (PythonQtImporter *)obj;
167 PyObject *path = NULL;
163 PyObject *path = NULL;
168 char *fullname;
164 char *fullname;
169
165
170 if (!PyArg_ParseTuple(args, "s|O:PythonQtImporter.find_module",
166 if (!PyArg_ParseTuple(args, "s|O:PythonQtImporter.find_module",
171 &fullname, &path))
167 &fullname, &path))
172 return NULL;
168 return NULL;
173
169
174 qDebug() << "looking for " << fullname << " at " << *self->_path;
170 qDebug() << "looking for " << fullname << " at " << *self->_path;
175
171
176 // mlabDebugConst("MLABPython", "FindModule " << fullname << " in " << *self->_path);
172 // mlabDebugConst("MLABPython", "FindModule " << fullname << " in " << *self->_path);
177
173
178 PythonQtImport::module_info info = PythonQtImport::getModuleInfo(self, fullname);
174 PythonQtImport::module_info info = PythonQtImport::getModuleInfo(self, fullname);
179 if (info == PythonQtImport::MI_MODULE || info == PythonQtImport::MI_PACKAGE ||
175 if (info == PythonQtImport::MI_MODULE || info == PythonQtImport::MI_PACKAGE ||
180 info== PythonQtImport::MI_SHAREDLIBRARY) {
176 info== PythonQtImport::MI_SHAREDLIBRARY) {
181 Py_INCREF(self);
177 Py_INCREF(self);
182 return (PyObject *)self;
178 return (PyObject *)self;
183 } else {
179 } else {
184 Py_INCREF(Py_None);
180 Py_INCREF(Py_None);
185 return Py_None;
181 return Py_None;
186 }
182 }
187 }
183 }
188
184
189 /* Load and return the module named by 'fullname'. */
185 /* Load and return the module named by 'fullname'. */
190 PyObject *
186 PyObject *
191 PythonQtImporter_load_module(PyObject *obj, PyObject *args)
187 PythonQtImporter_load_module(PyObject *obj, PyObject *args)
192 {
188 {
193 PythonQtImporter *self = (PythonQtImporter *)obj;
189 PythonQtImporter *self = (PythonQtImporter *)obj;
194 PyObject *code, *mod, *dict;
190 PyObject *code, *mod, *dict;
195 char *fullname;
191 char *fullname;
196 QString modpath;
192 QString modpath;
197 int ispackage;
193 int ispackage;
198
194
199 if (!PyArg_ParseTuple(args, "s:PythonQtImporter.load_module",
195 if (!PyArg_ParseTuple(args, "s:PythonQtImporter.load_module",
200 &fullname))
196 &fullname))
201 return NULL;
197 return NULL;
202
198
203 code = PythonQtImport::getModuleCode(self, fullname, &ispackage, modpath);
199 code = PythonQtImport::getModuleCode(self, fullname, &ispackage, modpath);
204 if (code == NULL) {
200 if (code == NULL) {
205 return NULL;
201 return NULL;
206 }
202 }
207
203
208 mod = PyImport_AddModule(fullname);
204 mod = PyImport_AddModule(fullname);
209 if (mod == NULL) {
205 if (mod == NULL) {
210 Py_DECREF(code);
206 Py_DECREF(code);
211 return NULL;
207 return NULL;
212 }
208 }
213 dict = PyModule_GetDict(mod);
209 dict = PyModule_GetDict(mod);
214
210
215 if (PyDict_SetItemString(dict, "__loader__", (PyObject *)self) != 0) {
211 if (PyDict_SetItemString(dict, "__loader__", (PyObject *)self) != 0) {
216 Py_DECREF(code);
212 Py_DECREF(code);
217 Py_DECREF(mod);
213 Py_DECREF(mod);
218 return NULL;
214 return NULL;
219 }
215 }
220
216
221 if (ispackage) {
217 if (ispackage) {
222 PyObject *pkgpath, *fullpath;
218 PyObject *pkgpath, *fullpath;
223 QString subname = PythonQtImport::getSubName(fullname);
219 QString subname = PythonQtImport::getSubName(fullname);
224 int err;
220 int err;
225
221
226 fullpath = PyString_FromFormat("%s%c%s",
222 fullpath = PyString_FromFormat("%s%c%s",
227 self->_path->toLatin1().constData(),
223 self->_path->toLatin1().constData(),
228 SEP,
224 SEP,
229 subname.toLatin1().constData());
225 subname.toLatin1().constData());
230 if (fullpath == NULL) {
226 if (fullpath == NULL) {
231 Py_DECREF(code);
227 Py_DECREF(code);
232 Py_DECREF(mod);
228 Py_DECREF(mod);
233 return NULL;
229 return NULL;
234 }
230 }
235
231
236 pkgpath = Py_BuildValue("[O]", fullpath);
232 pkgpath = Py_BuildValue("[O]", fullpath);
237 Py_DECREF(fullpath);
233 Py_DECREF(fullpath);
238 if (pkgpath == NULL) {
234 if (pkgpath == NULL) {
239 Py_DECREF(code);
235 Py_DECREF(code);
240 Py_DECREF(mod);
236 Py_DECREF(mod);
241 return NULL;
237 return NULL;
242 }
238 }
243 err = PyDict_SetItemString(dict, "__path__", pkgpath);
239 err = PyDict_SetItemString(dict, "__path__", pkgpath);
244 Py_DECREF(pkgpath);
240 Py_DECREF(pkgpath);
245 if (err != 0) {
241 if (err != 0) {
246 Py_DECREF(code);
242 Py_DECREF(code);
247 Py_DECREF(mod);
243 Py_DECREF(mod);
248 return NULL;
244 return NULL;
249 }
245 }
250 }
246 }
251 mod = PyImport_ExecCodeModuleEx(fullname, code, (char*)modpath.toLatin1().data());
247 mod = PyImport_ExecCodeModuleEx(fullname, code, (char*)modpath.toLatin1().data());
252 Py_DECREF(code);
248 Py_DECREF(code);
253 if (Py_VerboseFlag) {
249 if (Py_VerboseFlag) {
254 PySys_WriteStderr("import %s # loaded from %s\n",
250 PySys_WriteStderr("import %s # loaded from %s\n",
255 fullname, modpath.toLatin1().constData());
251 fullname, modpath.toLatin1().constData());
256 }
252 }
257 return mod;
253 return mod;
258 }
254 }
259
255
260
256
261 PyObject *
257 PyObject *
262 PythonQtImporter_get_data(PyObject* /*obj*/, PyObject* /*args*/)
258 PythonQtImporter_get_data(PyObject* /*obj*/, PyObject* /*args*/)
263 {
259 {
264 // EXTRA, NOT YET IMPLEMENTED
260 // EXTRA, NOT YET IMPLEMENTED
265 return NULL;
261 return NULL;
266 }
262 }
267
263
268 PyObject *
264 PyObject *
269 PythonQtImporter_get_code(PyObject *obj, PyObject *args)
265 PythonQtImporter_get_code(PyObject *obj, PyObject *args)
270 {
266 {
271 PythonQtImporter *self = (PythonQtImporter *)obj;
267 PythonQtImporter *self = (PythonQtImporter *)obj;
272 char *fullname;
268 char *fullname;
273
269
274 if (!PyArg_ParseTuple(args, "s:PythonQtImporter.get_code", &fullname))
270 if (!PyArg_ParseTuple(args, "s:PythonQtImporter.get_code", &fullname))
275 return NULL;
271 return NULL;
276
272
277 QString notused;
273 QString notused;
278 return PythonQtImport::getModuleCode(self, fullname, NULL, notused);
274 return PythonQtImport::getModuleCode(self, fullname, NULL, notused);
279 }
275 }
280
276
281 PyObject *
277 PyObject *
282 PythonQtImporter_get_source(PyObject * /*obj*/, PyObject * /*args*/)
278 PythonQtImporter_get_source(PyObject * /*obj*/, PyObject * /*args*/)
283 {
279 {
284 // EXTRA, NOT YET IMPLEMENTED
280 // EXTRA, NOT YET IMPLEMENTED
285 /*
281 /*
286 PythonQtImporter *self = (PythonQtImporter *)obj;
282 PythonQtImporter *self = (PythonQtImporter *)obj;
287 PyObject *toc_entry;
283 PyObject *toc_entry;
288 char *fullname, *subname, path[MAXPATHLEN+1];
284 char *fullname, *subname, path[MAXPATHLEN+1];
289 int len;
285 int len;
290 enum module_info mi;
286 enum module_info mi;
291
287
292 if (!PyArg_ParseTuple(args, "s:PythonQtImporter.get_source", &fullname))
288 if (!PyArg_ParseTuple(args, "s:PythonQtImporter.get_source", &fullname))
293 return NULL;
289 return NULL;
294
290
295 mi = get_module_info(self, fullname);
291 mi = get_module_info(self, fullname);
296 if (mi == MI_ERROR)
292 if (mi == MI_ERROR)
297 return NULL;
293 return NULL;
298 if (mi == MI_NOT_FOUND) {
294 if (mi == MI_NOT_FOUND) {
299 PyErr_Format(PythonQtImportError, "can't find module '%.200s'",
295 PyErr_Format(PythonQtImportError, "can't find module '%.200s'",
300 fullname);
296 fullname);
301 return NULL;
297 return NULL;
302 }
298 }
303 subname = get_subname(fullname);
299 subname = get_subname(fullname);
304
300
305 len = make_filename(PyString_AsString(self->prefix), subname, path);
301 len = make_filename(PyString_AsString(self->prefix), subname, path);
306 if (len < 0)
302 if (len < 0)
307 return NULL;
303 return NULL;
308
304
309 if (mi == MI_PACKAGE) {
305 if (mi == MI_PACKAGE) {
310 path[len] = SEP;
306 path[len] = SEP;
311 strcpy(path + len + 1, "__init__.py");
307 strcpy(path + len + 1, "__init__.py");
312 }
308 }
313 else
309 else
314 strcpy(path + len, ".py");
310 strcpy(path + len, ".py");
315
311
316 toc_entry = PyDict_GetItemString(self->files, path);
312 toc_entry = PyDict_GetItemString(self->files, path);
317 if (toc_entry != NULL)
313 if (toc_entry != NULL)
318 return get_data(PyString_AsString(self->archive), toc_entry);
314 return get_data(PyString_AsString(self->archive), toc_entry);
319
315
320 Py_INCREF(Py_None);
316 Py_INCREF(Py_None);
321 return Py_None;
317 return Py_None;
322 */
318 */
323 return NULL;
319 return NULL;
324 }
320 }
325
321
326 PyDoc_STRVAR(doc_find_module,
322 PyDoc_STRVAR(doc_find_module,
327 "find_module(fullname, path=None) -> self or None.\n\
323 "find_module(fullname, path=None) -> self or None.\n\
328 \n\
324 \n\
329 Search for a module specified by 'fullname'. 'fullname' must be the\n\
325 Search for a module specified by 'fullname'. 'fullname' must be the\n\
330 fully qualified (dotted) module name. It returns the PythonQtImporter\n\
326 fully qualified (dotted) module name. It returns the PythonQtImporter\n\
331 instance itself if the module was found, or None if it wasn't.\n\
327 instance itself if the module was found, or None if it wasn't.\n\
332 The optional 'path' argument is ignored -- it's there for compatibility\n\
328 The optional 'path' argument is ignored -- it's there for compatibility\n\
333 with the importer protocol.");
329 with the importer protocol.");
334
330
335 PyDoc_STRVAR(doc_load_module,
331 PyDoc_STRVAR(doc_load_module,
336 "load_module(fullname) -> module.\n\
332 "load_module(fullname) -> module.\n\
337 \n\
333 \n\
338 Load the module specified by 'fullname'. 'fullname' must be the\n\
334 Load the module specified by 'fullname'. 'fullname' must be the\n\
339 fully qualified (dotted) module name. It returns the imported\n\
335 fully qualified (dotted) module name. It returns the imported\n\
340 module, or raises PythonQtImportError if it wasn't found.");
336 module, or raises PythonQtImportError if it wasn't found.");
341
337
342 PyDoc_STRVAR(doc_get_data,
338 PyDoc_STRVAR(doc_get_data,
343 "get_data(pathname) -> string with file data.\n\
339 "get_data(pathname) -> string with file data.\n\
344 \n\
340 \n\
345 Return the data associated with 'pathname'. Raise IOError if\n\
341 Return the data associated with 'pathname'. Raise IOError if\n\
346 the file wasn't found.");
342 the file wasn't found.");
347
343
348 PyDoc_STRVAR(doc_get_code,
344 PyDoc_STRVAR(doc_get_code,
349 "get_code(fullname) -> code object.\n\
345 "get_code(fullname) -> code object.\n\
350 \n\
346 \n\
351 Return the code object for the specified module. Raise PythonQtImportError\n\
347 Return the code object for the specified module. Raise PythonQtImportError\n\
352 is the module couldn't be found.");
348 is the module couldn't be found.");
353
349
354 PyDoc_STRVAR(doc_get_source,
350 PyDoc_STRVAR(doc_get_source,
355 "get_source(fullname) -> source string.\n\
351 "get_source(fullname) -> source string.\n\
356 \n\
352 \n\
357 Return the source code for the specified module. Raise PythonQtImportError\n\
353 Return the source code for the specified module. Raise PythonQtImportError\n\
358 is the module couldn't be found, return None if the archive does\n\
354 is the module couldn't be found, return None if the archive does\n\
359 contain the module, but has no source for it.");
355 contain the module, but has no source for it.");
360
356
361 PyMethodDef PythonQtImporter_methods[] = {
357 PyMethodDef PythonQtImporter_methods[] = {
362 {"find_module", PythonQtImporter_find_module, METH_VARARGS,
358 {"find_module", PythonQtImporter_find_module, METH_VARARGS,
363 doc_find_module},
359 doc_find_module},
364 {"load_module", PythonQtImporter_load_module, METH_VARARGS,
360 {"load_module", PythonQtImporter_load_module, METH_VARARGS,
365 doc_load_module},
361 doc_load_module},
366 {"get_data", PythonQtImporter_get_data, METH_VARARGS,
362 {"get_data", PythonQtImporter_get_data, METH_VARARGS,
367 doc_get_data},
363 doc_get_data},
368 {"get_code", PythonQtImporter_get_code, METH_VARARGS,
364 {"get_code", PythonQtImporter_get_code, METH_VARARGS,
369 doc_get_code},
365 doc_get_code},
370 {"get_source", PythonQtImporter_get_source, METH_VARARGS,
366 {"get_source", PythonQtImporter_get_source, METH_VARARGS,
371 doc_get_source},
367 doc_get_source},
372 {NULL, NULL, 0 , NULL} /* sentinel */
368 {NULL, NULL, 0 , NULL} /* sentinel */
373 };
369 };
374
370
375
371
376 PyDoc_STRVAR(PythonQtImporter_doc,
372 PyDoc_STRVAR(PythonQtImporter_doc,
377 "PythonQtImporter(path) -> PythonQtImporter object\n\
373 "PythonQtImporter(path) -> PythonQtImporter object\n\
378 \n\
374 \n\
379 Create a new PythonQtImporter instance. 'path' must be a valid path on disk/or inside of a zip file known to MeVisLab\n\
375 Create a new PythonQtImporter instance. 'path' must be a valid path on disk/or inside of a zip file known to MeVisLab\n\
380 . Every path is accepted.");
376 . Every path is accepted.");
381
377
382 #define DEFERRED_ADDRESS(ADDR) 0
378 #define DEFERRED_ADDRESS(ADDR) 0
383
379
384 PyTypeObject PythonQtImporter_Type = {
380 PyTypeObject PythonQtImporter_Type = {
385 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
381 PyObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type))
386 0,
382 0,
387 "PythonQtImport.PythonQtImporter",
383 "PythonQtImport.PythonQtImporter",
388 sizeof(PythonQtImporter),
384 sizeof(PythonQtImporter),
389 0, /* tp_itemsize */
385 0, /* tp_itemsize */
390 (destructor)PythonQtImporter_dealloc, /* tp_dealloc */
386 (destructor)PythonQtImporter_dealloc, /* tp_dealloc */
391 0, /* tp_print */
387 0, /* tp_print */
392 0, /* tp_getattr */
388 0, /* tp_getattr */
393 0, /* tp_setattr */
389 0, /* tp_setattr */
394 0, /* tp_compare */
390 0, /* tp_compare */
395 0, /* tp_repr */
391 0, /* tp_repr */
396 0, /* tp_as_number */
392 0, /* tp_as_number */
397 0, /* tp_as_sequence */
393 0, /* tp_as_sequence */
398 0, /* tp_as_mapping */
394 0, /* tp_as_mapping */
399 0, /* tp_hash */
395 0, /* tp_hash */
400 0, /* tp_call */
396 0, /* tp_call */
401 0, /* tp_str */
397 0, /* tp_str */
402 PyObject_GenericGetAttr, /* tp_getattro */
398 PyObject_GenericGetAttr, /* tp_getattro */
403 0, /* tp_setattro */
399 0, /* tp_setattro */
404 0, /* tp_as_buffer */
400 0, /* tp_as_buffer */
405 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE , /* tp_flags */
401 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE , /* tp_flags */
406 PythonQtImporter_doc, /* tp_doc */
402 PythonQtImporter_doc, /* tp_doc */
407 0, /* tp_traverse */
403 0, /* tp_traverse */
408 0, /* tp_clear */
404 0, /* tp_clear */
409 0, /* tp_richcompare */
405 0, /* tp_richcompare */
410 0, /* tp_weaklistoffset */
406 0, /* tp_weaklistoffset */
411 0, /* tp_iter */
407 0, /* tp_iter */
412 0, /* tp_iternext */
408 0, /* tp_iternext */
413 PythonQtImporter_methods, /* tp_methods */
409 PythonQtImporter_methods, /* tp_methods */
414 0, /* tp_members */
410 0, /* tp_members */
415 0, /* tp_getset */
411 0, /* tp_getset */
416 0, /* tp_base */
412 0, /* tp_base */
417 0, /* tp_dict */
413 0, /* tp_dict */
418 0, /* tp_descr_get */
414 0, /* tp_descr_get */
419 0, /* tp_descr_set */
415 0, /* tp_descr_set */
420 0, /* tp_dictoffset */
416 0, /* tp_dictoffset */
421 (initproc)PythonQtImporter_init, /* tp_init */
417 (initproc)PythonQtImporter_init, /* tp_init */
422 PyType_GenericAlloc, /* tp_alloc */
418 PyType_GenericAlloc, /* tp_alloc */
423 PyType_GenericNew, /* tp_new */
419 PyType_GenericNew, /* tp_new */
424 PyObject_Del, /* tp_free */
420 PyObject_Del, /* tp_free */
425 };
421 };
426
422
427
423
428 /* Given a buffer, return the long that is represented by the first
424 /* Given a buffer, return the long that is represented by the first
429 4 bytes, encoded as little endian. This partially reimplements
425 4 bytes, encoded as little endian. This partially reimplements
430 marshal.c:r_long() */
426 marshal.c:r_long() */
431 long
427 long
432 PythonQtImport::getLong(unsigned char *buf)
428 PythonQtImport::getLong(unsigned char *buf)
433 {
429 {
434 long x;
430 long x;
435 x = buf[0];
431 x = buf[0];
436 x |= (long)buf[1] << 8;
432 x |= (long)buf[1] << 8;
437 x |= (long)buf[2] << 16;
433 x |= (long)buf[2] << 16;
438 x |= (long)buf[3] << 24;
434 x |= (long)buf[3] << 24;
439 #if SIZEOF_LONG > 4
435 #if SIZEOF_LONG > 4
440 /* Sign extension for 64-bit machines */
436 /* Sign extension for 64-bit machines */
441 x |= -(x & 0x80000000L);
437 x |= -(x & 0x80000000L);
442 #endif
438 #endif
443 return x;
439 return x;
444 }
440 }
445
441
446 FILE *
442 FILE *
447 open_exclusive(const QString& filename)
443 open_exclusive(const QString& filename)
448 {
444 {
449 #if defined(O_EXCL)&&defined(O_CREAT)&&defined(O_WRONLY)&&defined(O_TRUNC)
445 #if defined(O_EXCL)&&defined(O_CREAT)&&defined(O_WRONLY)&&defined(O_TRUNC)
450 /* Use O_EXCL to avoid a race condition when another process tries to
446 /* Use O_EXCL to avoid a race condition when another process tries to
451 write the same file. When that happens, our open() call fails,
447 write the same file. When that happens, our open() call fails,
452 which is just fine (since it's only a cache).
448 which is just fine (since it's only a cache).
453 XXX If the file exists and is writable but the directory is not
449 XXX If the file exists and is writable but the directory is not
454 writable, the file will never be written. Oh well.
450 writable, the file will never be written. Oh well.
455 */
451 */
456 QFile::remove(filename);
452 QFile::remove(filename);
457
453
458 int fd;
454 int fd;
459 int flags = O_EXCL|O_CREAT|O_WRONLY|O_TRUNC;
455 int flags = O_EXCL|O_CREAT|O_WRONLY|O_TRUNC;
460 #ifdef O_BINARY
456 #ifdef O_BINARY
461 flags |= O_BINARY; /* necessary for Windows */
457 flags |= O_BINARY; /* necessary for Windows */
462 #endif
458 #endif
463 #ifdef WIN32
459 #ifdef WIN32
464 fd = _wopen(filename.ucs2(), flags, 0666);
460 fd = _wopen(filename.ucs2(), flags, 0666);
465 #else
461 #else
466 fd = open(filename.local8Bit(), flags, 0666);
462 fd = open(filename.local8Bit(), flags, 0666);
467 #endif
463 #endif
468 if (fd < 0)
464 if (fd < 0)
469 return NULL;
465 return NULL;
470 return fdopen(fd, "wb");
466 return fdopen(fd, "wb");
471 #else
467 #else
472 /* Best we can do -- on Windows this can't happen anyway */
468 /* Best we can do -- on Windows this can't happen anyway */
473 return fopen(filename.toLocal8Bit().constData(), "wb");
469 return fopen(filename.toLocal8Bit().constData(), "wb");
474 #endif
470 #endif
475 }
471 }
476
472
477
473
478 void PythonQtImport::writeCompiledModule(PyCodeObject *co, const QString& filename, long mtime)
474 void PythonQtImport::writeCompiledModule(PyCodeObject *co, const QString& filename, long mtime)
479 {
475 {
480 FILE *fp;
476 FILE *fp;
481 // we do not want to write Qt resources to disk, do we?
477 // we do not want to write Qt resources to disk, do we?
482 if (filename.startsWith(":")) {
478 if (filename.startsWith(":")) {
483 return;
479 return;
484 }
480 }
485 fp = open_exclusive(filename);
481 fp = open_exclusive(filename);
486 if (fp == NULL) {
482 if (fp == NULL) {
487 if (Py_VerboseFlag)
483 if (Py_VerboseFlag)
488 PySys_WriteStderr(
484 PySys_WriteStderr(
489 "# can't create %s\n", filename.toLatin1().constData());
485 "# can't create %s\n", filename.toLatin1().constData());
490 return;
486 return;
491 }
487 }
492 #if PY_VERSION_HEX < 0x02040000
488 #if PY_VERSION_HEX < 0x02040000
493 PyMarshal_WriteLongToFile(PyImport_GetMagicNumber(), fp);
489 PyMarshal_WriteLongToFile(PyImport_GetMagicNumber(), fp);
494 #else
490 #else
495 PyMarshal_WriteLongToFile(PyImport_GetMagicNumber(), fp, Py_MARSHAL_VERSION);
491 PyMarshal_WriteLongToFile(PyImport_GetMagicNumber(), fp, Py_MARSHAL_VERSION);
496 #endif
492 #endif
497 /* First write a 0 for mtime */
493 /* First write a 0 for mtime */
498 #if PY_VERSION_HEX < 0x02040000
494 #if PY_VERSION_HEX < 0x02040000
499 PyMarshal_WriteLongToFile(0L, fp);
495 PyMarshal_WriteLongToFile(0L, fp);
500 #else
496 #else
501 PyMarshal_WriteLongToFile(0L, fp, Py_MARSHAL_VERSION);
497 PyMarshal_WriteLongToFile(0L, fp, Py_MARSHAL_VERSION);
502 #endif
498 #endif
503 #if PY_VERSION_HEX < 0x02040000
499 #if PY_VERSION_HEX < 0x02040000
504 PyMarshal_WriteObjectToFile((PyObject *)co, fp);
500 PyMarshal_WriteObjectToFile((PyObject *)co, fp);
505 #else
501 #else
506 PyMarshal_WriteObjectToFile((PyObject *)co, fp, Py_MARSHAL_VERSION);
502 PyMarshal_WriteObjectToFile((PyObject *)co, fp, Py_MARSHAL_VERSION);
507 #endif
503 #endif
508 if (ferror(fp)) {
504 if (ferror(fp)) {
509 if (Py_VerboseFlag)
505 if (Py_VerboseFlag)
510 PySys_WriteStderr("# can't write %s\n", filename.toLatin1().constData());
506 PySys_WriteStderr("# can't write %s\n", filename.toLatin1().constData());
511 /* Don't keep partial file */
507 /* Don't keep partial file */
512 fclose(fp);
508 fclose(fp);
513 QFile::remove(filename);
509 QFile::remove(filename);
514 return;
510 return;
515 }
511 }
516 /* Now write the true mtime */
512 /* Now write the true mtime */
517 fseek(fp, 4L, 0);
513 fseek(fp, 4L, 0);
518 #if PY_VERSION_HEX < 0x02040000
514 #if PY_VERSION_HEX < 0x02040000
519 PyMarshal_WriteLongToFile(mtime, fp);
515 PyMarshal_WriteLongToFile(mtime, fp);
520 #else
516 #else
521 PyMarshal_WriteLongToFile(mtime, fp, Py_MARSHAL_VERSION);
517 PyMarshal_WriteLongToFile(mtime, fp, Py_MARSHAL_VERSION);
522 #endif
518 #endif
523 fflush(fp);
519 fflush(fp);
524 fclose(fp);
520 fclose(fp);
525 if (Py_VerboseFlag)
521 if (Py_VerboseFlag)
526 PySys_WriteStderr("# wrote %s\n", filename.toLatin1().constData());
522 PySys_WriteStderr("# wrote %s\n", filename.toLatin1().constData());
527 //#ifdef macintosh
523 //#ifdef macintosh
528 // PyMac_setfiletype(cpathname, 'Pyth', 'PYC ');
524 // PyMac_setfiletype(cpathname, 'Pyth', 'PYC ');
529 //#endif
525 //#endif
530 }
526 }
531
527
532 /* Given the contents of a .py[co] file in a buffer, unmarshal the data
528 /* Given the contents of a .py[co] file in a buffer, unmarshal the data
533 and return the code object. Return None if it the magic word doesn't
529 and return the code object. Return None if it the magic word doesn't
534 match (we do this instead of raising an exception as we fall back
530 match (we do this instead of raising an exception as we fall back
535 to .py if available and we don't want to mask other errors).
531 to .py if available and we don't want to mask other errors).
536 Returns a new reference. */
532 Returns a new reference. */
537 PyObject *
533 PyObject *
538 PythonQtImport::unmarshalCode(const QString& path, const QByteArray& data, time_t mtime)
534 PythonQtImport::unmarshalCode(const QString& path, const QByteArray& data, time_t mtime)
539 {
535 {
540 PyObject *code;
536 PyObject *code;
541 // ugly cast, but Python API is not const safe
537 // ugly cast, but Python API is not const safe
542 char *buf = (char*) data.constData();
538 char *buf = (char*) data.constData();
543 int size = data.size();
539 int size = data.size();
544
540
545 if (size <= 9) {
541 if (size <= 9) {
546 PySys_WriteStderr("# %s has bad pyc data\n",
542 PySys_WriteStderr("# %s has bad pyc data\n",
547 path.toLatin1().constData());
543 path.toLatin1().constData());
548 Py_INCREF(Py_None);
544 Py_INCREF(Py_None);
549 return Py_None;
545 return Py_None;
550 }
546 }
551
547
552 if (getLong((unsigned char *)buf) != PyImport_GetMagicNumber()) {
548 if (getLong((unsigned char *)buf) != PyImport_GetMagicNumber()) {
553 if (Py_VerboseFlag)
549 if (Py_VerboseFlag)
554 PySys_WriteStderr("# %s has bad magic\n",
550 PySys_WriteStderr("# %s has bad magic\n",
555 path.toLatin1().constData());
551 path.toLatin1().constData());
556 Py_INCREF(Py_None);
552 Py_INCREF(Py_None);
557 return Py_None;
553 return Py_None;
558 }
554 }
559
555
560 if (mtime != 0 && !(getLong((unsigned char *)buf + 4) == mtime)) {
556 if (mtime != 0 && !(getLong((unsigned char *)buf + 4) == mtime)) {
561 if (Py_VerboseFlag)
557 if (Py_VerboseFlag)
562 PySys_WriteStderr("# %s has bad mtime\n",
558 PySys_WriteStderr("# %s has bad mtime\n",
563 path.toLatin1().constData());
559 path.toLatin1().constData());
564 Py_INCREF(Py_None);
560 Py_INCREF(Py_None);
565 return Py_None;
561 return Py_None;
566 }
562 }
567
563
568 code = PyMarshal_ReadObjectFromString(buf + 8, size - 8);
564 code = PyMarshal_ReadObjectFromString(buf + 8, size - 8);
569 if (code == NULL)
565 if (code == NULL)
570 return NULL;
566 return NULL;
571 if (!PyCode_Check(code)) {
567 if (!PyCode_Check(code)) {
572 Py_DECREF(code);
568 Py_DECREF(code);
573 PyErr_Format(PyExc_TypeError,
569 PyErr_Format(PyExc_TypeError,
574 "compiled module %.200s is not a code object",
570 "compiled module %.200s is not a code object",
575 path.toLatin1().constData());
571 path.toLatin1().constData());
576 return NULL;
572 return NULL;
577 }
573 }
578 return code;
574 return code;
579 }
575 }
580
576
581
577
582 /* Given a string buffer containing Python source code, compile it
578 /* Given a string buffer containing Python source code, compile it
583 return and return a code object as a new reference. */
579 return and return a code object as a new reference. */
584 PyObject *
580 PyObject *
585 PythonQtImport::compileSource(const QString& path, const QByteArray& data)
581 PythonQtImport::compileSource(const QString& path, const QByteArray& data)
586 {
582 {
587 PyObject *code;
583 PyObject *code;
588 QByteArray data1 = data;
584 QByteArray data1 = data;
589 // in qt4, data is null terminated
585 // in qt4, data is null terminated
590 // data1.resize(data.size()+1);
586 // data1.resize(data.size()+1);
591 // data1.data()[data.size()-1] = 0;
587 // data1.data()[data.size()-1] = 0;
592 code = Py_CompileString(data.data(), path.toLatin1().constData(),
588 code = Py_CompileString(data.data(), path.toLatin1().constData(),
593 Py_file_input);
589 Py_file_input);
594 return code;
590 return code;
595 }
591 }
596
592
597
593
598 /* Return the code object for the module named by 'fullname' from the
594 /* Return the code object for the module named by 'fullname' from the
599 Zip archive as a new reference. */
595 Zip archive as a new reference. */
600 PyObject *
596 PyObject *
601 PythonQtImport::getCodeFromData(const QString& path, int isbytecode,int /*ispackage*/, time_t mtime)
597 PythonQtImport::getCodeFromData(const QString& path, int isbytecode,int /*ispackage*/, time_t mtime)
602 {
598 {
603 PyObject *code;
599 PyObject *code;
604
600
605 QByteArray qdata;
601 QByteArray qdata;
606 if (!isbytecode) {
602 if (!isbytecode) {
607 // mlabDebugConst("MLABPython", "reading source " << path);
603 // mlabDebugConst("MLABPython", "reading source " << path);
608 bool ok;
604 bool ok;
609 qdata = PythonQt::importInterface()->readSourceFile(path, ok);
605 qdata = PythonQt::importInterface()->readSourceFile(path, ok);
610 if (!ok) {
606 if (!ok) {
611 // mlabErrorConst("PythonQtImporter","File could not be verified" << path);
607 // mlabErrorConst("PythonQtImporter","File could not be verified" << path);
612 return NULL;
608 return NULL;
613 }
609 }
614 if (qdata == " ") {
610 if (qdata == " ") {
615 qdata.clear();
611 qdata.clear();
616 }
612 }
617 } else {
613 } else {
618 qdata = PythonQt::importInterface()->readFileAsBytes(path);
614 qdata = PythonQt::importInterface()->readFileAsBytes(path);
619 }
615 }
620
616
621 if (isbytecode) {
617 if (isbytecode) {
622 // mlabDebugConst("MLABPython", "reading bytecode " << path);
618 // mlabDebugConst("MLABPython", "reading bytecode " << path);
623 code = unmarshalCode(path, qdata, mtime);
619 code = unmarshalCode(path, qdata, mtime);
624 }
620 }
625 else {
621 else {
626 // mlabDebugConst("MLABPython", "compiling source " << path);
622 // mlabDebugConst("MLABPython", "compiling source " << path);
627 code = compileSource(path, qdata);
623 code = compileSource(path, qdata);
628 if (code) {
624 if (code) {
629 // save a pyc file if possible
625 // save a pyc file if possible
630 QDateTime time;
626 QDateTime time;
631 time = PythonQt::importInterface()->lastModifiedDate(path);
627 time = PythonQt::importInterface()->lastModifiedDate(path);
632 writeCompiledModule((PyCodeObject*)code, path+"c", time.toTime_t());
628 writeCompiledModule((PyCodeObject*)code, path+"c", time.toTime_t());
633 }
629 }
634 }
630 }
635 return code;
631 return code;
636 }
632 }
637
633
638 time_t
634 time_t
639 PythonQtImport::getMTimeOfSource(const QString& path)
635 PythonQtImport::getMTimeOfSource(const QString& path)
640 {
636 {
641 time_t mtime = 0;
637 time_t mtime = 0;
642 QString path2 = path;
638 QString path2 = path;
643 path2.truncate(path.length()-1);
639 path2.truncate(path.length()-1);
644
640
645 if (PythonQt::importInterface()->exists(path2)) {
641 if (PythonQt::importInterface()->exists(path2)) {
646 mtime = PythonQt::importInterface()->lastModifiedDate(path2).toTime_t();
642 mtime = PythonQt::importInterface()->lastModifiedDate(path2).toTime_t();
647 }
643 }
648
644
649 return mtime;
645 return mtime;
650 }
646 }
651
647
652 /* Get the code object associated with the module specified by
648 /* Get the code object associated with the module specified by
653 'fullname'. */
649 'fullname'. */
654 PyObject *
650 PyObject *
655 PythonQtImport::getModuleCode(PythonQtImporter *self, char *fullname,
651 PythonQtImport::getModuleCode(PythonQtImporter *self, char *fullname,
656 int *p_ispackage, QString& modpath)
652 int *p_ispackage, QString& modpath)
657 {
653 {
658 QString subname;
654 QString subname;
659 struct st_mlab_searchorder *zso;
655 struct st_mlab_searchorder *zso;
660
656
661 subname = getSubName(fullname);
657 subname = getSubName(fullname);
662 QString path = *self->_path + "/" + subname;
658 QString path = *self->_path + "/" + subname;
663
659
664 QString test;
660 QString test;
665 for (zso = mlab_searchorder; *zso->suffix; zso++) {
661 for (zso = mlab_searchorder; *zso->suffix; zso++) {
666 PyObject *code = NULL;
662 PyObject *code = NULL;
667 test = path + zso->suffix;
663 test = path + zso->suffix;
668
664
669 if (Py_VerboseFlag > 1)
665 if (Py_VerboseFlag > 1)
670 PySys_WriteStderr("# trying %s\n",
666 PySys_WriteStderr("# trying %s\n",
671 test.toLatin1().constData());
667 test.toLatin1().constData());
672 if (PythonQt::importInterface()->exists(test)) {
668 if (PythonQt::importInterface()->exists(test)) {
673 time_t mtime = 0;
669 time_t mtime = 0;
674 int ispackage = zso->type & IS_PACKAGE;
670 int ispackage = zso->type & IS_PACKAGE;
675 int isbytecode = zso->type & IS_BYTECODE;
671 int isbytecode = zso->type & IS_BYTECODE;
676
672
677 if (isbytecode)
673 if (isbytecode)
678 mtime = getMTimeOfSource(test);
674 mtime = getMTimeOfSource(test);
679 if (p_ispackage != NULL)
675 if (p_ispackage != NULL)
680 *p_ispackage = ispackage;
676 *p_ispackage = ispackage;
681 code = getCodeFromData(test, isbytecode, ispackage, mtime);
677 code = getCodeFromData(test, isbytecode, ispackage, mtime);
682 if (code == Py_None) {
678 if (code == Py_None) {
683 Py_DECREF(code);
679 Py_DECREF(code);
684 continue;
680 continue;
685 }
681 }
686 if (code != NULL)
682 if (code != NULL)
687 modpath = test;
683 modpath = test;
688 return code;
684 return code;
689 }
685 }
690 }
686 }
691 PyErr_Format(PythonQtImportError, "can't find module '%.200s'", fullname);
687 PyErr_Format(PythonQtImportError, "can't find module '%.200s'", fullname);
692
688
693 return NULL;
689 return NULL;
694 }
690 }
695
691
696 QString PythonQtImport::replaceExtension(const QString& str, const QString& ext)
692 QString PythonQtImport::replaceExtension(const QString& str, const QString& ext)
697 {
693 {
698 QString r;
694 QString r;
699 int i = str.lastIndexOf('.');
695 int i = str.lastIndexOf('.');
700 if (i!=-1) {
696 if (i!=-1) {
701 r = str.mid(0,i) + "." + ext;
697 r = str.mid(0,i) + "." + ext;
702 } else {
698 } else {
703 r = str + "." + ext;
699 r = str + "." + ext;
704 }
700 }
705 return r;
701 return r;
706 }
702 }
707
703
708 PyObject* PythonQtImport::getCodeFromPyc(const QString& file)
704 PyObject* PythonQtImport::getCodeFromPyc(const QString& file)
709 {
705 {
710 PyObject* code;
706 PyObject* code;
711 const static QString pycStr("pyc");
707 const static QString pycStr("pyc");
712 QString pyc = replaceExtension(file, pycStr);
708 QString pyc = replaceExtension(file, pycStr);
713 if (PythonQt::importInterface()->exists(pyc)) {
709 if (PythonQt::importInterface()->exists(pyc)) {
714 time_t mtime = 0;
710 time_t mtime = 0;
715 mtime = getMTimeOfSource(pyc);
711 mtime = getMTimeOfSource(pyc);
716 code = getCodeFromData(pyc, true, false, mtime);
712 code = getCodeFromData(pyc, true, false, mtime);
717 if (code != Py_None && code != NULL) {
713 if (code != Py_None && code != NULL) {
718 return code;
714 return code;
719 }
715 }
720 if (code) {
716 if (code) {
721 Py_DECREF(code);
717 Py_DECREF(code);
722 }
718 }
723 }
719 }
724 code = getCodeFromData(file,false,false,0);
720 code = getCodeFromData(file,false,false,0);
725 return code;
721 return code;
726 }
722 }
727
723
728 /* Module init */
724 /* Module init */
729
725
730 PyDoc_STRVAR(mlabimport_doc,
726 PyDoc_STRVAR(mlabimport_doc,
731 "Imports python files into PythonQt, completely replaces internal python import");
727 "Imports python files into PythonQt, completely replaces internal python import");
732
728
733 void PythonQtImport::init()
729 void PythonQtImport::init()
734 {
730 {
735 static bool first = true;
731 static bool first = true;
736 if (!first) {
732 if (!first) {
737 return;
733 return;
738 }
734 }
739 first = false;
735 first = false;
740
736
741 PyObject *mod;
737 PyObject *mod;
742
738
743 if (PyType_Ready(&PythonQtImporter_Type) < 0)
739 if (PyType_Ready(&PythonQtImporter_Type) < 0)
744 return;
740 return;
745
741
746 /* Correct directory separator */
742 /* Correct directory separator */
747 mlab_searchorder[0].suffix[0] = SEP;
743 mlab_searchorder[0].suffix[0] = SEP;
748 mlab_searchorder[1].suffix[0] = SEP;
744 mlab_searchorder[1].suffix[0] = SEP;
749 mlab_searchorder[2].suffix[0] = SEP;
745 mlab_searchorder[2].suffix[0] = SEP;
750 if (Py_OptimizeFlag) {
746 if (Py_OptimizeFlag) {
751 /* Reverse *.pyc and *.pyo */
747 /* Reverse *.pyc and *.pyo */
752 struct st_mlab_searchorder tmp;
748 struct st_mlab_searchorder tmp;
753 tmp = mlab_searchorder[0];
749 tmp = mlab_searchorder[0];
754 mlab_searchorder[0] = mlab_searchorder[1];
750 mlab_searchorder[0] = mlab_searchorder[1];
755 mlab_searchorder[1] = tmp;
751 mlab_searchorder[1] = tmp;
756 tmp = mlab_searchorder[3];
752 tmp = mlab_searchorder[3];
757 mlab_searchorder[3] = mlab_searchorder[4];
753 mlab_searchorder[3] = mlab_searchorder[4];
758 mlab_searchorder[4] = tmp;
754 mlab_searchorder[4] = tmp;
759 }
755 }
760
756
761 mod = Py_InitModule4("PythonQtImport", NULL, mlabimport_doc,
757 mod = Py_InitModule4("PythonQtImport", NULL, mlabimport_doc,
762 NULL, PYTHON_API_VERSION);
758 NULL, PYTHON_API_VERSION);
763
759
764 PythonQtImportError = PyErr_NewException("PythonQtImport.PythonQtImportError",
760 PythonQtImportError = PyErr_NewException("PythonQtImport.PythonQtImportError",
765 PyExc_ImportError, NULL);
761 PyExc_ImportError, NULL);
766 if (PythonQtImportError == NULL)
762 if (PythonQtImportError == NULL)
767 return;
763 return;
768
764
769 Py_INCREF(PythonQtImportError);
765 Py_INCREF(PythonQtImportError);
770 if (PyModule_AddObject(mod, "PythonQtImportError",
766 if (PyModule_AddObject(mod, "PythonQtImportError",
771 PythonQtImportError) < 0)
767 PythonQtImportError) < 0)
772 return;
768 return;
773
769
774 Py_INCREF(&PythonQtImporter_Type);
770 Py_INCREF(&PythonQtImporter_Type);
775 if (PyModule_AddObject(mod, "PythonQtImporter",
771 if (PyModule_AddObject(mod, "PythonQtImporter",
776 (PyObject *)&PythonQtImporter_Type) < 0)
772 (PyObject *)&PythonQtImporter_Type) < 0)
777 return;
773 return;
778
774
779 // set our importer into the path_hooks to handle all path on sys.path
775 // set our importer into the path_hooks to handle all path on sys.path
780 PyObject* classobj = PyDict_GetItemString(PyModule_GetDict(mod), "PythonQtImporter");
776 PyObject* classobj = PyDict_GetItemString(PyModule_GetDict(mod), "PythonQtImporter");
781 PyObject* path_hooks = PySys_GetObject("path_hooks");
777 PyObject* path_hooks = PySys_GetObject("path_hooks");
782 PyList_Append(path_hooks, classobj);
778 PyList_Append(path_hooks, classobj);
783
779
784 #ifndef WIN32
780 #ifndef WIN32
785 // reload the encodings module, because it might fail to custom import requirements (e.g. encryption).
781 // reload the encodings module, because it might fail to custom import requirements (e.g. encryption).
786 PyObject* modules = PyImport_GetModuleDict();
782 PyObject* modules = PyImport_GetModuleDict();
787 PyObject* encodingsModule = PyDict_GetItemString(modules, "encodings");
783 PyObject* encodingsModule = PyDict_GetItemString(modules, "encodings");
788 if (encodingsModule != NULL) {
784 if (encodingsModule != NULL) {
789 PyImport_ReloadModule(encodingsModule);
785 PyImport_ReloadModule(encodingsModule);
790 }
786 }
791 #endif
787 #endif
792 }
788 }
General Comments 0
You need to be logged in to leave comments. Login now