Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-hcloud for openSUSE:Factory checked in at 2026-08-22 21:34:53 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-hcloud (Old) and /work/SRC/openSUSE:Factory/.python-hcloud.new.1258 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-hcloud" Sat Aug 22 21:34:53 2026 rev:22 rq:1372925 version:2.23.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-hcloud/python-hcloud.changes 2026-07-02 20:13:09.381083437 +0200 +++ /work/SRC/openSUSE:Factory/.python-hcloud.new.1258/python-hcloud.changes 2026-08-22 21:36:56.922937993 +0200 @@ -1,0 +2,12 @@ +Fri Aug 21 20:02:53 UTC 2026 - Dirk Müller <[email protected]> + +- update to 2.23.0: + * ### Removed deprecated Datacenter property from Server and + * Removed the deprecated Datacenter property from the Server + and PrimaryIP resources. Since the property was already + removed from the Hetzner Cloud API, we do not consider this a + breaking change (see changelog entry). + * remove datacenter property from server and primary_ip + * add deprecation info to load balancer type + +------------------------------------------------------------------- Old: ---- hcloud-2.22.0.tar.gz New: ---- hcloud-2.23.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-hcloud.spec ++++++ --- /var/tmp/diff_new_pack.nugDt9/_old 2026-08-22 21:36:57.598963026 +0200 +++ /var/tmp/diff_new_pack.nugDt9/_new 2026-08-22 21:36:57.599963063 +0200 @@ -18,7 +18,7 @@ %{?sle15_python_module_pythons} Name: python-hcloud -Version: 2.22.0 +Version: 2.23.0 Release: 0 Summary: Hetzner Cloud Python library License: MIT ++++++ hcloud-2.22.0.tar.gz -> hcloud-2.23.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-2.22.0/CHANGELOG.md new/hcloud-2.23.0/CHANGELOG.md --- old/hcloud-2.22.0/CHANGELOG.md 2026-06-18 17:33:29.000000000 +0200 +++ new/hcloud-2.23.0/CHANGELOG.md 2026-07-21 14:31:07.000000000 +0200 @@ -1,5 +1,41 @@ # Changelog +## [v2.23.0](https://github.com/hetznercloud/hcloud-python/releases/tag/v2.23.0) + +[Compare to previous version](https://github.com/hetznercloud/hcloud-python/compare/v2.22.0...v2.23.0) + +### Removed deprecated Datacenter property from Server and PrimaryIP + +Removed the deprecated Datacenter property from the Server and PrimaryIP resources. Since the property was already removed from the Hetzner Cloud API, we do not consider this a breaking change (see [changelog entry](https://docs.hetzner.cloud/changelog#2026-07-01-removing-datacenters)). + +> [!IMPORTANT] +> **Action required:** Please update all code that accesses `server.datacenter` or `primary_ip.datacenter` to use the `location` property instead, as shown below. + +**Before:** + +```python +server = client.server.get_by_id(5) +print(server.datacenter) + +primary_ip = client.primary_ip.get_by_id(5) +print(primary_ip.datacenter) +``` + +**After:** + +```python +server = client.server.get_by_id(5) +print(server.location) + +primary_ip = client.primary_ip.get_by_id(5) +print(primary_ip.location) +``` + +### Features + +- remove datacenter property from server and primary_ip (#668) ([abdadf3](https://github.com/hetznercloud/hcloud-python/commit/abdadf3e7cc5d0edeb38f369955fa83f71b102e5)) +- add deprecation info to load balancer type (#674) ([aeebcf8](https://github.com/hetznercloud/hcloud-python/commit/aeebcf8bd32df390163089a33c57815bb7214763)) + ## [v2.22.0](https://github.com/hetznercloud/hcloud-python/releases/tag/v2.22.0) ### Datacenters resource is now deprecated diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-2.22.0/PKG-INFO new/hcloud-2.23.0/PKG-INFO --- old/hcloud-2.22.0/PKG-INFO 2026-06-18 17:33:37.063018800 +0200 +++ new/hcloud-2.23.0/PKG-INFO 2026-07-21 14:31:20.442855600 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.4 Name: hcloud -Version: 2.22.0 +Version: 2.23.0 Summary: Official Hetzner Cloud python library Home-page: https://github.com/hetznercloud/hcloud-python Author: Hetzner Cloud GmbH @@ -31,11 +31,11 @@ Requires-Dist: myst-parser<5.2,>=5; extra == "docs" Requires-Dist: watchdog<6.1,>=6; extra == "docs" Provides-Extra: test -Requires-Dist: coverage<7.15,>=7.14; extra == "test" +Requires-Dist: coverage<7.16,>=7.15; extra == "test" Requires-Dist: pylint<4.1,>=4; extra == "test" -Requires-Dist: pytest<9.1,>=9; extra == "test" +Requires-Dist: pytest<9.2,>=9; extra == "test" Requires-Dist: pytest-cov<7.2,>=7; extra == "test" -Requires-Dist: mypy<2.2,>=2.1; extra == "test" +Requires-Dist: mypy<2.4,>=2.3; extra == "test" Requires-Dist: types-python-dateutil; extra == "test" Requires-Dist: types-requests; extra == "test" Dynamic: author diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-2.22.0/hcloud/_version.py new/hcloud-2.23.0/hcloud/_version.py --- old/hcloud-2.22.0/hcloud/_version.py 2026-06-18 17:33:29.000000000 +0200 +++ new/hcloud-2.23.0/hcloud/_version.py 2026-07-21 14:31:07.000000000 +0200 @@ -1,3 +1,3 @@ from __future__ import annotations -__version__ = "2.22.0" # x-releaser-pleaser-version +__version__ = "2.23.0" # x-releaser-pleaser-version diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-2.22.0/hcloud/load_balancer_types/domain.py new/hcloud-2.23.0/hcloud/load_balancer_types/domain.py --- old/hcloud-2.22.0/hcloud/load_balancer_types/domain.py 2026-06-18 17:33:29.000000000 +0200 +++ new/hcloud-2.23.0/hcloud/load_balancer_types/domain.py 2026-07-21 14:31:07.000000000 +0200 @@ -3,6 +3,7 @@ from typing import Any from ..core import BaseDomain, DomainIdentityMixin +from ..deprecation import DeprecationInfo __all__ = [ "LoadBalancerType", @@ -28,7 +29,7 @@ Max amount of certificates the Load Balancer can serve :param prices: List of dict Prices in different locations - + :param deprecation: Define if and when the Load Balancer Type is deprecated. """ __api_properties__ = ( @@ -40,6 +41,7 @@ "max_targets", "max_assigned_certificates", "prices", + "deprecation", ) __slots__ = __api_properties__ @@ -53,6 +55,7 @@ max_targets: int | None = None, max_assigned_certificates: int | None = None, prices: list[dict[str, Any]] | None = None, + deprecation: dict[str, Any] | None = None, ): self.id = id self.name = name @@ -62,3 +65,4 @@ self.max_targets = max_targets self.max_assigned_certificates = max_assigned_certificates self.prices = prices + self.deprecation = deprecation and DeprecationInfo.from_dict(deprecation) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-2.22.0/hcloud/primary_ips/client.py new/hcloud-2.23.0/hcloud/primary_ips/client.py --- old/hcloud-2.22.0/hcloud/primary_ips/client.py 2026-06-18 17:33:29.000000000 +0200 +++ new/hcloud-2.23.0/hcloud/primary_ips/client.py 2026-07-21 14:31:07.000000000 +0200 @@ -16,7 +16,6 @@ if TYPE_CHECKING: from .._client import Client - from ..datacenters import BoundDatacenter, Datacenter from ..locations import BoundLocation, Location @@ -39,15 +38,8 @@ complete: bool = True, ): # pylint: disable=import-outside-toplevel - from ..datacenters import BoundDatacenter from ..locations import BoundLocation - raw = data.get("datacenter", {}) - if raw: - with warnings.catch_warnings(): - warnings.filterwarnings("ignore", category=DeprecationWarning) - data["datacenter"] = BoundDatacenter(client._parent.datacenters, raw) - raw = data.get("location", {}) if raw: data["location"] = BoundLocation(client._parent.locations, raw) @@ -311,7 +303,6 @@ self, type: str, name: str, - datacenter: Datacenter | BoundDatacenter | None = None, location: Location | BoundLocation | None = None, assignee_type: str | None = None, assignee_id: int | None = None, @@ -322,7 +313,6 @@ :param type: str Primary IP type Choices: ipv4, ipv6 :param name: str - :param datacenter: Datacenter (optional) :param location: Location (optional) :param assignee_type: str (optional) :param assignee_id: int (optional) @@ -336,15 +326,6 @@ "auto_delete": auto_delete, } - if datacenter is not None: - warnings.warn( - "The 'datacenter' argument is deprecated and will be removed after 1 July 2026. " - "Please use the 'location' argument instead. " - "See https://docs.hetzner.cloud/changelog#2025-12-16-phasing-out-datacenters", - DeprecationWarning, - stacklevel=2, - ) - data["datacenter"] = datacenter.id_or_name if location is not None: data["location"] = location.id_or_name if assignee_id is not None: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-2.22.0/hcloud/primary_ips/domain.py new/hcloud-2.23.0/hcloud/primary_ips/domain.py --- old/hcloud-2.22.0/hcloud/primary_ips/domain.py 2026-06-18 17:33:29.000000000 +0200 +++ new/hcloud-2.23.0/hcloud/primary_ips/domain.py 2026-07-21 14:31:07.000000000 +0200 @@ -1,13 +1,11 @@ from __future__ import annotations -import warnings from typing import TYPE_CHECKING, TypedDict from ..core import BaseDomain, DomainIdentityMixin if TYPE_CHECKING: from ..actions import BoundAction - from ..datacenters import BoundDatacenter from ..locations import BoundLocation from ..rdns import DNSPtr from .client import BoundPrimaryIP @@ -30,14 +28,6 @@ Type of Primary IP. Choices: `ipv4`, `ipv6` :param dns_ptr: List[Dict] Array of reverse DNS entries - :param datacenter: :class:`Datacenter <hcloud.datacenters.client.BoundDatacenter>` - Datacenter the Primary IP was created in. - - This property is deprecated and will be removed after 1 July 2026. - Please use the ``location`` property instead. - - See https://docs.hetzner.cloud/changelog#2025-12-16-phasing-out-datacenters. - :param location: :class:`Location <hcloud.locations.client.BoundLocation>` Location the Primary IP was created in. :param blocked: boolean @@ -58,7 +48,7 @@ Delete the Primary IP when the Assignee it is assigned to is deleted. """ - __properties__ = ( + __api_properties__ = ( "id", "ip", "type", @@ -73,14 +63,7 @@ "assignee_type", "auto_delete", ) - __api_properties__ = ( - *__properties__, - "datacenter", - ) - __slots__ = ( - *__properties__, - "_datacenter", - ) + __slots__ = __api_properties__ def __init__( self, @@ -88,7 +71,6 @@ type: str | None = None, ip: str | None = None, dns_ptr: list[DNSPtr] | None = None, - datacenter: BoundDatacenter | None = None, location: BoundLocation | None = None, blocked: bool | None = None, protection: PrimaryIPProtection | None = None, @@ -103,7 +85,6 @@ self.type = type self.ip = ip self.dns_ptr = dns_ptr - self.datacenter = datacenter self.location = location self.blocked = blocked self.protection = protection @@ -114,24 +95,6 @@ self.assignee_type = assignee_type self.auto_delete = auto_delete - @property - def datacenter(self) -> BoundDatacenter | None: - """ - :meta private: - """ - warnings.warn( - "The 'datacenter' property is deprecated and will be removed after 1 July 2026. " - "Please use the 'location' property instead. " - "See https://docs.hetzner.cloud/changelog#2025-12-16-phasing-out-datacenters.", - DeprecationWarning, - stacklevel=2, - ) - return self._datacenter - - @datacenter.setter - def datacenter(self, value: BoundDatacenter | None) -> None: - self._datacenter = value - class PrimaryIPProtection(TypedDict): delete: bool diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-2.22.0/hcloud/servers/client.py new/hcloud-2.23.0/hcloud/servers/client.py --- old/hcloud-2.22.0/hcloud/servers/client.py 2026-06-18 17:33:29.000000000 +0200 +++ new/hcloud-2.23.0/hcloud/servers/client.py 2026-07-21 14:31:07.000000000 +0200 @@ -1,6 +1,5 @@ from __future__ import annotations -import warnings from datetime import datetime from typing import TYPE_CHECKING, Any, NamedTuple @@ -15,7 +14,6 @@ ) from ..actions.client import ResourceClientBaseActionsMixin from ..core import BoundModelBase, Meta, ResourceClientBase -from ..datacenters import BoundDatacenter from ..firewalls import BoundFirewall from ..floating_ips import BoundFloatingIP from ..images import BoundImage, CreateImageResponse @@ -44,7 +42,6 @@ if TYPE_CHECKING: from .._client import Client - from ..datacenters import Datacenter from ..firewalls import Firewall from ..images import Image from ..isos import Iso @@ -75,12 +72,6 @@ data: dict[str, Any], complete: bool = True, ): - raw = data.get("datacenter") - if raw: - with warnings.catch_warnings(): - warnings.filterwarnings("ignore", category=DeprecationWarning) - data["datacenter"] = BoundDatacenter(client._parent.datacenters, raw) - raw = data.get("location") if raw: data["location"] = BoundLocation(client._parent.locations, raw) @@ -636,7 +627,6 @@ user_data: str | None = None, labels: dict[str, str] | None = None, location: Location | BoundLocation | None = None, - datacenter: Datacenter | BoundDatacenter | None = None, start_after_create: bool | None = True, automount: bool | None = None, placement_group: PlacementGroup | BoundPlacementGroup | None = None, @@ -661,7 +651,6 @@ :param labels: Dict[str,str] (optional) User-defined labels (key-value pairs) :param location: :class:`BoundLocation <hcloud.locations.client.BoundLocation>` or :class:`Location <hcloud.locations.domain.Location>` - :param datacenter: :class:`BoundDatacenter <hcloud.datacenters.client.BoundDatacenter>` or :class:`Datacenter <hcloud.datacenters.domain.Datacenter>` :param start_after_create: boolean (optional) Start Server right after creation. Defaults to True. :param automount: boolean (optional) @@ -681,15 +670,6 @@ if location is not None: data["location"] = location.id_or_name - if datacenter is not None: - warnings.warn( - "The 'datacenter' argument is deprecated and will be removed after 1 July 2026. " - "Please use the 'location' argument instead. " - "See https://docs.hetzner.cloud/changelog#2025-12-16-phasing-out-datacenters", - DeprecationWarning, - stacklevel=2, - ) - data["datacenter"] = datacenter.id_or_name if ssh_keys is not None: data["ssh_keys"] = [ssh_key.id_or_name for ssh_key in ssh_keys] if volumes is not None: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-2.22.0/hcloud/servers/domain.py new/hcloud-2.23.0/hcloud/servers/domain.py --- old/hcloud-2.22.0/hcloud/servers/domain.py 2026-06-18 17:33:29.000000000 +0200 +++ new/hcloud-2.23.0/hcloud/servers/domain.py 2026-07-21 14:31:07.000000000 +0200 @@ -1,13 +1,11 @@ from __future__ import annotations -import warnings from typing import TYPE_CHECKING, Literal, TypedDict from ..core import BaseDomain, DomainIdentityMixin if TYPE_CHECKING: from ..actions import BoundAction - from ..datacenters import BoundDatacenter from ..firewalls import BoundFirewall from ..floating_ips import BoundFloatingIP from ..images import BoundImage @@ -56,12 +54,6 @@ :param public_net: :class:`PublicNetwork <hcloud.servers.domain.PublicNetwork>` Public network information. :param server_type: :class:`BoundServerType <hcloud.server_types.client.BoundServerType>` - :param datacenter: :class:`BoundDatacenter <hcloud.datacenters.client.BoundDatacenter>` - - This property is deprecated and will be removed after 1 July 2026. - Please use the ``location`` property instead. - - See https://docs.hetzner.cloud/changelog#2025-12-16-phasing-out-datacenters. :param location: :class:`BoundLocation <hcloud.locations.client.BoundLocation>` :param image: :class:`BoundImage <hcloud.images.client.BoundImage>`, None :param iso: :class:`BoundIso <hcloud.isos.client.BoundIso>`, None @@ -108,7 +100,7 @@ STATUS_UNKNOWN = "unknown" """Server Status unknown""" - __properties__ = ( + __api_properties__ = ( "id", "name", "status", @@ -131,14 +123,7 @@ "primary_disk_size", "placement_group", ) - __api_properties__ = ( - *__properties__, - "datacenter", - ) - __slots__ = ( - *__properties__, - "_datacenter", - ) + __slots__ = __api_properties__ # pylint: disable=too-many-locals def __init__( @@ -149,7 +134,6 @@ created: str | None = None, public_net: PublicNetwork | None = None, server_type: BoundServerType | None = None, - datacenter: BoundDatacenter | None = None, location: BoundLocation | None = None, image: BoundImage | None = None, iso: BoundIso | None = None, @@ -172,7 +156,6 @@ self.created = self._parse_datetime(created) self.public_net = public_net self.server_type = server_type - self.datacenter = datacenter self.location = location self.image = image self.iso = iso @@ -199,24 +182,6 @@ return o return None - @property - def datacenter(self) -> BoundDatacenter | None: - """ - :meta private: - """ - warnings.warn( - "The 'datacenter' property is deprecated and will be removed after 1 July 2026. " - "Please use the 'location' property instead. " - "See https://docs.hetzner.cloud/changelog#2025-12-16-phasing-out-datacenters.", - DeprecationWarning, - stacklevel=2, - ) - return self._datacenter - - @datacenter.setter - def datacenter(self, value: BoundDatacenter | None) -> None: - self._datacenter = value - class ServerProtection(TypedDict): rebuild: bool diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-2.22.0/hcloud.egg-info/PKG-INFO new/hcloud-2.23.0/hcloud.egg-info/PKG-INFO --- old/hcloud-2.22.0/hcloud.egg-info/PKG-INFO 2026-06-18 17:33:37.000000000 +0200 +++ new/hcloud-2.23.0/hcloud.egg-info/PKG-INFO 2026-07-21 14:31:20.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.4 Name: hcloud -Version: 2.22.0 +Version: 2.23.0 Summary: Official Hetzner Cloud python library Home-page: https://github.com/hetznercloud/hcloud-python Author: Hetzner Cloud GmbH @@ -31,11 +31,11 @@ Requires-Dist: myst-parser<5.2,>=5; extra == "docs" Requires-Dist: watchdog<6.1,>=6; extra == "docs" Provides-Extra: test -Requires-Dist: coverage<7.15,>=7.14; extra == "test" +Requires-Dist: coverage<7.16,>=7.15; extra == "test" Requires-Dist: pylint<4.1,>=4; extra == "test" -Requires-Dist: pytest<9.1,>=9; extra == "test" +Requires-Dist: pytest<9.2,>=9; extra == "test" Requires-Dist: pytest-cov<7.2,>=7; extra == "test" -Requires-Dist: mypy<2.2,>=2.1; extra == "test" +Requires-Dist: mypy<2.4,>=2.3; extra == "test" Requires-Dist: types-python-dateutil; extra == "test" Requires-Dist: types-requests; extra == "test" Dynamic: author diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-2.22.0/hcloud.egg-info/requires.txt new/hcloud-2.23.0/hcloud.egg-info/requires.txt --- old/hcloud-2.22.0/hcloud.egg-info/requires.txt 2026-06-18 17:33:37.000000000 +0200 +++ new/hcloud-2.23.0/hcloud.egg-info/requires.txt 2026-07-21 14:31:20.000000000 +0200 @@ -8,10 +8,10 @@ watchdog<6.1,>=6 [test] -coverage<7.15,>=7.14 +coverage<7.16,>=7.15 pylint<4.1,>=4 -pytest<9.1,>=9 +pytest<9.2,>=9 pytest-cov<7.2,>=7 -mypy<2.2,>=2.1 +mypy<2.4,>=2.3 types-python-dateutil types-requests diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-2.22.0/setup.py new/hcloud-2.23.0/setup.py --- old/hcloud-2.22.0/setup.py 2026-06-18 17:33:29.000000000 +0200 +++ new/hcloud-2.23.0/setup.py 2026-07-21 14:31:07.000000000 +0200 @@ -7,7 +7,7 @@ setup( name="hcloud", - version="2.22.0", # x-releaser-pleaser-version + version="2.23.0", # x-releaser-pleaser-version keywords="hcloud hetzner cloud", description="Official Hetzner Cloud python library", long_description=readme, @@ -46,11 +46,11 @@ "watchdog>=6,<6.1", ], "test": [ - "coverage>=7.14,<7.15", + "coverage>=7.15,<7.16", "pylint>=4,<4.1", - "pytest>=9,<9.1", + "pytest>=9,<9.2", "pytest-cov>=7,<7.2", - "mypy>=2.1,<2.2", + "mypy>=2.3,<2.4", "types-python-dateutil", "types-requests", ], diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-2.22.0/tests/unit/load_balancer_types/conftest.py new/hcloud-2.23.0/tests/unit/load_balancer_types/conftest.py --- old/hcloud-2.22.0/tests/unit/load_balancer_types/conftest.py 2026-06-18 17:33:29.000000000 +0200 +++ new/hcloud-2.23.0/tests/unit/load_balancer_types/conftest.py 2026-07-21 14:31:07.000000000 +0200 @@ -4,114 +4,49 @@ @pytest.fixture() -def load_balancer_type_response(): +def load_balancer_type1(): return { - "load_balancer_type": { - "id": 1, - "name": "LB11", - "description": "LB11", - "max_connections": 1, - "max_services": 1, - "max_targets": 1, - "max_assigned_certificates": 1, - "deprecated": None, - "prices": [ - { - "location": "fsn1", - "price_hourly": { - "net": "1.0000000000", - "gross": "1.1900000000000000", - }, - "price_monthly": { - "net": "1.0000000000", - "gross": "1.1900000000000000", - }, - } - ], - } - } - - [email protected]() -def two_load_balancer_types_response(): - return { - "load_balancer_types": [ - { - "id": 1, - "name": "LB11", - "description": "LB11D", - "max_connections": 1, - "max_services": 1, - "max_targets": 1, - "max_assigned_certificates": 1, - "deprecated": None, - "prices": [ - { - "location": "fsn1", - "price_hourly": { - "net": "1.0000000000", - "gross": "1.1900000000000000", - }, - "price_monthly": { - "net": "1.0000000000", - "gross": "1.1900000000000000", - }, - } - ], - }, + "id": 1, + "name": "lb11", + "description": "LB11", + "max_connections": 10000, + "max_services": 5, + "max_targets": 25, + "max_assigned_certificates": 10, + "deprecation": { + "announced": "2023-06-01T00:00:00Z", + "unavailable_after": "2023-09-01T00:00:00Z", + }, + "prices": [ { - "id": 2, - "name": "LB21", - "description": "LB21D", - "max_connections": 2, - "max_services": 2, - "max_targets": 2, - "max_assigned_certificates": 2, - "deprecated": None, - "prices": [ - { - "location": "fsn1", - "price_hourly": { - "net": "1.0000000000", - "gross": "1.1900000000000000", - }, - "price_monthly": { - "net": "1.0000000000", - "gross": "1.1900000000000000", - }, - } - ], + "location": "fsn1", + "price_hourly": {"net": "0.0120", "gross": "0.0120"}, + "price_monthly": {"net": "7.4900", "gross": "7.4900"}, + "price_per_tb_traffic": {"net": "1.0000", "gross": "1.0000"}, + "included_traffic": 21990232555520, }, - ] + ], } @pytest.fixture() -def one_load_balancer_types_response(): +def load_balancer_type2(): return { - "load_balancer_types": [ + "id": 2, + "name": "lb21", + "description": "LB21", + "max_connections": 20000, + "max_services": 15, + "max_targets": 75, + "max_assigned_certificates": 25, + "deprecation": None, + "prices": [ { - "id": 2, - "name": "LB21", - "description": "LB21D", - "max_connections": 2, - "max_services": 2, - "max_targets": 2, - "max_assigned_certificates": 2, - "deprecated": None, - "prices": [ - { - "location": "fsn1", - "price_hourly": { - "net": "1.0000000000", - "gross": "1.1900000000000000", - }, - "price_monthly": { - "net": "1.0000000000", - "gross": "1.1900000000000000", - }, - } - ], - } - ] + "location": "fsn1", + "price_hourly": {"net": "0.0344", "gross": "0.0344"}, + "price_monthly": {"net": "21.4900", "gross": "21.4900"}, + "price_per_tb_traffic": {"net": "1.0000", "gross": "1.0000"}, + "included_traffic": 21990232555520, + }, + ], } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-2.22.0/tests/unit/load_balancer_types/test_client.py new/hcloud-2.23.0/tests/unit/load_balancer_types/test_client.py --- old/hcloud-2.22.0/tests/unit/load_balancer_types/test_client.py 2026-06-18 17:33:29.000000000 +0200 +++ new/hcloud-2.23.0/tests/unit/load_balancer_types/test_client.py 2026-07-21 14:31:07.000000000 +0200 @@ -3,6 +3,7 @@ from unittest import mock import pytest +from dateutil.parser import isoparse from hcloud import Client from hcloud.load_balancer_types import LoadBalancerTypesClient @@ -17,31 +18,55 @@ self, request_mock: mock.MagicMock, load_balancer_types_client: LoadBalancerTypesClient, - load_balancer_type_response, + load_balancer_type1, ): - request_mock.return_value = load_balancer_type_response + request_mock.return_value = { + "load_balancer_type": load_balancer_type1, + } - load_balancer_type = load_balancer_types_client.get_by_id(1) + result = load_balancer_types_client.get_by_id(1) request_mock.assert_called_with( method="GET", url="/load_balancer_types/1", ) - assert load_balancer_type._client is load_balancer_types_client - assert load_balancer_type.id == 1 - assert load_balancer_type.name == "LB11" + + assert result._client is load_balancer_types_client + assert result.id == 1 + assert result.name == "lb11" + assert result.description == "LB11" + assert result.max_connections == 10000 + assert result.max_services == 5 + assert result.max_targets == 25 + assert result.max_assigned_certificates == 10 + assert result.prices == [ + { + "location": "fsn1", + "price_hourly": {"net": "0.0120", "gross": "0.0120"}, + "price_monthly": {"net": "7.4900", "gross": "7.4900"}, + "price_per_tb_traffic": {"net": "1.0000", "gross": "1.0000"}, + "included_traffic": 21990232555520, + } + ] + assert result.deprecation.announced == isoparse("2023-06-01T00:00:00+00:00") + assert result.deprecation.unavailable_after == isoparse( + "2023-09-01T00:00:00+00:00" + ) @pytest.mark.parametrize( - "params", [{"name": "LB11", "page": 1, "per_page": 10}, {"name": ""}, {}] + "params", [{"name": "lb11", "page": 1, "per_page": 10}, {"name": ""}, {}] ) def test_get_list( self, request_mock: mock.MagicMock, load_balancer_types_client: LoadBalancerTypesClient, - two_load_balancer_types_response, + load_balancer_type1, + load_balancer_type2, params, ): - request_mock.return_value = two_load_balancer_types_response + request_mock.return_value = { + "load_balancer_types": [load_balancer_type1, load_balancer_type2], + } result = load_balancer_types_client.get_list(**params) @@ -51,33 +76,31 @@ params=params, ) - load_balancer_types = result.load_balancer_types assert result.meta is not None + assert len(result.load_balancer_types) == 2 - assert len(load_balancer_types) == 2 - - load_balancer_types1 = load_balancer_types[0] - load_balancer_types2 = load_balancer_types[1] - - assert load_balancer_types1._client is load_balancer_types_client - assert load_balancer_types1.id == 1 - assert load_balancer_types1.name == "LB11" + assert result.load_balancer_types[0]._client is load_balancer_types_client + assert result.load_balancer_types[0].id == 1 + assert result.load_balancer_types[0].name == "lb11" - assert load_balancer_types2._client is load_balancer_types_client - assert load_balancer_types2.id == 2 - assert load_balancer_types2.name == "LB21" + assert result.load_balancer_types[1]._client is load_balancer_types_client + assert result.load_balancer_types[1].id == 2 + assert result.load_balancer_types[1].name == "lb21" - @pytest.mark.parametrize("params", [{"name": "LB21"}]) + @pytest.mark.parametrize("params", [{"name": "lb11"}]) def test_get_all( self, request_mock: mock.MagicMock, load_balancer_types_client: LoadBalancerTypesClient, - two_load_balancer_types_response, + load_balancer_type1, + load_balancer_type2, params, ): - request_mock.return_value = two_load_balancer_types_response + request_mock.return_value = { + "load_balancer_types": [load_balancer_type1, load_balancer_type2] + } - load_balancer_types = load_balancer_types_client.get_all(**params) + result = load_balancer_types_client.get_all(**params) params.update({"page": 1, "per_page": 50}) @@ -87,37 +110,34 @@ params=params, ) - assert len(load_balancer_types) == 2 + assert len(result) == 2 - load_balancer_types1 = load_balancer_types[0] - load_balancer_types2 = load_balancer_types[1] - - assert load_balancer_types1._client is load_balancer_types_client - assert load_balancer_types1.id == 1 - assert load_balancer_types1.name == "LB11" - - assert load_balancer_types2._client is load_balancer_types_client - assert load_balancer_types2.id == 2 - assert load_balancer_types2.name == "LB21" + assert result[0]._client is load_balancer_types_client + assert result[0].id == 1 + assert result[0].name == "lb11" + + assert result[1]._client is load_balancer_types_client + assert result[1].id == 2 + assert result[1].name == "lb21" def test_get_by_name( self, request_mock: mock.MagicMock, load_balancer_types_client: LoadBalancerTypesClient, - one_load_balancer_types_response, + load_balancer_type1, ): - request_mock.return_value = one_load_balancer_types_response - - load_balancer_type = load_balancer_types_client.get_by_name("LB21") + request_mock.return_value = { + "load_balancer_types": [load_balancer_type1], + } - params = {"name": "LB21"} + result = load_balancer_types_client.get_by_name("lb11") request_mock.assert_called_with( method="GET", url="/load_balancer_types", - params=params, + params={"name": "lb11"}, ) - assert load_balancer_type._client is load_balancer_types_client - assert load_balancer_type.id == 2 - assert load_balancer_type.name == "LB21" + assert result._client is load_balancer_types_client + assert result.id == 1 + assert result.name == "lb11" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-2.22.0/tests/unit/primary_ips/conftest.py new/hcloud-2.23.0/tests/unit/primary_ips/conftest.py --- old/hcloud-2.22.0/tests/unit/primary_ips/conftest.py 2026-06-18 17:33:29.000000000 +0200 +++ new/hcloud-2.23.0/tests/unit/primary_ips/conftest.py 2026-07-21 14:31:07.000000000 +0200 @@ -14,10 +14,6 @@ "assignee_type": "server", "auto_delete": True, "blocked": False, - "datacenter": { - "id": 4, - "name": "fsn1-dc14", - }, "location": { "id": 1, "name": "fsn1", @@ -42,10 +38,6 @@ "assignee_type": "server", "auto_delete": True, "blocked": False, - "datacenter": { - "id": 4, - "name": "fsn1-dc14", - }, "location": { "id": 1, "name": "fsn1", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-2.22.0/tests/unit/primary_ips/test_client.py new/hcloud-2.23.0/tests/unit/primary_ips/test_client.py --- old/hcloud-2.22.0/tests/unit/primary_ips/test_client.py 2026-06-18 17:33:29.000000000 +0200 +++ new/hcloud-2.23.0/tests/unit/primary_ips/test_client.py 2026-07-21 14:31:07.000000000 +0200 @@ -5,7 +5,6 @@ import pytest from hcloud import Client -from hcloud.datacenters import BoundDatacenter, Datacenter from hcloud.locations import BoundLocation, Location from hcloud.primary_ips import BoundPrimaryIP, PrimaryIP, PrimaryIPsClient @@ -62,13 +61,6 @@ assert o.location.id == 1 assert o.location.name == "fsn1" - with pytest.deprecated_call(): - datacenter = o.datacenter - - assert isinstance(datacenter, BoundDatacenter) - assert datacenter.id == 4 - assert datacenter.name == "fsn1-dc14" - class TestPrimaryIPsClient: @pytest.fixture() @@ -166,37 +158,6 @@ "auto_delete": False, }, ) - assert_bound_primary_ip1(result.primary_ip, resource_client) - assert result.action is None - - def test_create_with_datacenter( - self, - request_mock: mock.MagicMock, - resource_client: PrimaryIPsClient, - primary_ip1, - ): - request_mock.return_value = { - "primary_ip": primary_ip1, - "action": None, - } - - with pytest.deprecated_call(): - result = resource_client.create( - type="ipv4", - name="primary-ip1", - datacenter=Datacenter(name="fsn1-dc14"), - ) - - request_mock.assert_called_with( - method="POST", - url="/primary_ips", - json={ - "name": "primary-ip1", - "type": "ipv4", - "datacenter": "fsn1-dc14", - "auto_delete": False, - }, - ) assert_bound_primary_ip1(result.primary_ip, resource_client) assert result.action is None diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-2.22.0/tests/unit/servers/conftest.py new/hcloud-2.23.0/tests/unit/servers/conftest.py --- old/hcloud-2.22.0/tests/unit/servers/conftest.py 2026-06-18 17:33:29.000000000 +0200 +++ new/hcloud-2.23.0/tests/unit/servers/conftest.py 2026-07-21 14:31:07.000000000 +0200 @@ -58,25 +58,6 @@ "storage_type": "local", "cpu_type": "shared", }, - "datacenter": { - "id": 1, - "name": "fsn1-dc8", - "description": "Falkenstein 1 DC 8", - "location": { - "id": 1, - "name": "fsn1", - "description": "Falkenstein DC Park 1", - "country": "DE", - "city": "Falkenstein", - "latitude": 50.47612, - "longitude": 12.370071, - }, - "server_types": { - "supported": [1, 2, 3], - "available": [1, 2, 3], - "available_for_migration": [1, 2, 3], - }, - }, "image": { "id": 4711, "type": "snapshot", @@ -159,25 +140,6 @@ "storage_type": "local", "cpu_type": "shared", }, - "datacenter": { - "id": 1, - "name": "fsn1-dc8", - "description": "Falkenstein 1 DC 8", - "location": { - "id": 1, - "name": "fsn1", - "description": "Falkenstein DC Park 1", - "country": "DE", - "city": "Falkenstein", - "latitude": 50.47612, - "longitude": 12.370071, - }, - "server_types": { - "supported": [1, 2, 3], - "available": [1, 2, 3], - "available_for_migration": [1, 2, 3], - }, - }, "image": { "id": 4711, "type": "snapshot", @@ -281,25 +243,6 @@ "storage_type": "local", "cpu_type": "shared", }, - "datacenter": { - "id": 1, - "name": "fsn1-dc8", - "description": "Falkenstein 1 DC 8", - "location": { - "id": 1, - "name": "fsn1", - "description": "Falkenstein DC Park 1", - "country": "DE", - "city": "Falkenstein", - "latitude": 50.47612, - "longitude": 12.370071, - }, - "server_types": { - "supported": [1, 2, 3], - "available": [1, 2, 3], - "available_for_migration": [1, 2, 3], - }, - }, "image": { "id": 4711, "type": "snapshot", @@ -444,25 +387,6 @@ "storage_type": "local", "cpu_type": "shared", }, - "datacenter": { - "id": 1, - "name": "fsn1-dc8", - "description": "Falkenstein 1 DC 8", - "location": { - "id": 1, - "name": "fsn1", - "description": "Falkenstein DC Park 1", - "country": "DE", - "city": "Falkenstein", - "latitude": 50.47612, - "longitude": 12.370071, - }, - "server_types": { - "supported": [1, 2, 3], - "available": [1, 2, 3], - "available_for_migration": [1, 2, 3], - }, - }, "image": { "id": 4711, "type": "snapshot", @@ -546,25 +470,6 @@ "storage_type": "local", "cpu_type": "shared", }, - "datacenter": { - "id": 1, - "name": "fsn1-dc8", - "description": "Falkenstein 1 DC 8", - "location": { - "id": 1, - "name": "fsn1", - "description": "Falkenstein DC Park 1", - "country": "DE", - "city": "Falkenstein", - "latitude": 50.47612, - "longitude": 12.370071, - }, - "server_types": { - "supported": [1, 2, 3], - "available": [1, 2, 3], - "available_for_migration": [1, 2, 3], - }, - }, "image": { "id": 4711, "type": "snapshot", @@ -643,25 +548,6 @@ "storage_type": "local", "cpu_type": "shared", }, - "datacenter": { - "id": 1, - "name": "fsn1-dc8", - "description": "Falkenstein 1 DC 8", - "location": { - "id": 1, - "name": "fsn1", - "description": "Falkenstein DC Park 1", - "country": "DE", - "city": "Falkenstein", - "latitude": 50.47612, - "longitude": 12.370071, - }, - "server_types": { - "supported": [1, 2, 3], - "available": [1, 2, 3], - "available_for_migration": [1, 2, 3], - }, - }, "image": { "id": 4711, "type": "snapshot", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/hcloud-2.22.0/tests/unit/servers/test_client.py new/hcloud-2.23.0/tests/unit/servers/test_client.py --- old/hcloud-2.22.0/tests/unit/servers/test_client.py 2026-06-18 17:33:29.000000000 +0200 +++ new/hcloud-2.23.0/tests/unit/servers/test_client.py 2026-07-21 14:31:07.000000000 +0200 @@ -6,7 +6,6 @@ from hcloud import Client from hcloud.actions import BoundAction -from hcloud.datacenters import BoundDatacenter, Datacenter from hcloud.firewalls import BoundFirewall, Firewall from hcloud.floating_ips import BoundFloatingIP from hcloud.images import BoundImage, Image @@ -100,14 +99,6 @@ assert bound_server.public_net.floating_ips[0].id == 478 assert bound_server.public_net.floating_ips[0].complete is False - with pytest.deprecated_call(): - datacenter = bound_server.datacenter - - assert isinstance(datacenter, BoundDatacenter) - assert datacenter._client == bound_server._client._parent.datacenters - assert datacenter.id == 1 - assert datacenter.complete is True - assert isinstance(bound_server.server_type, BoundServerType) assert ( bound_server.server_type._client @@ -281,46 +272,6 @@ assert bound_server.id == 1 assert bound_server.name == "my-server" - def test_create_with_datacenter( - self, - request_mock: mock.MagicMock, - servers_client: ServersClient, - response_create_simple_server, - ): - request_mock.return_value = response_create_simple_server - - with pytest.deprecated_call(): - response = servers_client.create( - "my-server", - server_type=ServerType(name="cx11"), - image=Image(id=4711), - datacenter=Datacenter(id=1), - ) - - request_mock.assert_called_with( - method="POST", - url="/servers", - json={ - "name": "my-server", - "server_type": "cx11", - "image": 4711, - "datacenter": 1, - "start_after_create": True, - }, - ) - - bound_server = response.server - bound_action = response.action - - assert bound_server._client is servers_client - assert bound_server.id == 1 - assert bound_server.name == "my-server" - - assert isinstance(bound_action, BoundAction) - assert bound_action._client == servers_client._parent.actions - assert bound_action.id == 1 - assert bound_action.command == "create_server" - def test_create_with_location( self, request_mock: mock.MagicMock,
