Skip to content

Commit 87e7fd8

Browse files
committed
refactor(svm): align supports_svm with supports_window_control pattern
Per cdnninja review (2026-08-06): supports_svm was a probe method on VehicleManager/ApiImpl (GET getSVMDetails, check image_bytes), deviating from the library's capability convention. supports_window_control and supports_valet_mode are per-region class attributes on the region API, stamped onto Vehicle by VehicleManager.initialize_vehicles — no API call. Align supports_svm to the same pattern: - ApiImpl: class attr supports_svm = False (was a probe stub method) - HyundaiBlueLinkApiUSA: class attr supports_svm = True (was a probe method) - VehicleManager: stamp vehicle.supports_svm = api.supports_svm in initialize_vehicles; drop the supports_svm(vehicle_id) wrapper - Vehicle.supports_svm field unchanged (canonical source, now stamped) Tradeoff: capability is per-region, not per-vehicle. Models without SVM hardware will show the entity; capture fails at runtime — same as supports_window_control today. ijojog (tester) accepted flag-on-Vehicle. Also fix latent ruff violations exposed by removing .ruff.toml (prev commit, which unmasked pyproject.toml [tool.ruff] py312 rule set): - I001 import sort (ApiImpl, VehicleManager, us_svm_test) - PYI041 svm._parse_float: int | float -> float - PIE790 SafetyAcknowledgmentError unnecessary pass - UP017 dt.timezone.utc -> dt.UTC (tests) - SIM117 collapse nested with (tests) - TRY004 noqa on _FakeResponse.json ValueError (JSONDecodeError semantic) Tests: drop 10 probe tests, add 3 class-attr/stamp tests. 450 pass, ruff clean.
1 parent 33e24c4 commit 87e7fd8

6 files changed

Lines changed: 81 additions & 210 deletions

File tree

hyundai_kia_connect_api/ApiImpl.py

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@
2525
VEHICLE_LOCK_ACTION,
2626
WINDOW_STATE,
2727
)
28+
from .svm import SVMDetails
2829
from .Token import Token
2930
from .utils import get_child_value, to_int_enum
3031
from .Vehicle import Vehicle
31-
from .svm import SVMDetails
3232

3333
_LOGGER = logging.getLogger(__name__)
3434

@@ -165,6 +165,7 @@ class ApiImpl:
165165
previous_longitude: float = None
166166
supports_window_control: bool = False
167167
supports_valet_mode: bool = False
168+
supports_svm: bool = False
168169

169170
def __init__(self) -> None:
170171
"""Initialize."""
@@ -460,14 +461,3 @@ def request_svm_capture(
460461
raise NotImplementedError(
461462
"request_svm_capture is not implemented for this region"
462463
)
463-
464-
def supports_svm(self, token: Token, vehicle: Vehicle) -> bool:
465-
"""Return whether this vehicle supports SVM.
466-
467-
The base implementation returns a cached value if present, otherwise
468-
False without mutating the vehicle. Region subclasses that support SVM
469-
should override and probe.
470-
"""
471-
if vehicle.supports_svm is not None:
472-
return vehicle.supports_svm
473-
return False

hyundai_kia_connect_api/HyundaiBlueLinkApiUSA.py

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,11 @@ class HyundaiBlueLinkApiUSA(ApiImpl):
141141
_SVM_POLL_TIMEOUT_SECONDS = 120
142142
_SVM_INITIAL_WAIT_SECONDS = 15
143143

144+
# Hyundai BlueLink USA exposes SVM / Find My Car for supported vehicles.
145+
# Capability is declared per-region (like supports_window_control); the
146+
# actual image is fetched on demand via get_svm_details / request_svm_capture.
147+
supports_svm: bool = True
148+
144149
# Maps transaction IDs to service_type values for action status polling.
145150
# Horn/hazard commands need HORN_AND_LIGHTS or LIGHTS_ONLY instead of
146151
# the default REMOTE_POLL.
@@ -1028,21 +1033,6 @@ def request_svm_capture(
10281033
f"{self._SVM_POLL_TIMEOUT_SECONDS} seconds"
10291034
)
10301035

1031-
def supports_svm(self, token: Token, vehicle: Vehicle) -> bool:
1032-
"""Probe whether this USA Hyundai vehicle supports SVM.
1033-
1034-
Caches the result on the vehicle. Any API or auth failure is treated
1035-
as "not supported" so that consumers do not have to handle exceptions.
1036-
"""
1037-
if vehicle.supports_svm is not None:
1038-
return vehicle.supports_svm
1039-
try:
1040-
details = self.get_svm_details(token, vehicle)
1041-
vehicle.supports_svm = bool(details.image_bytes)
1042-
except Exception:
1043-
vehicle.supports_svm = False
1044-
return vehicle.supports_svm
1045-
10461036
@staticmethod
10471037
def _svm_is_fresh(
10481038
details: SVMDetails,

hyundai_kia_connect_api/VehicleManager.py

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
ScheduleChargingClimateRequestOptions,
1515
WindowRequestOptions,
1616
)
17-
from .svm import SVMDetails
1817
from .const import (
1918
BRAND_GENESIS,
2019
BRAND_HYUNDAI,
@@ -45,6 +44,7 @@
4544
from .KiaUvoApiEU import KiaUvoApiEU
4645
from .KiaUvoApiIN import KiaUvoApiIN
4746
from .KiaUvoApiUSA import KiaUvoApiUSA
47+
from .svm import SVMDetails
4848
from .Token import Token
4949
from .Vehicle import Vehicle
5050

@@ -131,6 +131,7 @@ def initialize_vehicles(self):
131131
for vehicle in vehicles:
132132
vehicle.supports_window_control = self.api.supports_window_control
133133
vehicle.supports_valet_mode = self.api.supports_valet_mode
134+
vehicle.supports_svm = self.api.supports_svm
134135
self.vehicles[vehicle.id] = vehicle
135136

136137
def get_vehicle(self, vehicle_id: str) -> Vehicle:
@@ -192,20 +193,6 @@ def force_refresh_vehicle_state(self, vehicle_id: str) -> None:
192193
else:
193194
_LOGGER.debug(f"{DOMAIN} - Vehicle Disabled, skipping.")
194195

195-
def supports_svm(self, vehicle_id: str) -> bool:
196-
"""Return whether the given vehicle supports SVM.
197-
198-
Delegates to the region-specific API implementation. Missing vehicles
199-
and any API failures are reported as False.
200-
"""
201-
vehicle = self.vehicles.get(vehicle_id)
202-
if vehicle is None:
203-
return False
204-
try:
205-
return self.api.supports_svm(self.token, vehicle)
206-
except Exception:
207-
return False
208-
209196
def get_svm_details(self, vehicle_id: str) -> SVMDetails:
210197
"""Return the latest cached SVM composite image and metadata.
211198

hyundai_kia_connect_api/exceptions.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,6 @@ class SafetyAcknowledgmentError(APIError):
7171
before it can be executed (e.g. SVM/Find My Car capture).
7272
"""
7373

74-
pass
75-
7674

7775
class UnsupportedControlError(APIError):
7876
"""

hyundai_kia_connect_api/svm.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def _parse_int(value: str | int | None) -> int | None:
2929
return None
3030

3131

32-
def _parse_float(value: str | float | int | None) -> float | None:
32+
def _parse_float(value: str | float | None) -> float | None:
3333
if value is None:
3434
return None
3535
try:

0 commit comments

Comments
 (0)