ChimeraTK-ApplicationCore  04.01.00
PythonBindings.cc
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Deutsches Elektronen-Synchrotron DESY, MSK, ChimeraTK Project <chimeratk-support@desy.de>
2 // SPDX-License-Identifier: LGPL-3.0-or-later
3 
4 #include <pybind11/pybind11.h>
5 // pybind11.h must come first
6 
7 #include "Application.h"
8 #include "PyApplicationModule.h"
9 #include "PyArrayAccessor.h"
10 #include "PyConfigReader.h"
11 #include "PyDataConsistencyGroup.h"
12 #include "PyLogger.h"
13 #include "PyModuleGroup.h"
14 #include "PyOwnershipManagement.h"
15 #include "PyReadAnyGroup.h"
16 #include "PyScalarAccessor.h"
17 #include "PyVariableGroup.h"
18 #include <pybind11/chrono.h>
19 #include <pybind11/operators.h>
20 #include <pybind11/pytypes.h>
21 #include <pybind11/stl.h>
22 
23 #include <ChimeraTK/DataConsistencyGroup.h>
24 #include <ChimeraTK/SupportedUserTypes.h>
25 #include <ChimeraTK/VariantUserTypes.h>
26 
27 #include <boost/fusion/algorithm.hpp>
28 #include <boost/fusion/container/map.hpp>
29 
30 #include <iostream>
31 #include <map>
32 #include <string>
33 #include <variant>
34 
35 namespace py = pybind11;
36 using namespace py::literals;
37 
44 namespace ChimeraTK {
45 
48  if(Application::hasInstance()) { // hasInstance check required for stubgen tool (it doesn't instantiate an app)
49  // We assume here that the reason for PyApplicationCore lib unload is application shutdown.
50  // We need to deinitialize PythonModuleManager early in order to get back global interpreter lock.
51  // Some static library deinitialsers (in particular exception object used by pybind11 register_exception)
52  // assume that we own the GIL.
53  // The PythonModuleManager will also shut down all PyApplicationModules (i.e. their internal threads) while
54  // keeping the rest of the Application intact for now.
55  Application::getInstance().getPythonModuleManager().deinit();
56  }
57  }
58  };
66  template<class UnloadHook>
67  static void registerUnloadHook() {
68  static UnloadHook hook;
69  }
70 
71  /********************************************************************************************************************/
72 
73  PYBIND11_MODULE(PyApplicationCore, m) {
77  py::register_exception<ChimeraTK::logic_error>(m, "LogicError", PyExc_RuntimeError);
78 
82  py::class_<DataType> mDataType(m, "DataType");
83  mDataType.def(py::init<DataType::TheType>())
84  .def("__str__", &DataType::getAsString)
85  .def(py::self == py::self)
86  .def("__repr__", [](const DataType& type) { return "DataType." + type.getAsString(); });
87  py::enum_<DataType::TheType>(mDataType, "TheType")
88  .value("none", DataType::none)
89  .value("int8", DataType::int8)
90  .value("uint8", DataType::uint8)
91  .value("int16", DataType::int16)
92  .value("uint16", DataType::uint16)
93  .value("int32", DataType::int32)
94  .value("uint32", DataType::uint32)
95  .value("int64", DataType::int64)
96  .value("uint64", DataType::uint64)
97  .value("float32", DataType::float32)
98  .value("float64", DataType::float64)
99  .value("string", DataType::string)
100  .value("Boolean", DataType::Boolean)
101  .value("Void", DataType::Void)
102  .export_values();
103  py::implicitly_convertible<DataType::TheType, DataType>();
104  py::implicitly_convertible<DataType, DataType::TheType>();
105 
109  py::enum_<DataValidity>(m, "DataValidity")
110  .value("ok", DataValidity::ok)
111  .value("faulty", DataValidity::faulty)
112  .export_values();
113 
117  py::class_<VersionNumber>(m, "VersionNumber")
118  .def(py::init<>())
119  .def(py::init<std::chrono::system_clock::time_point>())
120  .def(py::init<std::nullptr_t>(), py::arg("version").none(true))
121  // NOLINTBEGIN(misc-redundant-expression)
122  .def(py::self == py::self)
123  .def(py::self != py::self)
124  .def(py::self < py::self)
125  .def(py::self <= py::self)
126  .def(py::self > py::self)
127  .def(py::self >= py::self)
128  // NOLINTEND(misc-redundant-expression)
129  .def("getTime", &VersionNumber::getTime, R"(Return the time stamp associated with this version number.)")
130  .def("__str__", [](VersionNumber& v) { return std::string(v); })
131  .def("__repr__", [](VersionNumber& v) { return "VersionNumber(" + std::string(v) + ")"; });
132 
136  py::class_<TransferElementID>(m, "TransferElementID")
137  .def(py::init<>())
138  // NOLINTBEGIN(misc-redundant-expression)
139  .def(py::self == py::self)
140  .def(py::self != py::self)
141  // NOLINTEND(misc-redundant-expression)
142  .def("isValid", &TransferElementID::isValid, R"(Check whether the ID is valid.)")
143  .def("__str__",
144  [](TransferElementID& id) {
145  std::stringstream ss;
146  ss << id;
147  return ss.str();
148  })
149  .def("__repr__", [](TransferElementID& id) {
150  std::stringstream ss;
151  ss << id;
152  return "TransferElementID(" + ss.str() + ")";
153  });
154 
159  py::class_<PyOwnedObject> pwnedObject(m, "PyOwnedObject");
160  py::class_<PyOwningObject> pwningObject(m, "PyOwningObject");
161 
169  PyTransferElementBase::bind(m);
170 
174  PyReadAnyGroup::bind(m);
175 
179  PyDataConsistencyGroup::bind(m);
180 
184  PyLogger::bind(m);
185 
189  PyScalarAccessor::bind(m);
190 
194  PyArrayAccessor::bind(m);
195 
199  PyVariableGroup::bind(m);
200 
204  PyApplicationModule::bind(m);
205 
209  PyModuleGroup::bind(m);
210 
214  PyConfigReader::bind(m);
215 
216  /*
217  * Set the main ModuleGroup as an attribute of the bindings module. This is done with a callback to avoid
218  * problems with the symbol visibility (all pybind11 classes are hidden, so we cannot pass them directly between
219  * the bindings .so and the main library .so).
220  */
221  if(Application::hasInstance()) {
222  Application::getInstance().getPythonModuleManager().setOnMainGroupChange(
223  [m](const std::unique_ptr<PyModuleGroup>& mainGroup) {
224  m.attr("app") = py::cast(mainGroup.get(), py::return_value_policy::reference);
225  });
226  }
227 
228  registerUnloadHook<PyApplicationCoreUnload>();
229  }
230 
231  /********************************************************************************************************************/
232 
233 } // namespace ChimeraTK
PyModuleGroup.h
PyVariableGroup.h
PyApplicationModule.h
PyConfigReader.h
PyReadAnyGroup.h
PyScalarAccessor.h
ChimeraTK::PyApplicationCoreUnload::~PyApplicationCoreUnload
~PyApplicationCoreUnload()
Definition: PythonBindings.cc:47
PyArrayAccessor.h
PyLogger.h
PyOwnershipManagement.h
Application.h
PyDataConsistencyGroup.h
pybind11
Definition: PyModuleGroup.h:10
ChimeraTK::PYBIND11_MODULE
PYBIND11_MODULE(PyApplicationCore, m)
Definition: PythonBindings.cc:73
ChimeraTK
InvalidityTracer application module.
Definition: spec_dataValidityPropagation.dox:2
ChimeraTK::PyApplicationCoreUnload
Definition: PythonBindings.cc:46