File 0001-Make-protobuf-python_api-fully-optional.patch of Package failed_pybind11_protobuf
From 019038ef4e9d4bcf9eb137a4ac20fc9a5cd30f64 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20Br=C3=BCns?= <stefan.bruens@rwth-aachen.de>
Date: Sun, 16 Jun 2024 18:11:52 +0200
Subject: [PATCH 1/6] Make protobuf python_api fully optional
In case `PYBIND11_PROTOBUF_ENABLE_PYPROTO_API` is not defined, the
py_proto_api_ member of the GlobalState singleton is never changed from
its default nullptr value.
Any code protected by a `GlobalState::instance()->py_proto_api()` check
can thus also be made dependent on the `PYPROTO_API` define. This allows
to remove the dependency on the proto_api.h header file.
As the call to check_unknown_fields::CheckRecursively is also protected
by the `py_proto_api()` it can be stubbed out.
See #127.
---
pybind11_protobuf/check_unknown_fields.cc | 4 ++++
pybind11_protobuf/check_unknown_fields.h | 7 ++++++-
pybind11_protobuf/proto_cast_util.cc | 18 +++++++++++++++++-
3 files changed, 27 insertions(+), 2 deletions(-)
diff --git a/pybind11_protobuf/check_unknown_fields.cc b/pybind11_protobuf/check_unknown_fields.cc
index bb67d69..c2b0b87 100644
--- a/pybind11_protobuf/check_unknown_fields.cc
+++ b/pybind11_protobuf/check_unknown_fields.cc
@@ -34,6 +34,7 @@ std::string MakeAllowListKey(
return absl::StrCat(top_message_descriptor_full_name, ":",
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`.
@@ -173,6 +174,7 @@ std::string HasUnknownFields::BuildErrorMessage() const {
return emsg;
}
+#endif
} // namespace
void AllowUnknownFieldsFor(absl::string_view top_message_descriptor_full_name,
@@ -181,6 +183,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<std::string> CheckRecursively(
const ::google::protobuf::python::PyProto_API* py_proto_api,
const ::google::protobuf::Message* message, bool build_error_message_if_any) {
@@ -198,5 +201,6 @@ std::optional<std::string> CheckRecursively(
}
return search.BuildErrorMessage();
}
+#endif
} // namespace pybind11_protobuf::check_unknown_fields
diff --git a/pybind11_protobuf/check_unknown_fields.h b/pybind11_protobuf/check_unknown_fields.h
index e37adc7..00375af 100644
--- a/pybind11_protobuf/check_unknown_fields.h
+++ b/pybind11_protobuf/check_unknown_fields.h
@@ -3,9 +3,12 @@
#include <optional>
+#include "absl/strings/string_view.h"
#include "google/protobuf/message.h"
+
+#if defined(PYBIND11_PROTOBUF_ENABLE_PYPROTO_API)
#include "python/google/protobuf/proto_api.h"
-#include "absl/strings/string_view.h"
+#endif // PYBIND11_PROTOBUF_ENABLE_PYPROTO_API
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<std::string> CheckRecursively(
const ::google::protobuf::python::PyProto_API* py_proto_api,
const ::google::protobuf::Message* top_message, bool build_error_message_if_any);
+#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 0f7ba29..a734222 100644
--- a/pybind11_protobuf/proto_cast_util.cc
+++ b/pybind11_protobuf/proto_cast_util.cc
@@ -23,7 +23,13 @@
#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"
+#else
+namespace google::protobuf::python {
+struct PyProto_API;
+}
+#endif
#include "pybind11_protobuf/check_unknown_fields.h"
#if defined(GOOGLE_PROTOBUF_VERSION)
@@ -42,7 +48,6 @@ 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 {
namespace {
@@ -254,6 +259,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<PyProto_API*>(PyCapsule_Import(PyProtoAPICapsuleName(), 0));
if (py_proto_api_ == nullptr) {
@@ -342,6 +348,7 @@ py::object GlobalState::PyMessageInstance(const Descriptor* descriptor) {
module_name + "?");
}
+#if defined(PYBIND11_PROTOBUF_ENABLE_PYPROTO_API)
std::pair<py::object, Message*> GlobalState::PyFastCppProtoMessageInstance(
const Descriptor* descriptor) {
assert(descriptor != nullptr);
@@ -382,6 +389,7 @@ std::pair<py::object, Message*> 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.
@@ -521,6 +529,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<py::object>(
@@ -539,6 +548,7 @@ class PythonDescriptorPoolWrapper {
PyErr_Print();
}
}
+#endif
return output->ParsePartialFromString(
PyBytesAsStringView(py_file_descriptor.attr("serialized_pb")));
@@ -736,6 +746,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);
@@ -809,6 +820,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) {
@@ -819,6 +831,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() &&
@@ -843,6 +858,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
--
2.45.0