From 0e13914fce9306790d067d16ed78d0967fdb117b Mon Sep 17 00:00:00 2001 From: Ivan Habunek Date: Thu, 1 Dec 2022 10:20:50 +0100 Subject: [PATCH] Add duration parsing --- tests/test_utils.py | 46 +++++++++++++++++++++++++++++++++++++++++++++ toot/console.py | 37 ++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+) diff --git a/tests/test_utils.py b/tests/test_utils.py index 5b68606..a1bba9a 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1,3 +1,7 @@ +from argparse import ArgumentTypeError +import pytest + +from toot.console import duration from toot.wcstring import wc_wrap, trunc, pad, fit_text @@ -155,3 +159,45 @@ def test_wc_wrap_indented(): "dolores. Illo reiciendis nulla ea. Facilis nostrum", "non qui inventore sit.", ] + + +def test_duration(): + # Long hand + assert duration("1 second") == 1 + assert duration("1 seconds") == 1 + assert duration("100 second") == 100 + assert duration("100 seconds") == 100 + assert duration("5 minutes") == 5 * 60 + assert duration("5 minutes 10 seconds") == 5 * 60 + 10 + assert duration("1 hour 5 minutes") == 3600 + 5 * 60 + assert duration("1 hour 5 minutes 1 second") == 3600 + 5 * 60 + 1 + assert duration("5 days") == 5 * 86400 + assert duration("5 days 3 minutes") == 5 * 86400 + 3 * 60 + assert duration("5 days 10 hours 3 minutes 1 second") == 5 * 86400 + 10 * 3600 + 3 * 60 + 1 + + # Short hand + assert duration("1s") == 1 + assert duration("100s") == 100 + assert duration("5m") == 5 * 60 + assert duration("5m10s") == 5 * 60 + 10 + assert duration("5m 10s") == 5 * 60 + 10 + assert duration("1h5m1s") == 3600 + 5 * 60 + 1 + assert duration("1h 5m 1s") == 3600 + 5 * 60 + 1 + assert duration("5d") == 5 * 86400 + assert duration("5d3m") == 5 * 86400 + 3 * 60 + assert duration("5d 3m") == 5 * 86400 + 3 * 60 + assert duration("5d 10h 3m 1s") == 5 * 86400 + 10 * 3600 + 3 * 60 + 1 + assert duration("5d10h3m1s") == 5 * 86400 + 10 * 3600 + 3 * 60 + 1 + + with pytest.raises(ArgumentTypeError): + duration("") + + with pytest.raises(ArgumentTypeError): + duration("100") + + # Wrong order + with pytest.raises(ArgumentTypeError): + duration("1m1d") + + with pytest.raises(ArgumentTypeError): + duration("banana") diff --git a/toot/console.py b/toot/console.py index 4a30a83..8e6a332 100644 --- a/toot/console.py +++ b/toot/console.py @@ -2,6 +2,7 @@ import logging import os +import re import shutil import sys @@ -40,6 +41,42 @@ def timeline_count(value): return n +DURATION_UNITS = { + "m": 60, + "h": 60 * 60, + "d": 60 * 60 * 24, +} + + +def duration(value: str): + match = re.match(r"""^ + (([0-9]+)\s*(days|day|d))?\s* + (([0-9]+)\s*(hours|hour|h))?\s* + (([0-9]+)\s*(minutes|minute|m))?\s* + (([0-9]+)\s*(seconds|second|s))?\s* + $""", value, re.X) + + if not match: + raise ArgumentTypeError(f"Invalid duration: {value}") + + days = match.group(2) + hours = match.group(5) + minutes = match.group(8) + seconds = match.group(11) + + days = int(match.group(2) or 0) * 60 * 60 * 24 + hours = int(match.group(5) or 0) * 60 * 60 + minutes = int(match.group(8) or 0) * 60 + seconds = int(match.group(11) or 0) + + duration = days + hours + minutes + seconds + + if duration == 0: + raise ArgumentTypeError("Empty duration") + + return duration + + def editor(value): if not value: raise ArgumentTypeError(