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