From 03dc5bb27c2583ea6d80351615d62722e04138d9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 21 Aug 2026 06:32:29 +0000 Subject: [PATCH 1/5] Handle repeated fields in PythonMessage __getattr__ and __setattr__ Co-authored-by: wawanbreton <601114+wawanbreton@users.noreply.github.com> --- src/PythonMessage.cpp | 230 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 230 insertions(+) diff --git a/src/PythonMessage.cpp b/src/PythonMessage.cpp index 2e9e52f..2ac93d5 100644 --- a/src/PythonMessage.cpp +++ b/src/PythonMessage.cpp @@ -5,6 +5,8 @@ #include +#include + #include #include @@ -60,6 +62,56 @@ bool Arcus::PythonMessage::__hasattr__(const std::string& field_name) const return bool(field); } +// Helper: convert a single scalar value at a given repeated-field index to a PyObject. +static PyObject* getRepeatedScalar(const google::protobuf::Reflection* reflection, + const google::protobuf::Message& message, + const google::protobuf::FieldDescriptor* field, + int index) +{ + switch (field->type()) + { + case FieldDescriptor::TYPE_FLOAT: + return PyFloat_FromDouble(reflection->GetRepeatedFloat(message, field, index)); + case FieldDescriptor::TYPE_DOUBLE: + return PyFloat_FromDouble(reflection->GetRepeatedDouble(message, field, index)); + case FieldDescriptor::TYPE_INT32: + case FieldDescriptor::TYPE_FIXED32: + case FieldDescriptor::TYPE_SINT32: + case FieldDescriptor::TYPE_SFIXED32: + return PyLong_FromLong(reflection->GetRepeatedInt32(message, field, index)); + case FieldDescriptor::TYPE_INT64: + case FieldDescriptor::TYPE_FIXED64: + case FieldDescriptor::TYPE_SINT64: + case FieldDescriptor::TYPE_SFIXED64: + return PyLong_FromLongLong(reflection->GetRepeatedInt64(message, field, index)); + case FieldDescriptor::TYPE_UINT32: + return PyLong_FromUnsignedLong(reflection->GetRepeatedUInt32(message, field, index)); + case FieldDescriptor::TYPE_UINT64: + return PyLong_FromUnsignedLongLong(reflection->GetRepeatedUInt64(message, field, index)); + case FieldDescriptor::TYPE_BOOL: + if (reflection->GetRepeatedBool(message, field, index)) + { + Py_RETURN_TRUE; + } + else + { + Py_RETURN_FALSE; + } + case FieldDescriptor::TYPE_BYTES: + { + std::string data = reflection->GetRepeatedString(message, field, index); + return PyBytes_FromStringAndSize(data.c_str(), data.size()); + } + case FieldDescriptor::TYPE_STRING: + return PyUnicode_FromString(reflection->GetRepeatedString(message, field, index).c_str()); + case FieldDescriptor::TYPE_ENUM: + return PyLong_FromLong(reflection->GetRepeatedEnumValue(message, field, index)); + default: + PyErr_SetString(PyExc_ValueError, "Could not handle value of repeated field"); + return nullptr; + } +} + PyObject* Arcus::PythonMessage::__getattr__(const std::string& field_name) const { auto field = findFieldByNameHack(_descriptor, field_name); @@ -69,6 +121,27 @@ PyObject* Arcus::PythonMessage::__getattr__(const std::string& field_name) const return nullptr; } + if (field->is_repeated()) + { + int count = _reflection->FieldSize(*_message, field); + PyObject* list = PyList_New(count); + if (! list) + { + return nullptr; + } + for (int i = 0; i < count; ++i) + { + PyObject* item = getRepeatedScalar(_reflection, *_message, field, i); + if (! item) + { + Py_DECREF(list); + return nullptr; + } + PyList_SET_ITEM(list, i, item); // steals reference + } + return list; + } + switch (field->type()) { case FieldDescriptor::TYPE_FLOAT: @@ -113,6 +186,140 @@ PyObject* Arcus::PythonMessage::__getattr__(const std::string& field_name) const } } +// Helper: append a single Python scalar value to a repeated field. +static bool addRepeatedScalar(google::protobuf::Message* message, + const google::protobuf::Reflection* reflection, + const google::protobuf::FieldDescriptor* field, + PyObject* item) +{ + switch (field->type()) + { + case FieldDescriptor::TYPE_FLOAT: + { + double v = PyFloat_AsDouble(item); + if (v == -1.0 && PyErr_Occurred()) + { + return false; + } + reflection->AddFloat(message, field, static_cast(v)); + break; + } + case FieldDescriptor::TYPE_DOUBLE: + { + double v = PyFloat_AsDouble(item); + if (v == -1.0 && PyErr_Occurred()) + { + return false; + } + reflection->AddDouble(message, field, v); + break; + } + case FieldDescriptor::TYPE_INT32: + case FieldDescriptor::TYPE_SFIXED32: + case FieldDescriptor::TYPE_FIXED32: + case FieldDescriptor::TYPE_SINT32: + { + long v = PyLong_AsLong(item); + if (v == -1 && PyErr_Occurred()) + { + return false; + } + reflection->AddInt32(message, field, static_cast(v)); + break; + } + case FieldDescriptor::TYPE_INT64: + case FieldDescriptor::TYPE_FIXED64: + case FieldDescriptor::TYPE_SINT64: + case FieldDescriptor::TYPE_SFIXED64: + { + long long v = PyLong_AsLongLong(item); + if (v == -1 && PyErr_Occurred()) + { + return false; + } + reflection->AddInt64(message, field, static_cast(v)); + break; + } + case FieldDescriptor::TYPE_UINT32: + { + unsigned long v = PyLong_AsUnsignedLong(item); + if (v == static_cast(-1) && PyErr_Occurred()) + { + return false; + } + reflection->AddUInt32(message, field, static_cast(v)); + break; + } + case FieldDescriptor::TYPE_UINT64: + { + unsigned long long v = PyLong_AsUnsignedLongLong(item); + if (v == static_cast(-1) && PyErr_Occurred()) + { + return false; + } + reflection->AddUInt64(message, field, static_cast(v)); + break; + } + case FieldDescriptor::TYPE_BOOL: + reflection->AddBool(message, field, item == Py_True); + break; + case FieldDescriptor::TYPE_BYTES: + { + Py_buffer buffer; + if (PyObject_GetBuffer(item, &buffer, PyBUF_SIMPLE) < 0) + { + return false; + } + std::string str(reinterpret_cast(buffer.buf), buffer.len); + PyBuffer_Release(&buffer); + reflection->AddString(message, field, str); + break; + } + case FieldDescriptor::TYPE_STRING: + { + const char* str = PyUnicode_AsUTF8(item); + if (! str) + { + return false; + } + reflection->AddString(message, field, str); + break; + } + case FieldDescriptor::TYPE_ENUM: + { + if (PyUnicode_Check(item)) + { + const char* name = PyUnicode_AsUTF8(item); + if (! name) + { + return false; + } + auto enum_value = field->enum_type()->FindValueByName(name); + if (! enum_value) + { + PyErr_Format(PyExc_ValueError, "Unknown enum value: %s", name); + return false; + } + reflection->AddEnum(message, field, enum_value); + } + else + { + long v = PyLong_AsLong(item); + if (v == -1 && PyErr_Occurred()) + { + return false; + } + reflection->AddEnumValue(message, field, static_cast(v)); + } + break; + } + default: + PyErr_SetString(PyExc_ValueError, "Could not handle value of repeated field"); + return false; + } + return true; +} + void Arcus::PythonMessage::__setattr__(const std::string& field_name, PyObject* value) { auto field = findFieldByNameHack(_descriptor, field_name); @@ -122,6 +329,29 @@ void Arcus::PythonMessage::__setattr__(const std::string& field_name, PyObject* return; } + if (field->is_repeated()) + { + PyObject* iter = PyObject_GetIter(value); + if (! iter) + { + return; + } + _reflection->ClearField(_message, field); + PyObject* item; + while ((item = PyIter_Next(iter)) != nullptr) + { + bool ok = addRepeatedScalar(_message, _reflection, field, item); + Py_DECREF(item); + if (! ok) + { + Py_DECREF(iter); + return; + } + } + Py_DECREF(iter); + return; + } + switch (field->type()) { case FieldDescriptor::TYPE_FLOAT: From c83264024625b4fb94924e5d510f7d664b0e50e3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 21 Aug 2026 06:55:01 +0000 Subject: [PATCH 2/5] Deduplicate repeated/singular switch blocks using unified helpers Co-authored-by: wawanbreton <601114+wawanbreton@users.noreply.github.com> --- src/PythonMessage.cpp | 280 ++++++++++++++++++------------------------ 1 file changed, 122 insertions(+), 158 deletions(-) diff --git a/src/PythonMessage.cpp b/src/PythonMessage.cpp index 2ac93d5..d9d684c 100644 --- a/src/PythonMessage.cpp +++ b/src/PythonMessage.cpp @@ -62,52 +62,66 @@ bool Arcus::PythonMessage::__hasattr__(const std::string& field_name) const return bool(field); } -// Helper: convert a single scalar value at a given repeated-field index to a PyObject. -static PyObject* getRepeatedScalar(const google::protobuf::Reflection* reflection, - const google::protobuf::Message& message, - const google::protobuf::FieldDescriptor* field, - int index) +// Read one scalar value from a field and return it as a Python object. +// Pass index >= 0 for a repeated field element, or index < 0 for a singular field. +static PyObject* getScalarField(const google::protobuf::Reflection* reflection, + const google::protobuf::Message& message, + const google::protobuf::FieldDescriptor* field, + int index) { + const bool repeated = index >= 0; switch (field->type()) { case FieldDescriptor::TYPE_FLOAT: - return PyFloat_FromDouble(reflection->GetRepeatedFloat(message, field, index)); + return PyFloat_FromDouble(repeated ? reflection->GetRepeatedFloat(message, field, index) + : reflection->GetFloat(message, field)); case FieldDescriptor::TYPE_DOUBLE: - return PyFloat_FromDouble(reflection->GetRepeatedDouble(message, field, index)); + return PyFloat_FromDouble(repeated ? reflection->GetRepeatedDouble(message, field, index) + : reflection->GetDouble(message, field)); case FieldDescriptor::TYPE_INT32: case FieldDescriptor::TYPE_FIXED32: case FieldDescriptor::TYPE_SINT32: case FieldDescriptor::TYPE_SFIXED32: - return PyLong_FromLong(reflection->GetRepeatedInt32(message, field, index)); + return PyLong_FromLong(repeated ? reflection->GetRepeatedInt32(message, field, index) + : reflection->GetInt32(message, field)); case FieldDescriptor::TYPE_INT64: case FieldDescriptor::TYPE_FIXED64: case FieldDescriptor::TYPE_SINT64: case FieldDescriptor::TYPE_SFIXED64: - return PyLong_FromLongLong(reflection->GetRepeatedInt64(message, field, index)); + return PyLong_FromLongLong(repeated ? reflection->GetRepeatedInt64(message, field, index) + : reflection->GetInt64(message, field)); case FieldDescriptor::TYPE_UINT32: - return PyLong_FromUnsignedLong(reflection->GetRepeatedUInt32(message, field, index)); + return PyLong_FromUnsignedLong(repeated ? reflection->GetRepeatedUInt32(message, field, index) + : reflection->GetUInt32(message, field)); case FieldDescriptor::TYPE_UINT64: - return PyLong_FromUnsignedLongLong(reflection->GetRepeatedUInt64(message, field, index)); + return PyLong_FromUnsignedLongLong(repeated ? reflection->GetRepeatedUInt64(message, field, index) + : reflection->GetUInt64(message, field)); case FieldDescriptor::TYPE_BOOL: - if (reflection->GetRepeatedBool(message, field, index)) + { + bool v = repeated ? reflection->GetRepeatedBool(message, field, index) : reflection->GetBool(message, field); + if (v) { Py_RETURN_TRUE; } - else - { - Py_RETURN_FALSE; - } + Py_RETURN_FALSE; + } case FieldDescriptor::TYPE_BYTES: { - std::string data = reflection->GetRepeatedString(message, field, index); + std::string data = repeated ? reflection->GetRepeatedString(message, field, index) + : reflection->GetString(message, field); return PyBytes_FromStringAndSize(data.c_str(), data.size()); } case FieldDescriptor::TYPE_STRING: - return PyUnicode_FromString(reflection->GetRepeatedString(message, field, index).c_str()); + { + std::string data = repeated ? reflection->GetRepeatedString(message, field, index) + : reflection->GetString(message, field); + return PyUnicode_FromString(data.c_str()); + } case FieldDescriptor::TYPE_ENUM: - return PyLong_FromLong(reflection->GetRepeatedEnumValue(message, field, index)); + return PyLong_FromLong(repeated ? reflection->GetRepeatedEnumValue(message, field, index) + : reflection->GetEnumValue(message, field)); default: - PyErr_SetString(PyExc_ValueError, "Could not handle value of repeated field"); + PyErr_SetString(PyExc_ValueError, "Could not handle value of field"); return nullptr; } } @@ -131,7 +145,7 @@ PyObject* Arcus::PythonMessage::__getattr__(const std::string& field_name) const } for (int i = 0; i < count; ++i) { - PyObject* item = getRepeatedScalar(_reflection, *_message, field, i); + PyObject* item = getScalarField(_reflection, *_message, field, i); if (! item) { Py_DECREF(list); @@ -142,89 +156,64 @@ PyObject* Arcus::PythonMessage::__getattr__(const std::string& field_name) const return list; } - switch (field->type()) - { - case FieldDescriptor::TYPE_FLOAT: - return PyFloat_FromDouble(_reflection->GetFloat(*_message, field)); - case FieldDescriptor::TYPE_DOUBLE: - return PyFloat_FromDouble(_reflection->GetDouble(*_message, field)); - case FieldDescriptor::TYPE_INT32: - case FieldDescriptor::TYPE_FIXED32: - case FieldDescriptor::TYPE_SINT32: - case FieldDescriptor::TYPE_SFIXED32: - return PyLong_FromLong(_reflection->GetInt32(*_message, field)); - case FieldDescriptor::TYPE_INT64: - case FieldDescriptor::TYPE_FIXED64: - case FieldDescriptor::TYPE_SINT64: - case FieldDescriptor::TYPE_SFIXED64: - return PyLong_FromLongLong(_reflection->GetInt64(*_message, field)); - case FieldDescriptor::TYPE_UINT32: - return PyLong_FromUnsignedLong(_reflection->GetUInt32(*_message, field)); - case FieldDescriptor::TYPE_UINT64: - return PyLong_FromUnsignedLongLong(_reflection->GetUInt64(*_message, field)); - case FieldDescriptor::TYPE_BOOL: - if (_reflection->GetBool(*_message, field)) - { - Py_RETURN_TRUE; - } - else - { - Py_RETURN_FALSE; - } - case FieldDescriptor::TYPE_BYTES: - { - std::string data = _reflection->GetString(*_message, field); - return PyBytes_FromStringAndSize(data.c_str(), data.size()); - } - case FieldDescriptor::TYPE_STRING: - return PyUnicode_FromString(_reflection->GetString(*_message, field).c_str()); - case FieldDescriptor::TYPE_ENUM: - return PyLong_FromLong(_reflection->GetEnumValue(*_message, field)); - default: - PyErr_SetString(PyExc_ValueError, "Could not handle value of field"); - return nullptr; - } + return getScalarField(_reflection, *_message, field, -1); } -// Helper: append a single Python scalar value to a repeated field. -static bool addRepeatedScalar(google::protobuf::Message* message, - const google::protobuf::Reflection* reflection, - const google::protobuf::FieldDescriptor* field, - PyObject* item) +// Write one scalar Python value into a field. +// Pass add = true to append to a repeated field, or add = false to set a singular field. +static bool setScalarField(google::protobuf::Message* message, + const google::protobuf::Reflection* reflection, + const google::protobuf::FieldDescriptor* field, + PyObject* value, + bool add) { switch (field->type()) { case FieldDescriptor::TYPE_FLOAT: { - double v = PyFloat_AsDouble(item); + double v = PyFloat_AsDouble(value); if (v == -1.0 && PyErr_Occurred()) { return false; } - reflection->AddFloat(message, field, static_cast(v)); + if (add) + { + reflection->AddFloat(message, field, static_cast(v)); + } + else + { + reflection->SetFloat(message, field, static_cast(v)); + } break; } case FieldDescriptor::TYPE_DOUBLE: { - double v = PyFloat_AsDouble(item); + double v = PyFloat_AsDouble(value); if (v == -1.0 && PyErr_Occurred()) { return false; } - reflection->AddDouble(message, field, v); + add ? reflection->AddDouble(message, field, v) : reflection->SetDouble(message, field, v); break; } case FieldDescriptor::TYPE_INT32: - case FieldDescriptor::TYPE_SFIXED32: case FieldDescriptor::TYPE_FIXED32: case FieldDescriptor::TYPE_SINT32: + case FieldDescriptor::TYPE_SFIXED32: { - long v = PyLong_AsLong(item); + long v = PyLong_AsLong(value); if (v == -1 && PyErr_Occurred()) { return false; } - reflection->AddInt32(message, field, static_cast(v)); + if (add) + { + reflection->AddInt32(message, field, static_cast(v)); + } + else + { + reflection->SetInt32(message, field, static_cast(v)); + } break; } case FieldDescriptor::TYPE_INT64: @@ -232,64 +221,92 @@ static bool addRepeatedScalar(google::protobuf::Message* message, case FieldDescriptor::TYPE_SINT64: case FieldDescriptor::TYPE_SFIXED64: { - long long v = PyLong_AsLongLong(item); + long long v = PyLong_AsLongLong(value); if (v == -1 && PyErr_Occurred()) { return false; } - reflection->AddInt64(message, field, static_cast(v)); + if (add) + { + reflection->AddInt64(message, field, static_cast(v)); + } + else + { + reflection->SetInt64(message, field, static_cast(v)); + } break; } case FieldDescriptor::TYPE_UINT32: { - unsigned long v = PyLong_AsUnsignedLong(item); + unsigned long v = PyLong_AsUnsignedLong(value); if (v == static_cast(-1) && PyErr_Occurred()) { return false; } - reflection->AddUInt32(message, field, static_cast(v)); + if (add) + { + reflection->AddUInt32(message, field, static_cast(v)); + } + else + { + reflection->SetUInt32(message, field, static_cast(v)); + } break; } case FieldDescriptor::TYPE_UINT64: { - unsigned long long v = PyLong_AsUnsignedLongLong(item); + unsigned long long v = PyLong_AsUnsignedLongLong(value); if (v == static_cast(-1) && PyErr_Occurred()) { return false; } - reflection->AddUInt64(message, field, static_cast(v)); + if (add) + { + reflection->AddUInt64(message, field, static_cast(v)); + } + else + { + reflection->SetUInt64(message, field, static_cast(v)); + } break; } case FieldDescriptor::TYPE_BOOL: - reflection->AddBool(message, field, item == Py_True); + { + int v = PyObject_IsTrue(value); + if (v < 0) + { + return false; + } + add ? reflection->AddBool(message, field, v != 0) : reflection->SetBool(message, field, v != 0); break; + } case FieldDescriptor::TYPE_BYTES: { Py_buffer buffer; - if (PyObject_GetBuffer(item, &buffer, PyBUF_SIMPLE) < 0) + if (PyObject_GetBuffer(value, &buffer, PyBUF_SIMPLE) < 0) { return false; } std::string str(reinterpret_cast(buffer.buf), buffer.len); PyBuffer_Release(&buffer); - reflection->AddString(message, field, str); + add ? reflection->AddString(message, field, str) : reflection->SetString(message, field, str); break; } case FieldDescriptor::TYPE_STRING: { - const char* str = PyUnicode_AsUTF8(item); + const char* str = PyUnicode_AsUTF8(value); if (! str) { return false; } - reflection->AddString(message, field, str); + add ? reflection->AddString(message, field, str) : reflection->SetString(message, field, str); break; } case FieldDescriptor::TYPE_ENUM: { - if (PyUnicode_Check(item)) + if (PyUnicode_Check(value)) { - const char* name = PyUnicode_AsUTF8(item); + const char* name = PyUnicode_AsUTF8(value); if (! name) { return false; @@ -300,21 +317,28 @@ static bool addRepeatedScalar(google::protobuf::Message* message, PyErr_Format(PyExc_ValueError, "Unknown enum value: %s", name); return false; } - reflection->AddEnum(message, field, enum_value); + add ? reflection->AddEnum(message, field, enum_value) : reflection->SetEnum(message, field, enum_value); } else { - long v = PyLong_AsLong(item); + long v = PyLong_AsLong(value); if (v == -1 && PyErr_Occurred()) { return false; } - reflection->AddEnumValue(message, field, static_cast(v)); + if (add) + { + reflection->AddEnumValue(message, field, static_cast(v)); + } + else + { + reflection->SetEnumValue(message, field, static_cast(v)); + } } break; } default: - PyErr_SetString(PyExc_ValueError, "Could not handle value of repeated field"); + PyErr_SetString(PyExc_ValueError, "Could not handle value of field"); return false; } return true; @@ -340,7 +364,7 @@ void Arcus::PythonMessage::__setattr__(const std::string& field_name, PyObject* PyObject* item; while ((item = PyIter_Next(iter)) != nullptr) { - bool ok = addRepeatedScalar(_message, _reflection, field, item); + bool ok = setScalarField(_message, _reflection, field, item, true); Py_DECREF(item); if (! ok) { @@ -349,74 +373,14 @@ void Arcus::PythonMessage::__setattr__(const std::string& field_name, PyObject* } } Py_DECREF(iter); - return; - } - - switch (field->type()) - { - case FieldDescriptor::TYPE_FLOAT: - _reflection->SetFloat(_message, field, PyFloat_AsDouble(value)); - break; - case FieldDescriptor::TYPE_DOUBLE: - _reflection->SetDouble(_message, field, PyFloat_AsDouble(value)); - break; - case FieldDescriptor::TYPE_INT32: - case FieldDescriptor::TYPE_SFIXED32: - case FieldDescriptor::TYPE_FIXED32: - case FieldDescriptor::TYPE_SINT32: - _reflection->SetInt32(_message, field, PyLong_AsLong(value)); - break; - case FieldDescriptor::TYPE_INT64: - case FieldDescriptor::TYPE_FIXED64: - case FieldDescriptor::TYPE_SINT64: - case FieldDescriptor::TYPE_SFIXED64: - _reflection->SetInt64(_message, field, PyLong_AsLongLong(value)); - break; - case FieldDescriptor::TYPE_UINT32: - _reflection->SetUInt32(_message, field, PyLong_AsUnsignedLong(value)); - break; - case FieldDescriptor::TYPE_UINT64: - _reflection->SetUInt64(_message, field, PyLong_AsUnsignedLongLong(value)); - break; - case FieldDescriptor::TYPE_BOOL: - if (value == Py_True) - { - _reflection->SetBool(_message, field, true); - } - else - { - _reflection->SetBool(_message, field, false); - } - break; - case FieldDescriptor::TYPE_BYTES: - { - Py_buffer buffer; - PyObject_GetBuffer(value, &buffer, PyBUF_SIMPLE); - - std::string str(reinterpret_cast(buffer.buf), buffer.len); - _reflection->SetString(_message, field, str); - break; - } - case FieldDescriptor::TYPE_STRING: - _reflection->SetString(_message, field, PyUnicode_AsUTF8(value)); - break; - case FieldDescriptor::TYPE_ENUM: - { - if (PyUnicode_Check(value)) - { - auto enum_value = _descriptor->FindEnumValueByName(PyUnicode_AsUTF8(value)); - _reflection->SetEnum(_message, field, enum_value); - } - else + if (PyErr_Occurred()) { - _reflection->SetEnumValue(_message, field, PyLong_AsLong(value)); + return; } - break; - } - default: - PyErr_SetString(PyExc_ValueError, "Could not handle value of field"); - break; + return; } + + setScalarField(_message, _reflection, field, value, false); } PythonMessage* Arcus::PythonMessage::addRepeatedMessage(const std::string& field_name) From 65be09bd469f61df9b11239a14f81a57b09f4136 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Fri, 21 Aug 2026 10:03:32 +0200 Subject: [PATCH 3/5] Clean code CURA-9839 --- include/pyArcus/PythonMessage.h | 33 +++- src/PythonMessage.cpp | 267 +++++++++++++++----------------- 2 files changed, 151 insertions(+), 149 deletions(-) diff --git a/include/pyArcus/PythonMessage.h b/include/pyArcus/PythonMessage.h index 2e730f5..97c58ca 100644 --- a/include/pyArcus/PythonMessage.h +++ b/include/pyArcus/PythonMessage.h @@ -6,6 +6,7 @@ #include "Arcus/Types.h" #include +#include namespace google { @@ -13,6 +14,7 @@ namespace protobuf { class Descriptor; class Reflection; +class FieldDescriptor; } // namespace protobuf } // namespace google @@ -60,7 +62,7 @@ class PythonMessage /** * Get the number of messages in a repeated message field. */ - int repeatedMessageCount(const std::string& field_name) const; + [[nodiscard]] int repeatedMessageCount(const std::string& field_name) const; /** * Get a specific instance of a message in a repeated message field. @@ -88,12 +90,37 @@ class PythonMessage * * \return The integer value of the specified enum. */ - int getEnumValue(const std::string& enum_value) const; + [[nodiscard]] int getEnumValue(const std::string& enum_value) const; /** * Internal. */ - MessagePtr getSharedMessage() const; + [[nodiscard]] MessagePtr getSharedMessage() const; + +private: + /*! + * Get the python object corresponding to the value of the given field + * @param field The field which value is to be retrieved + * @param index The index of the element if the field is repeatable, otherwise nullopt + * @return The corresponding python object, or nullptr if an error occured + */ + PyObject* getFieldValue(const google::protobuf::FieldDescriptor* field, const std::optional& index = std::nullopt) const; + + /*! + * Sets the value of the field given the corresponding python object + * @param field The field which value is to be set + * @param value The value to be set, as a raw python object + * @param append Whether the value should be appended to a repeatable field, or just set as a scalar value + * @return True if the value was correctly set, false otherwise + */ + bool setFieldValue(const google::protobuf::FieldDescriptor* field, PyObject* value, bool append); + + /*! + * @brief Replaces `_descriptor->FindFieldByName(field_name)` since it sometimes doesn't give an actual existing field + * @param field_name The name of the fields to be used + * @return The matching field descriptor, or nullptr if it was not found + */ + [[nodiscard]] const google::protobuf::FieldDescriptor* findFieldByNameHack(const std::string& field_name) const; private: MessagePtr _shared_message; diff --git a/src/PythonMessage.cpp b/src/PythonMessage.cpp index d9d684c..fe4e584 100644 --- a/src/PythonMessage.cpp +++ b/src/PythonMessage.cpp @@ -8,47 +8,39 @@ #include #include -#include +// #include -using namespace Arcus; -using namespace google::protobuf; +namespace gp = google::protobuf; -PythonMessage::PythonMessage(google::protobuf::Message* message) +namespace Arcus { - _message = message; - _reflection = message->GetReflection(); - _descriptor = message->GetDescriptor(); -} -Arcus::PythonMessage::PythonMessage(const MessagePtr& message) +PythonMessage::PythonMessage(gp::Message* message) : _message(message), _reflection(message->GetReflection()), _descriptor(message->GetDescriptor()) { - _shared_message = message; - _message = message.get(); - _reflection = message->GetReflection(); - _descriptor = message->GetDescriptor(); } -PythonMessage::~PythonMessage() +PythonMessage::PythonMessage(const MessagePtr& message) : _shared_message(message), _message(message.get()), _reflection(message->GetReflection()), _descriptor(message->GetDescriptor()) { } -std::string Arcus::PythonMessage::getTypeName() const +PythonMessage::~PythonMessage() = default; + +std::string PythonMessage::getTypeName() const { return std::string(_message->GetTypeName()); } -MessagePtr Arcus::PythonMessage::getSharedMessage() const +MessagePtr PythonMessage::getSharedMessage() const { return _shared_message; } -// Instead of `_descriptor->FindFieldByName(field_name)`. -const google::protobuf::FieldDescriptor* findFieldByNameHack(const google::protobuf::Descriptor* _descriptor, const std::string_view field_name) +const gp::FieldDescriptor* PythonMessage::findFieldByNameHack(const std::string& field_name) const { for (int ii = 0; ii < _descriptor->field_count(); ++ii) { - auto candidate = _descriptor->field(ii); - if (field_name.compare(candidate->name()) == 0) + const gp::FieldDescriptor* candidate = _descriptor->field(ii); + if (field_name == candidate->name()) { return candidate; } @@ -56,79 +48,65 @@ const google::protobuf::FieldDescriptor* findFieldByNameHack(const google::proto return nullptr; } -bool Arcus::PythonMessage::__hasattr__(const std::string& field_name) const +bool PythonMessage::__hasattr__(const std::string& field_name) const { - auto field = findFieldByNameHack(_descriptor, field_name); + const gp::FieldDescriptor* field = findFieldByNameHack(field_name); return bool(field); } -// Read one scalar value from a field and return it as a Python object. -// Pass index >= 0 for a repeated field element, or index < 0 for a singular field. -static PyObject* getScalarField(const google::protobuf::Reflection* reflection, - const google::protobuf::Message& message, - const google::protobuf::FieldDescriptor* field, - int index) +PyObject* PythonMessage::getFieldValue(const gp::FieldDescriptor* field, const std::optional& index) const { - const bool repeated = index >= 0; + const bool repeated = index.has_value(); switch (field->type()) { - case FieldDescriptor::TYPE_FLOAT: - return PyFloat_FromDouble(repeated ? reflection->GetRepeatedFloat(message, field, index) - : reflection->GetFloat(message, field)); - case FieldDescriptor::TYPE_DOUBLE: - return PyFloat_FromDouble(repeated ? reflection->GetRepeatedDouble(message, field, index) - : reflection->GetDouble(message, field)); - case FieldDescriptor::TYPE_INT32: - case FieldDescriptor::TYPE_FIXED32: - case FieldDescriptor::TYPE_SINT32: - case FieldDescriptor::TYPE_SFIXED32: - return PyLong_FromLong(repeated ? reflection->GetRepeatedInt32(message, field, index) - : reflection->GetInt32(message, field)); - case FieldDescriptor::TYPE_INT64: - case FieldDescriptor::TYPE_FIXED64: - case FieldDescriptor::TYPE_SINT64: - case FieldDescriptor::TYPE_SFIXED64: - return PyLong_FromLongLong(repeated ? reflection->GetRepeatedInt64(message, field, index) - : reflection->GetInt64(message, field)); - case FieldDescriptor::TYPE_UINT32: - return PyLong_FromUnsignedLong(repeated ? reflection->GetRepeatedUInt32(message, field, index) - : reflection->GetUInt32(message, field)); - case FieldDescriptor::TYPE_UINT64: - return PyLong_FromUnsignedLongLong(repeated ? reflection->GetRepeatedUInt64(message, field, index) - : reflection->GetUInt64(message, field)); - case FieldDescriptor::TYPE_BOOL: + case gp::FieldDescriptor::TYPE_FLOAT: + return PyFloat_FromDouble(repeated ? _reflection->GetRepeatedFloat(*_message, field, *index) : _reflection->GetFloat(*_message, field)); + case gp::FieldDescriptor::TYPE_DOUBLE: + return PyFloat_FromDouble(repeated ? _reflection->GetRepeatedDouble(*_message, field, *index) : _reflection->GetDouble(*_message, field)); + case gp::FieldDescriptor::TYPE_INT32: + case gp::FieldDescriptor::TYPE_FIXED32: + case gp::FieldDescriptor::TYPE_SINT32: + case gp::FieldDescriptor::TYPE_SFIXED32: + return PyLong_FromLong(repeated ? _reflection->GetRepeatedInt32(*_message, field, *index) : _reflection->GetInt32(*_message, field)); + case gp::FieldDescriptor::TYPE_INT64: + case gp::FieldDescriptor::TYPE_FIXED64: + case gp::FieldDescriptor::TYPE_SINT64: + case gp::FieldDescriptor::TYPE_SFIXED64: + return PyLong_FromLongLong(repeated ? _reflection->GetRepeatedInt64(*_message, field, *index) : _reflection->GetInt64(*_message, field)); + case gp::FieldDescriptor::TYPE_UINT32: + return PyLong_FromUnsignedLong(repeated ? _reflection->GetRepeatedUInt32(*_message, field, *index) : _reflection->GetUInt32(*_message, field)); + case gp::FieldDescriptor::TYPE_UINT64: + return PyLong_FromUnsignedLongLong(repeated ? _reflection->GetRepeatedUInt64(*_message, field, *index) : _reflection->GetUInt64(*_message, field)); + case gp::FieldDescriptor::TYPE_BOOL: { - bool v = repeated ? reflection->GetRepeatedBool(message, field, index) : reflection->GetBool(message, field); - if (v) + const bool value_bool = repeated ? _reflection->GetRepeatedBool(*_message, field, *index) : _reflection->GetBool(*_message, field); + if (value_bool) { Py_RETURN_TRUE; } Py_RETURN_FALSE; } - case FieldDescriptor::TYPE_BYTES: + case gp::FieldDescriptor::TYPE_BYTES: { - std::string data = repeated ? reflection->GetRepeatedString(message, field, index) - : reflection->GetString(message, field); + const std::string data = repeated ? _reflection->GetRepeatedString(*_message, field, *index) : _reflection->GetString(*_message, field); return PyBytes_FromStringAndSize(data.c_str(), data.size()); } - case FieldDescriptor::TYPE_STRING: + case gp::FieldDescriptor::TYPE_STRING: { - std::string data = repeated ? reflection->GetRepeatedString(message, field, index) - : reflection->GetString(message, field); + const std::string data = repeated ? _reflection->GetRepeatedString(*_message, field, *index) : _reflection->GetString(*_message, field); return PyUnicode_FromString(data.c_str()); } - case FieldDescriptor::TYPE_ENUM: - return PyLong_FromLong(repeated ? reflection->GetRepeatedEnumValue(message, field, index) - : reflection->GetEnumValue(message, field)); + case gp::FieldDescriptor::TYPE_ENUM: + return PyLong_FromLong(repeated ? _reflection->GetRepeatedEnumValue(*_message, field, *index) : _reflection->GetEnumValue(*_message, field)); default: PyErr_SetString(PyExc_ValueError, "Could not handle value of field"); return nullptr; } } -PyObject* Arcus::PythonMessage::__getattr__(const std::string& field_name) const +PyObject* PythonMessage::__getattr__(const std::string& field_name) const { - auto field = findFieldByNameHack(_descriptor, field_name); + const gp::FieldDescriptor* field = findFieldByNameHack(field_name); if (! field) { PyErr_SetString(PyExc_AttributeError, field_name.c_str()); @@ -137,7 +115,7 @@ PyObject* Arcus::PythonMessage::__getattr__(const std::string& field_name) const if (field->is_repeated()) { - int count = _reflection->FieldSize(*_message, field); + const int count = _reflection->FieldSize(*_message, field); PyObject* list = PyList_New(count); if (! list) { @@ -145,7 +123,7 @@ PyObject* Arcus::PythonMessage::__getattr__(const std::string& field_name) const } for (int i = 0; i < count; ++i) { - PyObject* item = getScalarField(_reflection, *_message, field, i); + PyObject* item = getFieldValue(field, i); if (! item) { Py_DECREF(list); @@ -156,153 +134,148 @@ PyObject* Arcus::PythonMessage::__getattr__(const std::string& field_name) const return list; } - return getScalarField(_reflection, *_message, field, -1); + return getFieldValue(field); } -// Write one scalar Python value into a field. -// Pass add = true to append to a repeated field, or add = false to set a singular field. -static bool setScalarField(google::protobuf::Message* message, - const google::protobuf::Reflection* reflection, - const google::protobuf::FieldDescriptor* field, - PyObject* value, - bool add) +bool PythonMessage::setFieldValue(const gp::FieldDescriptor* field, PyObject* value, bool append) { switch (field->type()) { - case FieldDescriptor::TYPE_FLOAT: + case gp::FieldDescriptor::TYPE_FLOAT: { - double v = PyFloat_AsDouble(value); - if (v == -1.0 && PyErr_Occurred()) + double value_double = PyFloat_AsDouble(value); + if (value_double == -1.0 && PyErr_Occurred()) { return false; } - if (add) + if (append) { - reflection->AddFloat(message, field, static_cast(v)); + _reflection->AddFloat(_message, field, static_cast(value_double)); } else { - reflection->SetFloat(message, field, static_cast(v)); + _reflection->SetFloat(_message, field, static_cast(value_double)); } break; } - case FieldDescriptor::TYPE_DOUBLE: + case gp::FieldDescriptor::TYPE_DOUBLE: { - double v = PyFloat_AsDouble(value); - if (v == -1.0 && PyErr_Occurred()) + double value_double = PyFloat_AsDouble(value); + if (value_double == -1.0 && PyErr_Occurred()) { return false; } - add ? reflection->AddDouble(message, field, v) : reflection->SetDouble(message, field, v); + append ? _reflection->AddDouble(_message, field, value_double) : _reflection->SetDouble(_message, field, value_double); break; } - case FieldDescriptor::TYPE_INT32: - case FieldDescriptor::TYPE_FIXED32: - case FieldDescriptor::TYPE_SINT32: - case FieldDescriptor::TYPE_SFIXED32: + case gp::FieldDescriptor::TYPE_INT32: + case gp::FieldDescriptor::TYPE_FIXED32: + case gp::FieldDescriptor::TYPE_SINT32: + case gp::FieldDescriptor::TYPE_SFIXED32: { - long v = PyLong_AsLong(value); - if (v == -1 && PyErr_Occurred()) + long value_long = PyLong_AsLong(value); + if (value_long == -1 && PyErr_Occurred()) { return false; } - if (add) + if (append) { - reflection->AddInt32(message, field, static_cast(v)); + _reflection->AddInt32(_message, field, static_cast(value_long)); } else { - reflection->SetInt32(message, field, static_cast(v)); + _reflection->SetInt32(_message, field, static_cast(value_long)); } break; } - case FieldDescriptor::TYPE_INT64: - case FieldDescriptor::TYPE_FIXED64: - case FieldDescriptor::TYPE_SINT64: - case FieldDescriptor::TYPE_SFIXED64: + case gp::FieldDescriptor::TYPE_INT64: + case gp::FieldDescriptor::TYPE_FIXED64: + case gp::FieldDescriptor::TYPE_SINT64: + case gp::FieldDescriptor::TYPE_SFIXED64: { - long long v = PyLong_AsLongLong(value); - if (v == -1 && PyErr_Occurred()) + long long value_ll = PyLong_AsLongLong(value); + if (value_ll == -1 && PyErr_Occurred()) { return false; } - if (add) + if (append) { - reflection->AddInt64(message, field, static_cast(v)); + _reflection->AddInt64(_message, field, static_cast(value_ll)); } else { - reflection->SetInt64(message, field, static_cast(v)); + _reflection->SetInt64(_message, field, static_cast(value_ll)); } break; } - case FieldDescriptor::TYPE_UINT32: + case gp::FieldDescriptor::TYPE_UINT32: { - unsigned long v = PyLong_AsUnsignedLong(value); - if (v == static_cast(-1) && PyErr_Occurred()) + unsigned long value_ul = PyLong_AsUnsignedLong(value); + if (value_ul == static_cast(-1) && PyErr_Occurred()) { return false; } - if (add) + if (append) { - reflection->AddUInt32(message, field, static_cast(v)); + _reflection->AddUInt32(_message, field, static_cast(value_ul)); } else { - reflection->SetUInt32(message, field, static_cast(v)); + _reflection->SetUInt32(_message, field, static_cast(value_ul)); } break; } - case FieldDescriptor::TYPE_UINT64: + case gp::FieldDescriptor::TYPE_UINT64: { - unsigned long long v = PyLong_AsUnsignedLongLong(value); - if (v == static_cast(-1) && PyErr_Occurred()) + unsigned long long value_ull = PyLong_AsUnsignedLongLong(value); + if (value_ull == static_cast(-1) && PyErr_Occurred()) { return false; } - if (add) + if (append) { - reflection->AddUInt64(message, field, static_cast(v)); + _reflection->AddUInt64(_message, field, static_cast(value_ull)); } else { - reflection->SetUInt64(message, field, static_cast(v)); + _reflection->SetUInt64(_message, field, static_cast(value_ull)); } break; } - case FieldDescriptor::TYPE_BOOL: + case gp::FieldDescriptor::TYPE_BOOL: { - int v = PyObject_IsTrue(value); - if (v < 0) + int value_int = PyObject_IsTrue(value); + if (value_int < 0) { return false; } - add ? reflection->AddBool(message, field, v != 0) : reflection->SetBool(message, field, v != 0); + const bool value_bool = value_int != 0; + append ? _reflection->AddBool(_message, field, value_bool) : _reflection->SetBool(_message, field, value_bool); break; } - case FieldDescriptor::TYPE_BYTES: + case gp::FieldDescriptor::TYPE_BYTES: { Py_buffer buffer; if (PyObject_GetBuffer(value, &buffer, PyBUF_SIMPLE) < 0) { return false; } - std::string str(reinterpret_cast(buffer.buf), buffer.len); + std::string const str(reinterpret_cast(buffer.buf), buffer.len); PyBuffer_Release(&buffer); - add ? reflection->AddString(message, field, str) : reflection->SetString(message, field, str); + append ? _reflection->AddString(_message, field, str) : _reflection->SetString(_message, field, str); break; } - case FieldDescriptor::TYPE_STRING: + case gp::FieldDescriptor::TYPE_STRING: { const char* str = PyUnicode_AsUTF8(value); if (! str) { return false; } - add ? reflection->AddString(message, field, str) : reflection->SetString(message, field, str); + append ? _reflection->AddString(_message, field, str) : _reflection->SetString(_message, field, str); break; } - case FieldDescriptor::TYPE_ENUM: + case gp::FieldDescriptor::TYPE_ENUM: { if (PyUnicode_Check(value)) { @@ -317,22 +290,22 @@ static bool setScalarField(google::protobuf::Message* message, PyErr_Format(PyExc_ValueError, "Unknown enum value: %s", name); return false; } - add ? reflection->AddEnum(message, field, enum_value) : reflection->SetEnum(message, field, enum_value); + append ? _reflection->AddEnum(_message, field, enum_value) : _reflection->SetEnum(_message, field, enum_value); } else { - long v = PyLong_AsLong(value); - if (v == -1 && PyErr_Occurred()) + long value_long = PyLong_AsLong(value); + if (value_long == -1 && PyErr_Occurred()) { return false; } - if (add) + if (append) { - reflection->AddEnumValue(message, field, static_cast(v)); + _reflection->AddEnumValue(_message, field, static_cast(value_long)); } else { - reflection->SetEnumValue(message, field, static_cast(v)); + _reflection->SetEnumValue(_message, field, static_cast(value_long)); } } break; @@ -344,9 +317,9 @@ static bool setScalarField(google::protobuf::Message* message, return true; } -void Arcus::PythonMessage::__setattr__(const std::string& field_name, PyObject* value) +void PythonMessage::__setattr__(const std::string& field_name, PyObject* value) { - auto field = findFieldByNameHack(_descriptor, field_name); + auto field = findFieldByNameHack(field_name); if (! field) { PyErr_SetString(PyExc_AttributeError, field_name.c_str()); @@ -364,7 +337,7 @@ void Arcus::PythonMessage::__setattr__(const std::string& field_name, PyObject* PyObject* item; while ((item = PyIter_Next(iter)) != nullptr) { - bool ok = setScalarField(_message, _reflection, field, item, true); + bool ok = setFieldValue(field, item, true); Py_DECREF(item); if (! ok) { @@ -380,25 +353,25 @@ void Arcus::PythonMessage::__setattr__(const std::string& field_name, PyObject* return; } - setScalarField(_message, _reflection, field, value, false); + setFieldValue(field, value, false); } -PythonMessage* Arcus::PythonMessage::addRepeatedMessage(const std::string& field_name) +PythonMessage* PythonMessage::addRepeatedMessage(const std::string& field_name) { - auto field = findFieldByNameHack(_descriptor, field_name); + auto field = findFieldByNameHack(field_name); if (! field) { PyErr_SetString(PyExc_AttributeError, field_name.c_str()); return nullptr; } - Message* message = _reflection->AddMessage(_message, field); + gp::Message* message = _reflection->AddMessage(_message, field); return new PythonMessage(message); } int PythonMessage::repeatedMessageCount(const std::string& field_name) const { - auto field = findFieldByNameHack(_descriptor, field_name); + auto field = findFieldByNameHack(field_name); if (! field) { PyErr_SetString(PyExc_AttributeError, field_name.c_str()); @@ -408,9 +381,9 @@ int PythonMessage::repeatedMessageCount(const std::string& field_name) const return _reflection->FieldSize(*_message, field); } -PythonMessage* Arcus::PythonMessage::getMessage(const std::string& field_name) +PythonMessage* PythonMessage::getMessage(const std::string& field_name) { - auto field = findFieldByNameHack(_descriptor, field_name); + auto field = findFieldByNameHack(field_name); if (! field) { PyErr_SetString(PyExc_AttributeError, field_name.c_str()); @@ -419,9 +392,9 @@ PythonMessage* Arcus::PythonMessage::getMessage(const std::string& field_name) return new PythonMessage(_reflection->MutableMessage(_message, field)); } -PythonMessage* Arcus::PythonMessage::getRepeatedMessage(const std::string& field_name, int index) +PythonMessage* PythonMessage::getRepeatedMessage(const std::string& field_name, int index) { - auto field = findFieldByNameHack(_descriptor, field_name); + auto field = findFieldByNameHack(field_name); if (! field) { PyErr_SetString(PyExc_AttributeError, field_name.c_str()); @@ -437,7 +410,7 @@ PythonMessage* Arcus::PythonMessage::getRepeatedMessage(const std::string& field return new PythonMessage(_reflection->MutableRepeatedMessage(_message, field, index)); } -int Arcus::PythonMessage::getEnumValue(const std::string& enum_value) const +int PythonMessage::getEnumValue(const std::string& enum_value) const { auto field = _descriptor->FindEnumValueByName(enum_value); if (! field) @@ -447,3 +420,5 @@ int Arcus::PythonMessage::getEnumValue(const std::string& enum_value) const return field->number(); } + +} // namespace Arcus \ No newline at end of file From 1873e78aba82ce3ad0952b36ccfe18e4ac911004 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Fri, 21 Aug 2026 10:20:47 +0200 Subject: [PATCH 4/5] Remove unnecessary extra checks CURA-9839 --- include/pyArcus/PythonMessage.h | 3 +- src/PythonMessage.cpp | 139 +++++--------------------------- 2 files changed, 21 insertions(+), 121 deletions(-) diff --git a/include/pyArcus/PythonMessage.h b/include/pyArcus/PythonMessage.h index 97c58ca..bc51ebb 100644 --- a/include/pyArcus/PythonMessage.h +++ b/include/pyArcus/PythonMessage.h @@ -111,9 +111,8 @@ class PythonMessage * @param field The field which value is to be set * @param value The value to be set, as a raw python object * @param append Whether the value should be appended to a repeatable field, or just set as a scalar value - * @return True if the value was correctly set, false otherwise */ - bool setFieldValue(const google::protobuf::FieldDescriptor* field, PyObject* value, bool append); + void setFieldValue(const google::protobuf::FieldDescriptor* field, PyObject* value, bool append); /*! * @brief Replaces `_descriptor->FindFieldByName(field_name)` since it sometimes doesn't give an actual existing field diff --git a/src/PythonMessage.cpp b/src/PythonMessage.cpp index fe4e584..b7d0bda 100644 --- a/src/PythonMessage.cpp +++ b/src/PythonMessage.cpp @@ -8,7 +8,6 @@ #include #include -// #include namespace gp = google::protobuf; @@ -137,34 +136,19 @@ PyObject* PythonMessage::__getattr__(const std::string& field_name) const return getFieldValue(field); } -bool PythonMessage::setFieldValue(const gp::FieldDescriptor* field, PyObject* value, bool append) +void PythonMessage::setFieldValue(const gp::FieldDescriptor* field, PyObject* value, bool append) { switch (field->type()) { case gp::FieldDescriptor::TYPE_FLOAT: { - double value_double = PyFloat_AsDouble(value); - if (value_double == -1.0 && PyErr_Occurred()) - { - return false; - } - if (append) - { - _reflection->AddFloat(_message, field, static_cast(value_double)); - } - else - { - _reflection->SetFloat(_message, field, static_cast(value_double)); - } + const double value_double = PyFloat_AsDouble(value); + append ? _reflection->AddFloat(_message, field, static_cast(value_double)) : _reflection->SetFloat(_message, field, static_cast(value_double)); break; } case gp::FieldDescriptor::TYPE_DOUBLE: { - double value_double = PyFloat_AsDouble(value); - if (value_double == -1.0 && PyErr_Occurred()) - { - return false; - } + const double value_double = PyFloat_AsDouble(value); append ? _reflection->AddDouble(_message, field, value_double) : _reflection->SetDouble(_message, field, value_double); break; } @@ -173,19 +157,8 @@ bool PythonMessage::setFieldValue(const gp::FieldDescriptor* field, PyObject* va case gp::FieldDescriptor::TYPE_SINT32: case gp::FieldDescriptor::TYPE_SFIXED32: { - long value_long = PyLong_AsLong(value); - if (value_long == -1 && PyErr_Occurred()) - { - return false; - } - if (append) - { - _reflection->AddInt32(_message, field, static_cast(value_long)); - } - else - { - _reflection->SetInt32(_message, field, static_cast(value_long)); - } + const long value_long = PyLong_AsLong(value); + append ? _reflection->AddInt32(_message, field, static_cast(value_long)) : _reflection->SetInt32(_message, field, static_cast(value_long)); break; } case gp::FieldDescriptor::TYPE_INT64: @@ -193,85 +166,40 @@ bool PythonMessage::setFieldValue(const gp::FieldDescriptor* field, PyObject* va case gp::FieldDescriptor::TYPE_SINT64: case gp::FieldDescriptor::TYPE_SFIXED64: { - long long value_ll = PyLong_AsLongLong(value); - if (value_ll == -1 && PyErr_Occurred()) - { - return false; - } - if (append) - { - _reflection->AddInt64(_message, field, static_cast(value_ll)); - } - else - { - _reflection->SetInt64(_message, field, static_cast(value_ll)); - } + const long long value_ll = PyLong_AsLongLong(value); + append ? _reflection->AddInt64(_message, field, static_cast(value_ll)) : _reflection->SetInt64(_message, field, static_cast(value_ll)); break; } case gp::FieldDescriptor::TYPE_UINT32: { - unsigned long value_ul = PyLong_AsUnsignedLong(value); - if (value_ul == static_cast(-1) && PyErr_Occurred()) - { - return false; - } - if (append) - { - _reflection->AddUInt32(_message, field, static_cast(value_ul)); - } - else - { - _reflection->SetUInt32(_message, field, static_cast(value_ul)); - } + const unsigned long value_ul = PyLong_AsUnsignedLong(value); + append ? _reflection->AddUInt32(_message, field, static_cast(value_ul)) : _reflection->SetUInt32(_message, field, static_cast(value_ul)); break; } case gp::FieldDescriptor::TYPE_UINT64: { - unsigned long long value_ull = PyLong_AsUnsignedLongLong(value); - if (value_ull == static_cast(-1) && PyErr_Occurred()) - { - return false; - } - if (append) - { - _reflection->AddUInt64(_message, field, static_cast(value_ull)); - } - else - { - _reflection->SetUInt64(_message, field, static_cast(value_ull)); - } + const unsigned long long value_ull = PyLong_AsUnsignedLongLong(value); + append ? _reflection->AddUInt64(_message, field, static_cast(value_ull)) : _reflection->SetUInt64(_message, field, static_cast(value_ull)); break; } case gp::FieldDescriptor::TYPE_BOOL: { - int value_int = PyObject_IsTrue(value); - if (value_int < 0) - { - return false; - } - const bool value_bool = value_int != 0; + const bool value_bool = value == Py_True; append ? _reflection->AddBool(_message, field, value_bool) : _reflection->SetBool(_message, field, value_bool); break; } case gp::FieldDescriptor::TYPE_BYTES: { Py_buffer buffer; - if (PyObject_GetBuffer(value, &buffer, PyBUF_SIMPLE) < 0) - { - return false; - } + PyObject_GetBuffer(value, &buffer, PyBUF_SIMPLE); + std::string const str(reinterpret_cast(buffer.buf), buffer.len); - PyBuffer_Release(&buffer); append ? _reflection->AddString(_message, field, str) : _reflection->SetString(_message, field, str); break; } case gp::FieldDescriptor::TYPE_STRING: { const char* str = PyUnicode_AsUTF8(value); - if (! str) - { - return false; - } append ? _reflection->AddString(_message, field, str) : _reflection->SetString(_message, field, str); break; } @@ -279,42 +207,20 @@ bool PythonMessage::setFieldValue(const gp::FieldDescriptor* field, PyObject* va { if (PyUnicode_Check(value)) { - const char* name = PyUnicode_AsUTF8(value); - if (! name) - { - return false; - } - auto enum_value = field->enum_type()->FindValueByName(name); - if (! enum_value) - { - PyErr_Format(PyExc_ValueError, "Unknown enum value: %s", name); - return false; - } + const auto enum_value = _descriptor->FindEnumValueByName(PyUnicode_AsUTF8(value)); append ? _reflection->AddEnum(_message, field, enum_value) : _reflection->SetEnum(_message, field, enum_value); } else { - long value_long = PyLong_AsLong(value); - if (value_long == -1 && PyErr_Occurred()) - { - return false; - } - if (append) - { - _reflection->AddEnumValue(_message, field, static_cast(value_long)); - } - else - { - _reflection->SetEnumValue(_message, field, static_cast(value_long)); - } + const int value_int = static_cast(PyLong_AsLong(value)); + append ? _reflection->AddEnumValue(_message, field, value_int) : _reflection->SetEnumValue(_message, field, value_int); } break; } default: PyErr_SetString(PyExc_ValueError, "Could not handle value of field"); - return false; + break; } - return true; } void PythonMessage::__setattr__(const std::string& field_name, PyObject* value) @@ -337,13 +243,8 @@ void PythonMessage::__setattr__(const std::string& field_name, PyObject* value) PyObject* item; while ((item = PyIter_Next(iter)) != nullptr) { - bool ok = setFieldValue(field, item, true); + setFieldValue(field, item, true); Py_DECREF(item); - if (! ok) - { - Py_DECREF(iter); - return; - } } Py_DECREF(iter); if (PyErr_Occurred()) From 5dfb9263b69041eb0fe04e15fe7483c0fd653ec5 Mon Sep 17 00:00:00 2001 From: Erwan MATHIEU Date: Mon, 24 Aug 2026 08:34:06 +0200 Subject: [PATCH 5/5] Bump version CURA-9839 --- conandata.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conandata.yml b/conandata.yml index 180b137..6ea3484 100644 --- a/conandata.yml +++ b/conandata.yml @@ -1,3 +1,3 @@ -version: "5.11.2-alpha.0" +version: "5.12.0" requirements: - "arcus/5.11.1"