python-duco-connectivity 0.11.0__tar.gz → 0.13.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {python_duco_connectivity-0.11.0/src/python_duco_connectivity.egg-info → python_duco_connectivity-0.13.0}/PKG-INFO +7 -4
- {python_duco_connectivity-0.11.0 → python_duco_connectivity-0.13.0}/README.md +6 -3
- {python_duco_connectivity-0.11.0 → python_duco_connectivity-0.13.0}/pyproject.toml +1 -1
- {python_duco_connectivity-0.11.0 → python_duco_connectivity-0.13.0}/src/duco_connectivity/__init__.py +2 -0
- {python_duco_connectivity-0.11.0 → python_duco_connectivity-0.13.0}/src/duco_connectivity/client.py +35 -1
- {python_duco_connectivity-0.11.0 → python_duco_connectivity-0.13.0}/src/duco_connectivity/models.py +15 -6
- {python_duco_connectivity-0.11.0 → python_duco_connectivity-0.13.0/src/python_duco_connectivity.egg-info}/PKG-INFO +7 -4
- {python_duco_connectivity-0.11.0 → python_duco_connectivity-0.13.0}/tests/test_client.py +98 -6
- {python_duco_connectivity-0.11.0 → python_duco_connectivity-0.13.0}/LICENSE +0 -0
- {python_duco_connectivity-0.11.0 → python_duco_connectivity-0.13.0}/setup.cfg +0 -0
- {python_duco_connectivity-0.11.0 → python_duco_connectivity-0.13.0}/src/duco_connectivity/__main__.py +0 -0
- {python_duco_connectivity-0.11.0 → python_duco_connectivity-0.13.0}/src/duco_connectivity/cli.py +0 -0
- {python_duco_connectivity-0.11.0 → python_duco_connectivity-0.13.0}/src/duco_connectivity/exceptions.py +0 -0
- {python_duco_connectivity-0.11.0 → python_duco_connectivity-0.13.0}/src/duco_connectivity/py.typed +0 -0
- {python_duco_connectivity-0.11.0 → python_duco_connectivity-0.13.0}/src/python_duco_connectivity.egg-info/SOURCES.txt +0 -0
- {python_duco_connectivity-0.11.0 → python_duco_connectivity-0.13.0}/src/python_duco_connectivity.egg-info/dependency_links.txt +0 -0
- {python_duco_connectivity-0.11.0 → python_duco_connectivity-0.13.0}/src/python_duco_connectivity.egg-info/entry_points.txt +0 -0
- {python_duco_connectivity-0.11.0 → python_duco_connectivity-0.13.0}/src/python_duco_connectivity.egg-info/requires.txt +0 -0
- {python_duco_connectivity-0.11.0 → python_duco_connectivity-0.13.0}/src/python_duco_connectivity.egg-info/top_level.txt +0 -0
- {python_duco_connectivity-0.11.0 → python_duco_connectivity-0.13.0}/tests/test_api_reference.py +0 -0
- {python_duco_connectivity-0.11.0 → python_duco_connectivity-0.13.0}/tests/test_cli.py +0 -0
- {python_duco_connectivity-0.11.0 → python_duco_connectivity-0.13.0}/tests/test_exceptions.py +0 -0
- {python_duco_connectivity-0.11.0 → python_duco_connectivity-0.13.0}/tests/test_local_sample_validation.py +0 -0
- {python_duco_connectivity-0.11.0 → python_duco_connectivity-0.13.0}/tests/test_models.py +0 -0
- {python_duco_connectivity-0.11.0 → python_duco_connectivity-0.13.0}/tests/test_pytest_live_support.py +0 -0
- {python_duco_connectivity-0.11.0 → python_duco_connectivity-0.13.0}/tests/test_replay_helpers.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-duco-connectivity
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.13.0
|
|
4
4
|
Summary: Async HTTP client for the local Duco Connectivity API
|
|
5
5
|
Author: Ronald van der Meer
|
|
6
6
|
License-Expression: MIT
|
|
@@ -80,9 +80,11 @@ bypass-target helper returns a typed target model for successful parameter-
|
|
|
80
80
|
specific reads and raises `DucoError` if the requested target field is missing
|
|
81
81
|
from an otherwise valid `/config` response.
|
|
82
82
|
|
|
83
|
-
Diagnostic subsystem reads
|
|
84
|
-
`
|
|
85
|
-
|
|
83
|
+
Diagnostic subsystem reads expose known status values as normalized `DiagStatus`
|
|
84
|
+
members (`ok`, `disabled`, or `error`). Each `DiagComponent` also keeps the exact
|
|
85
|
+
API value in `raw_status`; an unrecognized future value produces `status=None`
|
|
86
|
+
without discarding the raw value. Subsystem names remain unfiltered so future
|
|
87
|
+
components are available to downstream consumers.
|
|
86
88
|
|
|
87
89
|
## Getting started
|
|
88
90
|
|
|
@@ -184,6 +186,7 @@ For local function probes without activating the environment first:
|
|
|
184
186
|
.venv/bin/python -m duco_connectivity --host 192.168.1.10 call async_get_board_info
|
|
185
187
|
.venv/bin/duco-probe --host 192.168.1.10 call async_get_board_info
|
|
186
188
|
.venv/bin/duco-probe --host 192.168.1.10 call async_get_ventilation_temperature_info
|
|
189
|
+
.venv/bin/duco-probe --host 192.168.1.10 call async_get_bypass_supply_temperature_targets
|
|
187
190
|
.venv/bin/duco-probe --host 192.168.1.10 call async_get_bypass_supply_temperature_target --kwargs '{"zone_id": 1}'
|
|
188
191
|
```
|
|
189
192
|
|
|
@@ -48,9 +48,11 @@ bypass-target helper returns a typed target model for successful parameter-
|
|
|
48
48
|
specific reads and raises `DucoError` if the requested target field is missing
|
|
49
49
|
from an otherwise valid `/config` response.
|
|
50
50
|
|
|
51
|
-
Diagnostic subsystem reads
|
|
52
|
-
`
|
|
53
|
-
|
|
51
|
+
Diagnostic subsystem reads expose known status values as normalized `DiagStatus`
|
|
52
|
+
members (`ok`, `disabled`, or `error`). Each `DiagComponent` also keeps the exact
|
|
53
|
+
API value in `raw_status`; an unrecognized future value produces `status=None`
|
|
54
|
+
without discarding the raw value. Subsystem names remain unfiltered so future
|
|
55
|
+
components are available to downstream consumers.
|
|
54
56
|
|
|
55
57
|
## Getting started
|
|
56
58
|
|
|
@@ -152,6 +154,7 @@ For local function probes without activating the environment first:
|
|
|
152
154
|
.venv/bin/python -m duco_connectivity --host 192.168.1.10 call async_get_board_info
|
|
153
155
|
.venv/bin/duco-probe --host 192.168.1.10 call async_get_board_info
|
|
154
156
|
.venv/bin/duco-probe --host 192.168.1.10 call async_get_ventilation_temperature_info
|
|
157
|
+
.venv/bin/duco-probe --host 192.168.1.10 call async_get_bypass_supply_temperature_targets
|
|
155
158
|
.venv/bin/duco-probe --host 192.168.1.10 call async_get_bypass_supply_temperature_target --kwargs '{"zone_id": 1}'
|
|
156
159
|
```
|
|
157
160
|
|
|
@@ -54,6 +54,7 @@ from .models import (
|
|
|
54
54
|
DeviceGroupConfigSubmoduleSelector,
|
|
55
55
|
DiagComponent,
|
|
56
56
|
DiagInfo,
|
|
57
|
+
DiagStatus,
|
|
57
58
|
DucoSerialNumber,
|
|
58
59
|
DucoVersion,
|
|
59
60
|
HostName,
|
|
@@ -167,6 +168,7 @@ __all__ = [
|
|
|
167
168
|
"DeviceGroupConfigSubmoduleSelector",
|
|
168
169
|
"DiagComponent",
|
|
169
170
|
"DiagInfo",
|
|
171
|
+
"DiagStatus",
|
|
170
172
|
"DucoClient",
|
|
171
173
|
"DucoConnectionError",
|
|
172
174
|
"DucoError",
|
{python_duco_connectivity-0.11.0 → python_duco_connectivity-0.13.0}/src/duco_connectivity/client.py
RENAMED
|
@@ -58,6 +58,7 @@ from .models import (
|
|
|
58
58
|
DeviceGroupConfigSubmoduleSelector,
|
|
59
59
|
DiagComponent,
|
|
60
60
|
DiagInfo,
|
|
61
|
+
DiagStatus,
|
|
61
62
|
InfoGeneralSubmoduleSelector,
|
|
62
63
|
InfoGroup,
|
|
63
64
|
InfoGroupStruct,
|
|
@@ -400,6 +401,19 @@ class DucoClient:
|
|
|
400
401
|
|
|
401
402
|
return cls._build_bypass_supply_temperature_target(zone_id, raw_value)
|
|
402
403
|
|
|
404
|
+
@classmethod
|
|
405
|
+
def _extract_bypass_supply_temperature_targets(
|
|
406
|
+
cls,
|
|
407
|
+
config: Config,
|
|
408
|
+
) -> dict[int, BypassSupplyTemperatureTarget]:
|
|
409
|
+
"""Read all bypass supply targets from a typed config response."""
|
|
410
|
+
return {
|
|
411
|
+
zone_id: target
|
|
412
|
+
for zone_id in range(1, 9)
|
|
413
|
+
if (target := cls._extract_bypass_supply_temperature_target(config, zone_id))
|
|
414
|
+
is not None
|
|
415
|
+
}
|
|
416
|
+
|
|
403
417
|
@staticmethod
|
|
404
418
|
def _read_scalar_value(payload: dict[str, Any], key: str) -> Any:
|
|
405
419
|
raw_value = payload[key]
|
|
@@ -2054,7 +2068,8 @@ class DucoClient:
|
|
|
2054
2068
|
|
|
2055
2069
|
return DiagComponent(
|
|
2056
2070
|
component=component,
|
|
2057
|
-
status=status,
|
|
2071
|
+
status=DiagStatus.from_api_value(status),
|
|
2072
|
+
raw_status=status,
|
|
2058
2073
|
raw_payload=cls._preserve_raw_payload(payload),
|
|
2059
2074
|
)
|
|
2060
2075
|
|
|
@@ -2318,6 +2333,25 @@ class DucoClient:
|
|
|
2318
2333
|
raise DucoError(msg)
|
|
2319
2334
|
return target
|
|
2320
2335
|
|
|
2336
|
+
async def async_get_bypass_supply_temperature_targets(
|
|
2337
|
+
self,
|
|
2338
|
+
) -> dict[int, BypassSupplyTemperatureTarget]:
|
|
2339
|
+
"""Return all bypass supply targets exposed through `/config` in Celsius."""
|
|
2340
|
+
try:
|
|
2341
|
+
config = await self.async_get_config(
|
|
2342
|
+
module=ConfigModuleSelector.HEAT_RECOVERY,
|
|
2343
|
+
submodule=ConfigHeatRecoverySubmoduleSelector.BYPASS,
|
|
2344
|
+
)
|
|
2345
|
+
except DucoResponseError as err:
|
|
2346
|
+
if _is_unsupported_optional_endpoint_error(err, "/config"):
|
|
2347
|
+
raise DucoUnsupportedCapabilityError(
|
|
2348
|
+
err.status,
|
|
2349
|
+
err.path,
|
|
2350
|
+
err.body,
|
|
2351
|
+
) from err
|
|
2352
|
+
raise
|
|
2353
|
+
return self._extract_bypass_supply_temperature_targets(config)
|
|
2354
|
+
|
|
2321
2355
|
async def async_set_bypass_supply_temperature_target(
|
|
2322
2356
|
self,
|
|
2323
2357
|
zone_id: int,
|
{python_duco_connectivity-0.11.0 → python_duco_connectivity-0.13.0}/src/duco_connectivity/models.py
RENAMED
|
@@ -587,12 +587,20 @@ def _coerce_node_motor_position(value: NodeMotorPosition | int) -> NodeMotorPosi
|
|
|
587
587
|
|
|
588
588
|
|
|
589
589
|
class DiagStatus(StrEnum):
|
|
590
|
-
"""
|
|
590
|
+
"""Known normalized health states returned by the diagnostics API."""
|
|
591
591
|
|
|
592
|
-
OK = "
|
|
593
|
-
|
|
594
|
-
ERROR = "
|
|
595
|
-
|
|
592
|
+
OK = "ok"
|
|
593
|
+
DISABLED = "disabled"
|
|
594
|
+
ERROR = "error"
|
|
595
|
+
|
|
596
|
+
@classmethod
|
|
597
|
+
def from_api_value(cls, value: str) -> Self | None:
|
|
598
|
+
"""Return the known normalized status for a raw API value."""
|
|
599
|
+
return {
|
|
600
|
+
"Ok": cls.OK,
|
|
601
|
+
"Disable": cls.DISABLED,
|
|
602
|
+
"Error": cls.ERROR,
|
|
603
|
+
}.get(value)
|
|
596
604
|
|
|
597
605
|
|
|
598
606
|
class ActionResultStatus(StrEnum):
|
|
@@ -1572,7 +1580,8 @@ class DiagComponent:
|
|
|
1572
1580
|
"""Health state for a diagnostic subsystem."""
|
|
1573
1581
|
|
|
1574
1582
|
component: str
|
|
1575
|
-
status:
|
|
1583
|
+
status: DiagStatus | None
|
|
1584
|
+
raw_status: str
|
|
1576
1585
|
raw_payload: dict[str, Any] = field(default_factory=dict, repr=False, compare=False)
|
|
1577
1586
|
|
|
1578
1587
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-duco-connectivity
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.13.0
|
|
4
4
|
Summary: Async HTTP client for the local Duco Connectivity API
|
|
5
5
|
Author: Ronald van der Meer
|
|
6
6
|
License-Expression: MIT
|
|
@@ -80,9 +80,11 @@ bypass-target helper returns a typed target model for successful parameter-
|
|
|
80
80
|
specific reads and raises `DucoError` if the requested target field is missing
|
|
81
81
|
from an otherwise valid `/config` response.
|
|
82
82
|
|
|
83
|
-
Diagnostic subsystem reads
|
|
84
|
-
`
|
|
85
|
-
|
|
83
|
+
Diagnostic subsystem reads expose known status values as normalized `DiagStatus`
|
|
84
|
+
members (`ok`, `disabled`, or `error`). Each `DiagComponent` also keeps the exact
|
|
85
|
+
API value in `raw_status`; an unrecognized future value produces `status=None`
|
|
86
|
+
without discarding the raw value. Subsystem names remain unfiltered so future
|
|
87
|
+
components are available to downstream consumers.
|
|
86
88
|
|
|
87
89
|
## Getting started
|
|
88
90
|
|
|
@@ -184,6 +186,7 @@ For local function probes without activating the environment first:
|
|
|
184
186
|
.venv/bin/python -m duco_connectivity --host 192.168.1.10 call async_get_board_info
|
|
185
187
|
.venv/bin/duco-probe --host 192.168.1.10 call async_get_board_info
|
|
186
188
|
.venv/bin/duco-probe --host 192.168.1.10 call async_get_ventilation_temperature_info
|
|
189
|
+
.venv/bin/duco-probe --host 192.168.1.10 call async_get_bypass_supply_temperature_targets
|
|
187
190
|
.venv/bin/duco-probe --host 192.168.1.10 call async_get_bypass_supply_temperature_target --kwargs '{"zone_id": 1}'
|
|
188
191
|
```
|
|
189
192
|
|
|
@@ -42,6 +42,7 @@ from duco_connectivity import (
|
|
|
42
42
|
DeviceGroupConfigSubmoduleSelector,
|
|
43
43
|
DiagComponent,
|
|
44
44
|
DiagInfo,
|
|
45
|
+
DiagStatus,
|
|
45
46
|
DucoClient,
|
|
46
47
|
DucoConnectionError,
|
|
47
48
|
DucoError,
|
|
@@ -2066,7 +2067,8 @@ async def test_get_diagnostics(diag_data: dict[str, object]) -> None:
|
|
|
2066
2067
|
|
|
2067
2068
|
assert len(diags) == 3
|
|
2068
2069
|
assert diags[0].component == "Ventilation"
|
|
2069
|
-
assert diags[0].status
|
|
2070
|
+
assert diags[0].status is DiagStatus.OK
|
|
2071
|
+
assert diags[0].raw_status == "Ok"
|
|
2070
2072
|
assert diags[0].raw_payload is diag_data["Diag"]["SubSystems"][0]
|
|
2071
2073
|
|
|
2072
2074
|
|
|
@@ -2085,13 +2087,19 @@ async def test_get_diagnostics_info_exposes_typed_subsystems(
|
|
|
2085
2087
|
assert_type(diag_info, DiagInfo)
|
|
2086
2088
|
assert_type(diag_info.diagnostic_subsystems, tuple[DiagComponent, ...])
|
|
2087
2089
|
assert_type(diag_info.diagnostic_subsystems[0].component, str)
|
|
2088
|
-
assert_type(diag_info.diagnostic_subsystems[0].status,
|
|
2090
|
+
assert_type(diag_info.diagnostic_subsystems[0].status, DiagStatus | None)
|
|
2091
|
+
assert_type(diag_info.diagnostic_subsystems[0].raw_status, str)
|
|
2089
2092
|
assert tuple(item.component for item in diag_info.diagnostic_subsystems) == (
|
|
2090
2093
|
"Ventilation",
|
|
2091
2094
|
"VentCool",
|
|
2092
2095
|
"SunCtrl",
|
|
2093
2096
|
)
|
|
2094
2097
|
assert tuple(item.status for item in diag_info.diagnostic_subsystems) == (
|
|
2098
|
+
DiagStatus.OK,
|
|
2099
|
+
DiagStatus.OK,
|
|
2100
|
+
DiagStatus.OK,
|
|
2101
|
+
)
|
|
2102
|
+
assert tuple(item.raw_status for item in diag_info.diagnostic_subsystems) == (
|
|
2095
2103
|
"Ok",
|
|
2096
2104
|
"Ok",
|
|
2097
2105
|
"Ok",
|
|
@@ -2115,7 +2123,8 @@ async def test_get_diagnostics_preserves_unknown_status() -> None:
|
|
|
2115
2123
|
diags = await client.async_get_diagnostics()
|
|
2116
2124
|
|
|
2117
2125
|
assert len(diags) == 1
|
|
2118
|
-
assert diags[0].status
|
|
2126
|
+
assert diags[0].status is None
|
|
2127
|
+
assert diags[0].raw_status == "FutureState"
|
|
2119
2128
|
|
|
2120
2129
|
|
|
2121
2130
|
async def test_get_diagnostics_preserves_unknown_component_name() -> None:
|
|
@@ -2182,9 +2191,11 @@ async def test_get_diagnostics_info_skips_partial_entries() -> None:
|
|
|
2182
2191
|
with patch.object(session, "request", _request(mock_response)):
|
|
2183
2192
|
diag_info = await client.async_get_diagnostics_info()
|
|
2184
2193
|
|
|
2185
|
-
assert tuple(
|
|
2186
|
-
(
|
|
2187
|
-
|
|
2194
|
+
assert tuple(
|
|
2195
|
+
(item.component, item.status, item.raw_status) for item in diag_info.diagnostic_subsystems
|
|
2196
|
+
) == (
|
|
2197
|
+
("Ventilation", DiagStatus.OK, "Ok"),
|
|
2198
|
+
("SunCtrl", None, "FutureState"),
|
|
2188
2199
|
)
|
|
2189
2200
|
|
|
2190
2201
|
|
|
@@ -2213,6 +2224,12 @@ async def test_get_diagnostics_info_does_not_filter_product_specific_subsystems(
|
|
|
2213
2224
|
"SunCtrl",
|
|
2214
2225
|
"FutureSubsystem",
|
|
2215
2226
|
)
|
|
2227
|
+
assert tuple((item.status, item.raw_status) for item in diag_info.diagnostic_subsystems) == (
|
|
2228
|
+
(DiagStatus.ERROR, "Error"),
|
|
2229
|
+
(DiagStatus.OK, "Ok"),
|
|
2230
|
+
(DiagStatus.OK, "Ok"),
|
|
2231
|
+
(DiagStatus.DISABLED, "Disable"),
|
|
2232
|
+
)
|
|
2216
2233
|
|
|
2217
2234
|
|
|
2218
2235
|
async def test_get_nodes_parses_full_payload(nodes_data: dict[str, object]) -> None:
|
|
@@ -3794,6 +3811,81 @@ async def test_get_bypass_supply_temperature_target_returns_converted_values(
|
|
|
3794
3811
|
}
|
|
3795
3812
|
|
|
3796
3813
|
|
|
3814
|
+
async def test_get_bypass_supply_temperature_targets_returns_available_targets(
|
|
3815
|
+
config_data: dict[str, object],
|
|
3816
|
+
) -> None:
|
|
3817
|
+
"""Bulk bypass target reads should return all available targets in Celsius."""
|
|
3818
|
+
mock_response = _response(json_payload=config_data)
|
|
3819
|
+
|
|
3820
|
+
async with aiohttp.ClientSession() as session:
|
|
3821
|
+
client = DucoClient(session=session, host="192.0.2.94")
|
|
3822
|
+
request_mock = _request(mock_response)
|
|
3823
|
+
with patch.object(session, "request", request_mock):
|
|
3824
|
+
targets = await client.async_get_bypass_supply_temperature_targets()
|
|
3825
|
+
|
|
3826
|
+
assert targets == {
|
|
3827
|
+
1: BypassSupplyTemperatureTarget(
|
|
3828
|
+
zone_id=1,
|
|
3829
|
+
value=18.0,
|
|
3830
|
+
minimum=12.0,
|
|
3831
|
+
increment=0.5,
|
|
3832
|
+
maximum=22.0,
|
|
3833
|
+
),
|
|
3834
|
+
2: BypassSupplyTemperatureTarget(
|
|
3835
|
+
zone_id=2,
|
|
3836
|
+
value=18.5,
|
|
3837
|
+
minimum=12.0,
|
|
3838
|
+
increment=0.5,
|
|
3839
|
+
maximum=22.0,
|
|
3840
|
+
),
|
|
3841
|
+
}
|
|
3842
|
+
assert request_mock.call_args.kwargs["params"] == {
|
|
3843
|
+
"module": "HeatRecovery",
|
|
3844
|
+
"submodule": "Bypass",
|
|
3845
|
+
}
|
|
3846
|
+
|
|
3847
|
+
|
|
3848
|
+
async def test_get_bypass_supply_temperature_targets_returns_empty_when_absent() -> None:
|
|
3849
|
+
"""Bulk bypass target reads should omit targets absent from the response."""
|
|
3850
|
+
mock_response = _response(json_payload={"HeatRecovery": {"Bypass": {}}})
|
|
3851
|
+
|
|
3852
|
+
async with aiohttp.ClientSession() as session:
|
|
3853
|
+
client = DucoClient(session=session, host="192.0.2.94")
|
|
3854
|
+
with patch.object(session, "request", _request(mock_response)):
|
|
3855
|
+
targets = await client.async_get_bypass_supply_temperature_targets()
|
|
3856
|
+
|
|
3857
|
+
assert targets == {}
|
|
3858
|
+
|
|
3859
|
+
|
|
3860
|
+
async def test_get_bypass_supply_temperature_targets_raises_when_unsupported() -> None:
|
|
3861
|
+
"""Unsupported bulk bypass target reads should raise a typed capability error."""
|
|
3862
|
+
mock_response = _response(
|
|
3863
|
+
status=400,
|
|
3864
|
+
text_payload='{"Code":3,"Result":"FAILED"}',
|
|
3865
|
+
)
|
|
3866
|
+
|
|
3867
|
+
async with aiohttp.ClientSession() as session:
|
|
3868
|
+
client = DucoClient(session=session, host="192.0.2.94")
|
|
3869
|
+
with (
|
|
3870
|
+
patch.object(session, "request", _request(mock_response)),
|
|
3871
|
+
pytest.raises(DucoUnsupportedCapabilityError),
|
|
3872
|
+
):
|
|
3873
|
+
await client.async_get_bypass_supply_temperature_targets()
|
|
3874
|
+
|
|
3875
|
+
|
|
3876
|
+
async def test_get_bypass_supply_temperature_targets_reraises_other_client_errors() -> None:
|
|
3877
|
+
"""Unexpected bulk bypass target failures should remain visible to callers."""
|
|
3878
|
+
mock_response = _response(status=400, text_payload='{"Code":4,"Result":"FAILED"}')
|
|
3879
|
+
|
|
3880
|
+
async with aiohttp.ClientSession() as session:
|
|
3881
|
+
client = DucoClient(session=session, host="192.0.2.94")
|
|
3882
|
+
with (
|
|
3883
|
+
patch.object(session, "request", _request(mock_response)),
|
|
3884
|
+
pytest.raises(DucoResponseError),
|
|
3885
|
+
):
|
|
3886
|
+
await client.async_get_bypass_supply_temperature_targets()
|
|
3887
|
+
|
|
3888
|
+
|
|
3797
3889
|
async def test_get_bypass_supply_temperature_target_raises_when_not_reported() -> None:
|
|
3798
3890
|
"""Missing bypass targets should fail for parameter-specific helper reads."""
|
|
3799
3891
|
mock_response = _response(json_payload={"HeatRecovery": {"Bypass": {}}})
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_duco_connectivity-0.11.0 → python_duco_connectivity-0.13.0}/src/duco_connectivity/cli.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_duco_connectivity-0.11.0 → python_duco_connectivity-0.13.0}/src/duco_connectivity/py.typed
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_duco_connectivity-0.11.0 → python_duco_connectivity-0.13.0}/tests/test_api_reference.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_duco_connectivity-0.11.0 → python_duco_connectivity-0.13.0}/tests/test_exceptions.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_duco_connectivity-0.11.0 → python_duco_connectivity-0.13.0}/tests/test_replay_helpers.py
RENAMED
|
File without changes
|