FMT 1.2.0
Forest management tools for forest planning
Loading...
Searching...
No Matches
FMTpythoncore.h
Go to the documentation of this file.
1/*
2Copyright (c) 2019 Gouvernement du Québec
3
4SPDX-License-Identifier: LiLiQ-R-1.1
5License-Filename: LICENSES/EN/LiLiQ-R11unicode.txt
6*/
7
8#ifndef FMTPYTHONCORE_Hm_included
9#define FMTPYTHONCORE_Hm_included
10
11#if defined FMTWITHPYTHON
12#ifndef BOOST_DYNAMIC_BITSET_DONT_USE_FRIENDS
13 #define BOOST_DYNAMIC_BITSET_DONT_USE_FRIENDS
14#endif
15
16#include <boost/python.hpp>
17#include <boost/algorithm/string.hpp>
18#include <boost/python/stl_iterator.hpp>
19#include <boost/regex.h>
20#include <iterator>
21#include <iostream>
22#include <fstream>
23#include <string>
24#include <vector>
25#include <limits>
26#include <map>
27#include <tuple>
28#include <set>
29#include <boost/dynamic_bitset.hpp>
30#include <boost/unordered_map.hpp>
31#include "FMTException.h"
32#include "FMTError.h"
33#include "FMTWarning.h"
34
35
36
37namespace boost{
38
39// DocString: boost::pyHash
46template<class T>
47static size_t pyHash(const T& value)
48 {
49 return boost::hash<T>()(value);
50 }
51}
52
53namespace Python
54{
55 // DocString: Python::MapToDict
61 template <class K, class V>
62 struct MapToDict
63 {
64 // DocString: Python::MapToDict::convert
70 static PyObject* convert(const std::map<K, V>& lmap)
71 {
72 boost::python::dict* dictionary = new boost::python::dict();
73 for (typename std::map<K, V>::const_iterator it = lmap.begin(); it != lmap.end(); ++it)
74 {
75 dictionary->operator[](it->first) = it->second;
76 }
77 return dictionary->ptr();
78 }
79
80 };
81
82 // DocString: Python::UMapToDict
88 template <class K, class V>
89 struct UMapToDict
90 {
91 // DocString: Python::UMapToDict::convert
97 static PyObject* convert(const boost::unordered_map<K, V>& lmap)
98 {
99 boost::python::dict* dictionary = new boost::python::dict();
100 for (typename boost::unordered_map<K, V>::const_iterator it = lmap.begin(); it != lmap.end(); ++it)
101 {
102 dictionary->operator[](it->first) = it->second;
103 }
104 return dictionary->ptr();
105 }
106
107 };
108
109
110
111 // DocString: Python::VecToList
116 template<class T>
117 struct VecToList
118 {
119 // DocString: Python::VecToList::convert
125 static PyObject* convert(const std::vector<T>& vec)
126 {
127 boost::python::list* l = new boost::python::list();
128 for (size_t i = 0; i < vec.size(); i++) {
129 l->append(vec[i]);
130 }
131
132 return l->ptr();
133 }
134 };
135
136 // DocString: Python::SetToList
141 template<class T>
142 struct SetToList
143 {
144 // DocString: Python::SetToList::convert
150 static PyObject* convert(const std::set<T>& p_set)
151 {
152 boost::python::list* l = new boost::python::list();
153 for (const auto& i : p_set)
154 {
155 l->append(i);
156 }
157 return l->ptr();
158 }
159 };
160
161 // DocString: Python::VecFrList
166 template<typename T>
167 struct VecFrList
168 {
169
170 // DocString: Python::VecFrList::VecFrList()
174 VecFrList()
175 {
176 boost::python::converter::registry::push_back(&VecFrList<T>::convertible,
177 &VecFrList<T>::construct,
178 boost::python::type_id<std::vector<T> >());
179 }
180
181 // Determine if obj_ptr can be converted in a std::vector<T>
182 // DocString: Python::VecFrList::convertible
188 static void* convertible(PyObject* obj_ptr)
189 {
190 if (!PyList_Check(obj_ptr)) {
191 PyObject* nullobj = nullptr;
192 return nullobj;
193 }
194 return obj_ptr;
195 }
196
197 // Convert obj_ptr into a std::vector<T>
198 // DocString: Python::VecFrList::construct
204 static void construct(
205 PyObject* obj_ptr,
206 boost::python::converter::rvalue_from_python_stage1_data* data)
207 {
208 // Extract the character data from the python string
209 // const char* value = PyString_AsString(obj_ptr);
210 boost::python::list l(boost::python::handle<>(boost::python::borrowed(obj_ptr)));
211
212 // // Verify that obj_ptr is a string (should be ensured by convertible())
213 // assert(value);
214
215 // Grab pointer to memory into which to construct the new std::vector<T>
216 void* storage = (
217 (boost::python::converter::rvalue_from_python_storage<std::vector<T> >*)
218 data)->storage.bytes;
219
220 // in-place construct the new std::vector<T> using the character data
221 // extraced from the python object
222 std::vector<T>& v = *(new (storage) std::vector<T>());
223
224 // populate the vector from list contains !!!
225 int le = static_cast<int>(boost::python::len(l));
226 v.resize(le);
227 for (int i = 0; i != le; ++i) {
228 v[i] = boost::python::extract<T>(l[i]);
229 }
230
231 // Stash the memory chunk pointer for later use by boost.python
232 data->convertible = storage;
233 }
234 };
235
236
237
238 // DocString: Python::iterable_converter
242 struct iterable_converter
243 {
246 // DocString: Python::iterable_converter::from_python
252 template <typename Container>
253 iterable_converter&
254 from_python()
255 {
256 boost::python::converter::registry::push_back(
257 &iterable_converter::convertible,
258 &iterable_converter::construct<Container>,
259 boost::python::type_id<Container>());
260
261 // Support chaining.
262 return *this;
263 }
264
265 // DocString: Python::iterable_converter::convertible
271 static void* convertible(PyObject* object)
272 {
273 return PyObject_GetIter(object) ? object : NULL;
274 }
275
276 // DocString: Python::iterable_converter::construct
283 template <typename Container>
284 static void construct(
285 PyObject* object,
286 boost::python::converter::rvalue_from_python_stage1_data* data)
287 {
288
289 // Object is a borrowed reference, so create a handle indicting it is
290 // borrowed for proper reference counting.
291 boost::python::handle<> handle(boost::python::borrowed(object));
292
293 // Obtain a handle to the memory block that the converter has allocated
294 // for the C++ type.
295 typedef boost::python::converter::rvalue_from_python_storage<Container>
296 storage_type;
297 void* storage = reinterpret_cast<storage_type*>(data)->storage.bytes;
298
299 typedef boost::python::stl_input_iterator<typename Container::value_type>
300 iterator;
301
302 // Allocate the C++ type into the converter's memory block, and assign
303 // its handle to the converter's convertible variable. The C++
304 // container is populated by passing the begin and end iterators of
305 // the python object to the container's constructor.
306 new (storage) Container(
307 iterator(boost::python::object(handle)), // begin
308 iterator()); // end
309 data->convertible = storage;
310 }
311 };
312
313 // DocString: Python::MapFrDict
319 template<class k, class e>
320 struct MapFrDict
321 {
324 // DocString: Python::MapFrDict::MapFrDict()
328 MapFrDict()
329 {
330
331 boost::python::converter::registry::push_back(&MapFrDict<k, e>::convertible,
332 &MapFrDict<k, e>::construct,
333 boost::python::type_id<std::map<k, e> >());
334
335
336 }
337
338 // DocString: Python::MapFrDict::convertible
344 static void* convertible(PyObject* obj_ptr)
345 {
346 if (PyMapping_Check(obj_ptr)) {
347 return obj_ptr;
348 }
349 else {
350 PyObject* nullobj = nullptr;
351 return nullobj;
352 }
353 }
354
355
356 // DocString: Python::MapFrDict::construct
362 static void construct(
363 PyObject* obj_ptr,
364 boost::python::converter::rvalue_from_python_stage1_data* data)
365 {
366 boost::python::dict mapping(boost::python::handle<>(boost::python::borrowed(obj_ptr)));
367
368 // // Verify that obj_ptr is a string (should be ensured by convertible())
369 // assert(value);
370
371 // Grab pointer to memory into which to construct the new std::vector<T>
372 void* storage = (
373 (boost::python::converter::rvalue_from_python_storage<std::map<k, e>>*)
374 data)->storage.bytes;
375
376 // in-place construct the new std::vector<T> using the character data
377 // extraced from the python object
378 std::map<k, e>& v = *(new (storage) std::map<k, e>());
379
380 // populate the vector from list contains !!!
381 boost::python::list keys = mapping.keys();
382 for (int i = 0; i < boost::python::len(keys); ++i)
383 {
384 boost::python::extract<k> extractedKey(keys[i]);
385 k newkey = extractedKey;
386 boost::python::extract<e> extractedVal(mapping[newkey]);
387 e value = extractedVal;
388 v[newkey] = value;
389 }
390
391 // Stash the memory chunk pointer for later use by boost.python
392 data->convertible = storage;
393 }
394 };
395
396
397 // DocString: Python::FMTtranslate_warning
402 void FMTtranslate_warning(Exception::FMTWarning const& e)
403 {
404 PyErr_SetString(PyExc_UserWarning, e.what());
405 }
406
407 PyObject* FMTexceptiontype = NULL;
408
409 // DocString: Python::FMTtranslate_error
414 void FMTtranslate_error(Exception::FMTError const& error) //should be implemented more like https://stackoverflow.com/questions/9620268/boost-python-custom-exception-class
415 {
416 if (error.hold())
417 {
418 assert(FMTexceptiontype != NULL);
419 boost::python::object pythonExceptionInstance(error);
420 PyErr_SetObject(FMTexceptiontype, pythonExceptionInstance.ptr());
421 }
422 else {
423 PyErr_SetString(PyExc_RuntimeError, error.what());
424 }
425 }
426
427 // DocString: Python::PairToPythonConverter
433 template<typename T1, typename T2>
434 struct PairToPythonConverter {
435 // DocString: Python::PairToPythonConverter::convert
441 static PyObject* convert(const std::pair<T1, T2>& pair)
442 {
443 return boost::python::incref(boost::python::make_tuple(pair.first, pair.second).ptr());
444 }
445 };
446
447 // DocString: Python::PythonToPairConverter
453 template<typename T1, typename T2>
454 struct PythonToPairConverter {
455 // DocString: Python::PythonToPairConverter::PythonToPairConverter()
459 PythonToPairConverter()
460 {
461 boost::python::converter::registry::push_back(&convertible, &construct, boost::python::type_id<std::pair<T1, T2> >());
462 }
463 // DocString: Python::PythonToPairConverter::convertible
469 static void* convertible(PyObject* obj)
470 {
471 if (!PyTuple_CheckExact(obj)) return 0;
472 if (PyTuple_Size(obj) != 2) return 0;
473 return obj;
474 }
475 // DocString: Python::PythonToPairConverter::construct
481 static void construct(PyObject* obj, boost::python::converter::rvalue_from_python_stage1_data* data)
482 {
483 boost::python::tuple tuple(boost::python::borrowed(obj));
484 void* storage = ((boost::python::converter::rvalue_from_python_storage<std::pair<T1, T2> >*) data)->storage.bytes;
485 new (storage) std::pair<T1, T2>(boost::python::extract<T1>(tuple[0]), boost::python::extract<T2>(tuple[1]));
486 data->convertible = storage;
487 }
488 };
489
490 // DocString: Python::py_pair
496 template<typename T1, typename T2>
497 struct py_pair {
498 boost::python::to_python_converter<std::pair<T1, T2>, PairToPythonConverter<T1, T2> > toPy;
499 PythonToPairConverter<T1, T2> fromPy;
500 };
501
502}
503
504#endif
505
506#endif
Exception class derived from FMTException for errors thrown in FMT.
Definition: FMTError.h:32
bool hold() const
Return the value of the holdup member.
const char * what() const noexcept override
Override the what function of the base exception class returning the message string.
Exception class derived from FMTException for warnings in FMT.
Definition: FMTWarning.h:31
Definition: PYdefinitions.h:14
Definition: FMTAction.h:463