diff --git a/lint-tasks.yml b/lint-tasks.yml index f454d176..71712060 100644 --- a/lint-tasks.yml +++ b/lint-tasks.yml @@ -109,8 +109,14 @@ tasks: # TODO: Before all clang-tidy violations are resolved, we should only run clang-tidy on # the files whose violations we've fixed, both to ensure they remain free of violations # and so that the workflow doesn't fail due to violations in other files. + - "{{.CLP_FFI_PY_CPP_SRC_DIR}}/api_decoration.hpp" + - "{{.CLP_FFI_PY_CPP_SRC_DIR}}/error_messages.hpp" + - "{{.CLP_FFI_PY_CPP_SRC_DIR}}/ExceptionFFI.hpp" - "{{.CLP_FFI_PY_CPP_SRC_DIR}}/Py_utils.cpp" - "{{.CLP_FFI_PY_CPP_SRC_DIR}}/Py_utils.hpp" + - "{{.CLP_FFI_PY_CPP_SRC_DIR}}/PyExceptionContext.hpp" + - "{{.CLP_FFI_PY_CPP_SRC_DIR}}/PyObjectCast.hpp" + - "{{.CLP_FFI_PY_CPP_SRC_DIR}}/PyObjectUtils.hpp" - "{{.CLP_FFI_PY_CPP_SRC_DIR}}/utils.cpp" - "{{.CLP_FFI_PY_CPP_SRC_DIR}}/utils.hpp" - "{{.G_CPP_WRAPPED_FACADE_HEADERS_DIR}}" diff --git a/src/clp_ffi_py/PyObjectCast.hpp b/src/clp_ffi_py/PyObjectCast.hpp index 384bb16c..1da0f147 100644 --- a/src/clp_ffi_py/PyObjectCast.hpp +++ b/src/clp_ffi_py/PyObjectCast.hpp @@ -57,26 +57,26 @@ auto py_releasebufferproc_cast(Src src) noexcept -> releasebufferproc { * @tparam T */ template -struct is_python_object { +struct IsPythonObject { static constexpr bool cValue = false; }; /** - * This template const expression is a wrapper of underlying `cValue` stored in `is_python_object`, + * This template const expression is a wrapper of underlying `cValue` stored in `IsPythonObject`, * which is used to determine whether a type T is a valid Python object type. * @tparam T */ template // NOLINTNEXTLINE(readability-identifier-naming) -constexpr bool is_python_object_v{is_python_object::cValue}; +constexpr bool is_python_object_v{IsPythonObject::cValue}; /** - * The macro to create a specialization of is_python_object for a given type T. Only types that are + * The macro to create a specialization of `IsPythonObject` for a given type T. Only types that are * marked with this macro will be considered as a valid Python object type. */ // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define CLP_FFI_PY_MARK_AS_PYOBJECT(T) \ template <> \ - struct is_python_object { \ + struct IsPythonObject { \ static constexpr bool cValue = true; \ } diff --git a/src/clp_ffi_py/error_messages.hpp b/src/clp_ffi_py/error_messages.hpp index b4742a8b..ad61f0b2 100644 --- a/src/clp_ffi_py/error_messages.hpp +++ b/src/clp_ffi_py/error_messages.hpp @@ -1,14 +1,18 @@ #ifndef CLP_FFI_PY_ERROR_MESSAGES #define CLP_FFI_PY_ERROR_MESSAGES +#include + namespace clp_ffi_py { -constexpr char const* const cOutofMemoryError = "Failed to allocate memory."; -constexpr char const* const cPyTypeError = "Wrong Python Type received."; -constexpr char const* const cSetstateInputError - = "Python dictionary is expected to be the input of __setstate__ method."; -constexpr char const* const cSetstateKeyErrorTemplate = "\"%s\" not found in the state dictionary."; -constexpr char const* const cTimezoneObjectNotInitialzed - = "Timezone (tzinfo) object is not yet initialized."; +constexpr std::string_view cOutOfMemoryError{"Failed to allocate memory."}; +constexpr std::string_view cPyTypeError{"Wrong Python Type received."}; +constexpr std::string_view cSetstateInputError{ + "Python dictionary is expected to be the input of __setstate__ method." +}; +constexpr std::string_view cSetstateKeyErrorTemplate{"\"%s\" not found in the state dictionary."}; +constexpr std::string_view cTimezoneObjectNotInitialized{ + "Timezone (tzinfo) object is not yet initialized." +}; } // namespace clp_ffi_py #endif // CLP_FFI_PY_ERROR_MESSAGES diff --git a/src/clp_ffi_py/ir/native/PyDeserializerBuffer.cpp b/src/clp_ffi_py/ir/native/PyDeserializerBuffer.cpp index 9287c832..ea71fd86 100644 --- a/src/clp_ffi_py/ir/native/PyDeserializerBuffer.cpp +++ b/src/clp_ffi_py/ir/native/PyDeserializerBuffer.cpp @@ -385,7 +385,10 @@ auto PyDeserializerBuffer::create(PyObject* input_stream, Py_ssize_t buf_capacit // NOLINTNEXTLINE(cppcoreguidelines-pro-type-cstyle-cast) PyDeserializerBuffer* self{PyObject_New(PyDeserializerBuffer, get_py_type())}; if (nullptr == self) { - PyErr_SetString(PyExc_MemoryError, clp_ffi_py::cOutofMemoryError); + PyErr_SetString( + PyExc_MemoryError, + get_c_str_from_constexpr_string_view(clp_ffi_py::cOutOfMemoryError) + ); return nullptr; } self->default_init(); diff --git a/src/clp_ffi_py/ir/native/PyKeyValuePairLogEvent.cpp b/src/clp_ffi_py/ir/native/PyKeyValuePairLogEvent.cpp index f65e7fe6..53d92286 100644 --- a/src/clp_ffi_py/ir/native/PyKeyValuePairLogEvent.cpp +++ b/src/clp_ffi_py/ir/native/PyKeyValuePairLogEvent.cpp @@ -644,7 +644,10 @@ auto decode_as_encoded_text_ast(Value const& val) -> std::optional auto PyKeyValuePairLogEvent::init(clp::ffi::KeyValuePairLogEvent kv_pair_log_event) -> bool { m_kv_pair_log_event = new clp::ffi::KeyValuePairLogEvent{std::move(kv_pair_log_event)}; if (nullptr == m_kv_pair_log_event) { - PyErr_SetString(PyExc_RuntimeError, clp_ffi_py::cOutofMemoryError); + PyErr_SetString( + PyExc_RuntimeError, + get_c_str_from_constexpr_string_view(clp_ffi_py::cOutOfMemoryError) + ); return false; } return true; @@ -679,7 +682,6 @@ auto PyKeyValuePairLogEvent::create(clp::ffi::KeyValuePairLogEvent kv_log_event // NOLINTNEXTLINE(cppcoreguidelines-pro-type-cstyle-cast) PyKeyValuePairLogEvent* self{PyObject_New(PyKeyValuePairLogEvent, get_py_type())}; if (nullptr == self) { - PyErr_SetString(PyExc_MemoryError, clp_ffi_py::cOutofMemoryError); return nullptr; } self->default_init(); diff --git a/src/clp_ffi_py/ir/native/PyLogEvent.cpp b/src/clp_ffi_py/ir/native/PyLogEvent.cpp index 6919449f..d011acc0 100644 --- a/src/clp_ffi_py/ir/native/PyLogEvent.cpp +++ b/src/clp_ffi_py/ir/native/PyLogEvent.cpp @@ -64,7 +64,10 @@ auto PyLogEvent_init(PyLogEvent* self, PyObject* args, PyObject* keywords) -> in if (has_metadata && false == static_cast(PyObject_TypeCheck(metadata, PyMetadata::get_py_type()))) { - PyErr_SetString(PyExc_TypeError, clp_ffi_py::cPyTypeError); + PyErr_SetString( + PyExc_TypeError, + get_c_str_from_constexpr_string_view(clp_ffi_py::cPyTypeError) + ); return -1; } @@ -175,13 +178,20 @@ auto PyLogEvent_setstate(PyLogEvent* self, PyObject* state) -> PyObject* { self->default_init(); if (false == static_cast(PyDict_CheckExact(state))) { - PyErr_SetString(PyExc_ValueError, clp_ffi_py::cSetstateInputError); + PyErr_SetString( + PyExc_ValueError, + get_c_str_from_constexpr_string_view(clp_ffi_py::cSetstateInputError) + ); return nullptr; } auto* log_message_obj{PyDict_GetItemString(state, cStateLogMessage)}; if (nullptr == log_message_obj) { - PyErr_Format(PyExc_KeyError, clp_ffi_py::cSetstateKeyErrorTemplate, cStateLogMessage); + PyErr_Format( + PyExc_KeyError, + get_c_str_from_constexpr_string_view(clp_ffi_py::cSetstateKeyErrorTemplate), + cStateLogMessage + ); return nullptr; } std::string log_message; @@ -193,7 +203,7 @@ auto PyLogEvent_setstate(PyLogEvent* self, PyObject* state) -> PyObject* { if (nullptr == formatted_timestamp_obj) { PyErr_Format( PyExc_KeyError, - clp_ffi_py::cSetstateKeyErrorTemplate, + get_c_str_from_constexpr_string_view(clp_ffi_py::cSetstateKeyErrorTemplate), cStateFormattedTimestamp ); return nullptr; @@ -205,7 +215,11 @@ auto PyLogEvent_setstate(PyLogEvent* self, PyObject* state) -> PyObject* { auto* timestamp_obj{PyDict_GetItemString(state, cStateTimestamp)}; if (nullptr == timestamp_obj) { - PyErr_Format(PyExc_KeyError, clp_ffi_py::cSetstateKeyErrorTemplate, cStateTimestamp); + PyErr_Format( + PyExc_KeyError, + get_c_str_from_constexpr_string_view(clp_ffi_py::cSetstateKeyErrorTemplate), + cStateTimestamp + ); return nullptr; } clp::ir::epoch_time_ms_t timestamp{0}; @@ -215,7 +229,11 @@ auto PyLogEvent_setstate(PyLogEvent* self, PyObject* state) -> PyObject* { auto* index_obj{PyDict_GetItemString(state, cStateIndex)}; if (nullptr == index_obj) { - PyErr_Format(PyExc_KeyError, clp_ffi_py::cSetstateKeyErrorTemplate, cStateIndex); + PyErr_Format( + PyExc_KeyError, + get_c_str_from_constexpr_string_view(clp_ffi_py::cSetstateKeyErrorTemplate), + cStateIndex + ); return nullptr; } size_t index{0}; @@ -301,7 +319,7 @@ PyDoc_STRVAR( auto PyLogEvent_match_query(PyLogEvent* self, PyObject* query) -> PyObject* { if (false == static_cast(PyObject_TypeCheck(query, PyQuery::get_py_type()))) { - PyErr_SetString(PyExc_TypeError, cPyTypeError); + PyErr_SetString(PyExc_TypeError, get_c_str_from_constexpr_string_view(cPyTypeError)); return nullptr; } auto* py_query{py_reinterpret_cast(query)}; @@ -478,7 +496,10 @@ auto PyLogEvent::init( // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) m_log_event = new LogEvent(log_message, timestamp, index, formatted_timestamp); if (nullptr == m_log_event) { - PyErr_SetString(PyExc_RuntimeError, clp_ffi_py::cOutofMemoryError); + PyErr_SetString( + PyExc_RuntimeError, + get_c_str_from_constexpr_string_view(clp_ffi_py::cOutOfMemoryError) + ); return false; } set_metadata(metadata); @@ -510,7 +531,6 @@ auto PyLogEvent::create_new_log_event( // NOLINTNEXTLINE(cppcoreguidelines-pro-type-cstyle-cast) PyLogEvent* self{PyObject_New(PyLogEvent, get_py_type())}; if (nullptr == self) { - PyErr_SetString(PyExc_MemoryError, clp_ffi_py::cOutofMemoryError); return nullptr; } self->default_init(); diff --git a/src/clp_ffi_py/ir/native/PyMetadata.cpp b/src/clp_ffi_py/ir/native/PyMetadata.cpp index 1b540c1c..ff6a1e10 100644 --- a/src/clp_ffi_py/ir/native/PyMetadata.cpp +++ b/src/clp_ffi_py/ir/native/PyMetadata.cpp @@ -139,7 +139,10 @@ PyDoc_STRVAR( auto PyMetadata_get_timezone(PyMetadata* self) -> PyObject* { auto* timezone{self->get_py_timezone()}; if (nullptr == timezone) { - PyErr_SetString(PyExc_RuntimeError, clp_ffi_py::cTimezoneObjectNotInitialzed); + PyErr_SetString( + PyExc_RuntimeError, + get_c_str_from_constexpr_string_view(clp_ffi_py::cTimezoneObjectNotInitialized) + ); return nullptr; } Py_INCREF(timezone); @@ -227,7 +230,10 @@ auto PyMetadata::init( // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) m_metadata = new Metadata(ref_timestamp, input_timestamp_format, input_timezone); if (nullptr == m_metadata) { - PyErr_SetString(PyExc_RuntimeError, clp_ffi_py::cOutofMemoryError); + PyErr_SetString( + PyExc_RuntimeError, + get_c_str_from_constexpr_string_view(clp_ffi_py::cOutOfMemoryError) + ); return false; } return init_py_timezone(); @@ -243,7 +249,10 @@ auto PyMetadata::init(nlohmann::json const& metadata, bool is_four_byte_encoding return false; } if (nullptr == m_metadata) { - PyErr_SetString(PyExc_RuntimeError, clp_ffi_py::cOutofMemoryError); + PyErr_SetString( + PyExc_RuntimeError, + get_c_str_from_constexpr_string_view(clp_ffi_py::cOutOfMemoryError) + ); return false; } return init_py_timezone(); diff --git a/src/clp_ffi_py/ir/native/PyQuery.cpp b/src/clp_ffi_py/ir/native/PyQuery.cpp index 93e6eacf..9ea0d63d 100644 --- a/src/clp_ffi_py/ir/native/PyQuery.cpp +++ b/src/clp_ffi_py/ir/native/PyQuery.cpp @@ -35,7 +35,10 @@ auto deserialize_wildcard_queries( } if (false == static_cast(PyObject_TypeCheck(py_wildcard_queries, &PyList_Type))) { - PyErr_SetString(PyExc_TypeError, clp_ffi_py::cPyTypeError); + PyErr_SetString( + PyExc_TypeError, + get_c_str_from_constexpr_string_view(clp_ffi_py::cPyTypeError) + ); return false; } @@ -44,7 +47,10 @@ auto deserialize_wildcard_queries( for (Py_ssize_t idx{0}; idx < wildcard_queries_size; ++idx) { auto* wildcard_query{PyList_GetItem(py_wildcard_queries, idx)}; if (1 != PyObject_IsInstance(wildcard_query, PyQuery::get_py_wildcard_query_type())) { - PyErr_SetString(PyExc_TypeError, clp_ffi_py::cPyTypeError); + PyErr_SetString( + PyExc_TypeError, + get_c_str_from_constexpr_string_view(clp_ffi_py::cPyTypeError) + ); return false; } auto* wildcard_query_py_str{PyObject_GetAttrString(wildcard_query, "wildcard_query")}; @@ -275,7 +281,10 @@ auto PyQuery_setstate(PyQuery* self, PyObject* state) -> PyObject* { self->default_init(); if (false == static_cast(PyDict_CheckExact(state))) { - PyErr_SetString(PyExc_ValueError, clp_ffi_py::cSetstateInputError); + PyErr_SetString( + PyExc_ValueError, + get_c_str_from_constexpr_string_view(clp_ffi_py::cSetstateInputError) + ); return nullptr; } @@ -283,7 +292,7 @@ auto PyQuery_setstate(PyQuery* self, PyObject* state) -> PyObject* { if (nullptr == search_time_lower_bound_obj) { PyErr_Format( PyExc_KeyError, - clp_ffi_py::cSetstateKeyErrorTemplate, + get_c_str_from_constexpr_string_view(clp_ffi_py::cSetstateKeyErrorTemplate), cStateSearchTimeLowerBound ); return nullptr; @@ -302,7 +311,7 @@ auto PyQuery_setstate(PyQuery* self, PyObject* state) -> PyObject* { if (nullptr == search_time_upper_bound_obj) { PyErr_Format( PyExc_KeyError, - clp_ffi_py::cSetstateKeyErrorTemplate, + get_c_str_from_constexpr_string_view(clp_ffi_py::cSetstateKeyErrorTemplate), cStateSearchTimeUpperBound ); return nullptr; @@ -319,7 +328,11 @@ auto PyQuery_setstate(PyQuery* self, PyObject* state) -> PyObject* { auto* py_wildcard_queries{PyDict_GetItemString(state, cStateWildcardQueries)}; if (nullptr == py_wildcard_queries) { - PyErr_Format(PyExc_KeyError, clp_ffi_py::cSetstateKeyErrorTemplate, cStateWildcardQueries); + PyErr_Format( + PyExc_KeyError, + get_c_str_from_constexpr_string_view(clp_ffi_py::cSetstateKeyErrorTemplate), + cStateWildcardQueries + ); return nullptr; } std::vector wildcard_queries; @@ -333,7 +346,7 @@ auto PyQuery_setstate(PyQuery* self, PyObject* state) -> PyObject* { if (nullptr == search_time_termination_margin_obj) { PyErr_Format( PyExc_KeyError, - clp_ffi_py::cSetstateKeyErrorTemplate, + get_c_str_from_constexpr_string_view(clp_ffi_py::cSetstateKeyErrorTemplate), cStateSearchTimeTerminationMargin ); return nullptr; @@ -377,7 +390,7 @@ PyDoc_STRVAR( auto PyQuery_match_log_event(PyQuery* self, PyObject* log_event) -> PyObject* { if (false == static_cast(PyObject_TypeCheck(log_event, PyLogEvent::get_py_type()))) { - PyErr_SetString(PyExc_TypeError, cPyTypeError); + PyErr_SetString(PyExc_TypeError, get_c_str_from_constexpr_string_view(cPyTypeError)); return nullptr; } auto* py_log_event{py_reinterpret_cast(log_event)}; @@ -620,15 +633,18 @@ auto PyQuery::init( wildcard_queries, search_time_termination_margin ); + if (nullptr == m_query) { + PyErr_SetString( + PyExc_RuntimeError, + get_c_str_from_constexpr_string_view(clp_ffi_py::cOutOfMemoryError) + ); + return false; + } } catch (clp_ffi_py::ExceptionFFI& ex) { handle_traceable_exception(ex); m_query = nullptr; return false; } - if (nullptr == m_query) { - PyErr_SetString(PyExc_RuntimeError, clp_ffi_py::cOutofMemoryError); - return false; - } return true; } diff --git a/src/clp_ffi_py/ir/native/PySerializer.cpp b/src/clp_ffi_py/ir/native/PySerializer.cpp index 7d3c15e0..4afedf6e 100644 --- a/src/clp_ffi_py/ir/native/PySerializer.cpp +++ b/src/clp_ffi_py/ir/native/PySerializer.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -403,7 +404,10 @@ auto PySerializer::init( m_serializer = new PySerializer::ClpIrSerializer{std::move(serializer)}; m_buffer_size_limit = buffer_size_limit; if (nullptr == m_serializer) { - PyErr_SetString(PyExc_RuntimeError, clp_ffi_py::cOutofMemoryError); + PyErr_SetString( + PyExc_RuntimeError, + get_c_str_from_constexpr_string_view(clp_ffi_py::cOutOfMemoryError) + ); return false; } auto const preamble_size{get_ir_buf_size()}; diff --git a/src/clp_ffi_py/ir/native/deserialization_methods.cpp b/src/clp_ffi_py/ir/native/deserialization_methods.cpp index 09b1138a..99da0ad9 100644 --- a/src/clp_ffi_py/ir/native/deserialization_methods.cpp +++ b/src/clp_ffi_py/ir/native/deserialization_methods.cpp @@ -184,7 +184,7 @@ auto deserialize_preamble(PyObject* Py_UNUSED(self), PyObject* py_deserializer_b PyObject_TypeCheck(py_deserializer_buffer, PyDeserializerBuffer::get_py_type()) )) { - PyErr_SetString(PyExc_TypeError, cPyTypeError); + PyErr_SetString(PyExc_TypeError, get_c_str_from_constexpr_string_view(cPyTypeError)); return nullptr; } @@ -329,7 +329,7 @@ auto deserialize_next_log_event(PyObject* Py_UNUSED(self), PyObject* args, PyObj if (is_query_given && false == static_cast(PyObject_TypeCheck(query_obj, PyQuery::get_py_type()))) { - PyErr_SetString(PyExc_TypeError, cPyTypeError); + PyErr_SetString(PyExc_TypeError, get_c_str_from_constexpr_string_view(cPyTypeError)); return nullptr; } diff --git a/src/clp_ffi_py/utils.hpp b/src/clp_ffi_py/utils.hpp index 5d99a917..bde772ca 100644 --- a/src/clp_ffi_py/utils.hpp +++ b/src/clp_ffi_py/utils.hpp @@ -95,9 +95,7 @@ template * @return The underlying C-string of the given constexpr string view. */ [[nodiscard]] consteval auto get_c_str_from_constexpr_string_view(std::string_view const& sv -) -> char const* { - return sv.data(); -} +) -> char const*; template auto parse_py_int(PyObject* py_int, IntType& val) -> bool { @@ -132,6 +130,10 @@ auto parse_py_int(PyObject* py_int, IntType& val) -> bool { return (nullptr == PyErr_Occurred()); } + +consteval auto get_c_str_from_constexpr_string_view(std::string_view const& sv) -> char const* { + return sv.data(); +} } // namespace clp_ffi_py #endif // CLP_FFI_PY_UTILS_HPP