diff --git a/hcloud/images/domain.py b/hcloud/images/domain.py index 915ace64..c1e2d18c 100644 --- a/hcloud/images/domain.py +++ b/hcloud/images/domain.py @@ -1,8 +1,11 @@ from __future__ import annotations -from typing import TYPE_CHECKING, TypedDict +import warnings +from datetime import datetime +from typing import TYPE_CHECKING, Any, TypedDict from ..core import BaseDomain, DomainIdentityMixin +from ..deprecation import DeprecationInfo if TYPE_CHECKING: from ..actions import BoundAction @@ -52,8 +55,10 @@ class Image(BaseDomain, DomainIdentityMixin): Protection configuration for the image :param deprecated: datetime, None Point in time when the image is considered to be deprecated (in ISO-8601 format) + :param deprecation: + Describes wether the resources is deprecated. :param labels: Dict - User-defined labels (key-value pairs) + User-defined labels (key-value pairs) """ __api_properties__ = ( @@ -73,11 +78,11 @@ class Image(BaseDomain, DomainIdentityMixin): "protection", "labels", "created", - "deprecated", + "deprecation", ) __slots__ = __api_properties__ - # pylint: disable=too-many-locals + # pylint: disable=too-many-locals,unused-argument def __init__( self, id: int | None = None, @@ -87,7 +92,7 @@ def __init__( description: str | None = None, image_size: int | None = None, disk_size: int | None = None, - deprecated: str | None = None, + deprecated: str | None = None, # Preserved for backward compatibility bound_to: Server | BoundServer | None = None, os_flavor: str | None = None, os_version: str | None = None, @@ -97,6 +102,7 @@ def __init__( protection: ImageProtection | None = None, labels: dict[str, str] | None = None, status: str | None = None, + deprecation: dict[str, Any] | None = None, ): self.id = id self.name = name @@ -105,7 +111,6 @@ def __init__( self.description = description self.image_size = image_size self.disk_size = disk_size - self.deprecated = self._parse_datetime(deprecated) self.bound_to = bound_to self.os_flavor = os_flavor self.os_version = os_version @@ -115,6 +120,27 @@ def __init__( self.protection = protection self.labels = labels self.status = status + self.deprecation = ( + None if deprecation is None else DeprecationInfo.from_dict(deprecation) + ) + + @property + def deprecated(self) -> datetime | None: + """ + .. deprecated:: 2.24.0 + The 'deprecated' property is deprecated. Please use to the '.deprecation' property instead. + + See https://docs.hetzner.cloud/changelog#2026-09-08-removing-the-deprecated-field. + """ + warnings.warn( + "The 'deprecated' property is deprecated. Please use to the '.deprecation' property instead. " + "See https://docs.hetzner.cloud/changelog#2026-09-08-removing-the-deprecated-field.", + DeprecationWarning, + stacklevel=2, + ) + if self.deprecation is None: + return None + return self.deprecation.announced class ImageProtection(TypedDict): diff --git a/tests/unit/images/conftest.py b/tests/unit/images/conftest.py index 887c1eb9..5c83fa34 100644 --- a/tests/unit/images/conftest.py +++ b/tests/unit/images/conftest.py @@ -13,7 +13,10 @@ def image1(): "created": "2021-08-16T11:12:01Z", "created_from": None, "deleted": None, - "deprecated": "2026-08-31T06:21:44Z", + "deprecation": { + "announced": "2026-08-31T06:21:44Z", + "unavailable_after": "2026-12-01T00:00:00Z", + }, "description": "Debian 11", "disk_size": 5, "image_size": None, @@ -42,7 +45,7 @@ def image2(): "name": "server1", }, "deleted": None, - "deprecated": None, + "deprecation": None, "description": "snapshot 2026-09-08T13:44:08Z", "disk_size": 80, "image_size": 0.7237785009765625, diff --git a/tests/unit/images/test_client.py b/tests/unit/images/test_client.py index 38251a11..0ae6b07f 100644 --- a/tests/unit/images/test_client.py +++ b/tests/unit/images/test_client.py @@ -64,7 +64,10 @@ def test_init(self, image1, image2): assert o.rapid_deploy is True assert o.labels == {} assert o.protection == {"delete": False} - assert o.deprecated == isoparse("2026-08-31T06:21:44Z") + with pytest.deprecated_call(): + assert o.deprecated == isoparse("2026-08-31T06:21:44Z") + assert o.deprecation.announced == isoparse("2026-08-31T06:21:44Z") + assert o.deprecation.unavailable_after == isoparse("2026-12-01T00:00:00Z") o = BoundImage(client=mock.MagicMock(), data=image2) @@ -87,7 +90,9 @@ def test_init(self, image1, image2): assert o.rapid_deploy is False assert o.labels == {"key": "value"} assert o.protection == {"delete": True} - assert o.deprecated is None + with pytest.deprecated_call(): + assert o.deprecated is None + assert o.deprecation is None class TestImagesClient: