annotate Sources/PythonLock.cpp @ 30:4a0932c22ddb

todo
author Sebastien Jodogne <s.jodogne@gmail.com>
date Wed, 06 May 2020 14:57:28 +0200
parents b2bbb516056e
children fd58eb5749ed
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
1 /**
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
2 * Python plugin for Orthanc
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
3 * Copyright (C) 2017-2020 Osimis S.A., Belgium
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
4 *
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
5 * This program is free software: you can redistribute it and/or
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
6 * modify it under the terms of the GNU Affero General Public License
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
7 * as published by the Free Software Foundation, either version 3 of
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
8 * the License, or (at your option) any later version.
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
9 *
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
10 * This program is distributed in the hope that it will be useful, but
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
13 * Affero General Public License for more details.
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
14 *
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
15 * You should have received a copy of the GNU Affero General Public License
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
17 **/
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
18
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
19
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
20 #include "PythonLock.h"
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
21
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
22 #include "PythonFunction.h"
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
23 #include "PythonModule.h"
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
24
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
25 #include <OrthancPluginCppWrapper.h>
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
26
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
27 #include <boost/thread/mutex.hpp>
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
28
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
29 static boost::mutex mutex_;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
30 static PyThreadState* interpreterState_ = NULL;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
31 static PythonLock::ModuleFunctionsInstaller moduleFunctions_ = NULL;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
32 static PythonLock::ModuleClassesInstaller moduleClasses_ = NULL;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
33 static std::string moduleName_;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
34 static std::string exceptionName_;
28
b2bbb516056e The "Calling Python..." info logs are disabled if "PythonVerbose" is "false"
Sebastien Jodogne <s.jodogne@gmail.com>
parents: 13
diff changeset
35 static bool verbose_ = false;
0
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
36
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
37
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
38 struct module_state
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
39 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
40 PyObject *exceptionClass_ = NULL;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
41 };
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
42
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
43 #if PY_MAJOR_VERSION >= 3
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
44 # define GETSTATE(module) ((struct module_state*) PyModule_GetState(module))
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
45 #else
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
46 # define GETSTATE(module) (&_state)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
47 static struct module_state _state;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
48 #endif
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
49
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
50
13
952e969a2240 cppcheck
Sebastien Jodogne <s.jodogne@gmail.com>
parents: 12
diff changeset
51 PythonLock::PythonLock() :
952e969a2240 cppcheck
Sebastien Jodogne <s.jodogne@gmail.com>
parents: 12
diff changeset
52 gstate_(PyGILState_Ensure())
0
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
53 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
54 //OrthancPlugins::LogInfo("Python lock (GIL) acquired");
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
55 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
56
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
57
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
58 PythonLock::~PythonLock()
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
59 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
60 PyGILState_Release(gstate_);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
61 //OrthancPlugins::LogInfo("Python lock (GIL) released");
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
62 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
63
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
64
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
65 void PythonLock::ExecuteCommand(const std::string& s)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
66 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
67 if (PyRun_SimpleString(s.c_str()) != 0)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
68 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
69 OrthancPlugins::LogError("Error while executing a Python command");
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
70 ORTHANC_PLUGINS_THROW_EXCEPTION(Plugin);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
71 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
72 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
73
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
74
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
75 void PythonLock::ExecuteFile(const std::string& path)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
76 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
77 OrthancPlugins::MemoryBuffer buffer;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
78 buffer.ReadFile(path);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
79
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
80 std::string script;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
81 buffer.ToString(script);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
82
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
83 ExecuteCommand(script);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
84 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
85
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
86
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
87 bool PythonLock::HasErrorOccurred(std::string& target)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
88 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
89 if (PyErr_Occurred())
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
90 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
91 PyObject *exceptionType = NULL;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
92 PyObject *exceptionValue = NULL;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
93 PyObject *traceback = NULL;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
94 PyErr_Fetch(&exceptionType, &exceptionValue, &traceback);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
95
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
96 if (exceptionType == NULL)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
97 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
98 return false;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
99 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
100
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
101 PyErr_NormalizeException(&exceptionType, &exceptionValue, &traceback);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
102
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
103 #if PY_MAJOR_VERSION >= 3
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
104 if (traceback != NULL)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
105 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
106 PyException_SetTraceback(exceptionValue, traceback);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
107 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
108 #endif
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
109
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
110 if (exceptionType != NULL)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
111 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
112 PythonObject temp(*this, PyObject_Str(exceptionType));
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
113 std::string s;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
114 if (temp.ToUtf8String(s))
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
115 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
116 target += s + "\n";
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
117 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
118 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
119
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
120 if (exceptionValue != NULL)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
121 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
122 PythonObject temp(*this, PyObject_Str(exceptionValue));
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
123 std::string s;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
124 if (temp.ToUtf8String(s))
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
125 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
126 target += s + "\n";
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
127 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
128 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
129
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
130 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
131 PythonModule module(*this, "traceback");
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
132 PythonFunction f(*this, module, "format_tb");
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
133
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
134 if (traceback != NULL &&
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
135 f.IsValid())
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
136 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
137 PythonObject args(*this, PyTuple_New(1));
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
138 PyTuple_SetItem(args.GetPyObject(), 0, traceback);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
139
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
140 std::auto_ptr<PythonObject> value(f.CallUnchecked(args.GetPyObject()));
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
141
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
142 if (value->IsValid())
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
143 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
144 Py_ssize_t len = PyList_Size(value->GetPyObject());
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
145 for (Py_ssize_t i = 0; i < len; i++)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
146 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
147 PythonObject item(*this, PyList_GetItem(value->GetPyObject(), i), true /* borrowed */);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
148 std::string line;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
149 if (item.ToUtf8String(line))
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
150 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
151 target += "\n" + line;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
152 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
153 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
154 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
155 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
156 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
157
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
158
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
159 /**
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
160 * "This call takes away a reference to each object: you must own
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
161 * a reference to each object before the call and after the call
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
162 * you no longer own these references. (If you don't understand
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
163 * this, don't use this function. I warned you.)"
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
164 * => I don't use PyErr_Restore()
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
165 **/
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
166
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
167 //PyErr_Restore(exceptionType, exceptionValue, traceback);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
168 //PyErr_Clear();
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
169
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
170 return true;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
171 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
172 else
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
173 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
174 return false;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
175 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
176 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
177
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
178
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
179 static void RegisterException(PyObject* module,
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
180 const std::string& name)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
181 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
182 struct module_state *state = GETSTATE(module);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
183
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
184 state->exceptionClass_ = PyErr_NewException(const_cast<char*>(name.c_str()), NULL, NULL);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
185 if (state->exceptionClass_ == NULL)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
186 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
187 Py_DECREF(module);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
188 OrthancPlugins::LogError("Cannot create the Python exception class");
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
189 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
190 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
191
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
192 #if 1
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
193 Py_XINCREF(state->exceptionClass_);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
194 if (PyModule_AddObject(module, "Exception", state->exceptionClass_) < 0)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
195 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
196 Py_XDECREF(state->exceptionClass_);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
197 Py_CLEAR(state->exceptionClass_);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
198 OrthancPlugins::LogError("Cannot create the Python exception class");
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
199 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
200 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
201 #else
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
202 // Install the exception class
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
203 PyObject* dict = PyModule_GetDict(module);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
204 PyDict_SetItemString(dict, "Exception", state->exceptionClass);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
205 #endif
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
206 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
207
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
208
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
209
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
210 #if PY_MAJOR_VERSION >= 3
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
211
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
212 static int sdk_traverse(PyObject *module, visitproc visit, void *arg)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
213 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
214 Py_VISIT(GETSTATE(module)->exceptionClass_);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
215 return 0;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
216 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
217
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
218 static int sdk_clear(PyObject *module)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
219 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
220 Py_CLEAR(GETSTATE(module)->exceptionClass_);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
221 return 0;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
222 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
223
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
224 static struct PyModuleDef moduledef =
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
225 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
226 PyModuleDef_HEAD_INIT,
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
227 NULL, /* m_name => TO BE FILLED */
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
228 NULL,
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
229 sizeof(struct module_state),
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
230 NULL, /* m_methods => TO BE FILLED */
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
231 NULL,
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
232 sdk_traverse,
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
233 sdk_clear,
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
234 NULL
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
235 };
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
236
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
237
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
238 PyMODINIT_FUNC InitializeModule()
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
239 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
240 if (moduleFunctions_ == NULL ||
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
241 moduleClasses_ == NULL ||
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
242 moduleName_.empty() ||
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
243 exceptionName_.empty())
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
244 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
245 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
246 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
247
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
248 moduledef.m_name = moduleName_.c_str();
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
249 moduledef.m_methods = moduleFunctions_();
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
250
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
251 PyObject *module = PyModule_Create(&moduledef);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
252 if (module == NULL)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
253 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
254 OrthancPlugins::LogError("Cannot create a Python module");
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
255 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
256 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
257
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
258 RegisterException(module, moduleName_ + "." + exceptionName_);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
259 moduleClasses_(module);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
260
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
261 return module;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
262 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
263
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
264 #else
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
265
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
266 void InitializeModule()
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
267 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
268 if (moduleFunctions_ == NULL ||
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
269 moduleClasses_ == NULL ||
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
270 moduleName_.empty() ||
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
271 exceptionName_.empty())
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
272 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
273 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
274 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
275
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
276 PyObject *module = Py_InitModule(moduleName_.c_str(), moduleFunctions_());
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
277 if (module == NULL)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
278 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
279 OrthancPlugins::LogError("Cannot create a Python module");
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
280 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
281 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
282
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
283 RegisterException(module, moduleName_ + "." + exceptionName_);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
284 moduleClasses_(module);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
285 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
286
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
287 #endif
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
288
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
289
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
290
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
291 void PythonLock::GlobalInitialize(const std::string& moduleName,
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
292 const std::string& exceptionName,
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
293 ModuleFunctionsInstaller moduleFunctions,
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
294 ModuleClassesInstaller moduleClasses,
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
295 bool verbose)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
296 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
297 boost::mutex::scoped_lock lock(mutex_);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
298
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
299 if (interpreterState_ != NULL)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
300 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
301 OrthancPlugins::LogError("Cannot initialize twice the Python interpreter");
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
302 ORTHANC_PLUGINS_THROW_EXCEPTION(BadSequenceOfCalls);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
303 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
304
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
305 if (moduleClasses == NULL ||
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
306 moduleFunctions == NULL)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
307 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
308 ORTHANC_PLUGINS_THROW_EXCEPTION(NullPointer);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
309 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
310
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
311 if (moduleName.empty() ||
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
312 exceptionName.empty())
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
313 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
314 ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
315 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
316
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
317 if (exceptionName.find('.') != std::string::npos)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
318 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
319 OrthancPlugins::LogError("The name of the exception cannot contain \".\", found: " +
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
320 exceptionName);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
321 ORTHANC_PLUGINS_THROW_EXCEPTION(ParameterOutOfRange);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
322 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
323
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
324 moduleClasses_ = moduleClasses;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
325 moduleFunctions_ = moduleFunctions;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
326 moduleName_ = moduleName;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
327 exceptionName_ = exceptionName;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
328
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
329 std::string executable;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
330
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
331 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
332 OrthancPlugins::OrthancString str;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
333 str.Assign(OrthancPluginGetOrthancPath(OrthancPlugins::GetGlobalContext()));
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
334 str.ToString(executable);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
335 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
336
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
337 OrthancPlugins::LogWarning("Program name: " + executable);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
338
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
339 #if PY_MAJOR_VERSION == 2
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
340 Py_SetProgramName(&executable[0]); /* optional but recommended */
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
341 #else
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
342 std::wstring wide(executable.begin(), executable.end());
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
343 Py_SetProgramName(&wide[0]); /* optional but recommended */
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
344 Py_UnbufferedStdioFlag = 1; // Write immediately to stdout after "sys.stdout.flush()" (only in Python 3.x)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
345 #endif
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
346
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
347 Py_InspectFlag = 1; // Don't exit the Orthanc process on Python error
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
348
28
b2bbb516056e The "Calling Python..." info logs are disabled if "PythonVerbose" is "false"
Sebastien Jodogne <s.jodogne@gmail.com>
parents: 13
diff changeset
349 verbose_ = verbose;
0
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
350 if (verbose)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
351 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
352 Py_VerboseFlag = 1;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
353 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
354
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
355 #if PY_MAJOR_VERSION >= 3
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
356 PyImport_AppendInittab(moduleName_.c_str(), InitializeModule);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
357 #endif
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
358
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
359 #if PY_VERSION_HEX < 0x03020000 /* 3.2.0 */
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
360 /**
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
361 * "Changed in version 3.2: This function cannot be called before
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
362 * Py_Initialize() anymore."
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
363 **/
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
364 if (!PyEval_ThreadsInitialized())
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
365 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
366 PyEval_InitThreads();
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
367 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
368 #endif
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
369
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
370 Py_InitializeEx(0 /* Python is embedded, skip signal handlers */);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
371
12
0b8239ce1bec removed debug logs
Sebastien Jodogne <s.jodogne@gmail.com>
parents: 0
diff changeset
372 #if 0
0
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
373 #if PY_MAJOR_VERSION == 2
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
374 std::cout << Py_GetPath() << std::endl;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
375 std::cout << Py_GetProgramName() << std::endl;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
376 std::cout << Py_GetProgramFullPath() << std::endl;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
377 #else
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
378 std::wcout << Py_GetPath() << std::endl;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
379 std::wcout << Py_GetProgramName() << std::endl;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
380 std::wcout << Py_GetProgramFullPath() << std::endl;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
381 #endif
12
0b8239ce1bec removed debug logs
Sebastien Jodogne <s.jodogne@gmail.com>
parents: 0
diff changeset
382 #endif
0
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
383
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
384 #if (PY_VERSION_HEX >= 0x03020000 /* 3.2.0 */ && \
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
385 PY_VERSION_HEX < 0x03070000 /* 3.7.0 */)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
386 /**
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
387 * Changed in version 3.7: This function is now called by
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
388 * Py_Initialize(), so you don't have to call it yourself anymore.
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
389 **/
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
390 if (!PyEval_ThreadsInitialized())
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
391 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
392 PyEval_InitThreads();
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
393 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
394 #endif
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
395
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
396
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
397 #if PY_MAJOR_VERSION == 2
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
398 InitializeModule();
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
399 #endif
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
400
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
401 // https://fr.slideshare.net/YiLungTsai/embed-python => slide 26
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
402 interpreterState_ = PyEval_SaveThread();
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
403 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
404
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
405
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
406 void PythonLock::AddSysPath(const std::string& path)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
407 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
408 /**
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
409 * "It is recommended that applications embedding the Python
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
410 * interpreter for purposes other than executing a single script
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
411 * pass 0 as updatepath, and update sys.path themselves if
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
412 * desired. See CVE-2008-5983."
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
413 * => Set "sys.path.append()" to the directory of the configuration file by default
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
414 **/
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
415
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
416 PythonLock lock;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
417
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
418 /**
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
419 * Initialization of "sys.path.append()" must be done before loading
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
420 * any module.
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
421 **/
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
422
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
423 PyObject *sysPath = PySys_GetObject(const_cast<char*>("path"));
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
424 if (sysPath == NULL)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
425 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
426 OrthancPlugins::LogError("Cannot find sys.path");
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
427 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
428 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
429
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
430 PyObject* pyPath = PyUnicode_FromString(path.c_str());
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
431 int result = PyList_Insert(sysPath, 0, pyPath);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
432 Py_DECREF(pyPath);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
433
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
434 if (result != 0)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
435 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
436 OrthancPlugins::LogError("Cannot run sys.path.append()");
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
437 ORTHANC_PLUGINS_THROW_EXCEPTION(InternalError);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
438 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
439 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
440
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
441
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
442 void PythonLock::GlobalFinalize()
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
443 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
444 boost::mutex::scoped_lock lock(mutex_);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
445
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
446 if (interpreterState_ != NULL)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
447 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
448 PyEval_RestoreThread(interpreterState_);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
449 interpreterState_ = NULL;
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
450 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
451
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
452 Py_Finalize();
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
453 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
454
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
455
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
456 void PythonLock::RaiseException(PyObject* module,
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
457 OrthancPluginErrorCode code)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
458 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
459 if (code != OrthancPluginErrorCode_Success)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
460 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
461 const char* message = OrthancPluginGetErrorDescription(OrthancPlugins::GetGlobalContext(), code);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
462
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
463 struct module_state *state = GETSTATE(module);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
464 if (state->exceptionClass_ == NULL)
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
465 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
466 OrthancPlugins::LogError("No Python exception has been registered");
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
467 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
468 else
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
469 {
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
470 PyErr_SetString(state->exceptionClass_, message);
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
471 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
472 }
7ed502b17b8f initial commit
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
diff changeset
473 }
28
b2bbb516056e The "Calling Python..." info logs are disabled if "PythonVerbose" is "false"
Sebastien Jodogne <s.jodogne@gmail.com>
parents: 13
diff changeset
474
b2bbb516056e The "Calling Python..." info logs are disabled if "PythonVerbose" is "false"
Sebastien Jodogne <s.jodogne@gmail.com>
parents: 13
diff changeset
475
b2bbb516056e The "Calling Python..." info logs are disabled if "PythonVerbose" is "false"
Sebastien Jodogne <s.jodogne@gmail.com>
parents: 13
diff changeset
476 void PythonLock::LogCall(const std::string& message)
b2bbb516056e The "Calling Python..." info logs are disabled if "PythonVerbose" is "false"
Sebastien Jodogne <s.jodogne@gmail.com>
parents: 13
diff changeset
477 {
b2bbb516056e The "Calling Python..." info logs are disabled if "PythonVerbose" is "false"
Sebastien Jodogne <s.jodogne@gmail.com>
parents: 13
diff changeset
478 /**
b2bbb516056e The "Calling Python..." info logs are disabled if "PythonVerbose" is "false"
Sebastien Jodogne <s.jodogne@gmail.com>
parents: 13
diff changeset
479 * For purity, this function should lock the global "mutex_", but
b2bbb516056e The "Calling Python..." info logs are disabled if "PythonVerbose" is "false"
Sebastien Jodogne <s.jodogne@gmail.com>
parents: 13
diff changeset
480 * "verbose_" cannot change after the initial call to
b2bbb516056e The "Calling Python..." info logs are disabled if "PythonVerbose" is "false"
Sebastien Jodogne <s.jodogne@gmail.com>
parents: 13
diff changeset
481 * "GlobalInitialize()".
b2bbb516056e The "Calling Python..." info logs are disabled if "PythonVerbose" is "false"
Sebastien Jodogne <s.jodogne@gmail.com>
parents: 13
diff changeset
482 **/
b2bbb516056e The "Calling Python..." info logs are disabled if "PythonVerbose" is "false"
Sebastien Jodogne <s.jodogne@gmail.com>
parents: 13
diff changeset
483
b2bbb516056e The "Calling Python..." info logs are disabled if "PythonVerbose" is "false"
Sebastien Jodogne <s.jodogne@gmail.com>
parents: 13
diff changeset
484 if (verbose_)
b2bbb516056e The "Calling Python..." info logs are disabled if "PythonVerbose" is "false"
Sebastien Jodogne <s.jodogne@gmail.com>
parents: 13
diff changeset
485 {
b2bbb516056e The "Calling Python..." info logs are disabled if "PythonVerbose" is "false"
Sebastien Jodogne <s.jodogne@gmail.com>
parents: 13
diff changeset
486 OrthancPlugins::LogInfo(message);
b2bbb516056e The "Calling Python..." info logs are disabled if "PythonVerbose" is "false"
Sebastien Jodogne <s.jodogne@gmail.com>
parents: 13
diff changeset
487 }
b2bbb516056e The "Calling Python..." info logs are disabled if "PythonVerbose" is "false"
Sebastien Jodogne <s.jodogne@gmail.com>
parents: 13
diff changeset
488 }