Skip to content

Commit cceabf0

Browse files
committed
Replace pendulum with whenever
1 parent 825363c commit cceabf0

File tree

8 files changed

+162
-156
lines changed

8 files changed

+162
-156
lines changed

infrahub_sdk/ctl/branch.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@
55
from rich.table import Table
66

77
from ..async_typer import AsyncTyper
8-
from ..ctl.client import initialize_client
9-
from ..ctl.utils import calculate_time_diff, catch_exception
8+
from ..utils import calculate_time_diff
9+
from .client import initialize_client
1010
from .parameters import CONFIG_PARAM
11+
from .utils import catch_exception
1112

1213
app = AsyncTyper()
1314
console = Console()

infrahub_sdk/ctl/utils.py

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,9 @@
88
from pathlib import Path
99
from typing import TYPE_CHECKING, Any, Callable, NoReturn, Optional, TypeVar
1010

11-
import pendulum
1211
import typer
1312
from click.exceptions import Exit
1413
from httpx import HTTPError
15-
from pendulum.datetime import DateTime
1614
from rich.console import Console
1715
from rich.logging import RichHandler
1816
from rich.markup import escape
@@ -152,20 +150,6 @@ def parse_cli_vars(variables: Optional[list[str]]) -> dict[str, str]:
152150
return {var.split("=")[0]: var.split("=")[1] for var in variables if "=" in var}
153151

154152

155-
def calculate_time_diff(value: str) -> str | None:
156-
"""Calculate the time in human format between a timedate in string format and now."""
157-
try:
158-
time_value = pendulum.parse(value)
159-
except pendulum.parsing.exceptions.ParserError:
160-
return None
161-
162-
if not isinstance(time_value, DateTime):
163-
return None
164-
165-
pendulum.set_locale("en")
166-
return time_value.diff_for_humans(other=pendulum.now(), absolute=True)
167-
168-
169153
def find_graphql_query(name: str, directory: str | Path = ".") -> str:
170154
if isinstance(directory, str):
171155
directory = Path(directory)

infrahub_sdk/timestamp.py

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22

33
import re
44

5-
import pendulum
6-
from pendulum.datetime import DateTime
5+
from whenever import Instant, ZonedDateTime
76

87
REGEX_MAPPING = {
98
"seconds": r"(\d+)(s|sec|second|seconds)",
@@ -16,47 +15,58 @@ class TimestampFormatError(ValueError): ...
1615

1716

1817
class Timestamp:
19-
def __init__(self, value: str | DateTime | Timestamp | None = None):
20-
if value and isinstance(value, DateTime):
18+
obj: ZonedDateTime
19+
20+
def __init__(self, value: str | ZonedDateTime | Timestamp | None = None):
21+
if value and isinstance(value, ZonedDateTime):
2122
self.obj = value
2223
elif value and isinstance(value, self.__class__):
2324
self.obj = value.obj
2425
elif isinstance(value, str):
2526
self.obj = self._parse_string(value)
2627
else:
27-
self.obj = DateTime.now(tz="UTC")
28+
self.obj = ZonedDateTime.now("UTC")
2829

2930
@classmethod
30-
def _parse_string(cls, value: str) -> DateTime:
31+
def _parse_string(cls, value: str) -> ZonedDateTime:
3132
try:
32-
parsed_date = pendulum.parse(value)
33-
if isinstance(parsed_date, DateTime):
33+
parsed_date = ZonedDateTime.parse_common_iso(value)
34+
if isinstance(parsed_date, ZonedDateTime):
3435
return parsed_date
35-
except (pendulum.parsing.exceptions.ParserError, ValueError):
36+
except ValueError:
37+
pass
38+
39+
try:
40+
parsed_date_instant = Instant.parse_common_iso(value)
41+
if isinstance(parsed_date_instant, Instant):
42+
return parsed_date_instant.to_tz("UTC")
43+
except ValueError:
3644
pass
3745

38-
params = {}
46+
params: dict[str, float] = {}
3947
for key, regex in REGEX_MAPPING.items():
4048
match = re.search(regex, value)
4149
if match:
42-
params[key] = int(match.group(1))
50+
params[key] = float(match.group(1))
4351

4452
if not params:
4553
raise TimestampFormatError(f"Invalid time format for {value}")
4654

47-
return DateTime.now(tz="UTC").subtract(**params)
55+
return ZonedDateTime.now("UTC").subtract(**params) # type: ignore[call-overload]
4856

4957
def __repr__(self) -> str:
5058
return f"Timestamp: {self.to_string()}"
5159

5260
def to_string(self, with_z: bool = True) -> str:
53-
iso8601_string = self.obj.to_iso8601_string()
54-
if not with_z and iso8601_string[-1] == "Z":
61+
if with_z:
62+
return self.obj.instant().format_common_iso()
63+
iso8601_string = self.obj.format_common_iso()
64+
if iso8601_string[-1] == "Z":
5565
iso8601_string = iso8601_string[:-1] + "+00:00"
5666
return iso8601_string
5767

5868
def to_timestamp(self) -> int:
59-
return self.obj.int_timestamp
69+
return self.obj.timestamp()
6070

6171
def __eq__(self, other: object) -> bool:
6272
if not isinstance(other, Timestamp):

infrahub_sdk/utils.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@
1818
from infrahub_sdk.repository import GitRepoManager
1919

2020
from .exceptions import FileNotValidError, JsonDecodeError
21+
from .timestamp import Timestamp, TimestampFormatError
2122

2223
if TYPE_CHECKING:
2324
from graphql import GraphQLResolveInfo
25+
from whenever import TimeDelta
2426

2527

2628
def base36encode(number: int) -> str:
@@ -367,3 +369,26 @@ def get_user_permissions(data: list[dict]) -> dict:
367369
groups[group_name] = permissions
368370

369371
return groups
372+
373+
374+
def calculate_time_diff(value: str) -> str | None:
375+
"""Calculate the time in human format between a timedate in string format and now."""
376+
try:
377+
time_value = Timestamp(value)
378+
except TimestampFormatError:
379+
return None
380+
381+
delta: TimeDelta = Timestamp().obj.difference(time_value.obj)
382+
(hrs, mins, secs, _) = delta.in_hrs_mins_secs_nanos()
383+
384+
if hrs and hrs < 24 and mins:
385+
return f"{hrs}h {mins}m and {secs}s ago"
386+
if hrs and hrs > 24:
387+
remaining_hrs = hrs % 24
388+
days = int((hrs - remaining_hrs) / 24)
389+
return f"{days}d and {remaining_hrs}h ago"
390+
if hrs == 0 and mins and secs:
391+
return f"{mins}m and {secs}s ago"
392+
if hrs == 0 and mins == 0 and secs:
393+
return f"{secs}s ago"
394+
return "now"

0 commit comments

Comments
 (0)