Commit e336d492 by Xiaofei Wang Committed by Copybara-Service

Make pybind11 support converting `absl::InfiniteDuration` to Python object.

PiperOrigin-RevId: 524369017
parent 429ae15d
...@@ -133,9 +133,14 @@ struct type_caster<absl::Duration> { ...@@ -133,9 +133,14 @@ struct type_caster<absl::Duration> {
!hasattr(src, "microseconds")) { !hasattr(src, "microseconds")) {
return false; return false;
} }
value = absl::Hours(24 * GetInt64Attr(src, "days")) + auto py_duration_t = module::import("datetime").attr("timedelta");
absl::Seconds(GetInt64Attr(src, "seconds")) + if (src == object(py_duration_t.attr("max"))) {
absl::Microseconds(GetInt64Attr(src, "microseconds")); value = absl::InfiniteDuration();
} else {
value = absl::Hours(24 * GetInt64Attr(src, "days")) +
absl::Seconds(GetInt64Attr(src, "seconds")) +
absl::Microseconds(GetInt64Attr(src, "microseconds"));
}
return true; return true;
} }
return false; return false;
...@@ -144,9 +149,13 @@ struct type_caster<absl::Duration> { ...@@ -144,9 +149,13 @@ struct type_caster<absl::Duration> {
// Conversion part 2 (C++ -> Python) // Conversion part 2 (C++ -> Python)
static handle cast(const absl::Duration& src, return_value_policy, handle) { static handle cast(const absl::Duration& src, return_value_policy, handle) {
absl::Duration remainder; absl::Duration remainder;
auto py_duration_t = module::import("datetime").attr("timedelta");
if (src == absl::InfiniteDuration()) {
auto py_duration = object(py_duration_t.attr("max"));
return py_duration.release();
}
int64_t secs = absl::IDivDuration(src, absl::Seconds(1), &remainder); int64_t secs = absl::IDivDuration(src, absl::Seconds(1), &remainder);
int64_t microsecs = absl::ToInt64Microseconds(remainder); int64_t microsecs = absl::ToInt64Microseconds(remainder);
auto py_duration_t = module::import("datetime").attr("timedelta");
auto py_duration = auto py_duration =
py_duration_t(arg("seconds") = secs, arg("microseconds") = microsecs); py_duration_t(arg("seconds") = secs, arg("microseconds") = microsecs);
return py_duration.release(); return py_duration.release();
......
...@@ -25,6 +25,12 @@ namespace test { ...@@ -25,6 +25,12 @@ namespace test {
absl::Duration MakeDuration(double secs) { return absl::Seconds(secs); } absl::Duration MakeDuration(double secs) { return absl::Seconds(secs); }
absl::Duration MakeInfiniteDuration() { return absl::InfiniteDuration(); }
bool IsInfiniteDuration(const absl::Duration& duration) {
return duration == absl::InfiniteDuration();
}
bool CheckDuration(const absl::Duration& duration, double secs) { bool CheckDuration(const absl::Duration& duration, double secs) {
return duration == MakeDuration(secs); return duration == MakeDuration(secs);
} }
...@@ -325,6 +331,8 @@ static_assert( ...@@ -325,6 +331,8 @@ static_assert(
PYBIND11_MODULE(absl_example, m) { PYBIND11_MODULE(absl_example, m) {
// absl::Time/Duration bindings. // absl::Time/Duration bindings.
m.def("make_duration", &MakeDuration, arg("secs")); m.def("make_duration", &MakeDuration, arg("secs"));
m.def("make_infinite_duration", &MakeInfiniteDuration);
m.def("is_infinite_duration", &IsInfiniteDuration);
m.def("check_duration", &CheckDuration, arg("duration"), arg("secs")); m.def("check_duration", &CheckDuration, arg("duration"), arg("secs"));
m.def("make_datetime", &MakeTime, arg("secs")); m.def("make_datetime", &MakeTime, arg("secs"));
m.def("check_datetime", &CheckDatetime, arg("datetime"), arg("secs")); m.def("check_datetime", &CheckDatetime, arg("datetime"), arg("secs"));
......
...@@ -38,6 +38,13 @@ class AbslTimeTest(parameterized.TestCase): ...@@ -38,6 +38,13 @@ class AbslTimeTest(parameterized.TestCase):
self.assertEqual(duration.seconds, 2) self.assertEqual(duration.seconds, 2)
self.assertEqual(duration.microseconds, 5e5) self.assertEqual(duration.microseconds, 5e5)
def test_infinite_duration(self):
duration = absl_example.make_infinite_duration()
self.assertEqual(duration, datetime.timedelta.max)
self.assertFalse(
absl_example.is_infinite_duration(absl_example.make_duration(123)))
self.assertTrue(absl_example.is_infinite_duration(duration))
def test_pass_positive_duration(self): def test_pass_positive_duration(self):
duration = datetime.timedelta(seconds=self.POSITIVE_SECS) duration = datetime.timedelta(seconds=self.POSITIVE_SECS)
self.assertTrue(absl_example.check_duration(duration, self.POSITIVE_SECS)) self.assertTrue(absl_example.check_duration(duration, self.POSITIVE_SECS))
......
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