From fc8fa7f2515d5e3a6fbce1b83ae6fa89d46aa945 Mon Sep 17 00:00:00 2001 From: Martin Valgur <martin.valgur@gmail.com> Date: Mon, 28 Oct 2024 00:37:22 +0200 Subject: [PATCH] Add .enums dictionary to MessageDatabase --- python/bindings/message_database.cpp | 3 ++- python/bindings/message_decoder.cpp | 4 ++-- python/bindings/oem_enums.cpp | 7 +++---- python/bindings/py_database.hpp | 7 ++++++- python/test/test_message_database.py | 31 ++++++++++++++++++++++++++++ 5 files changed, 44 insertions(+), 8 deletions(-) create mode 100644 python/test/test_message_database.py diff --git a/python/bindings/message_database.cpp b/python/bindings/message_database.cpp index 19f54e51a..674ba1b31 100644 --- a/python/bindings/message_database.cpp +++ b/python/bindings/message_database.cpp @@ -182,5 +182,6 @@ void init_common_message_database(nb::module_& m) .def("get_msg_def", nb::overload_cast<const std::string&>(&PyMessageDatabase::GetMsgDef, nb::const_), "msg_name"_a) .def("get_msg_def", nb::overload_cast<int32_t>(&PyMessageDatabase::GetMsgDef, nb::const_), "msg_id"_a) .def("get_enum_def", &PyMessageDatabase::GetEnumDefId, "enum_id"_a) - .def("get_enum_def", &PyMessageDatabase::GetEnumDefName, "enum_name"_a); + .def("get_enum_def", &PyMessageDatabase::GetEnumDefName, "enum_name"_a) + .def_prop_ro("enums", &PyMessageDatabase::GetEnumsByNameDict); } diff --git a/python/bindings/message_decoder.cpp b/python/bindings/message_decoder.cpp index 303bde403..863f171eb 100644 --- a/python/bindings/message_decoder.cpp +++ b/python/bindings/message_decoder.cpp @@ -20,8 +20,8 @@ nb::object convert_field(const FieldContainer& field, const PyMessageDatabase::C if (field.fieldDef->type == FIELD_TYPE::ENUM) { const std::string& enumId = static_cast<const EnumField*>(field.fieldDef.get())->enumId; - auto it = parent_db->GetEnumsByIdMap().find(enumId); - if (it == parent_db->GetEnumsByIdMap().end()) + auto it = parent_db->GetEnumsByIdDict().find(enumId); + if (it == parent_db->GetEnumsByIdDict().end()) { throw std::runtime_error("Enum definition for " + field.fieldDef->name + " field with ID '" + enumId + "' not found in the JSON database"); diff --git a/python/bindings/oem_enums.cpp b/python/bindings/oem_enums.cpp index b502ee075..183f325f1 100644 --- a/python/bindings/oem_enums.cpp +++ b/python/bindings/oem_enums.cpp @@ -7,10 +7,9 @@ using namespace novatel::edie; void init_novatel_oem_enums(nb::module_& m) { - nb::module_ enums_mod = m.def_submodule("enums", ""); - for (const auto& [_, enum_type] : MessageDbSingleton::get()->GetEnumsByIdMap()) + nb::module_ enums_mod = m.def_submodule("enums", "Enumerations used by NovAtel OEM message fields."); + for (const auto& [name, enum_type] : MessageDbSingleton::get()->GetEnumsByNameDict()) // { - nb::object name = enum_type.attr("_name"); - enums_mod.attr(name) = enum_type; + enums_mod.attr(name.c_str()) = enum_type; } } diff --git a/python/bindings/py_database.hpp b/python/bindings/py_database.hpp index b930b8b5d..44c6e57b9 100644 --- a/python/bindings/py_database.hpp +++ b/python/bindings/py_database.hpp @@ -20,7 +20,9 @@ class PyMessageDatabase final : public MessageDatabase explicit PyMessageDatabase(const MessageDatabase& message_db) : MessageDatabase(message_db) { UpdatePythonEnums(); } - [[nodiscard]] const std::unordered_map<std::string, nb::object>& GetEnumsByIdMap() const { return enums_by_id; } + [[nodiscard]] const std::unordered_map<std::string, nb::object>& GetEnumsByIdDict() const { return enums_by_id; } + + [[nodiscard]] const std::unordered_map<std::string, nb::object>& GetEnumsByNameDict() const { return enums_by_name; } private: void GenerateMappings() override @@ -33,6 +35,7 @@ class PyMessageDatabase final : public MessageDatabase { nb::object IntEnum = nb::module_::import_("enum").attr("IntEnum"); enums_by_id.clear(); + enums_by_name.clear(); for (const auto& enum_def : EnumDefinitions()) { nb::dict values; @@ -42,10 +45,12 @@ class PyMessageDatabase final : public MessageDatabase enum_type.attr("_name") = enum_name; enum_type.attr("_id") = enum_def->_id; enums_by_id[enum_def->_id.c_str()] = enum_type; + enums_by_name[enum_name] = enum_type; } } std::unordered_map<std::string, nb::object> enums_by_id{}; + std::unordered_map<std::string, nb::object> enums_by_name{}; public: using Ptr = std::shared_ptr<PyMessageDatabase>; diff --git a/python/test/test_message_database.py b/python/test/test_message_database.py new file mode 100644 index 000000000..f1a6ede27 --- /dev/null +++ b/python/test/test_message_database.py @@ -0,0 +1,31 @@ +################################################################################ +# +# COPYRIGHT NovAtel Inc, 2024. All rights reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +# +################################################################################= + +import novatel_edie as ne + + +def test_message_db_enums(json_db): + assert json_db.enums["Datum"].WGS84 == 61 + assert json_db.enums["Datum"].WGS84.name == "WGS84" + assert json_db.enums["Datum"].WGS84 == ne.enums.Datum.WGS84