From 6a5e7e9eb4dadc9062212ffd0e91d19cd9a55e3a Mon Sep 17 00:00:00 2001 From: Flynn Date: Wed, 21 Aug 2024 10:28:33 -0400 Subject: [PATCH 1/3] Don't rely on durationpy for formatting; just do it manually. This approach is less fragile, and also allows all three implementations (Rust, Go, and Python) to work in a similar way. Signed-off-by: Flynn --- kubernetes/utils/duration.py | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/kubernetes/utils/duration.py b/kubernetes/utils/duration.py index 3f434d0812..9b1db74a82 100644 --- a/kubernetes/utils/duration.py +++ b/kubernetes/utils/duration.py @@ -11,6 +11,8 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. +from typing import List + import datetime import re @@ -147,18 +149,26 @@ def format_duration(delta: datetime.timedelta) -> str: .format(delta) ) - # Second short-circuit. + # After that, do the usual div & mod tree to take seconds and get hours, + # minutes, and seconds from it. + secs = int(delta.total_seconds()) + + output: List[str] = [] + + hours = secs // 3600 + if hours > 0: + output.append(f"{hours}h") + secs -= hours * 3600 - delta -= datetime.timedelta(microseconds=delta_us) - delta_ms = delta_us // 1000 - delta_str = durationpy.to_str(delta) + minutes = secs // 60 + if minutes > 0: + output.append(f"{minutes}m") + secs -= minutes * 60 - if delta_ms > 0: - # We have milliseconds to add back in. Make sure to not have a leading - # "0" if we have no other duration components. - if delta == datetime.timedelta(0): - delta_str = "" + if secs > 0: + output.append(f"{secs}s") - delta_str += f"{delta_ms}ms" + if delta_us > 0: + output.append(f"{delta_us // 1000}ms") - return delta_str + return "".join(output) From 3b4121e55ad6204a93ceac8ea15c4d5402751b44 Mon Sep 17 00:00:00 2001 From: Flynn Date: Wed, 21 Aug 2024 10:28:56 -0400 Subject: [PATCH 2/3] Have an example program too. Signed-off-by: Flynn --- examples/gep2257.py | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 examples/gep2257.py diff --git a/examples/gep2257.py b/examples/gep2257.py new file mode 100644 index 0000000000..892c941db5 --- /dev/null +++ b/examples/gep2257.py @@ -0,0 +1,39 @@ +#!/usr/bin/python3 +# -*- coding:utf-8 -*- + +""" +This example uses kubernetes.utils.duration to parse and display +a GEP-2257 duration string (you can find the full specification at +https://gateway-api.sigs.k8s.io/geps/gep-2257/). + +Good things to try: +>>> python examples/gep2257.py 1h +Duration: 1h +>>> python examples/gep2257.py 3600s +Duration: 1h +>>> python examples/gep2257.py 90m +Duration: 1h30m +>>> python examples/gep2257.py 30m1h10s5s +Duration: 1h30m15s +>>> python examples/gep2257.py 0h0m0s0ms +Duration: 0s +>>> python examples/gep2257.py -5m +ValueError: Invalid duration format: -5m +>>> python examples/gep2257.py 1.5h +ValueError: Invalid duration format: 1.5h +""" + +import sys + +from kubernetes.utils import duration + +def main(): + if len(sys.argv) != 2: + print("Usage: {} ".format(sys.argv[0])) + sys.exit(1) + + dur = duration.parse_duration(sys.argv[1]) + print("Duration: %s" % duration.format_duration(dur)) + +if __name__ == "__main__": + main() From f05c642b4aa580be4613b2e4bb6ff35a3d6f0237 Mon Sep 17 00:00:00 2001 From: Flynn Date: Wed, 21 Aug 2024 12:19:30 -0400 Subject: [PATCH 3/3] Review feedback Signed-off-by: Flynn --- examples/{gep2257.py => duration-gep2257.py} | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) rename examples/{gep2257.py => duration-gep2257.py} (69%) diff --git a/examples/gep2257.py b/examples/duration-gep2257.py similarity index 69% rename from examples/gep2257.py rename to examples/duration-gep2257.py index 892c941db5..a7bda1bdb2 100644 --- a/examples/gep2257.py +++ b/examples/duration-gep2257.py @@ -7,19 +7,19 @@ https://gateway-api.sigs.k8s.io/geps/gep-2257/). Good things to try: ->>> python examples/gep2257.py 1h +>>> python examples/duration-gep2257.py 1h Duration: 1h ->>> python examples/gep2257.py 3600s +>>> python examples/duration-gep2257.py 3600s Duration: 1h ->>> python examples/gep2257.py 90m +>>> python examples/duration-gep2257.py 90m Duration: 1h30m ->>> python examples/gep2257.py 30m1h10s5s +>>> python examples/duration-gep2257.py 30m1h10s5s Duration: 1h30m15s ->>> python examples/gep2257.py 0h0m0s0ms +>>> python examples/duration-gep2257.py 0h0m0s0ms Duration: 0s ->>> python examples/gep2257.py -5m +>>> python examples/duration-gep2257.py -5m ValueError: Invalid duration format: -5m ->>> python examples/gep2257.py 1.5h +>>> python examples/duration-gep2257.py 1.5h ValueError: Invalid duration format: 1.5h """