From 13a107533eacceb42de5c974616d0fb99804af8d Mon Sep 17 00:00:00 2001 From: Stefan Bruens Date: Mon, 17 Jun 2024 19:57:49 -0700 Subject: [PATCH] Import https://github.com/pybind/pybind11_protobuf/pull/161 Manual import. The Google-internal repo is the source of truth for pybind11_protobuf. Sorry we didn't get to automating imports from GitHub PRs. PiperOrigin-RevId: 644215761 --- CMakeLists.txt | 38 ++++++++++++------ pybind11_protobuf/check_unknown_fields.cc | 6 +++ pybind11_protobuf/check_unknown_fields.h | 5 +++ pybind11_protobuf/proto_cast_util.cc | 47 +++++++---------------- 4 files changed, 50 insertions(+), 46 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 46388d1..02a773e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,6 +17,7 @@ set(CMAKE_POSITION_INDEPENDENT_CODE ON) # Options option(BUILD_TESTS "Build tests." OFF) +option(ENABLE_PYPROTO_API "Enable usage of proto_api." OFF) # ============================================================================ # Find Python @@ -60,7 +61,7 @@ target_include_directories( # ============================================================================ # pybind11_native_proto_caster shared library add_library( - pybind11_native_proto_caster SHARED + pybind11_native_proto_caster STATIC # bazel: pybind_library: native_proto_caster pybind11_protobuf/native_proto_caster.h # bazel: pybind_library: enum_type_caster @@ -68,10 +69,18 @@ add_library( # bazel: pybind_library: proto_cast_util pybind11_protobuf/proto_cast_util.cc pybind11_protobuf/proto_cast_util.h - pybind11_protobuf/proto_caster_impl.h + pybind11_protobuf/proto_caster_impl.h) + +target_sources( # bazel: cc_library::check_unknown_fields - pybind11_protobuf/check_unknown_fields.cc - pybind11_protobuf/check_unknown_fields.h) + pybind11_native_proto_caster # + PRIVATE pybind11_protobuf/check_unknown_fields.cc + pybind11_protobuf/check_unknown_fields.h) + +if(ENABLE_PYPROTO_API) + target_compile_definitions(pybind11_native_proto_caster + PRIVATE PYBIND11_PROTOBUF_ENABLE_PYPROTO_API) +endif() target_link_libraries( pybind11_native_proto_caster @@ -92,16 +101,24 @@ target_include_directories( # ============================================================================ # pybind11_wrapped_proto_caster shared library add_library( - pybind11_wrapped_proto_caster SHARED + pybind11_wrapped_proto_caster STATIC # bazel: pybind_library: wrapped_proto_caster pybind11_protobuf/wrapped_proto_caster.h # bazel: pybind_library: proto_cast_util pybind11_protobuf/proto_cast_util.cc pybind11_protobuf/proto_cast_util.h - pybind11_protobuf/proto_caster_impl.h - # bazel: cc_library: check_unknown_fields - pybind11_protobuf/check_unknown_fields.cc - pybind11_protobuf/check_unknown_fields.h) + pybind11_protobuf/proto_caster_impl.h) + +target_sources( + # bazel: cc_library::check_unknown_fields + pybind11_wrapped_proto_caster + PRIVATE pybind11_protobuf/check_unknown_fields.cc + pybind11_protobuf/check_unknown_fields.h) + +if(ENABLE_PYPROTO_API) + target_compile_definitions(pybind11_wrapped_proto_caster + PRIVATE PYBIND11_PROTOBUF_ENABLE_PYPROTO_API) +endif() target_link_libraries( pybind11_wrapped_proto_caster @@ -119,9 +136,6 @@ target_include_directories( PRIVATE ${PROJECT_SOURCE_DIR} ${protobuf_INCLUDE_DIRS} ${protobuf_SOURCE_DIR} ${pybind11_INCLUDE_DIRS}) -# TODO set defines PYBIND11_PROTOBUF_ENABLE_PYPROTO_API see: bazel: -# pybind_library: proto_cast_util - # bazel equivs. checklist # # bazel: pybind_library: enum_type_caster - enum_type_caster.h diff --git a/pybind11_protobuf/check_unknown_fields.cc b/pybind11_protobuf/check_unknown_fields.cc index 0639d09..5f1a808 100644 --- a/pybind11_protobuf/check_unknown_fields.cc +++ b/pybind11_protobuf/check_unknown_fields.cc @@ -35,6 +35,8 @@ std::string MakeAllowListKey( unknown_field_parent_message_fqn); } +#if defined(PYBIND11_PROTOBUF_ENABLE_PYPROTO_API) + /// Recurses through the message Descriptor class looking for valid extensions. /// Stores the result to `memoized`. bool MessageMayContainExtensionsRecursive(const ::google::protobuf::Descriptor* descriptor, @@ -173,6 +175,8 @@ std::string HasUnknownFields::BuildErrorMessage() const { return emsg; } +#endif + } // namespace void AllowUnknownFieldsFor(absl::string_view top_message_descriptor_full_name, @@ -181,6 +185,7 @@ void AllowUnknownFieldsFor(absl::string_view top_message_descriptor_full_name, unknown_field_parent_message_fqn)); } +#if defined(PYBIND11_PROTOBUF_ENABLE_PYPROTO_API) std::optional CheckRecursively( const ::google::protobuf::python::PyProto_API* py_proto_api, const ::google::protobuf::Message* message) { @@ -195,5 +200,6 @@ std::optional CheckRecursively( } return search.BuildErrorMessage(); } +#endif // PYBIND11_PROTOBUF_ENABLE_PYPROTO_API } // namespace pybind11_protobuf::check_unknown_fields diff --git a/pybind11_protobuf/check_unknown_fields.h b/pybind11_protobuf/check_unknown_fields.h index 79ac001..ffd0e6f 100644 --- a/pybind11_protobuf/check_unknown_fields.h +++ b/pybind11_protobuf/check_unknown_fields.h @@ -4,7 +4,10 @@ #include #include "google/protobuf/message.h" +#if defined(PYBIND11_PROTOBUF_ENABLE_PYPROTO_API) #include "python/google/protobuf/proto_api.h" +#endif // PYBIND11_PROTOBUF_ENABLE_PYPROTO_API + #include "absl/strings/string_view.h" namespace pybind11_protobuf::check_unknown_fields { @@ -45,9 +48,11 @@ class ExtensionsWithUnknownFieldsPolicy { void AllowUnknownFieldsFor(absl::string_view top_message_descriptor_full_name, absl::string_view unknown_field_parent_message_fqn); +#if defined(PYBIND11_PROTOBUF_ENABLE_PYPROTO_API) std::optional CheckRecursively( const ::google::protobuf::python::PyProto_API* py_proto_api, const ::google::protobuf::Message* top_message); +#endif // PYBIND11_PROTOBUF_ENABLE_PYPROTO_API } // namespace pybind11_protobuf::check_unknown_fields diff --git a/pybind11_protobuf/proto_cast_util.cc b/pybind11_protobuf/proto_cast_util.cc index 223b011..c317a27 100644 --- a/pybind11_protobuf/proto_cast_util.cc +++ b/pybind11_protobuf/proto_cast_util.cc @@ -27,41 +27,9 @@ #include "google/protobuf/descriptor.h" #include "google/protobuf/descriptor_database.h" #include "google/protobuf/dynamic_message.h" +#if defined(PYBIND11_PROTOBUF_ENABLE_PYPROTO_API) #include "python/google/protobuf/proto_api.h" -#include "pybind11_protobuf/check_unknown_fields.h" - -#if defined(GOOGLE_PROTOBUF_VERSION) -#include "absl/strings/numbers.h" -#include "absl/strings/str_split.h" -#endif - -namespace py = pybind11; - -using ::google::protobuf::Descriptor; -using ::google::protobuf::DescriptorDatabase; -using ::google::protobuf::DescriptorPool; -using ::google::protobuf::DynamicMessageFactory; -using ::google::protobuf::FileDescriptor; -using ::google::protobuf::FileDescriptorProto; -using ::google::protobuf::Message; -using ::google::protobuf::MessageFactory; -using ::google::protobuf::python::PyProto_API; -using ::google::protobuf::python::PyProtoAPICapsuleName; - -namespace pybind11_protobuf { - -std::string StripProtoSuffixFromDescriptorFileName(absl::string_view filename) { - if (absl::EndsWith(filename, ".protodevel")) { - return std::string(absl::StripSuffix(filename, ".protodevel")); - } else { - return std::string(absl::StripSuffix(filename, ".proto")); - } -} - -std::string InferPythonModuleNameFromDescriptorFileName( - absl::string_view filename) { - std::string basename = StripProtoSuffixFromDescriptorFileName(filename); - absl::StrReplaceAll({{"-", "_"}, {"/", "."}}, &basename); +#else return absl::StrCat(basename, "_pb2"); } @@ -266,6 +234,7 @@ GlobalState::GlobalState() { // // By default (3) is used, however if the define is set *and* the version // matches, then pybind11_protobuf will assume that this will work. + using ::google::protobuf::python::PyProtoAPICapsuleName; py_proto_api_ = static_cast(PyCapsule_Import(PyProtoAPICapsuleName(), 0)); if (py_proto_api_ == nullptr) { @@ -355,6 +324,7 @@ py::object GlobalState::PyMessageInstance(const Descriptor* descriptor) { module_name + "?"); } +#if defined(PYBIND11_PROTOBUF_ENABLE_PYPROTO_API) std::pair GlobalState::PyFastCppProtoMessageInstance( const Descriptor* descriptor) { assert(descriptor != nullptr); @@ -395,6 +365,7 @@ std::pair GlobalState::PyFastCppProtoMessageInstance( } return {std::move(result), message}; } +#endif // Create C++ DescriptorPools based on Python DescriptorPools. // The Python pool will provide message definitions when they are needed. @@ -534,6 +505,7 @@ class PythonDescriptorPoolWrapper { private: bool CopyToFileDescriptorProto(py::handle py_file_descriptor, FileDescriptorProto* output) { +#if defined(PYBIND11_PROTOBUF_ENABLE_PYPROTO_API) if (GlobalState::instance()->py_proto_api()) { try { py::object c_proto = py::reinterpret_steal( @@ -552,6 +524,7 @@ class PythonDescriptorPoolWrapper { PyErr_Print(); } } +#endif return output->ParsePartialFromString( PyBytesAsStringView(py_file_descriptor.attr("serialized_pb"))); @@ -750,6 +723,7 @@ py::handle GenericPyProtoCast(Message* src, py::return_value_policy policy, return py_proto.release(); } +#if defined(PYBIND11_PROTOBUF_ENABLE_PYPROTO_API) py::handle GenericFastCppProtoCast(Message* src, py::return_value_policy policy, py::handle parent, bool is_const) { assert(policy != pybind11::return_value_policy::automatic); @@ -823,6 +797,7 @@ py::handle GenericFastCppProtoCast(Message* src, py::return_value_policy policy, throw py::cast_error(message + ReturnValuePolicyName(policy)); } } +#endif py::handle GenericProtoCast(Message* src, py::return_value_policy policy, py::handle parent, bool is_const) { @@ -833,6 +808,9 @@ py::handle GenericProtoCast(Message* src, py::return_value_policy policy, // 1. The binary does not have a py_proto_api instance, or // 2. a) the proto is from the default pool and // b) the binary is not using fast_cpp_protos. +#if !defined(PYBIND11_PROTOBUF_ENABLE_PYPROTO_API) + return GenericPyProtoCast(src, policy, parent, is_const); +#else if (GlobalState::instance()->py_proto_api() == nullptr || (src->GetDescriptor()->file()->pool() == DescriptorPool::generated_pool() && @@ -861,6 +839,7 @@ py::handle GenericProtoCast(Message* src, py::return_value_policy policy, // construct a mapping between C++ pool() and python pool(), and then // use the PyProto_API to make it work. return GenericFastCppProtoCast(src, policy, parent, is_const); +#endif } } // namespace pybind11_protobuf