extensions/python/types/PyStateManager.cpp (112 lines of code) (raw):

/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, a * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "PyStateManager.h" extern "C" { namespace org::apache::nifi::minifi::extensions::python { static PyMethodDef PyStateManager_methods[] = { // NOLINT(cppcoreguidelines-avoid-c-arrays) {"get", (PyCFunction) PyStateManager::get, METH_VARARGS, nullptr}, {"set", (PyCFunction) PyStateManager::set, METH_VARARGS, nullptr}, {"clear", (PyCFunction) PyStateManager::clear, METH_VARARGS, nullptr}, {"replace", (PyCFunction) PyStateManager::replace, METH_VARARGS, nullptr}, {} /* Sentinel */ }; static PyType_Slot PyStateManagerTypeSpecSlots[] = { // NOLINT(cppcoreguidelines-avoid-c-arrays) {Py_tp_dealloc, reinterpret_cast<void*>(pythonAllocatedInstanceDealloc<PyStateManager>)}, {Py_tp_init, reinterpret_cast<void*>(PyStateManager::init)}, {Py_tp_methods, reinterpret_cast<void*>(PyStateManager_methods)}, {Py_tp_new, reinterpret_cast<void*>(newPythonAllocatedInstance<PyStateManager>)}, {} /* Sentinel */ }; static PyType_Spec PyStateManagerTypeSpec{ .name = "minifi_native.StateManager", .basicsize = sizeof(PyStateManager), .itemsize = 0, .flags = Py_TPFLAGS_DEFAULT, .slots = PyStateManagerTypeSpecSlots }; int PyStateManager::init(PyStateManager* self, PyObject* args, PyObject*) { PyObject* weak_ptr_capsule = nullptr; if (!PyArg_ParseTuple(args, "O", &weak_ptr_capsule)) { return -1; } auto state_manager = PyCapsule_GetPointer(weak_ptr_capsule, HeldTypeName); if (!state_manager) return -1; self->state_manager_ = *static_cast<HeldType*>(state_manager); return 0; } PyObject* PyStateManager::set(PyStateManager* self, PyObject* args) { if (!self->state_manager_) { PyErr_SetString(PyExc_AttributeError, "tried reading state manager outside 'on_trigger'"); return nullptr; } core::StateManager::State cpp_state; auto python_state = BorrowedDict::fromTuple(args, 0); auto python_state_keys = OwnedList(PyDict_Keys(python_state.get())); for (size_t i = 0; i < python_state_keys.length(); ++i) { BorrowedStr key{python_state_keys[i]}; if (auto value = python_state[key.toUtf8String()]) { BorrowedStr value_str{*value}; cpp_state[key.toUtf8String()] = value_str.toUtf8String(); } } return object::returnReference(self->state_manager_->set(cpp_state)); } PyObject* PyStateManager::get(PyStateManager* self, PyObject*) { if (!self->state_manager_) { PyErr_SetString(PyExc_AttributeError, "tried reading state manager outside 'on_trigger'"); return nullptr; } if (auto cpp_state = self->state_manager_->get()) { auto python_state = OwnedDict::create(); for (const auto& [cpp_state_key, cpp_state_value] : *cpp_state) { python_state.put(cpp_state_key, cpp_state_value); } return object::returnReference(python_state); } else { Py_RETURN_NONE; } } PyObject* PyStateManager::clear(PyStateManager* self, PyObject* /*args*/) { if (!self->state_manager_) { PyErr_SetString(PyExc_AttributeError, "tried reading state manager outside 'on_trigger'"); return nullptr; } self->state_manager_->clear(); Py_RETURN_NONE; } PyObject* PyStateManager::replace(PyStateManager* self, PyObject* args) { if (!self->state_manager_) { PyErr_SetString(PyExc_AttributeError, "tried reading state manager outside 'on_trigger'"); return nullptr; } core::StateManager::State old_cpp_state; auto old_state = BorrowedDict::fromTuple(args, 0); auto old_state_keys = OwnedList(PyDict_Keys(old_state.get())); for (size_t i = 0; i < old_state_keys.length(); ++i) { BorrowedStr key{old_state_keys[i]}; if (auto value = old_state[key.toUtf8String()]) { BorrowedStr value_str{*value}; old_cpp_state[key.toUtf8String()] = value_str.toUtf8String(); } } auto current_cpp_state = self->state_manager_->get(); if ((!current_cpp_state && old_state_keys.length() > 0) || (current_cpp_state && old_cpp_state != *current_cpp_state)) { return object::returnReference(false); } core::StateManager::State new_cpp_state; auto new_python_state = BorrowedDict::fromTuple(args, 1); auto new_python_state_keys = OwnedList(PyDict_Keys(new_python_state.get())); for (size_t i = 0; i < new_python_state_keys.length(); ++i) { BorrowedStr key{new_python_state_keys[i]}; if (auto value = new_python_state[key.toUtf8String()]) { BorrowedStr value_str{*value}; new_cpp_state[key.toUtf8String()] = value_str.toUtf8String(); } } return object::returnReference(self->state_manager_->set(new_cpp_state)); } PyTypeObject* PyStateManager::typeObject() { static OwnedObject PyStateManagerType{PyType_FromSpec(&PyStateManagerTypeSpec)}; return reinterpret_cast<PyTypeObject*>(PyStateManagerType.get()); } } // namespace org::apache::nifi::minifi::extensions::python } // extern "C"