Skip to content

Commit 3df9e69

Browse files
authored
refactor: use base domain parse datetime helper (#606)
Makes it easy to eventually swap `isoparse` with `datetime.fromisoformat` (first attempt was reverted in #231). Related to https://docs.hetzner.cloud/changelog#2025-12-09-api-timestamp-format-rfc3339
1 parent 0a46f0c commit 3df9e69

File tree

18 files changed

+40
-65
lines changed

18 files changed

+40
-65
lines changed

hcloud/actions/domain.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22

33
from typing import TYPE_CHECKING
44

5-
from dateutil.parser import isoparse
6-
75
from .._exceptions import HCloudException
86
from ..core import BaseDomain
97

@@ -59,8 +57,8 @@ def __init__(
5957

6058
self.status = status
6159
self.progress = progress
62-
self.started = isoparse(started) if started else None
63-
self.finished = isoparse(finished) if finished else None
60+
self.started = self._parse_datetime(started)
61+
self.finished = self._parse_datetime(finished)
6462
self.resources = resources
6563
self.error = error
6664

hcloud/certificates/domain.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22

33
from typing import TYPE_CHECKING
44

5-
from dateutil.parser import isoparse
6-
75
from ..core import BaseDomain, DomainIdentityMixin
86

97
if TYPE_CHECKING:
@@ -69,9 +67,9 @@ def __init__(
6967
self.certificate = certificate
7068
self.domain_names = domain_names
7169
self.fingerprint = fingerprint
72-
self.not_valid_before = isoparse(not_valid_before) if not_valid_before else None
73-
self.not_valid_after = isoparse(not_valid_after) if not_valid_after else None
74-
self.created = isoparse(created) if created else None
70+
self.not_valid_before = self._parse_datetime(not_valid_before)
71+
self.not_valid_after = self._parse_datetime(not_valid_after)
72+
self.created = self._parse_datetime(created)
7573
self.labels = labels
7674
self.status = status
7775

hcloud/core/domain.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
from __future__ import annotations
22

3-
from typing import Any
3+
from datetime import datetime
4+
from typing import Any, overload
5+
6+
from dateutil.parser import isoparse
47

58

69
class BaseDomain:
@@ -27,6 +30,16 @@ def __eq__(self, other: Any) -> bool:
2730
return False
2831
return True
2932

33+
@overload
34+
def _parse_datetime(self, value: str) -> datetime: ...
35+
@overload
36+
def _parse_datetime(self, value: None) -> None: ...
37+
38+
def _parse_datetime(self, value: str | None) -> datetime | None:
39+
if value is None:
40+
return None
41+
return isoparse(value)
42+
3043

3144
class DomainIdentityMixin:
3245

hcloud/deprecation/domain.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
from __future__ import annotations
22

3-
from dateutil.parser import isoparse
4-
53
from ..core import BaseDomain
64

75

@@ -28,7 +26,5 @@ def __init__(
2826
announced: str | None = None,
2927
unavailable_after: str | None = None,
3028
):
31-
self.announced = isoparse(announced) if announced else None
32-
self.unavailable_after = (
33-
isoparse(unavailable_after) if unavailable_after else None
34-
)
29+
self.announced = self._parse_datetime(announced)
30+
self.unavailable_after = self._parse_datetime(unavailable_after)

hcloud/firewalls/domain.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22

33
from typing import TYPE_CHECKING, Any
44

5-
from dateutil.parser import isoparse
6-
75
from ..core import BaseDomain, DomainIdentityMixin
86

97
if TYPE_CHECKING:
@@ -46,7 +44,7 @@ def __init__(
4644
self.rules = rules
4745
self.applied_to = applied_to
4846
self.labels = labels
49-
self.created = isoparse(created) if created else None
47+
self.created = self._parse_datetime(created)
5048

5149

5250
class FirewallRule(BaseDomain):

hcloud/floating_ips/domain.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22

33
from typing import TYPE_CHECKING
44

5-
from dateutil.parser import isoparse
6-
75
from ..core import BaseDomain, DomainIdentityMixin
86

97
if TYPE_CHECKING:
@@ -83,7 +81,7 @@ def __init__(
8381
self.blocked = blocked
8482
self.protection = protection
8583
self.labels = labels
86-
self.created = isoparse(created) if created else None
84+
self.created = self._parse_datetime(created)
8785
self.name = name
8886

8987

hcloud/images/domain.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22

33
from typing import TYPE_CHECKING
44

5-
from dateutil.parser import isoparse
6-
75
from ..core import BaseDomain, DomainIdentityMixin
86

97
if TYPE_CHECKING:
@@ -96,11 +94,11 @@ def __init__(
9694
self.id = id
9795
self.name = name
9896
self.type = type
99-
self.created = isoparse(created) if created else None
97+
self.created = self._parse_datetime(created)
10098
self.description = description
10199
self.image_size = image_size
102100
self.disk_size = disk_size
103-
self.deprecated = isoparse(deprecated) if deprecated else None
101+
self.deprecated = self._parse_datetime(deprecated)
104102
self.bound_to = bound_to
105103
self.os_flavor = os_flavor
106104
self.os_version = os_version

hcloud/load_balancers/domain.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
import warnings
44
from typing import TYPE_CHECKING, Any, Literal
55

6-
from dateutil.parser import isoparse
7-
86
from ..core import BaseDomain, DomainIdentityMixin
97

108
if TYPE_CHECKING:
@@ -93,7 +91,7 @@ def __init__(
9391
):
9492
self.id = id
9593
self.name = name
96-
self.created = isoparse(created) if created else None
94+
self.created = self._parse_datetime(created)
9795
self.public_net = public_net
9896
self.private_net = private_net
9997
self.location = location

hcloud/metrics/domain.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
from datetime import datetime
44
from typing import Literal
55

6-
from dateutil.parser import isoparse
7-
86
from ..core import BaseDomain
97

108
TimeSeries = dict[str, dict[Literal["values"], list[tuple[float, str]]]]
@@ -41,7 +39,7 @@ def __init__(
4139
step: float,
4240
time_series: TimeSeries,
4341
):
44-
self.start = isoparse(start)
45-
self.end = isoparse(end)
42+
self.start = self._parse_datetime(start)
43+
self.end = self._parse_datetime(end)
4644
self.step = step
4745
self.time_series = time_series

hcloud/networks/domain.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
import warnings
44
from typing import TYPE_CHECKING
55

6-
from dateutil.parser import isoparse
7-
86
from ..core import BaseDomain, DomainIdentityMixin
97

108
if TYPE_CHECKING:
@@ -65,7 +63,7 @@ def __init__(
6563
):
6664
self.id = id
6765
self.name = name
68-
self.created = isoparse(created) if created else None
66+
self.created = self._parse_datetime(created)
6967
self.ip_range = ip_range
7068
self.subnets = subnets
7169
self.routes = routes

0 commit comments

Comments
 (0)