Commit c4365058 by Ralf W. Grosse-Kunstleve Committed by Copybara-Service

Add `pybind11_abseil.ok_status_singleton` extension.

This change supports the PyCLIF-pybind11 integration.

PiperOrigin-RevId: 491973864
parent 3922b386
......@@ -25,6 +25,37 @@ pybind_library(
)
cc_library(
name = "ok_status_singleton_lib",
srcs = ["ok_status_singleton_lib.cc"],
hdrs = ["ok_status_singleton_lib.h"],
visibility = ["//visibility:public"],
deps = [
"@com_google_absl//absl/status",
"@local_config_python//:python_headers", # buildcleaner: keep
],
)
cc_library(
name = "ok_status_singleton_pyinit_google3",
srcs = ["ok_status_singleton_pyinit_google3.cc"],
visibility = ["//visibility:private"],
deps = [
":ok_status_singleton_lib",
"@local_config_python//:python_headers", # buildcleaner: keep
],
)
cc_binary(
name = "ok_status_singleton.so",
srcs = ["ok_status_singleton_pyinit_relative.cc"],
linkshared = 1,
deps = [
":ok_status_singleton_pyinit_google3",
"@local_config_python//:python_headers", # buildcleaner: keep
],
)
cc_library(
name = "no_throw_status",
hdrs = ["no_throw_status.h"],
)
......@@ -107,6 +138,7 @@ pybind_library(
":absl_casters",
":init_from_tag",
":no_throw_status",
":ok_status_singleton_lib",
":raw_ptr_from_capsule",
":status_caster",
":status_not_ok_exception",
......
#include "pybind11_abseil/ok_status_singleton_lib.h"
#include <Python.h>
#include "absl/status/status.h"
namespace pybind11_abseil {
const absl::Status* OkStatusSingleton() {
static const absl::Status* singleton = new absl::Status();
return singleton;
}
PyObject* PyOkStatusSingleton() {
static bool first_call = true;
static PyObject* py_singleton = nullptr;
if (first_call) {
PyObject* imported_mod =
PyImport_ImportModule("pybind11_abseil.status");
if (imported_mod == nullptr) {
PyErr_Clear();
py_singleton =
PyCapsule_New(const_cast<absl::Status*>(OkStatusSingleton()),
"::absl::Status", nullptr);
first_call = false;
if (py_singleton == nullptr) {
return nullptr;
}
} else {
PyObject* make_fn =
PyObject_GetAttrString(imported_mod, "_make_py_ok_status_singleton");
Py_DECREF(imported_mod);
if (make_fn == nullptr) {
first_call = false;
return nullptr;
}
PyObject* call_result = PyObject_CallObject(make_fn, nullptr);
Py_DECREF(make_fn);
if (call_result == nullptr) {
first_call = false;
return nullptr;
}
assert(call_result != Py_None);
py_singleton = call_result;
}
first_call = false;
}
if (py_singleton == nullptr) {
PyErr_SetString(PyExc_SystemError,
"FAILED: pybind11_abseil::PyOkStatusSingleton()");
return nullptr;
}
Py_INCREF(py_singleton);
return py_singleton;
}
} // namespace pybind11_abseil
#ifndef PYBIND11_ABSEIL_OK_STATUS_SINGLETON_LIB_H_
#define PYBIND11_ABSEIL_OK_STATUS_SINGLETON_LIB_H_
#include <Python.h>
#include "absl/status/status.h"
namespace pybind11_abseil {
const absl::Status* OkStatusSingleton();
PyObject* PyOkStatusSingleton();
} // namespace pybind11_abseil
#endif // PYBIND11_ABSEIL_OK_STATUS_SINGLETON_LIB_H_
#include <Python.h>
#include "pybind11_abseil/ok_status_singleton_lib.h"
namespace {
static PyObject* wrapOkStatusSingleton(PyObject*, PyObject*) {
return pybind11_abseil::PyOkStatusSingleton();
}
static PyMethodDef ThisMethodDef[] = {
{"OkStatusSingleton", wrapOkStatusSingleton, METH_NOARGS,
"OkStatusSingleton() -> capsule"},
{}};
static struct PyModuleDef ThisModuleDef = {
PyModuleDef_HEAD_INIT, // m_base
"ok_status_singleton", // m_name
nullptr, // m_doc
-1, // m_size
ThisMethodDef, // m_methods
nullptr, // m_slots
nullptr, // m_traverse
nullptr, // m_clear
nullptr // m_free
};
} // namespace
extern "C" PyObject*
GooglePyInit_google3_third__party_pybind11__abseil_ok__status__singleton() {
return PyModule_Create(&ThisModuleDef);
}
#include <Python.h>
extern "C" PyObject*
GooglePyInit_google3_third__party_pybind11__abseil_ok__status__singleton();
// Required only for OSS, but also compatible with the Google toolchain.
#if defined(WIN32) || defined(_WIN32)
#define LOCALDEFINE_DLLEXPORT __declspec(dllexport)
#else
#define LOCALDEFINE_DLLEXPORT __attribute__((visibility("default")))
#endif
extern "C" LOCALDEFINE_DLLEXPORT PyObject* PyInit_ok_status_singleton() {
// NOLINTNEXTLINE(whitespace/line_length)
return GooglePyInit_google3_third__party_pybind11__abseil_ok__status__singleton();
}
......@@ -16,6 +16,7 @@
#include "pybind11_abseil/absl_casters.h"
#include "pybind11_abseil/init_from_tag.h"
#include "pybind11_abseil/no_throw_status.h"
#include "pybind11_abseil/ok_status_singleton_lib.h"
#include "pybind11_abseil/raw_ptr_from_capsule.h"
#include "pybind11_abseil/status_caster.h"
#include "pybind11_abseil/status_not_ok_exception.h"
......@@ -278,7 +279,14 @@ void RegisterStatusBindings(module m) {
return decode_utf8_replace(
absl::StrCat(s.message(), " [", code_str, "]"));
})
.def_static("OkStatus", DoNotThrowStatus(&absl::OkStatus))
.def_static("OkStatus",
[]() {
handle py_singleton(pybind11_abseil::PyOkStatusSingleton());
if (!py_singleton) {
throw error_already_set();
}
return py_singleton;
})
.def("raw_code", &absl::Status::raw_code)
.def("CanonicalCode",
[](const absl::Status& self) {
......@@ -441,6 +449,12 @@ void RegisterStatusBindings(module m) {
return PyStatusNotOkTypeInUse()(
google::NoThrowStatus<absl::Status>(absl::Status(code, msg)));
});
m.def("_make_py_ok_status_singleton", []() {
return detail::type_caster_base<absl::Status>::cast(
pybind11_abseil::OkStatusSingleton(), return_value_policy::reference,
handle{});
});
}
} // namespace internal
......
......@@ -27,6 +27,14 @@ py_test(
srcs_version = "PY3",
)
py_test(
name = "ok_status_singleton_test",
srcs = ["ok_status_singleton_test.py"],
data = ["//pybind11_abseil:ok_status_singleton.so"],
python_version = "PY3",
srcs_version = "PY3",
)
pybind_extension(
name = "missing_import",
srcs = ["missing_import.cc"],
......
# Copyright (c) 2019-2022 The Pybind Development Team. All rights reserved.
#
# All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE file.
from absl.testing import absltest
from pybind11_abseil import ok_status_singleton
class OkStatusSingletonTest(absltest.TestCase):
def test_singleton(self):
cap = ok_status_singleton.OkStatusSingleton()
self.assertStartsWith(repr(cap), '<capsule object "::absl::Status" at 0x')
if __name__ == '__main__':
absltest.main()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment