python-duco-connectivity 0.12.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.12.0/src/python_duco_connectivity.egg-info → python_duco_connectivity-0.13.0}/PKG-INFO +6 -4
- {python_duco_connectivity-0.12.0 → python_duco_connectivity-0.13.0}/README.md +5 -3
- {python_duco_connectivity-0.12.0 → python_duco_connectivity-0.13.0}/pyproject.toml +1 -1
- {python_duco_connectivity-0.12.0 → python_duco_connectivity-0.13.0}/src/duco_connectivity/__init__.py +2 -0
- {python_duco_connectivity-0.12.0 → python_duco_connectivity-0.13.0}/src/duco_connectivity/client.py +3 -1
- {python_duco_connectivity-0.12.0 → python_duco_connectivity-0.13.0}/src/duco_connectivity/models.py +15 -6
- {python_duco_connectivity-0.12.0 → python_duco_connectivity-0.13.0/src/python_duco_connectivity.egg-info}/PKG-INFO +6 -4
- {python_duco_connectivity-0.12.0 → python_duco_connectivity-0.13.0}/tests/test_client.py +23 -6
- {python_duco_connectivity-0.12.0 → python_duco_connectivity-0.13.0}/LICENSE +0 -0
- {python_duco_connectivity-0.12.0 → python_duco_connectivity-0.13.0}/setup.cfg +0 -0
- {python_duco_connectivity-0.12.0 → python_duco_connectivity-0.13.0}/src/duco_connectivity/__main__.py +0 -0
- {python_duco_connectivity-0.12.0 → python_duco_connectivity-0.13.0}/src/duco_connectivity/cli.py +0 -0
- {python_duco_connectivity-0.12.0 → python_duco_connectivity-0.13.0}/src/duco_connectivity/exceptions.py +0 -0
- {python_duco_connectivity-0.12.0 → python_duco_connectivity-0.13.0}/src/duco_connectivity/py.typed +0 -0
- {python_duco_connectivity-0.12.0 → python_duco_connectivity-0.13.0}/src/python_duco_connectivity.egg-info/SOURCES.txt +0 -0
- {python_duco_connectivity-0.12.0 → python_duco_connectivity-0.13.0}/src/python_duco_connectivity.egg-info/dependency_links.txt +0 -0
- {python_duco_connectivity-0.12.0 → python_duco_connectivity-0.13.0}/src/python_duco_connectivity.egg-info/entry_points.txt +0 -0
- {python_duco_connectivity-0.12.0 → python_duco_connectivity-0.13.0}/src/python_duco_connectivity.egg-info/requires.txt +0 -0
- {python_duco_connectivity-0.12.0 → python_duco_connectivity-0.13.0}/src/python_duco_connectivity.egg-info/top_level.txt +0 -0
- {python_duco_connectivity-0.12.0 → python_duco_connectivity-0.13.0}/tests/test_api_reference.py +0 -0
- {python_duco_connectivity-0.12.0 → python_duco_connectivity-0.13.0}/tests/test_cli.py +0 -0
- {python_duco_connectivity-0.12.0 → python_duco_connectivity-0.13.0}/tests/test_exceptions.py +0 -0
- {python_duco_connectivity-0.12.0 → python_duco_connectivity-0.13.0}/tests/test_local_sample_validation.py +0 -0
- {python_duco_connectivity-0.12.0 → python_duco_connectivity-0.13.0}/tests/test_models.py +0 -0
- {python_duco_connectivity-0.12.0 → python_duco_connectivity-0.13.0}/tests/test_pytest_live_support.py +0 -0
- {python_duco_connectivity-0.12.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
|
|
|
@@ -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
|
|
|
@@ -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.12.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,
|
|
@@ -2067,7 +2068,8 @@ class DucoClient:
|
|
|
2067
2068
|
|
|
2068
2069
|
return DiagComponent(
|
|
2069
2070
|
component=component,
|
|
2070
|
-
status=status,
|
|
2071
|
+
status=DiagStatus.from_api_value(status),
|
|
2072
|
+
raw_status=status,
|
|
2071
2073
|
raw_payload=cls._preserve_raw_payload(payload),
|
|
2072
2074
|
)
|
|
2073
2075
|
|
{python_duco_connectivity-0.12.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
|
|
|
@@ -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:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_duco_connectivity-0.12.0 → python_duco_connectivity-0.13.0}/src/duco_connectivity/cli.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_duco_connectivity-0.12.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.12.0 → python_duco_connectivity-0.13.0}/tests/test_api_reference.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_duco_connectivity-0.12.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.12.0 → python_duco_connectivity-0.13.0}/tests/test_replay_helpers.py
RENAMED
|
File without changes
|