Commit 59827596 by Xiaofei Wang Committed by Copybara-Service

Make `type_caster<absl::StatusOr<T>>` supports loading Python instance as `absl::Status`.

PiperOrigin-RevId: 520478536
parent c6487c60
...@@ -45,9 +45,20 @@ struct type_caster<absl::StatusOr<PayloadType>> { ...@@ -45,9 +45,20 @@ struct type_caster<absl::StatusOr<PayloadType>> {
PYBIND11_TYPE_CASTER(absl::StatusOr<PayloadType>, PayloadCaster::name); PYBIND11_TYPE_CASTER(absl::StatusOr<PayloadType>, PayloadCaster::name);
bool load(handle src, bool convert) { bool load(handle src, bool convert) {
PayloadCaster base_caster; PayloadCaster payload_caster;
if (base_caster.load(src, convert)) { if (payload_caster.load(src, convert)) {
value = cast_op<PayloadType>(std::move(base_caster)); value = cast_op<PayloadType>(std::move(payload_caster));
return true;
}
StatusCaster status_caster;
if (status_caster.load(src, convert)) {
absl::Status status = cast_op<absl::Status>(std::move(status_caster));
if (status.ok()) {
throw cast_error(
"An OK status is not a valid constructor argument to StatusOr<T>.");
} else {
value = status;
}
return true; return true;
} }
return false; return false;
......
...@@ -34,6 +34,13 @@ bool CheckStatus(const absl::Status& status, absl::StatusCode code) { ...@@ -34,6 +34,13 @@ bool CheckStatus(const absl::Status& status, absl::StatusCode code) {
return status.code() == code; return status.code() == code;
} }
bool CheckStatusOr(const absl::StatusOr<int>& statusor, absl::StatusCode code) {
if (statusor.ok()) {
return true;
}
return statusor.status().code() == code;
}
absl::Status ReturnStatus(absl::StatusCode code, const std::string& text = "") { absl::Status ReturnStatus(absl::StatusCode code, const std::string& text = "") {
return absl::Status(code, text); return absl::Status(code, text);
} }
...@@ -151,6 +158,7 @@ PYBIND11_MODULE(status_example, m) { ...@@ -151,6 +158,7 @@ PYBIND11_MODULE(status_example, m) {
// absl::Status bindings // absl::Status bindings
m.def("check_status", &CheckStatus, arg("status"), arg("code")); m.def("check_status", &CheckStatus, arg("status"), arg("code"));
m.def("check_statusor", &CheckStatusOr, arg("statusor"), arg("code"));
m.def("return_status", &ReturnStatus, "Raise an error if code is not OK.", m.def("return_status", &ReturnStatus, "Raise an error if code is not OK.",
arg("code"), arg("text") = ""); arg("code"), arg("text") = "");
m.def("make_status", google::DoNotThrowStatus(&ReturnStatus), m.def("make_status", google::DoNotThrowStatus(&ReturnStatus),
......
...@@ -43,6 +43,22 @@ class StatusTest(parameterized.TestCase): ...@@ -43,6 +43,22 @@ class StatusTest(parameterized.TestCase):
self.assertTrue( self.assertTrue(
status_example.check_status(test_status, status.StatusCode.CANCELLED)) status_example.check_status(test_status, status.StatusCode.CANCELLED))
def test_pass_statusor(self):
test_status = status.Status(status.StatusCode.CANCELLED, 'test')
self.assertTrue(
status_example.check_statusor(test_status, status.StatusCode.CANCELLED))
test_status = status.Status(status.StatusCode.OK, 'test')
with self.assertRaises(RuntimeError) as ctx:
status_example.check_statusor(test_status, status.StatusCode.CANCELLED)
self.assertEqual(
str(ctx.exception),
'An OK status is not a valid constructor argument to StatusOr<T>.')
with self.assertRaises(RuntimeError) as ctx:
status_example.check_statusor(None, status.StatusCode.CANCELLED)
self.assertEqual(
str(ctx.exception),
'An OK status is not a valid constructor argument to StatusOr<T>.')
def test_return_status_return_type_from_doc(self): def test_return_status_return_type_from_doc(self):
self.assertEndsWith( self.assertEndsWith(
docstring_signature(status_example.return_status), ' -> None') docstring_signature(status_example.return_status), ' -> None')
......
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