blob: 540a74c48ee19d84b6db9fb96775352e3c549cf7 [file] [log] [blame]
/**
* 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 "PyProcessContext.h"
#include <string>
#include "PyStateManager.h"
#include "PyScriptFlowFile.h"
#include "core/Processor.h"
extern "C" {
namespace org::apache::nifi::minifi::extensions::python {
static PyMethodDef PyProcessContext_methods[] = { // NOLINT(cppcoreguidelines-avoid-c-arrays)
{"getProperty", (PyCFunction) PyProcessContext::getProperty, METH_VARARGS, nullptr},
{"getStateManager", (PyCFunction) PyProcessContext::getStateManager, METH_VARARGS, nullptr},
{"getControllerService", (PyCFunction) PyProcessContext::getControllerService, METH_VARARGS, nullptr},
{"getName", (PyCFunction) PyProcessContext::getName, METH_VARARGS, nullptr},
{"getProperties", (PyCFunction) PyProcessContext::getProperties, METH_VARARGS, nullptr},
{} /* Sentinel */
};
static PyType_Slot PyProcessContextTypeSpecSlots[] = { // NOLINT(cppcoreguidelines-avoid-c-arrays)
{Py_tp_dealloc, reinterpret_cast<void*>(pythonAllocatedInstanceDealloc<PyProcessContext>)},
{Py_tp_init, reinterpret_cast<void*>(PyProcessContext::init)},
{Py_tp_methods, reinterpret_cast<void*>(PyProcessContext_methods)},
{Py_tp_new, reinterpret_cast<void*>(newPythonAllocatedInstance<PyProcessContext>)},
{} /* Sentinel */
};
static PyType_Spec PyProcessContextTypeSpec{
.name = "minifi_native.ProcessContext",
.basicsize = sizeof(PyProcessContext),
.itemsize = 0,
.flags = Py_TPFLAGS_DEFAULT,
.slots = PyProcessContextTypeSpecSlots
};
int PyProcessContext::init(PyProcessContext* self, PyObject* args, PyObject*) {
PyObject* weak_ptr_capsule = nullptr;
if (!PyArg_ParseTuple(args, "O", &weak_ptr_capsule)) {
return -1;
}
auto process_context = PyCapsule_GetPointer(weak_ptr_capsule, HeldTypeName);
if (!process_context)
return -1;
self->process_context_ = *static_cast<HeldType*>(process_context);
return 0;
}
PyObject* PyProcessContext::getProperty(PyProcessContext* self, PyObject* args) {
auto context = self->process_context_.lock();
if (!context) {
PyErr_SetString(PyExc_AttributeError, "tried reading process context outside 'on_trigger'");
return nullptr;
}
const char* property_name = nullptr;
PyObject* script_flow_file = nullptr;
if (!PyArg_ParseTuple(args, "s|O", &property_name, &script_flow_file)) {
return nullptr;
}
std::string value;
if (!script_flow_file) {
if (!context->getProperty(property_name, value)) {
Py_RETURN_NONE;
}
} else {
auto py_flow = reinterpret_cast<PyScriptFlowFile*>(script_flow_file);
const auto flow_file = py_flow->script_flow_file_.lock();
if (!flow_file) {
PyErr_SetString(PyExc_AttributeError, "tried reading FlowFile outside 'on_trigger'");
return nullptr;
}
core::Property property{property_name, ""};
property.setSupportsExpressionLanguage(true);
if (!context->getProperty(property, value, flow_file.get())) {
Py_RETURN_NONE;
}
}
return object::returnReference(value);
}
PyObject* PyProcessContext::getStateManager(PyProcessContext* self, PyObject*) {
auto context = self->process_context_.lock();
if (!context) {
PyErr_SetString(PyExc_AttributeError, "tried reading process context outside 'on_trigger'");
return nullptr;
}
return object::returnReference(context->getStateManager());
}
PyObject* PyProcessContext::getControllerService(PyProcessContext* self, PyObject* args) {
auto context = self->process_context_.lock();
if (!context) {
PyErr_SetString(PyExc_AttributeError, "tried reading process context outside 'on_trigger'");
return nullptr;
}
const char* controller_service_name = nullptr;
const char* controller_service_type = nullptr;
if (!PyArg_ParseTuple(args, "s|s", &controller_service_name, &controller_service_type)) {
return nullptr;
}
if (auto controller_service = context->getControllerService(controller_service_name)) {
std::string controller_service_type_str = controller_service_type;
if (controller_service_type_str == "SSLContextService") {
auto ssl_ctx_service = std::dynamic_pointer_cast<controllers::SSLContextService>(controller_service);
return object::returnReference(std::weak_ptr(ssl_ctx_service));
}
}
Py_RETURN_NONE;
}
PyObject* PyProcessContext::getName(PyProcessContext* self, PyObject*) {
auto context = self->process_context_.lock();
if (!context) {
PyErr_SetString(PyExc_AttributeError, "tried reading process context outside 'on_trigger'");
return nullptr;
}
return object::returnReference(context->getProcessorNode()->getName());
}
PyObject* PyProcessContext::getProperties(PyProcessContext* self, PyObject*) {
auto context = self->process_context_.lock();
if (!context) {
PyErr_SetString(PyExc_AttributeError, "tried reading process context outside 'on_trigger'");
return nullptr;
}
auto processor = dynamic_cast<core::Processor*>(context->getProcessorNode()->getProcessor());
if (!processor) {
PyErr_SetString(PyExc_AttributeError, "Processor not available in getProperties");
return nullptr;
}
auto properties = processor->getProperties();
auto py_properties = OwnedDict::create();
for (const auto& [property_name, property] : properties) {
std::string value;
if (!context->getProperty(property_name, value)) {
continue;
}
py_properties.put(property_name, value);
}
return object::returnReference(py_properties);
}
PyTypeObject* PyProcessContext::typeObject() {
static OwnedObject PyProcessContextType{PyType_FromSpec(&PyProcessContextTypeSpec)};
return reinterpret_cast<PyTypeObject*>(PyProcessContextType.get());
}
} // namespace org::apache::nifi::minifi::extensions::python
} // extern "C"