wowool-sdk-cpp 3.6.1__cp313-cp313-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- wowool/native/core/wowool_sdk.cpp +655 -0
- wowool/package/lib/_wowool_plugin.cp313-win_amd64.pyd +0 -0
- wowool/package/lib/_wowool_sdk.cp313-win_amd64.pyd +0 -0
- wowool/package/lib/afst++.exe +0 -0
- wowool/package/lib/concrt140.dll +0 -0
- wowool/package/lib/icudt77.dll +0 -0
- wowool/package/lib/icuuc77.dll +0 -0
- wowool/package/lib/msvcp140.dll +0 -0
- wowool/package/lib/msvcp140_1.dll +0 -0
- wowool/package/lib/msvcp140_2.dll +0 -0
- wowool/package/lib/msvcp140_atomic_wait.dll +0 -0
- wowool/package/lib/msvcp140_codecvt_ids.dll +0 -0
- wowool/package/lib/vcruntime140.dll +0 -0
- wowool/package/lib/vcruntime140_1.dll +0 -0
- wowool/package/lib/woc++.exe +0 -0
- wowool/package/lib/wow++.exe +0 -0
- wowool/package/lib/wowool.dll +0 -0
- wowool/package/lib/wowool_plugin.py +22 -0
- wowool/package/lib/wowool_sdk.py +36 -0
- wowool/plugin/wowool_plugin.cpp +1432 -0
- wowool/plugin/wowool_plugin.hpp +157 -0
- wowool_sdk_cpp-3.6.1.dist-info/METADATA +33 -0
- wowool_sdk_cpp-3.6.1.dist-info/RECORD +25 -0
- wowool_sdk_cpp-3.6.1.dist-info/WHEEL +5 -0
- wowool_sdk_cpp-3.6.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,1432 @@
|
|
|
1
|
+
// ----------------------------------------------------------------------------------
|
|
2
|
+
// Copyright (c) 2024 Wowool, All Rights Reserved.
|
|
3
|
+
// NOTICE: All information contained herein is, and remains the property of Wowool.
|
|
4
|
+
// ----------------------------------------------------------------------------------
|
|
5
|
+
#define WITH_THREAD
|
|
6
|
+
|
|
7
|
+
#include "wowool_plugin.hpp"
|
|
8
|
+
// #include <codecvt>
|
|
9
|
+
#include <functional>
|
|
10
|
+
#include <iostream>
|
|
11
|
+
#include <mutex>
|
|
12
|
+
#include <pybind11/pybind11.h>
|
|
13
|
+
#include <pybind11/stl.h>
|
|
14
|
+
// #include <pybind11/stl_bind.h>
|
|
15
|
+
#include <regex>
|
|
16
|
+
#include <string>
|
|
17
|
+
#include <vector>
|
|
18
|
+
#include "nlohmann/json.hpp"
|
|
19
|
+
#include "plugins/api.hpp"
|
|
20
|
+
#include "wowool/common/c/plugin.h"
|
|
21
|
+
#include "wowool/common/exception.hpp"
|
|
22
|
+
#include "wowool/common/options.hpp"
|
|
23
|
+
|
|
24
|
+
// Undefine Logging
|
|
25
|
+
#define LOG_PLUGIN "[plugin]"
|
|
26
|
+
#define LOG_PYTHON "[py]"
|
|
27
|
+
#define TRACE 0
|
|
28
|
+
#define ERROR 0
|
|
29
|
+
#define DEBUG 0
|
|
30
|
+
#define WARNING 0
|
|
31
|
+
#define INFO 0
|
|
32
|
+
//#define WLOG(x, m) std::cout << m << std::endl;
|
|
33
|
+
#define WLOG(x, m)
|
|
34
|
+
// #define DEBUG_PYTHON_PLUGIN_MSG(x) std::cerr << "Thread ID: " << std::this_thread::get_id() << x << std::endl;
|
|
35
|
+
#define DEBUG_PYTHON_PLUGIN_MSG(x)
|
|
36
|
+
|
|
37
|
+
#ifdef __cplusplus
|
|
38
|
+
extern "C" {
|
|
39
|
+
#endif
|
|
40
|
+
|
|
41
|
+
struct _object;
|
|
42
|
+
typedef _object PyObject;
|
|
43
|
+
|
|
44
|
+
#ifdef __cplusplus
|
|
45
|
+
}
|
|
46
|
+
#endif
|
|
47
|
+
|
|
48
|
+
namespace py = pybind11;
|
|
49
|
+
using namespace wowool;
|
|
50
|
+
|
|
51
|
+
bool called_from_python_host_system = false;
|
|
52
|
+
///////////////////////////////////////////////////////////////////////////////////////
|
|
53
|
+
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
54
|
+
// forward declaration of global variable because the python people did not do a
|
|
55
|
+
// good job in creating a decent c/c++ api. we need to have this variable when
|
|
56
|
+
// we do the pytroushka :-) operation. which is from a python script :
|
|
57
|
+
// --> which call the wowool python api
|
|
58
|
+
// ----> which calls the c++ api
|
|
59
|
+
// ------> which triggers call in python
|
|
60
|
+
// ----------> which call back c++ functions
|
|
61
|
+
// -------------> which could eventually call python functions.
|
|
62
|
+
// in short when we call Py_IsInitialized from within a native python script
|
|
63
|
+
// we cannot call Py_IsInitialized otherwise the python people will make sure
|
|
64
|
+
// we crash. ( even if they say we need to ALWAYS call Py_IsInitialized ). but
|
|
65
|
+
// they forgot about the pytroushkas
|
|
66
|
+
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
|
67
|
+
|
|
68
|
+
py::object python_object_range_obj;
|
|
69
|
+
|
|
70
|
+
namespace wow {
|
|
71
|
+
namespace python {
|
|
72
|
+
|
|
73
|
+
// Convert a vector to a python list.
|
|
74
|
+
template<class T>
|
|
75
|
+
py::list to_list(std::vector<T> const &v)
|
|
76
|
+
{
|
|
77
|
+
typename std::vector<T>::const_iterator iter;
|
|
78
|
+
py::list list;
|
|
79
|
+
for (iter = v.begin(); iter != v.end(); ++iter)
|
|
80
|
+
{
|
|
81
|
+
list.append(*iter);
|
|
82
|
+
}
|
|
83
|
+
return list;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// wrapper class to make sure we close properly the python instance
|
|
87
|
+
class python_instance
|
|
88
|
+
{
|
|
89
|
+
public:
|
|
90
|
+
bool initialized_has_been_called = false;
|
|
91
|
+
python_instance(bool embbeded_in_python = false)
|
|
92
|
+
{
|
|
93
|
+
if (called_from_python_host_system)
|
|
94
|
+
return;
|
|
95
|
+
|
|
96
|
+
if (embbeded_in_python)
|
|
97
|
+
return;
|
|
98
|
+
|
|
99
|
+
{
|
|
100
|
+
DEBUG_PYTHON_PLUGIN_MSG("!!!!!!!!! Initialize Py_Initialize")
|
|
101
|
+
Py_Initialize();
|
|
102
|
+
DEBUG_PYTHON_PLUGIN_MSG("!!!!!!!!! Initialize PyEval_SaveThread")
|
|
103
|
+
PyEval_SaveThread();
|
|
104
|
+
initialized_has_been_called = true;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
~python_instance()
|
|
109
|
+
{
|
|
110
|
+
DEBUG_PYTHON_PLUGIN_MSG("!!!!!!!!! ~python_instance()")
|
|
111
|
+
if (called_from_python_host_system)
|
|
112
|
+
return;
|
|
113
|
+
if (initialized_has_been_called)
|
|
114
|
+
{
|
|
115
|
+
DEBUG_PYTHON_PLUGIN_MSG("!!!!!!!!! PyGILState_Ensure")
|
|
116
|
+
PyGILState_Ensure();
|
|
117
|
+
DEBUG_PYTHON_PLUGIN_MSG("!!!!!!!!! Py_Finalize")
|
|
118
|
+
Py_Finalize();
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
typedef std::function<bool(plugin_Annotation const *)>
|
|
124
|
+
filter_annotation_filter_type;
|
|
125
|
+
|
|
126
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
127
|
+
// AttributesPair
|
|
128
|
+
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
129
|
+
AttributesPair::AttributesPair()
|
|
130
|
+
: name_(nullptr)
|
|
131
|
+
, value_(nullptr)
|
|
132
|
+
{
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
AttributesPair::AttributesPair(void const *n, void *v)
|
|
136
|
+
: name_(std::string(wowool_plugin_string_to_string(n)))
|
|
137
|
+
, value_(std::string(wowool_plugin_any_to_string(v)))
|
|
138
|
+
{
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
std::string AttributesPair::to_string() const
|
|
142
|
+
{
|
|
143
|
+
std::string retval = name_;
|
|
144
|
+
retval += ":";
|
|
145
|
+
retval += value_;
|
|
146
|
+
return retval;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
150
|
+
// python_object_attributes
|
|
151
|
+
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
152
|
+
python_object_attributes::python_object_attributes()
|
|
153
|
+
: cncpt()
|
|
154
|
+
{
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
python_object_attributes::python_object_attributes(plugin_Annotation const *cncpt_)
|
|
158
|
+
: cncpt(cncpt_)
|
|
159
|
+
{
|
|
160
|
+
int idx = 0;
|
|
161
|
+
void *key = wowool_plugin_concept_attribute_key(cncpt, idx);
|
|
162
|
+
while (key)
|
|
163
|
+
{
|
|
164
|
+
void *value = wowool_plugin_concept_attribute_value(cncpt, idx);
|
|
165
|
+
this->emplace_back(key, value);
|
|
166
|
+
key = wowool_plugin_concept_attribute_key(cncpt, ++idx);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
bool python_object_attributes::has(std::string const &key) const
|
|
171
|
+
{
|
|
172
|
+
if (!this->empty())
|
|
173
|
+
{
|
|
174
|
+
return wowool_plugin_concept_has_attribute(cncpt, key.c_str());
|
|
175
|
+
}
|
|
176
|
+
return false;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
bool python_object_attributes::pybool() const
|
|
180
|
+
{
|
|
181
|
+
return cncpt == nullptr;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
std::string python_object_attributes::to_string() const
|
|
185
|
+
{
|
|
186
|
+
std::stringstream strm;
|
|
187
|
+
strm << '[';
|
|
188
|
+
std::copy(begin(), end(), std::ostream_iterator<AttributesPair>(strm, ", "));
|
|
189
|
+
strm << ']';
|
|
190
|
+
return strm.str();
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
std::once_flag once;
|
|
194
|
+
thread_local c_context thrd_context;
|
|
195
|
+
|
|
196
|
+
// #define PYTHON_LOCK python::python_lock pylock;
|
|
197
|
+
std::mutex global_python_mutex;
|
|
198
|
+
// #define PYTHON_LOCK std::lock_guard<std::mutex> guard(global_python_mutex);
|
|
199
|
+
// #define PYTHON_LOCK
|
|
200
|
+
std::string get_python_error_message();
|
|
201
|
+
|
|
202
|
+
class python_instance;
|
|
203
|
+
|
|
204
|
+
// return the current error message in the python module.
|
|
205
|
+
std::string get_python_error_message()
|
|
206
|
+
{
|
|
207
|
+
PyObject *type = nullptr, *value = nullptr, *traceback = nullptr,
|
|
208
|
+
*pyString = nullptr;
|
|
209
|
+
PyErr_Fetch(&type, &value, &traceback);
|
|
210
|
+
PyErr_Clear();
|
|
211
|
+
std::string message = "Python error: ";
|
|
212
|
+
if (type != nullptr && (pyString = PyObject_Str(type)) != nullptr && (PyUnicode_Check(pyString)))
|
|
213
|
+
{
|
|
214
|
+
PyObject *pyStr = PyUnicode_AsEncodedString(pyString, "utf-8", "Error ~");
|
|
215
|
+
const char *strExcType = PyBytes_AS_STRING(pyStr);
|
|
216
|
+
message += strExcType;
|
|
217
|
+
Py_XDECREF(strExcType);
|
|
218
|
+
Py_XDECREF(pyStr);
|
|
219
|
+
}
|
|
220
|
+
else
|
|
221
|
+
{
|
|
222
|
+
message += "<unknown exception type> ";
|
|
223
|
+
}
|
|
224
|
+
Py_XDECREF(pyString);
|
|
225
|
+
if (value != nullptr && (pyString = PyObject_Str(value)) != nullptr && (PyUnicode_Check(pyString)))
|
|
226
|
+
{
|
|
227
|
+
message += ": ";
|
|
228
|
+
PyObject *pyStr = PyUnicode_AsEncodedString(pyString, "utf-8", "Error ~");
|
|
229
|
+
const char *strExcType = PyBytes_AS_STRING(pyStr);
|
|
230
|
+
message += strExcType;
|
|
231
|
+
Py_XDECREF(strExcType);
|
|
232
|
+
Py_XDECREF(pyStr);
|
|
233
|
+
}
|
|
234
|
+
else
|
|
235
|
+
{
|
|
236
|
+
message += "<unknown exception date> ";
|
|
237
|
+
}
|
|
238
|
+
Py_XDECREF(pyString);
|
|
239
|
+
|
|
240
|
+
char const *verbose = std::getenv("WOWOOL_LOG_LEVEL");
|
|
241
|
+
if (verbose && strcmp(verbose, "DEBUG") == 0)
|
|
242
|
+
{
|
|
243
|
+
// Get the trace
|
|
244
|
+
PyObject *tracebackModule = PyImport_ImportModule("traceback");
|
|
245
|
+
if (tracebackModule != nullptr)
|
|
246
|
+
{
|
|
247
|
+
PyObject *tbList = nullptr;
|
|
248
|
+
PyObject *emptyString = nullptr;
|
|
249
|
+
PyObject *strRetval = nullptr;
|
|
250
|
+
|
|
251
|
+
tbList = PyObject_CallMethod(tracebackModule, "format_exception", "OOO", type, value == nullptr ? Py_None : value, traceback == nullptr ? Py_None : traceback);
|
|
252
|
+
|
|
253
|
+
if (tbList)
|
|
254
|
+
{
|
|
255
|
+
emptyString = PyUnicode_FromString("");
|
|
256
|
+
|
|
257
|
+
strRetval = PyObject_CallMethod(emptyString, "join", "O", tbList);
|
|
258
|
+
if (strRetval)
|
|
259
|
+
{
|
|
260
|
+
PyObject *pyStr = PyUnicode_AsEncodedString(strRetval, "utf-8", "Error ~");
|
|
261
|
+
const char *strExcType = PyBytes_AS_STRING(pyStr);
|
|
262
|
+
message += "\n";
|
|
263
|
+
message += strExcType;
|
|
264
|
+
Py_XDECREF(strExcType);
|
|
265
|
+
Py_XDECREF(pyStr);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
Py_DECREF(tbList);
|
|
269
|
+
if (emptyString)
|
|
270
|
+
Py_DECREF(emptyString);
|
|
271
|
+
}
|
|
272
|
+
if (strRetval)
|
|
273
|
+
Py_DECREF(strRetval);
|
|
274
|
+
Py_DECREF(tracebackModule);
|
|
275
|
+
}
|
|
276
|
+
else
|
|
277
|
+
{
|
|
278
|
+
// chrRetval = strdup("Unable to import traceback module.");
|
|
279
|
+
message += "Unable to import traceback module.";
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
Py_XDECREF(type);
|
|
283
|
+
Py_XDECREF(value);
|
|
284
|
+
Py_XDECREF(traceback);
|
|
285
|
+
|
|
286
|
+
return message;
|
|
287
|
+
// FIXME: Now we have an error message .. log it or something.
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
char *alloc_string(std::string const &str)
|
|
291
|
+
{
|
|
292
|
+
if (str.length() != 0)
|
|
293
|
+
{
|
|
294
|
+
char *data = (char *)malloc(str.size() + 1);
|
|
295
|
+
memcpy(data, str.c_str(), str.size());
|
|
296
|
+
data[str.size()] = 0;
|
|
297
|
+
return data;
|
|
298
|
+
}
|
|
299
|
+
else
|
|
300
|
+
{
|
|
301
|
+
return nullptr;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
//----------------------------------------------------------------
|
|
306
|
+
// class to collect the python modules
|
|
307
|
+
//----------------------------------------------------------------
|
|
308
|
+
class Facade
|
|
309
|
+
{
|
|
310
|
+
public:
|
|
311
|
+
Facade(std::string const &module);
|
|
312
|
+
char *call(char const *module_name, char const *function_name, wowool::plugins::Arguments const &arguments, tir_exception *ex);
|
|
313
|
+
~Facade();
|
|
314
|
+
|
|
315
|
+
std::string name;
|
|
316
|
+
py::object module;
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
typedef std::shared_ptr<Facade> Facade_ptr;
|
|
320
|
+
typedef std::map<std::string, Facade_ptr> FacadeCollection;
|
|
321
|
+
|
|
322
|
+
Facade::Facade(std::string const &module_name)
|
|
323
|
+
: name(module_name)
|
|
324
|
+
, module(py::module::import(name.c_str()))
|
|
325
|
+
{
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
Facade::~Facade()
|
|
329
|
+
{
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
char *Facade::call(char const *module_name, char const *function_name, wowool::plugins::Arguments const &arguments, tir_exception *ex)
|
|
333
|
+
{
|
|
334
|
+
assert(module);
|
|
335
|
+
WLOG(TRACE, LOG_PLUGIN << LOG_PYTHON << "call(" << function_name << ")");
|
|
336
|
+
PyObject *pFunc = nullptr;
|
|
337
|
+
pFunc = PyObject_GetAttrString(module.ptr(), function_name);
|
|
338
|
+
if (pFunc && PyCallable_Check(pFunc))
|
|
339
|
+
{
|
|
340
|
+
PyObject *pArgs, *pValue;
|
|
341
|
+
pArgs = PyTuple_New(arguments.size());
|
|
342
|
+
for (size_t i = 0; i < arguments.size(); ++i)
|
|
343
|
+
{
|
|
344
|
+
if (arguments[i].type == wowool::plugins::do_char_ptr)
|
|
345
|
+
{
|
|
346
|
+
pValue = PyUnicode_FromString((char *)arguments[i].data);
|
|
347
|
+
if (!pValue)
|
|
348
|
+
{
|
|
349
|
+
Py_DECREF(pArgs);
|
|
350
|
+
Py_XDECREF(pFunc);
|
|
351
|
+
WLOG(ERROR, "Cannot convert argument");
|
|
352
|
+
return nullptr;
|
|
353
|
+
}
|
|
354
|
+
/* pValue reference stolen here: */
|
|
355
|
+
PyTuple_SetItem(pArgs, i, pValue);
|
|
356
|
+
}
|
|
357
|
+
else if (arguments[i].type == wowool::plugins::do_pydict)
|
|
358
|
+
{
|
|
359
|
+
py::dict &data = *((py::dict *)(arguments[i].data));
|
|
360
|
+
data.inc_ref();
|
|
361
|
+
PyTuple_SetItem(pArgs, i, data.ptr());
|
|
362
|
+
}
|
|
363
|
+
else if (arguments[i].type == wowool::plugins::do_annotation)
|
|
364
|
+
{
|
|
365
|
+
try
|
|
366
|
+
{
|
|
367
|
+
// get the object constructor.
|
|
368
|
+
// create a python object.
|
|
369
|
+
py::object pyobj = python_object_range_obj((plugin_Annotation *)arguments[i].data);
|
|
370
|
+
pyobj.inc_ref();
|
|
371
|
+
PyTuple_SetItem(pArgs, i, pyobj.ptr());
|
|
372
|
+
} catch (std::exception &ex)
|
|
373
|
+
{
|
|
374
|
+
std::cerr << "error adding annotation attribute. " << ex.what() << std::endl;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
pValue = PyObject_CallObject(pFunc, pArgs);
|
|
380
|
+
if (pValue != nullptr)
|
|
381
|
+
{
|
|
382
|
+
std::string retval;
|
|
383
|
+
if (PyBool_Check(pValue))
|
|
384
|
+
{
|
|
385
|
+
if (PyObject_IsTrue(pValue))
|
|
386
|
+
{
|
|
387
|
+
retval = "true";
|
|
388
|
+
}
|
|
389
|
+
else
|
|
390
|
+
{
|
|
391
|
+
retval = "false";
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
else if (PyUnicode_Check(pValue))
|
|
395
|
+
{
|
|
396
|
+
retval = py::str(pValue);
|
|
397
|
+
}
|
|
398
|
+
Py_DECREF(pValue);
|
|
399
|
+
Py_DECREF(pArgs);
|
|
400
|
+
Py_XDECREF(pFunc);
|
|
401
|
+
WLOG(TRACE, LOG_PLUGIN << LOG_PYTHON << "RETURN (" << retval << ")");
|
|
402
|
+
return alloc_string(retval);
|
|
403
|
+
}
|
|
404
|
+
else
|
|
405
|
+
{
|
|
406
|
+
std::string errstr = get_python_error_message();
|
|
407
|
+
WLOG(ERROR, "Could not execute python function:" << function_name << " in module " << module_name << ":" << errstr.c_str());
|
|
408
|
+
wowool::common::throw_c_exception(ex, errstr.c_str());
|
|
409
|
+
return nullptr;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
Py_DECREF(pArgs);
|
|
413
|
+
Py_XDECREF(pFunc);
|
|
414
|
+
}
|
|
415
|
+
else
|
|
416
|
+
{
|
|
417
|
+
WLOG(ERROR, "Could not find python function:" << function_name << " in module " << module_name);
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
/* Release the thread. No Python API allowed beyond this point. */
|
|
421
|
+
// PyGILState_Release(gstate);
|
|
422
|
+
|
|
423
|
+
WLOG(ERROR, "Could not find python function:" << function_name << " in module " << module_name);
|
|
424
|
+
return nullptr;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
struct IsURI
|
|
428
|
+
{
|
|
429
|
+
IsURI(std::string const &uri_)
|
|
430
|
+
: uri(uri_.c_str())
|
|
431
|
+
{
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
const char *uri;
|
|
435
|
+
|
|
436
|
+
bool operator()(plugin_Annotation const *a) const
|
|
437
|
+
{
|
|
438
|
+
return ((wowool_plugin_get_type(a) == AnnotationType_Concept) && (strcmp(wowool_plugin_concept_uri(a), uri) == 0));
|
|
439
|
+
}
|
|
440
|
+
};
|
|
441
|
+
|
|
442
|
+
std::ostream &operator<<(std::ostream &out, AttributesPair const &data)
|
|
443
|
+
{
|
|
444
|
+
out << '(' << data.name() << '=' << data.value() << ')';
|
|
445
|
+
return out;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
typedef std::pair<std::string, std::string> AttributePair;
|
|
449
|
+
typedef std::map<std::string, std::string> AttributeCollection;
|
|
450
|
+
|
|
451
|
+
AttributeCollection convert_py_options(py::dict const &kwargs)
|
|
452
|
+
{
|
|
453
|
+
AttributeCollection options;
|
|
454
|
+
for (auto const item : kwargs)
|
|
455
|
+
{
|
|
456
|
+
options.emplace(py::str(item.first), py::str(item.second));
|
|
457
|
+
}
|
|
458
|
+
return options;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
c_context const &get_current_context() { return thrd_context; }
|
|
462
|
+
|
|
463
|
+
static std::shared_ptr<python::python_instance> python_instance_singleton;
|
|
464
|
+
|
|
465
|
+
void create_python_instance()
|
|
466
|
+
{
|
|
467
|
+
python_instance_singleton.reset(new python::python_instance());
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
void init_python_instance() { std::call_once(once, &create_python_instance); }
|
|
471
|
+
|
|
472
|
+
struct PyLock
|
|
473
|
+
{
|
|
474
|
+
PyLock()
|
|
475
|
+
{
|
|
476
|
+
DEBUG_PYTHON_PLUGIN_MSG(" >> PyGILState_Ensure");
|
|
477
|
+
gstate = PyGILState_Ensure();
|
|
478
|
+
DEBUG_PYTHON_PLUGIN_MSG(" << PyGILState_Ensure");
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
~PyLock()
|
|
482
|
+
{
|
|
483
|
+
DEBUG_PYTHON_PLUGIN_MSG(" >> PyGILState_Release");
|
|
484
|
+
PyGILState_Release(gstate);
|
|
485
|
+
DEBUG_PYTHON_PLUGIN_MSG(" << PyGILState_Release");
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
// PyThreadState *python_interprter;
|
|
489
|
+
PyGILState_STATE gstate;
|
|
490
|
+
};
|
|
491
|
+
|
|
492
|
+
struct python_user_data_object
|
|
493
|
+
{
|
|
494
|
+
python_user_data_object()
|
|
495
|
+
: pydict(nullptr)
|
|
496
|
+
{
|
|
497
|
+
pydict = new py::dict();
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
~python_user_data_object()
|
|
501
|
+
{
|
|
502
|
+
DEBUG_PYTHON_PLUGIN_MSG(">> ~python_user_data_object");
|
|
503
|
+
if (pydict)
|
|
504
|
+
{
|
|
505
|
+
PyLock pylock;
|
|
506
|
+
DEBUG_PYTHON_PLUGIN_MSG(">> delete python_user_data_object");
|
|
507
|
+
delete pydict;
|
|
508
|
+
DEBUG_PYTHON_PLUGIN_MSG("<< delete python_user_data_object");
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
// PyThreadState *python_interprter;
|
|
513
|
+
py::dict *pydict;
|
|
514
|
+
// std::shared_ptr<python::python_instance> py_instance;
|
|
515
|
+
};
|
|
516
|
+
|
|
517
|
+
typedef std::shared_ptr<python_user_data_object> python_user_data;
|
|
518
|
+
thread_local python_user_data thread_python_user_data;
|
|
519
|
+
|
|
520
|
+
// create the python dictionary as user document data.
|
|
521
|
+
python_user_data &create_userdata()
|
|
522
|
+
{
|
|
523
|
+
PyLock pylock;
|
|
524
|
+
DEBUG_PYTHON_PLUGIN_MSG("PYDEBUG: create_userdata");
|
|
525
|
+
|
|
526
|
+
thread_python_user_data.reset(new python_user_data_object);
|
|
527
|
+
// py::gil_scoped_acquire acquire;
|
|
528
|
+
thread_python_user_data->pydict = new py::dict();
|
|
529
|
+
|
|
530
|
+
return thread_python_user_data;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
python_user_data &get_current_userdata() { return thread_python_user_data; }
|
|
534
|
+
|
|
535
|
+
// release the user data when we are done with the document.
|
|
536
|
+
void release_userdata()
|
|
537
|
+
{
|
|
538
|
+
DEBUG_PYTHON_PLUGIN_MSG("PYDEBUG: release_userdata");
|
|
539
|
+
if (thread_python_user_data.get())
|
|
540
|
+
{
|
|
541
|
+
DEBUG_PYTHON_PLUGIN_MSG("PYDEBUG: release_userdata.reset()");
|
|
542
|
+
PyLock pylock;
|
|
543
|
+
thread_python_user_data.reset();
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
548
|
+
// python_token
|
|
549
|
+
// object that represents a token object in python.
|
|
550
|
+
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
551
|
+
python_token::python_token()
|
|
552
|
+
: token(nullptr)
|
|
553
|
+
{
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
python_token::python_token(plugin_Annotation const *token_)
|
|
557
|
+
: token(token_)
|
|
558
|
+
{
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
bool python_token::has_property(std::string const &prop) const
|
|
562
|
+
{
|
|
563
|
+
return wowool_plugin_token_has_attribute(token, prop.c_str());
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
std::string python_token::head() const
|
|
567
|
+
{
|
|
568
|
+
return wowool_plugin_token_head(token);
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
std::string python_token::pos(int idx) const
|
|
572
|
+
{
|
|
573
|
+
return wowool_plugin_token_pos(token, idx);
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
std::string python_token::stem(int idx) const
|
|
577
|
+
{
|
|
578
|
+
return wowool_plugin_token_stem(token, idx);
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
std::string python_token::lemma(int idx) const
|
|
582
|
+
{
|
|
583
|
+
return wowool_plugin_token_stem(token, idx);
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
std::string python_token::str() const
|
|
587
|
+
{
|
|
588
|
+
return std::string(wowool_plugin_token_literal(token));
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
std::string python_token::literal() const
|
|
592
|
+
{
|
|
593
|
+
return std::string(wowool_plugin_token_literal(token));
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
///////////////////////////////////////////////////////////////////////////////
|
|
597
|
+
// python_object_range
|
|
598
|
+
// object that represent a annotation range in python.
|
|
599
|
+
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
600
|
+
python_object_range::python_object_range() {}
|
|
601
|
+
|
|
602
|
+
python_object_range::python_object_range(plugin_Annotation const *cncpt)
|
|
603
|
+
{
|
|
604
|
+
begin = cncpt;
|
|
605
|
+
if (begin)
|
|
606
|
+
{
|
|
607
|
+
end = wowool_plugin_concept_get_end(cncpt);
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
python_object_range::~python_object_range() {}
|
|
612
|
+
|
|
613
|
+
python_object_range::python_object_range(plugin_Annotation const *begin_, plugin_Annotation const *end_)
|
|
614
|
+
{
|
|
615
|
+
begin = begin_;
|
|
616
|
+
end = end_;
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
void python_object_range::remove_concept()
|
|
620
|
+
{
|
|
621
|
+
wowool_plugin_concept_remove(const_cast<plugin_Annotation *>(begin));
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
int python_object_range::get_begin_offset() const
|
|
625
|
+
{
|
|
626
|
+
if (begin)
|
|
627
|
+
return wowool_plugin_get_begin_offset(begin);
|
|
628
|
+
return -1;
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
int python_object_range::get_end_offset() const
|
|
632
|
+
{
|
|
633
|
+
plugin_Annotation const *it = end;
|
|
634
|
+
while (it != nullptr)
|
|
635
|
+
{
|
|
636
|
+
if (wowool_plugin_get_type(it) == AnnotationType_Token)
|
|
637
|
+
{
|
|
638
|
+
return wowool_plugin_get_end_offset(it);
|
|
639
|
+
}
|
|
640
|
+
it = wowool_plugin_get_prev(it);
|
|
641
|
+
}
|
|
642
|
+
return get_begin_offset();
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
std::string python_object_range::get_uri() const
|
|
646
|
+
{
|
|
647
|
+
if (begin && wowool_plugin_get_type(begin) == AnnotationType_Concept)
|
|
648
|
+
return std::string(wowool_plugin_concept_uri(begin));
|
|
649
|
+
return "";
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
std::vector<python_object_range> python_object_range::find_with_filter(
|
|
653
|
+
filter_annotation_filter_type const &filter)
|
|
654
|
+
{
|
|
655
|
+
std::vector<python_object_range> retval;
|
|
656
|
+
// tir::wowool::is_concept filter;
|
|
657
|
+
|
|
658
|
+
// algin to the begin end offset of the given annotation.
|
|
659
|
+
auto it = wowool_plugin_align_begin(begin, end);
|
|
660
|
+
|
|
661
|
+
while (it != end)
|
|
662
|
+
{
|
|
663
|
+
if (filter(it))
|
|
664
|
+
{
|
|
665
|
+
if (!wowool_plugin_concept_is_deleted(it))
|
|
666
|
+
{
|
|
667
|
+
retval.emplace_back(python_object_range(it));
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
it = wowool_plugin_get_next(it);
|
|
671
|
+
}
|
|
672
|
+
return retval;
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
python_object_attributes python_object_range::attributes()
|
|
676
|
+
{
|
|
677
|
+
return python_object_attributes(begin);
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
bool python_object_range::has(std::string const &key) const
|
|
681
|
+
{
|
|
682
|
+
return wowool_plugin_concept_has_attribute(begin, key.c_str());
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
std::string python_object_range::get_attribute(std::string const &key) const
|
|
686
|
+
{
|
|
687
|
+
return std::string(wowool_plugin_concept_get_attribute(begin, key.c_str()));
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
bool python_object_range::add_attribute(std::string const &key, std::string const &value)
|
|
691
|
+
{
|
|
692
|
+
return wowool_plugin_concept_add_attribute(
|
|
693
|
+
const_cast<plugin_Annotation *>(begin), key.c_str(), value.c_str());
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
// filter a range of annotations.
|
|
697
|
+
std::vector<python_object_range>
|
|
698
|
+
python_object_range::regex(std::string const &uri)
|
|
699
|
+
{
|
|
700
|
+
std::regex re(uri);
|
|
701
|
+
std::smatch what;
|
|
702
|
+
// Note: uri is a char pointer !
|
|
703
|
+
return find_with_filter([&](plugin_Annotation const *a) -> bool {
|
|
704
|
+
if (wowool_plugin_get_type(a) == AnnotationType_Concept)
|
|
705
|
+
{
|
|
706
|
+
std::string uri = wowool_plugin_concept_uri(a);
|
|
707
|
+
return std::regex_match(uri, what, re);
|
|
708
|
+
}
|
|
709
|
+
return false;
|
|
710
|
+
});
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
python_object_range python_object_range::add_concept(std::string const &uri)
|
|
714
|
+
{
|
|
715
|
+
auto const context = python::get_current_context();
|
|
716
|
+
plugin_Annotation *annotation = wowool_plugin_update_concept_in_collection(&context, begin, end, uri.c_str());
|
|
717
|
+
if (annotation)
|
|
718
|
+
{
|
|
719
|
+
return python_object_range(annotation);
|
|
720
|
+
}
|
|
721
|
+
else
|
|
722
|
+
{
|
|
723
|
+
return python_object_range();
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
// implements the python calls capture["person" ]
|
|
728
|
+
// argument is a string
|
|
729
|
+
std::vector<python_object_range>
|
|
730
|
+
python_object_range::get_item(std::string const &uri)
|
|
731
|
+
{
|
|
732
|
+
return find(uri);
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
// implements the python calls capture["person","boss", .... ]
|
|
736
|
+
// argument is a tuple (a,b,c,...)
|
|
737
|
+
std::vector<python_object_range>
|
|
738
|
+
python_object_range::get_item(py::tuple const &elements)
|
|
739
|
+
{
|
|
740
|
+
std::vector<python_object_range> results;
|
|
741
|
+
for (auto const item : elements)
|
|
742
|
+
{
|
|
743
|
+
std::string key = py::str(item);
|
|
744
|
+
std::vector<python_object_range> tmp = find(key);
|
|
745
|
+
std::copy(tmp.begin(), tmp.end(), std::back_inserter(results));
|
|
746
|
+
}
|
|
747
|
+
return results;
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
// implements the python calls capture.person
|
|
751
|
+
// argument is a string
|
|
752
|
+
py::object python_object_range::get_attr(std::string const &uri)
|
|
753
|
+
{
|
|
754
|
+
return find_one(uri);
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
py::object python_object_range::find_one(std::string const &uri)
|
|
758
|
+
{
|
|
759
|
+
assert(begin);
|
|
760
|
+
// Note do note align for the attribute.
|
|
761
|
+
if (wowool_plugin_get_type(begin) == AnnotationType_Concept)
|
|
762
|
+
{
|
|
763
|
+
if (wowool_plugin_concept_has_attribute(begin, uri.c_str()))
|
|
764
|
+
{
|
|
765
|
+
return py::str(
|
|
766
|
+
std::string(wowool_plugin_concept_get_attribute(begin, uri.c_str())));
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
std::vector<python_object_range> results;
|
|
771
|
+
if (uri.size() >= 2 && uri[0] == '/' && uri[uri.size() - 1] == '/')
|
|
772
|
+
{
|
|
773
|
+
results = regex(uri.substr(1, uri.size() - 2));
|
|
774
|
+
}
|
|
775
|
+
else
|
|
776
|
+
{
|
|
777
|
+
IsURI filter(uri);
|
|
778
|
+
results = find_with_filter(filter);
|
|
779
|
+
}
|
|
780
|
+
if (results.size())
|
|
781
|
+
return py::cast(results[0]);
|
|
782
|
+
return py::none();
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
std::vector<python_object_range>
|
|
786
|
+
python_object_range::find(std::string const &uri)
|
|
787
|
+
{
|
|
788
|
+
if (uri.size() > 2 && uri[0] == '/' && uri[uri.size() - 1] == '/')
|
|
789
|
+
return regex(uri.substr(1, uri.size() - 2));
|
|
790
|
+
IsURI filter(uri);
|
|
791
|
+
return find_with_filter(filter);
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
std::vector<int> python_object_range::find_int(std::string const &uri)
|
|
795
|
+
{
|
|
796
|
+
return std::vector<int>();
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
py::list python_object_range::tokens()
|
|
800
|
+
{
|
|
801
|
+
if (begin == nullptr)
|
|
802
|
+
{
|
|
803
|
+
std::vector<python_token> v;
|
|
804
|
+
return python::to_list(v);
|
|
805
|
+
}
|
|
806
|
+
std::vector<python_token> retval;
|
|
807
|
+
std::stringstream strm;
|
|
808
|
+
auto it = begin;
|
|
809
|
+
while (it != end)
|
|
810
|
+
{
|
|
811
|
+
if (wowool_plugin_get_type(it) == AnnotationType_Token)
|
|
812
|
+
{
|
|
813
|
+
retval.emplace_back(it);
|
|
814
|
+
}
|
|
815
|
+
it = wowool_plugin_get_next(it);
|
|
816
|
+
}
|
|
817
|
+
return python::to_list(retval);
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
std::string python_object_range::str() { return literal(); }
|
|
821
|
+
|
|
822
|
+
std::string python_object_range::repr() const
|
|
823
|
+
{
|
|
824
|
+
std::stringstream out;
|
|
825
|
+
auto it = begin;
|
|
826
|
+
while (it != end)
|
|
827
|
+
{
|
|
828
|
+
if (wowool_plugin_get_type(it) == AnnotationType_Token)
|
|
829
|
+
{
|
|
830
|
+
out << "T:" << wowool_plugin_token_literal(it) << std::endl;
|
|
831
|
+
}
|
|
832
|
+
else if (wowool_plugin_get_type(it) == AnnotationType_Concept)
|
|
833
|
+
{
|
|
834
|
+
out << "C:" << wowool_plugin_concept_uri(it) << std::endl;
|
|
835
|
+
}
|
|
836
|
+
it = wowool_plugin_get_next(it);
|
|
837
|
+
}
|
|
838
|
+
return out.str();
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
std::string python_object_range::literal(std::string const delimiter)
|
|
842
|
+
{
|
|
843
|
+
if (begin == nullptr)
|
|
844
|
+
return "";
|
|
845
|
+
return std::string(
|
|
846
|
+
wowool_plugin_range_literal(begin, end, delimiter.c_str()));
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
std::string python_object_range::text()
|
|
850
|
+
{
|
|
851
|
+
if (begin == nullptr)
|
|
852
|
+
return "";
|
|
853
|
+
return std::string(
|
|
854
|
+
wowool_plugin_range_literal(begin, end, " "));
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
// Need to fix the canonical
|
|
858
|
+
// Example: vijf jaar geleden --> 5 jaar geleden
|
|
859
|
+
std::string python_object_range::canonical(std::string const delimiter)
|
|
860
|
+
{
|
|
861
|
+
if (begin == nullptr)
|
|
862
|
+
return "";
|
|
863
|
+
|
|
864
|
+
if (wowool_plugin_get_type(begin) == AnnotationType_Concept)
|
|
865
|
+
{
|
|
866
|
+
if (wowool_plugin_concept_has_attribute(begin, "canonical"))
|
|
867
|
+
{
|
|
868
|
+
return py::str(
|
|
869
|
+
std::string(wowool_plugin_concept_get_attribute(begin, "canonical")));
|
|
870
|
+
}
|
|
871
|
+
else
|
|
872
|
+
{
|
|
873
|
+
return literal(delimiter);
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
return std::string(
|
|
878
|
+
wowool_plugin_range_literal(begin, end, delimiter.c_str()));
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
std::string python_object_range::stem(std::string const delimiter)
|
|
882
|
+
{
|
|
883
|
+
if (begin == nullptr)
|
|
884
|
+
return "";
|
|
885
|
+
return std::string(wowool_plugin_range_stem(begin, end, delimiter.c_str()));
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
std::string python_object_range::lemma()
|
|
889
|
+
{
|
|
890
|
+
if (begin == nullptr)
|
|
891
|
+
return "";
|
|
892
|
+
return std::string(wowool_plugin_range_stem(begin, end, " "));
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
bool python_object_range::pybool() const
|
|
896
|
+
{
|
|
897
|
+
return begin != nullptr;
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
bool operator==(python_object_range const &lhs, python_object_range const &rhs)
|
|
901
|
+
{
|
|
902
|
+
return ((lhs.begin == rhs.begin) && (lhs.end == rhs.end));
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
// the match context api.
|
|
906
|
+
python_object_match_context::python_object_match_context() { context = python::get_current_context(); }
|
|
907
|
+
|
|
908
|
+
python_object_range python_object_match_context::capture()
|
|
909
|
+
{
|
|
910
|
+
return python_object_range(python::get_current_context().capture);
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
python_object_range python_object_match_context::rule()
|
|
914
|
+
{
|
|
915
|
+
if (context.rule == nullptr)
|
|
916
|
+
return python_object_range(python::get_current_context().capture);
|
|
917
|
+
return python_object_range(python::get_current_context().rule);
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
python_object_range python_object_match_context::sentence()
|
|
921
|
+
{
|
|
922
|
+
if (context.sent)
|
|
923
|
+
{
|
|
924
|
+
return python_object_range(wowool_plugin_sentence_begin(context.sent), wowool_plugin_sentence_end(context.sent));
|
|
925
|
+
}
|
|
926
|
+
return python_object_range();
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
python_object_range python_object_match_context::make_range(python_object_range begin_, python_object_range end_)
|
|
930
|
+
{
|
|
931
|
+
return python_object_range(begin_.begin, end_.end);
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
std::string python_object_match_context::to_string() { return wowool_plugin_concept_uri(context.capture); }
|
|
935
|
+
|
|
936
|
+
const std::string python_object_match_context::property(std::string const &key) { return wowool_plugin_property(&context, key.c_str()); }
|
|
937
|
+
|
|
938
|
+
}
|
|
939
|
+
} // namespace wow::python
|
|
940
|
+
// ----------------------------------------------------------------------------
|
|
941
|
+
// Plugin code to be loaded in the cpp module
|
|
942
|
+
// ----------------------------------------------------------------------------
|
|
943
|
+
namespace wow {
|
|
944
|
+
namespace python {
|
|
945
|
+
|
|
946
|
+
using wowool::plugins::Arguments;
|
|
947
|
+
|
|
948
|
+
// convert UTF-8 string to wstring
|
|
949
|
+
std::string wstring_to_utf8(const std::wstring &wstr)
|
|
950
|
+
{
|
|
951
|
+
std::string utf8;
|
|
952
|
+
for (wchar_t wc : wstr)
|
|
953
|
+
{
|
|
954
|
+
if (wc <= 0x7F)
|
|
955
|
+
{
|
|
956
|
+
utf8.push_back(static_cast<char>(wc)); // ASCII range (1 byte)
|
|
957
|
+
}
|
|
958
|
+
else if (wc <= 0x7FF)
|
|
959
|
+
{
|
|
960
|
+
utf8.push_back(static_cast<char>(0xC0 | ((wc >> 6) & 0x1F))); // 2 bytes
|
|
961
|
+
utf8.push_back(static_cast<char>(0x80 | (wc & 0x3F)));
|
|
962
|
+
}
|
|
963
|
+
else if (wc <= 0xFFFF)
|
|
964
|
+
{
|
|
965
|
+
utf8.push_back(static_cast<char>(0xE0 | ((wc >> 12) & 0x0F))); // 3 bytes
|
|
966
|
+
utf8.push_back(static_cast<char>(0x80 | ((wc >> 6) & 0x3F)));
|
|
967
|
+
utf8.push_back(static_cast<char>(0x80 | (wc & 0x3F)));
|
|
968
|
+
}
|
|
969
|
+
else
|
|
970
|
+
{
|
|
971
|
+
utf8.push_back(static_cast<char>(0xF0 | ((wc >> 18) & 0x07))); // 4 bytes
|
|
972
|
+
utf8.push_back(static_cast<char>(0x80 | ((wc >> 12) & 0x3F)));
|
|
973
|
+
utf8.push_back(static_cast<char>(0x80 | ((wc >> 6) & 0x3F)));
|
|
974
|
+
utf8.push_back(static_cast<char>(0x80 | (wc & 0x3F)));
|
|
975
|
+
}
|
|
976
|
+
}
|
|
977
|
+
return utf8;
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
std::wstring utf8_to_wstring(const std::string &str)
|
|
981
|
+
{
|
|
982
|
+
std::wstring wstr;
|
|
983
|
+
size_t i = 0;
|
|
984
|
+
while (i < str.size())
|
|
985
|
+
{
|
|
986
|
+
unsigned char ch = str[i];
|
|
987
|
+
wchar_t wc = 0;
|
|
988
|
+
int extra_bytes = 0;
|
|
989
|
+
|
|
990
|
+
if ((ch & 0x80) == 0)
|
|
991
|
+
{ // 1-byte character (ASCII)
|
|
992
|
+
wc = ch;
|
|
993
|
+
}
|
|
994
|
+
else if ((ch & 0xE0) == 0xC0)
|
|
995
|
+
{ // 2-byte character
|
|
996
|
+
wc = ch & 0x1F;
|
|
997
|
+
extra_bytes = 1;
|
|
998
|
+
}
|
|
999
|
+
else if ((ch & 0xF0) == 0xE0)
|
|
1000
|
+
{ // 3-byte character
|
|
1001
|
+
wc = ch & 0x0F;
|
|
1002
|
+
extra_bytes = 2;
|
|
1003
|
+
}
|
|
1004
|
+
else if ((ch & 0xF8) == 0xF0)
|
|
1005
|
+
{ // 4-byte character
|
|
1006
|
+
wc = ch & 0x07;
|
|
1007
|
+
extra_bytes = 3;
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
for (int j = 0; j < extra_bytes; ++j)
|
|
1011
|
+
{
|
|
1012
|
+
if (++i >= str.size()) return {}; // Invalid UTF-8
|
|
1013
|
+
wc = (wc << 6) | (str[i] & 0x3F);
|
|
1014
|
+
}
|
|
1015
|
+
wstr.push_back(wc);
|
|
1016
|
+
++i;
|
|
1017
|
+
}
|
|
1018
|
+
return wstr;
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
class Plugin : public wowool::plugins::API
|
|
1022
|
+
{
|
|
1023
|
+
public:
|
|
1024
|
+
Plugin();
|
|
1025
|
+
virtual ~Plugin();
|
|
1026
|
+
|
|
1027
|
+
virtual bool load_modules(char const *json_options, tir_exception *) noexcept;
|
|
1028
|
+
bool _nolock_load_modules(char const *json_options, tir_exception *) noexcept;
|
|
1029
|
+
|
|
1030
|
+
virtual char *call(char const *module_name, char const *name, wowool::plugins::Arguments const &arguments, tir_exception *ex) noexcept;
|
|
1031
|
+
|
|
1032
|
+
char *_nolock_call(char const *module_name, char const *name, wowool::plugins::Arguments const &arguments, tir_exception *ex) noexcept;
|
|
1033
|
+
|
|
1034
|
+
// virtual char *init(char const *module_name, char const *name, wowool::plugins::Arguments
|
|
1035
|
+
// const &arguments, tir_exception *ex) noexcept;
|
|
1036
|
+
virtual char *open_document(char const *module_name, char const *name, wowool::plugins::Arguments const &arguments, tir_exception *ex) noexcept;
|
|
1037
|
+
virtual char *close_document(char const *module_name, char const *name, wowool::plugins::Arguments const &arguments, tir_exception *ex) noexcept;
|
|
1038
|
+
virtual char *trigger(char const *module_name, char const *name, wowool::plugins::Arguments const &arguments, tir_exception *ex) noexcept;
|
|
1039
|
+
virtual void release_document(tir_exception *) noexcept;
|
|
1040
|
+
virtual void set_document_property(char const *key, char const *value, tir_exception *) noexcept;
|
|
1041
|
+
|
|
1042
|
+
virtual void release(void *ptr) noexcept;
|
|
1043
|
+
|
|
1044
|
+
virtual void delete_this(tir_exception *) noexcept { py_modules.clear(); }
|
|
1045
|
+
|
|
1046
|
+
virtual void set_context(c_context *ctxt) noexcept
|
|
1047
|
+
{
|
|
1048
|
+
thrd_context.blackbrd = ctxt->blackbrd;
|
|
1049
|
+
thrd_context.sent = ctxt->sent;
|
|
1050
|
+
thrd_context.rule = ctxt->rule;
|
|
1051
|
+
thrd_context.capture = ctxt->capture;
|
|
1052
|
+
}
|
|
1053
|
+
|
|
1054
|
+
private:
|
|
1055
|
+
FacadeCollection py_modules;
|
|
1056
|
+
};
|
|
1057
|
+
|
|
1058
|
+
Plugin::Plugin()
|
|
1059
|
+
: wowool::plugins::API()
|
|
1060
|
+
{
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
Plugin::~Plugin() {}
|
|
1064
|
+
|
|
1065
|
+
void Plugin::release_document(tir_exception *ex) noexcept
|
|
1066
|
+
{
|
|
1067
|
+
release_userdata();
|
|
1068
|
+
}
|
|
1069
|
+
|
|
1070
|
+
void Plugin::set_document_property(char const *key, char const *value, tir_exception *) noexcept
|
|
1071
|
+
{
|
|
1072
|
+
python_user_data &ud = get_current_userdata();
|
|
1073
|
+
if (ud.get() == nullptr)
|
|
1074
|
+
{
|
|
1075
|
+
ud = create_userdata();
|
|
1076
|
+
}
|
|
1077
|
+
PyLock py_lock;
|
|
1078
|
+
if (ud.get() != nullptr && ud->pydict != nullptr)
|
|
1079
|
+
{
|
|
1080
|
+
(*ud->pydict)[key] = value;
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
#define LOG_TRACE LOG(TRACE)
|
|
1085
|
+
#define TIR_LOG_DEBUG LOG(DEBUG)
|
|
1086
|
+
static std::string empty;
|
|
1087
|
+
|
|
1088
|
+
std::string const get(nlohmann::json const &options, std::string const key)
|
|
1089
|
+
{
|
|
1090
|
+
if (options.find(key) != options.end())
|
|
1091
|
+
{
|
|
1092
|
+
return options[key].get<std::string>();
|
|
1093
|
+
}
|
|
1094
|
+
return empty;
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
bool has(nlohmann::json const &options, std::string const key)
|
|
1098
|
+
{
|
|
1099
|
+
return (options.find(key) != options.end());
|
|
1100
|
+
}
|
|
1101
|
+
|
|
1102
|
+
// Load the given modules.
|
|
1103
|
+
bool Plugin::load_modules(char const *json_options, tir_exception *ex) noexcept
|
|
1104
|
+
{
|
|
1105
|
+
bool retval = false;
|
|
1106
|
+
retval = _nolock_load_modules(json_options, ex);
|
|
1107
|
+
return retval;
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
char *Plugin::call(char const *module_name, char const *name, wowool::plugins::Arguments const &arguments, tir_exception *ex) noexcept
|
|
1111
|
+
{
|
|
1112
|
+
try
|
|
1113
|
+
{
|
|
1114
|
+
char *retval = nullptr;
|
|
1115
|
+
// python_object_range_obj = py::module::import("wowool_plugin").attr("annotation_range");
|
|
1116
|
+
|
|
1117
|
+
python_user_data &ud = get_current_userdata();
|
|
1118
|
+
if (ud.get() == nullptr)
|
|
1119
|
+
{
|
|
1120
|
+
ud = create_userdata();
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1123
|
+
PyLock pylock;
|
|
1124
|
+
retval = _nolock_call(module_name, name, arguments, ex);
|
|
1125
|
+
return retval;
|
|
1126
|
+
} catch (pybind11::error_already_set const &ex)
|
|
1127
|
+
{
|
|
1128
|
+
std::cerr << "Error: already set" << ex.what() << std::endl;
|
|
1129
|
+
return nullptr;
|
|
1130
|
+
} catch (std::exception const &ex)
|
|
1131
|
+
{
|
|
1132
|
+
std::cerr << "Error: " << ex.what() << std::endl;
|
|
1133
|
+
return nullptr;
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1137
|
+
// Load the given modules.
|
|
1138
|
+
bool Plugin::_nolock_load_modules(char const *json_options, tir_exception *ex) noexcept
|
|
1139
|
+
{
|
|
1140
|
+
// std::ofstream fo("dump.txt");
|
|
1141
|
+
WLOG(TRACE, LOG_PLUGIN << LOG_PYTHON << "load_modules(" << json_options << ")\n");
|
|
1142
|
+
nlohmann::json options = nlohmann::json::parse(json_options);
|
|
1143
|
+
|
|
1144
|
+
//#ifdef WIN32
|
|
1145
|
+
// set_python_home(options);
|
|
1146
|
+
//#endif
|
|
1147
|
+
|
|
1148
|
+
bool embbeded_in_python = true;
|
|
1149
|
+
{
|
|
1150
|
+
if (!has(options, "pytryoshka"))
|
|
1151
|
+
{
|
|
1152
|
+
embbeded_in_python = false;
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
if (!embbeded_in_python)
|
|
1157
|
+
{
|
|
1158
|
+
WLOG(TRACE, LOG_PLUGIN << LOG_PYTHON << "init_python_instance");
|
|
1159
|
+
wow::python::init_python_instance(); // Py_Initialize();
|
|
1160
|
+
}
|
|
1161
|
+
|
|
1162
|
+
return true;
|
|
1163
|
+
}
|
|
1164
|
+
|
|
1165
|
+
using wowool::plugins::Arguments;
|
|
1166
|
+
namespace lbp = wowool::plugins;
|
|
1167
|
+
|
|
1168
|
+
char *Plugin::_nolock_call(char const *module_name, char const *name, wowool::plugins::Arguments const &arguments, tir_exception *ex) noexcept
|
|
1169
|
+
{
|
|
1170
|
+
if (auto it = py_modules.find(module_name); it != py_modules.end())
|
|
1171
|
+
{
|
|
1172
|
+
auto const &module = it->second;
|
|
1173
|
+
if (module.get())
|
|
1174
|
+
{
|
|
1175
|
+
char *retval = module->call(module_name, name, arguments, ex);
|
|
1176
|
+
return retval;
|
|
1177
|
+
}
|
|
1178
|
+
return nullptr;
|
|
1179
|
+
}
|
|
1180
|
+
else
|
|
1181
|
+
{
|
|
1182
|
+
WLOG(INFO, LOG_PLUGIN << LOG_PYTHON << "Loading python module: " << module_name);
|
|
1183
|
+
try
|
|
1184
|
+
{
|
|
1185
|
+
Facade_ptr ptr(new Facade(module_name));
|
|
1186
|
+
WLOG(DEBUG, LOG_PLUGIN << LOG_PYTHON << "OK Module:" << module_name);
|
|
1187
|
+
py_modules.emplace(module_name, ptr);
|
|
1188
|
+
auto const &module = py_modules.at(module_name);
|
|
1189
|
+
char *retval = module->call(module_name, name, arguments, ex);
|
|
1190
|
+
return retval;
|
|
1191
|
+
} catch (pybind11::error_already_set const &ex_import)
|
|
1192
|
+
{
|
|
1193
|
+
std::cerr << "Error:[wowool_plugin] Could not import " << module_name << " module"
|
|
1194
|
+
<< "\n"
|
|
1195
|
+
<< ex_import.what() << ")" << std::endl;
|
|
1196
|
+
py_modules.emplace(module_name, Facade_ptr());
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
|
|
1200
|
+
return nullptr;
|
|
1201
|
+
}
|
|
1202
|
+
|
|
1203
|
+
char *Plugin::open_document(char const *module, char const *name, wowool::plugins::Arguments const &arguments, tir_exception *ex) noexcept
|
|
1204
|
+
{
|
|
1205
|
+
create_userdata();
|
|
1206
|
+
return trigger(module, name, arguments, ex);
|
|
1207
|
+
}
|
|
1208
|
+
|
|
1209
|
+
char *Plugin::close_document(char const *module, char const *name, wowool::plugins::Arguments const &arguments, tir_exception *ex) noexcept
|
|
1210
|
+
{
|
|
1211
|
+
char *result = trigger(module, name, arguments, ex);
|
|
1212
|
+
release_userdata();
|
|
1213
|
+
return result;
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
char *Plugin::trigger(char const *module, char const *name, wowool::plugins::Arguments const &arguments, tir_exception *ex) noexcept
|
|
1217
|
+
{
|
|
1218
|
+
python_user_data &ud = get_current_userdata();
|
|
1219
|
+
if (ud.get() == nullptr)
|
|
1220
|
+
{
|
|
1221
|
+
create_userdata();
|
|
1222
|
+
}
|
|
1223
|
+
|
|
1224
|
+
Arguments decorated_arguments = arguments;
|
|
1225
|
+
if (ud.get() != nullptr)
|
|
1226
|
+
{
|
|
1227
|
+
decorated_arguments.emplace(decorated_arguments.begin(), wowool::plugins::do_pydict, ud->pydict);
|
|
1228
|
+
}
|
|
1229
|
+
char *retval = call(module, name, decorated_arguments, ex);
|
|
1230
|
+
return retval;
|
|
1231
|
+
}
|
|
1232
|
+
|
|
1233
|
+
// release a pointer which got return by this api, We need to have this as the
|
|
1234
|
+
// malloc and the free has to happen in the same module.
|
|
1235
|
+
// example alloc_string( ... )
|
|
1236
|
+
void Plugin::release(void *ptr) noexcept
|
|
1237
|
+
{
|
|
1238
|
+
DEBUG_PYTHON_PLUGIN_MSG("Plugin::release");
|
|
1239
|
+
if (ptr != nullptr)
|
|
1240
|
+
{
|
|
1241
|
+
free(ptr);
|
|
1242
|
+
}
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
} // namespace wow::python
|
|
1246
|
+
|
|
1247
|
+
//
|
|
1248
|
+
// Dynamic shared object (DSO) and dynamic-link library (DLL) support
|
|
1249
|
+
//
|
|
1250
|
+
#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || defined(__CYGWIN__)
|
|
1251
|
+
//#define WOW_BOOST_SYMBOL_EXPORT __attribute__((__dllexport__))
|
|
1252
|
+
#define WOW_BOOST_SYMBOL_EXPORT __declspec(dllexport)
|
|
1253
|
+
|
|
1254
|
+
#else
|
|
1255
|
+
#define WOW_BOOST_SYMBOL_EXPORT __attribute__((__visibility__("default")))
|
|
1256
|
+
#endif
|
|
1257
|
+
|
|
1258
|
+
extern "C" WOW_BOOST_SYMBOL_EXPORT wow::python::Plugin plugin;
|
|
1259
|
+
|
|
1260
|
+
wow::python::Plugin plugin;
|
|
1261
|
+
|
|
1262
|
+
// ----------------------------------------------------------------------------------
|
|
1263
|
+
// Copyright (c) 2024 Wowool, All Rights Reserved.
|
|
1264
|
+
// NOTICE: All information contained herein is, and remains the property of Wowool.
|
|
1265
|
+
// !!! Note merging the code with the python plugin module.
|
|
1266
|
+
// ----------------------------------------------------------------------------------
|
|
1267
|
+
typedef std::vector<wow::python::AttributesPair> python_object_attributes_type;
|
|
1268
|
+
typedef wow::python::python_object_range python_object_range;
|
|
1269
|
+
using wow::python::AttributesPair;
|
|
1270
|
+
using wow::python::python_object_attributes;
|
|
1271
|
+
using wow::python::python_object_match_context;
|
|
1272
|
+
using wow::python::python_token;
|
|
1273
|
+
|
|
1274
|
+
PYBIND11_MAKE_OPAQUE(python_object_attributes_type);
|
|
1275
|
+
|
|
1276
|
+
// ----------------------------------------------------------------------------
|
|
1277
|
+
// Python Bindings for the wowool_plugin.
|
|
1278
|
+
// ----------------------------------------------------------------------------
|
|
1279
|
+
PYBIND11_MODULE(_wowool_plugin, m)
|
|
1280
|
+
{
|
|
1281
|
+
using namespace pybind11::literals;
|
|
1282
|
+
|
|
1283
|
+
py::class_<python_token>(m, "python_token")
|
|
1284
|
+
.def("has_property", &python_token::has_property)
|
|
1285
|
+
.def_property_readonly("literal", [](python_token &self) { return self.literal(); })
|
|
1286
|
+
.def_property_readonly("text", [](python_token &self) { return self.literal(); })
|
|
1287
|
+
.def("head", &python_token::head)
|
|
1288
|
+
.def("pos", &python_token::pos, py::arg("idx") = 0)
|
|
1289
|
+
.def("stem", &python_token::stem, py::arg("idx") = 0)
|
|
1290
|
+
.def_property_readonly("lemma", [](python_token &self) { return self.lemma(0); })
|
|
1291
|
+
.def("__repr__", &python_token::str, "Returns literal")
|
|
1292
|
+
.def("__str__", &python_token::str, "Returns literal");
|
|
1293
|
+
|
|
1294
|
+
py::class_<python_object_range>(m, "annotation_range", "\nA annotation range marks the begin and "
|
|
1295
|
+
"end of a annotation collection.")
|
|
1296
|
+
.def(py::init([](plugin_Annotation *cnpt) {
|
|
1297
|
+
return new python_object_range(cnpt);
|
|
1298
|
+
})) // C++ constructor, shadowed by raw ctor
|
|
1299
|
+
.def_property_readonly("tokens", &python_object_range::tokens, "Returns a list with the tokens of this range.")
|
|
1300
|
+
.def_property_readonly("text", &python_object_range::text, "Returns the literal string of this range, you can specify the "
|
|
1301
|
+
"literal delimiter.")
|
|
1302
|
+
.def("literal", &python_object_range::literal, "\n:param separator: separator between the tokens, default space."
|
|
1303
|
+
"\n:type separator: str"
|
|
1304
|
+
":returns: a literal string of this range, you can specify the "
|
|
1305
|
+
"literal delimiter ",
|
|
1306
|
+
py::arg("separator") = " ")
|
|
1307
|
+
.def("canonical", &python_object_range::canonical, "\n:param separator: separator between the tokens, default space."
|
|
1308
|
+
"\n:type separator: str"
|
|
1309
|
+
":returns: a canonical string of this range, you can specify the "
|
|
1310
|
+
"canonical delimiter ",
|
|
1311
|
+
py::arg("separator") = " ")
|
|
1312
|
+
.def("__repr__", &python_object_range::repr, ":returns: the literal string of this range, you can specify the "
|
|
1313
|
+
"stem delimiter.")
|
|
1314
|
+
.def("__str__", &python_object_range::str, ":returns: the literal string of this range, you can specify the "
|
|
1315
|
+
"stem delimiter.")
|
|
1316
|
+
.def("stem", &python_object_range::stem, "\n:param separator: separator between the tokens, default space."
|
|
1317
|
+
"\n:type separator: str"
|
|
1318
|
+
":returns: a string with the stems of this range, you can specify "
|
|
1319
|
+
"the literal delimiter ",
|
|
1320
|
+
py::arg("separator") = " ")
|
|
1321
|
+
.def_property_readonly("lemma", &python_object_range::lemma, ":returns: a string with the stems of this range, you can specify ")
|
|
1322
|
+
.def("find", &python_object_range::find, "\n:param uri: uri of a concept to find."
|
|
1323
|
+
"\n:type uri: str"
|
|
1324
|
+
"\n:returns: a list of annotation_range object"
|
|
1325
|
+
"\n:type: list(annotation_range)",
|
|
1326
|
+
py::arg("uri"))
|
|
1327
|
+
.def("find_one", &python_object_range::find_one, "\n:param uri: uri of a concept to find."
|
|
1328
|
+
"\n:type uri: str"
|
|
1329
|
+
"\n:returns: a annotation_range object"
|
|
1330
|
+
"\n:type: annotation_range",
|
|
1331
|
+
py::arg("uri"))
|
|
1332
|
+
// when accessing the scope using a . then the return will be one range.
|
|
1333
|
+
// example capture.person will return the first person.
|
|
1334
|
+
// .def("__getattr__", &python_object_range::get_attr )
|
|
1335
|
+
.def(
|
|
1336
|
+
"__getattr__",
|
|
1337
|
+
static_cast<py::object (python_object_range::*)(std::string const &)>(
|
|
1338
|
+
&python_object_range::get_attr))
|
|
1339
|
+
// when accessing the scope using a ['person'] then the return will be a
|
|
1340
|
+
// vector of ranges example capture['person'] will return the all the
|
|
1341
|
+
// persons in the scope.
|
|
1342
|
+
.def("__getitem__", static_cast<std::vector<python_object_range> (python_object_range::*)(std::string const &)>(&python_object_range::get_item))
|
|
1343
|
+
.def("__getitem__", static_cast<std::vector<python_object_range> (python_object_range::*)(py::tuple const &)>(&python_object_range::get_item))
|
|
1344
|
+
.def("attributes", &python_object_range::attributes, "Returns the Attribute Object of this range.")
|
|
1345
|
+
.def("has", &python_object_range::has, "\n:param name: name of the attribute."
|
|
1346
|
+
"\n:type name: str"
|
|
1347
|
+
"\n:returns: true if this range has the given attribute."
|
|
1348
|
+
"\n:type: bool",
|
|
1349
|
+
py::arg("name"))
|
|
1350
|
+
.def("attribute", &python_object_range::get_attribute, "\n:param name: name of the attribute."
|
|
1351
|
+
"\n:type name: str"
|
|
1352
|
+
"\n:returns: the value of the given attribute."
|
|
1353
|
+
"\n:type: str",
|
|
1354
|
+
py::arg("name"))
|
|
1355
|
+
.def("add_attribute", &python_object_range::add_attribute, "Add a attribute to this range", py::arg("key"), py::arg("value"))
|
|
1356
|
+
.def("add_concept", &python_object_range::add_concept, "Add a concept ( semantic annotation ) over this range."
|
|
1357
|
+
"\n"
|
|
1358
|
+
"\n ::"
|
|
1359
|
+
"\n"
|
|
1360
|
+
"\n capture = match.capture()"
|
|
1361
|
+
"\n capture.add_concept('other_uri')"
|
|
1362
|
+
"\n",
|
|
1363
|
+
py::arg("uri"))
|
|
1364
|
+
.def_property_readonly("uri", &python_object_range::get_uri, "\n:returns: the uri of this annotation"
|
|
1365
|
+
"\n:type: str")
|
|
1366
|
+
.def_property_readonly("begin_offset", &python_object_range::get_begin_offset, "\n:returns: a int with the begin offset of this range."
|
|
1367
|
+
"\n:type begin_offset: int")
|
|
1368
|
+
.def_property_readonly("end_offset", &python_object_range::get_end_offset, "\n:returns: a int with the end offset of this range."
|
|
1369
|
+
"\n:type end_offset: int")
|
|
1370
|
+
.def("remove", &python_object_range::remove_concept, "remove the annotation over this range.")
|
|
1371
|
+
.def("__bool__", &python_object_range::pybool);
|
|
1372
|
+
|
|
1373
|
+
py::class_<python_object_match_context>(
|
|
1374
|
+
m, "match_info", "\nIs all the data related to the match of the triggered function."
|
|
1375
|
+
"\nThis object contains the capture, rule and the sentence where the "
|
|
1376
|
+
"match was located."
|
|
1377
|
+
"\n\nEXAMPLE"
|
|
1378
|
+
"\n match = wowool_plugin.match_info()"
|
|
1379
|
+
"\n capture_group = match.capture()")
|
|
1380
|
+
.def(py::init([]() { return new python_object_match_context(); }))
|
|
1381
|
+
.def("uri", &python_object_match_context::to_string, ":returns: the uro of the rule")
|
|
1382
|
+
.def("sentence", &python_object_match_context::sentence, "The sentence object (range) where the match has occurred.")
|
|
1383
|
+
.def("rule", &python_object_match_context::rule, ":returns: the annotation range that the rule has matched. "
|
|
1384
|
+
"\n"
|
|
1385
|
+
"\n ::"
|
|
1386
|
+
"\n"
|
|
1387
|
+
"\n ex rule: { <'Mr'> { <'Fawlty'> }= "
|
|
1388
|
+
"::python::module_name::silly_person }= rule_context;"
|
|
1389
|
+
"\n"
|
|
1390
|
+
"\nHere the range is 'Mr Fawlty'= rule_context."
|
|
1391
|
+
"\n:type: annotation_range")
|
|
1392
|
+
.def("capture", &python_object_match_context::capture, ":returns: the annotation range that we have captured. "
|
|
1393
|
+
"\n"
|
|
1394
|
+
"\n ::"
|
|
1395
|
+
"\n"
|
|
1396
|
+
"\n ex rule: { <'Mr'> { <'Fawlty'> }= "
|
|
1397
|
+
"::python::module_name::silly_person }= rule_context;"
|
|
1398
|
+
"\n"
|
|
1399
|
+
"\nHere the range is 'Fawlty'= silly_person."
|
|
1400
|
+
"\n:type: annotation_range")
|
|
1401
|
+
.def("property", &python_object_match_context::property, ":returns: a property of the range (ex: language)", py::arg("key"))
|
|
1402
|
+
.def("range", &python_object_match_context::make_range, "\n:param begin_range: begin position of the range."
|
|
1403
|
+
"\n:type begin_range: annotation_range"
|
|
1404
|
+
"\n:param end_range: end position of the range."
|
|
1405
|
+
"\n:type end_range: annotation_range"
|
|
1406
|
+
"\n:returns: a annotation range for the given begin and end "
|
|
1407
|
+
"annotation."
|
|
1408
|
+
"\n:type: annotation_range",
|
|
1409
|
+
py::arg("begin_range"),
|
|
1410
|
+
py::arg("end_range"));
|
|
1411
|
+
|
|
1412
|
+
// py::bind_vector<python_object_attributes>(m, "python_object_attributes");
|
|
1413
|
+
|
|
1414
|
+
py::class_<python_object_attributes>(m, "Attributes")
|
|
1415
|
+
.def("has", &python_object_attributes::has)
|
|
1416
|
+
.def("__len__", &python_object_attributes::size)
|
|
1417
|
+
.def(
|
|
1418
|
+
"__iter__",
|
|
1419
|
+
[](python_object_attributes &v) {
|
|
1420
|
+
return py::make_iterator(v.begin(), v.end());
|
|
1421
|
+
},
|
|
1422
|
+
py::keep_alive<0, 1>()) /*Keep vector alive while iterator is used*/
|
|
1423
|
+
.def("__bool__", &python_object_attributes::pybool)
|
|
1424
|
+
.def("__repr__", &python_object_attributes::to_string)
|
|
1425
|
+
.def("__str__", &python_object_attributes::to_string);
|
|
1426
|
+
|
|
1427
|
+
py::class_<AttributesPair>(m, "attributes_vp")
|
|
1428
|
+
.def("name", &AttributesPair::name)
|
|
1429
|
+
.def("value", &AttributesPair::value)
|
|
1430
|
+
.def("__repr__", &AttributesPair::to_string)
|
|
1431
|
+
.def("__str__", &AttributesPair::to_string);
|
|
1432
|
+
}
|