dimplex-controller 0.13.0__tar.gz → 0.13.1__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.
- {dimplex_controller-0.13.0 → dimplex_controller-0.13.1}/PKG-INFO +17 -6
- {dimplex_controller-0.13.0 → dimplex_controller-0.13.1}/README.md +15 -4
- {dimplex_controller-0.13.0 → dimplex_controller-0.13.1}/dimplex_controller/__init__.py +9 -2
- {dimplex_controller-0.13.0 → dimplex_controller-0.13.1}/dimplex_controller/capabilities.py +8 -1
- {dimplex_controller-0.13.0 → dimplex_controller-0.13.1}/dimplex_controller/client.py +42 -7
- {dimplex_controller-0.13.0 → dimplex_controller-0.13.1}/dimplex_controller/const.py +11 -2
- {dimplex_controller-0.13.0 → dimplex_controller-0.13.1}/dimplex_controller/models.py +3 -3
- {dimplex_controller-0.13.0 → dimplex_controller-0.13.1}/dimplex_controller/telemetry.py +1 -1
- {dimplex_controller-0.13.0 → dimplex_controller-0.13.1}/pyproject.toml +12 -7
- {dimplex_controller-0.13.0 → dimplex_controller-0.13.1}/LICENSE +0 -0
- {dimplex_controller-0.13.0 → dimplex_controller-0.13.1}/dimplex_controller/auth.py +0 -0
- {dimplex_controller-0.13.0 → dimplex_controller-0.13.1}/dimplex_controller/cli.py +0 -0
- {dimplex_controller-0.13.0 → dimplex_controller-0.13.1}/dimplex_controller/exceptions.py +0 -0
- {dimplex_controller-0.13.0 → dimplex_controller-0.13.1}/dimplex_controller/py.typed +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dimplex-controller
|
|
3
|
-
Version: 0.13.
|
|
4
|
-
Summary: Python client for Dimplex
|
|
3
|
+
Version: 0.13.1
|
|
4
|
+
Summary: Unofficial async Python client for Dimplex (GDHV IoT) heating appliances — not affiliated with Glen Dimplex
|
|
5
5
|
License: MIT
|
|
6
6
|
License-File: LICENSE
|
|
7
7
|
Keywords: dimplex,heating,control,iot,asyncio
|
|
@@ -40,14 +40,24 @@ Description-Content-Type: text/markdown
|
|
|
40
40
|
|
|
41
41
|
---
|
|
42
42
|
|
|
43
|
+
> [!IMPORTANT]
|
|
44
|
+
> **Unofficial library.** Not affiliated with, endorsed by, or supported by Dimplex, Glen
|
|
45
|
+
> Dimplex Heating & Ventilation (GDHV), or the Glen Dimplex Group. This is an independent
|
|
46
|
+
> project built by **reverse-engineering** the official Dimplex Control Android app and the
|
|
47
|
+
> private cloud API it talks to.
|
|
48
|
+
>
|
|
49
|
+
> There is no public or documented API. Dimplex can change or withdraw that API at any time
|
|
50
|
+
> and without notice, which may break this library. Use it at your own risk.
|
|
51
|
+
>
|
|
52
|
+
> No Dimplex code is included or redistributed. "Dimplex", "Quantum", "QRAD" and related
|
|
53
|
+
> marks belong to their respective owners and are used here only to describe compatibility.
|
|
54
|
+
|
|
43
55
|
## What does this do?
|
|
44
56
|
|
|
45
57
|
`dimplex-controller-py` is an asynchronous Python client that talks to the GDHV IoT cloud platform. It handles Azure B2C authentication (including automatic token refresh), discovers your Hubs, Zones and Appliances, and lets you read telemetry and send control commands — all from a script or a larger application.
|
|
46
58
|
|
|
47
59
|
It is the engine behind the [Dimplex Hub Home Assistant integration](https://github.com/KRoperUK/dimplex-controller-hass) and is published to PyPI as [`dimplex-controller`](https://pypi.org/project/dimplex-controller/).
|
|
48
60
|
|
|
49
|
-
> **Note:** This is an unofficial library and is not affiliated with or endorsed by Glen Dimplex Heating & Ventilation (GDHV). Use it at your own risk.
|
|
50
|
-
|
|
51
61
|
## Contents
|
|
52
62
|
|
|
53
63
|
- [Features](#features)
|
|
@@ -186,8 +196,9 @@ await client.set_open_window_detection(hub_id, [appliance_id], True)
|
|
|
186
196
|
# Timed Boost (ApplianceModes=2, Time = minutes)
|
|
187
197
|
await client.set_boost(hub_id, [appliance_id], temperature=25.0, duration_minutes=60)
|
|
188
198
|
|
|
189
|
-
# Away until a given moment (ApplianceModes=4). Away is a settable 7–
|
|
190
|
-
# setback and defaults to the 7 °C anti-freeze floor.
|
|
199
|
+
# Away until a given moment (ApplianceModes=4). Away is a settable 7–18 °C
|
|
200
|
+
# setback and defaults to the 7 °C anti-freeze floor. A higher temperature is
|
|
201
|
+
# clamped to 18 °C with a warning, matching what the cloud does to it anyway.
|
|
191
202
|
from datetime import datetime, timedelta, timezone
|
|
192
203
|
|
|
193
204
|
await client.set_away(
|
|
@@ -13,14 +13,24 @@
|
|
|
13
13
|
|
|
14
14
|
---
|
|
15
15
|
|
|
16
|
+
> [!IMPORTANT]
|
|
17
|
+
> **Unofficial library.** Not affiliated with, endorsed by, or supported by Dimplex, Glen
|
|
18
|
+
> Dimplex Heating & Ventilation (GDHV), or the Glen Dimplex Group. This is an independent
|
|
19
|
+
> project built by **reverse-engineering** the official Dimplex Control Android app and the
|
|
20
|
+
> private cloud API it talks to.
|
|
21
|
+
>
|
|
22
|
+
> There is no public or documented API. Dimplex can change or withdraw that API at any time
|
|
23
|
+
> and without notice, which may break this library. Use it at your own risk.
|
|
24
|
+
>
|
|
25
|
+
> No Dimplex code is included or redistributed. "Dimplex", "Quantum", "QRAD" and related
|
|
26
|
+
> marks belong to their respective owners and are used here only to describe compatibility.
|
|
27
|
+
|
|
16
28
|
## What does this do?
|
|
17
29
|
|
|
18
30
|
`dimplex-controller-py` is an asynchronous Python client that talks to the GDHV IoT cloud platform. It handles Azure B2C authentication (including automatic token refresh), discovers your Hubs, Zones and Appliances, and lets you read telemetry and send control commands — all from a script or a larger application.
|
|
19
31
|
|
|
20
32
|
It is the engine behind the [Dimplex Hub Home Assistant integration](https://github.com/KRoperUK/dimplex-controller-hass) and is published to PyPI as [`dimplex-controller`](https://pypi.org/project/dimplex-controller/).
|
|
21
33
|
|
|
22
|
-
> **Note:** This is an unofficial library and is not affiliated with or endorsed by Glen Dimplex Heating & Ventilation (GDHV). Use it at your own risk.
|
|
23
|
-
|
|
24
34
|
## Contents
|
|
25
35
|
|
|
26
36
|
- [Features](#features)
|
|
@@ -159,8 +169,9 @@ await client.set_open_window_detection(hub_id, [appliance_id], True)
|
|
|
159
169
|
# Timed Boost (ApplianceModes=2, Time = minutes)
|
|
160
170
|
await client.set_boost(hub_id, [appliance_id], temperature=25.0, duration_minutes=60)
|
|
161
171
|
|
|
162
|
-
# Away until a given moment (ApplianceModes=4). Away is a settable 7–
|
|
163
|
-
# setback and defaults to the 7 °C anti-freeze floor.
|
|
172
|
+
# Away until a given moment (ApplianceModes=4). Away is a settable 7–18 °C
|
|
173
|
+
# setback and defaults to the 7 °C anti-freeze floor. A higher temperature is
|
|
174
|
+
# clamped to 18 °C with a warning, matching what the cloud does to it anyway.
|
|
164
175
|
from datetime import datetime, timedelta, timezone
|
|
165
176
|
|
|
166
177
|
await client.set_away(
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
"""Dimplex Controller Client.
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
API.
|
|
3
|
+
Unofficial async Python client for the Glen Dimplex Heating & Ventilation
|
|
4
|
+
(GDHV) cloud API. Not affiliated with, endorsed by, or supported by Dimplex
|
|
5
|
+
or the Glen Dimplex Group: the protocol was recovered by reverse-engineering
|
|
6
|
+
the official Dimplex Control Android app, so Dimplex may change or withdraw
|
|
7
|
+
it without notice. See :class:`~dimplex_controller.client.DimplexControl` for the entry
|
|
5
8
|
point and :meth:`DimplexControl.get_appliance_overview` for the read path
|
|
6
9
|
used by the Home Assistant integration.
|
|
7
10
|
|
|
@@ -15,6 +18,8 @@ from .auth import TokenBundle, TokenListener
|
|
|
15
18
|
from .capabilities import ApplianceCapabilities, capabilities_for
|
|
16
19
|
from .client import DimplexControl
|
|
17
20
|
from .const import (
|
|
21
|
+
AWAY_TEMP_MAX,
|
|
22
|
+
AWAY_TEMP_MIN,
|
|
18
23
|
DEFAULT_AWAY_TEMPERATURE,
|
|
19
24
|
DEFAULT_BOOST_TEMPERATURE,
|
|
20
25
|
FROST_TEMPERATURE,
|
|
@@ -84,6 +89,8 @@ __all__ = [
|
|
|
84
89
|
"TsiEnergyReport",
|
|
85
90
|
"DEFAULT_AWAY_TEMPERATURE",
|
|
86
91
|
"DEFAULT_BOOST_TEMPERATURE",
|
|
92
|
+
"AWAY_TEMP_MIN",
|
|
93
|
+
"AWAY_TEMP_MAX",
|
|
87
94
|
"FROST_TEMPERATURE",
|
|
88
95
|
"MODE_TEMP_MIN",
|
|
89
96
|
"MODE_TEMP_MAX",
|
|
@@ -9,7 +9,7 @@ from __future__ import annotations
|
|
|
9
9
|
from dataclasses import dataclass
|
|
10
10
|
from typing import Any
|
|
11
11
|
|
|
12
|
-
from .const import FROST_TEMPERATURE, MODE_TEMP_MAX, MODE_TEMP_MIN
|
|
12
|
+
from .const import AWAY_TEMP_MAX, AWAY_TEMP_MIN, FROST_TEMPERATURE, MODE_TEMP_MAX, MODE_TEMP_MIN
|
|
13
13
|
from .models import Appliance, ApplianceStatus, AutomaticProvisioning, ProductModel
|
|
14
14
|
|
|
15
15
|
# Default boost lengths (minutes) offered by the mobile app for most heaters.
|
|
@@ -47,6 +47,11 @@ class ApplianceCapabilities:
|
|
|
47
47
|
climate: bool = True
|
|
48
48
|
min_temp: float = MODE_TEMP_MIN
|
|
49
49
|
max_temp: float = MODE_TEMP_MAX
|
|
50
|
+
# Away is the one carousel with its own bounds: it shares the 7 °C floor but
|
|
51
|
+
# stops at 18 °C rather than 30 °C (dimplex-controller-py#98). Consumers
|
|
52
|
+
# should gate the Away picker on these rather than on min_temp/max_temp.
|
|
53
|
+
away_min_temp: float = AWAY_TEMP_MIN
|
|
54
|
+
away_max_temp: float = AWAY_TEMP_MAX
|
|
50
55
|
frost_temp: float = FROST_TEMPERATURE
|
|
51
56
|
default_boost_minutes: int = DEFAULT_BOOST_MINUTES
|
|
52
57
|
boost_durations: tuple[int, ...] = DEFAULT_BOOST_DURATIONS
|
|
@@ -83,6 +88,8 @@ class ApplianceCapabilities:
|
|
|
83
88
|
"climate": self.climate,
|
|
84
89
|
"min_temp": self.min_temp,
|
|
85
90
|
"max_temp": self.max_temp,
|
|
91
|
+
"away_min_temp": self.away_min_temp,
|
|
92
|
+
"away_max_temp": self.away_max_temp,
|
|
86
93
|
"frost_temp": self.frost_temp,
|
|
87
94
|
"default_boost_minutes": self.default_boost_minutes,
|
|
88
95
|
"boost_durations": list(self.boost_durations),
|
|
@@ -12,6 +12,8 @@ import aiohttp
|
|
|
12
12
|
from .auth import AuthManager, TokenBundle, TokenListener
|
|
13
13
|
from .capabilities import ApplianceCapabilities, capabilities_for
|
|
14
14
|
from .const import (
|
|
15
|
+
AWAY_TEMP_MAX,
|
|
16
|
+
AWAY_TEMP_MIN,
|
|
15
17
|
BASE_URL,
|
|
16
18
|
DEFAULT_AWAY_TEMPERATURE,
|
|
17
19
|
DEFAULT_BOOST_TEMPERATURE,
|
|
@@ -70,6 +72,26 @@ _RETRYABLE_STATUS = frozenset({429, 500, 502, 503, 504})
|
|
|
70
72
|
DEFAULT_TIMEOUT = 30.0
|
|
71
73
|
|
|
72
74
|
|
|
75
|
+
def _clamp_away_temperature(temperature: float) -> float:
|
|
76
|
+
"""Clamp an Away target into the mode's own 7–18 °C range.
|
|
77
|
+
|
|
78
|
+
The cloud reduces a higher value silently, so clamping here keeps the value
|
|
79
|
+
the caller asked for and the value the appliance ends up at in agreement,
|
|
80
|
+
and the warning makes the adjustment visible.
|
|
81
|
+
"""
|
|
82
|
+
value = float(temperature)
|
|
83
|
+
clamped = min(max(value, AWAY_TEMP_MIN), AWAY_TEMP_MAX)
|
|
84
|
+
if clamped != value:
|
|
85
|
+
_LOGGER.warning(
|
|
86
|
+
"Away temperature %.1f °C is outside the %s–%s °C the app offers for Away; using %.1f °C",
|
|
87
|
+
value,
|
|
88
|
+
AWAY_TEMP_MIN,
|
|
89
|
+
AWAY_TEMP_MAX,
|
|
90
|
+
clamped,
|
|
91
|
+
)
|
|
92
|
+
return clamped
|
|
93
|
+
|
|
94
|
+
|
|
73
95
|
def _coerce_timeout(timeout: float | aiohttp.ClientTimeout | None) -> aiohttp.ClientTimeout | None:
|
|
74
96
|
"""Normalise a timeout value into an :class:`aiohttp.ClientTimeout`.
|
|
75
97
|
|
|
@@ -325,7 +347,7 @@ class DimplexControl:
|
|
|
325
347
|
"""Get details for a specific zone."""
|
|
326
348
|
payload = {"HubId": hub_id, "ZoneId": zone_id}
|
|
327
349
|
data = await self._request("POST", "/Zones/GetZone", json=payload)
|
|
328
|
-
return Zone.model_validate(data)
|
|
350
|
+
return Zone.model_validate(data)
|
|
329
351
|
|
|
330
352
|
async def get_appliance_overview(self, hub_id: str, appliance_ids: list[str]) -> list[ApplianceStatus]:
|
|
331
353
|
"""Get status overview for specific appliances.
|
|
@@ -351,7 +373,7 @@ class DimplexControl:
|
|
|
351
373
|
async def get_user_context(self) -> UserContext:
|
|
352
374
|
"""Get user profile/context."""
|
|
353
375
|
data = await self._request("GET", "/Identity/GetUserContext")
|
|
354
|
-
return UserContext.model_validate(data)
|
|
376
|
+
return UserContext.model_validate(data)
|
|
355
377
|
|
|
356
378
|
async def get_product_models(self) -> list[ProductModel]:
|
|
357
379
|
"""Return the cloud product catalogue (models + provisioning metadata).
|
|
@@ -371,7 +393,7 @@ class DimplexControl:
|
|
|
371
393
|
"TimerMode": 0, # Required field in request; value ignored on read
|
|
372
394
|
}
|
|
373
395
|
data = await self._request("POST", "/RemoteControl/GetTimerModeDetailsForAppliance", json=payload)
|
|
374
|
-
return TimerModeSettings.model_validate(data)
|
|
396
|
+
return TimerModeSettings.model_validate(data)
|
|
375
397
|
|
|
376
398
|
async def get_schedule(self, hub_id: str, appliance_id: str) -> TimerModeSettings:
|
|
377
399
|
"""Return the current timer mode + periods (alias of :meth:`get_appliance_features`)."""
|
|
@@ -591,15 +613,26 @@ class DimplexControl:
|
|
|
591
613
|
"""Enable or disable Away mode.
|
|
592
614
|
|
|
593
615
|
Sends ``ApplianceModes=4`` (:attr:`~dimplex_controller.ApplianceModeFlag.AWAY`).
|
|
594
|
-
Away is a *settable* setback: the app offers 7–
|
|
595
|
-
|
|
596
|
-
|
|
616
|
+
Away is a *settable* setback: the app offers 7–18 °C
|
|
617
|
+
(:data:`~dimplex_controller.AWAY_TEMP_MIN` / :data:`~dimplex_controller.AWAY_TEMP_MAX`)
|
|
618
|
+
and defaults to the 7 °C anti-freeze floor, so a low ``temperature`` is
|
|
619
|
+
the normal case rather than a bug.
|
|
597
620
|
|
|
598
621
|
``until`` is the "away until" datetime the app sends in ``Date``. Pass a
|
|
599
622
|
:class:`~datetime.datetime` or an ISO-8601 string. ``number_of_days`` is
|
|
600
623
|
retained for backwards compatibility and, when ``until`` is omitted, is
|
|
601
624
|
converted into an equivalent ``Date``.
|
|
602
625
|
|
|
626
|
+
When engaging Away, ``temperature`` is clamped into the Away range and a
|
|
627
|
+
warning logged if it had to be: the cloud silently reduces a higher
|
|
628
|
+
value, so clamping locally makes the outcome the caller actually gets
|
|
629
|
+
visible rather than surprising (dimplex-controller-py#98). The clamp is
|
|
630
|
+
skipped when clearing, where the temperature is inert.
|
|
631
|
+
|
|
632
|
+
.. versionchanged:: 0.13.1
|
|
633
|
+
``temperature`` is clamped to ``AWAY_TEMP_MIN``..``AWAY_TEMP_MAX``
|
|
634
|
+
when ``enable`` is true.
|
|
635
|
+
|
|
603
636
|
.. versionchanged:: 0.13.0
|
|
604
637
|
Previously sent ``ApplianceModes=32``, which is **FrostProtect** —
|
|
605
638
|
the appliance was pinned to the fixed 7 °C frost setpoint and the
|
|
@@ -607,6 +640,8 @@ class DimplexControl:
|
|
|
607
640
|
Away duration now travels in ``Date`` as the app does, not only in
|
|
608
641
|
``NumberOfDays``.
|
|
609
642
|
"""
|
|
643
|
+
if enable:
|
|
644
|
+
temperature = _clamp_away_temperature(temperature)
|
|
610
645
|
days = int(number_of_days)
|
|
611
646
|
if until is None and days > 0:
|
|
612
647
|
until = datetime.now(timezone.utc) + timedelta(days=days)
|
|
@@ -876,7 +911,7 @@ class DimplexControl:
|
|
|
876
911
|
"/RemoteControl/ApiGetTimerModeDetailsForHeatPumpHwcAppliance",
|
|
877
912
|
json=payload,
|
|
878
913
|
)
|
|
879
|
-
return TimerModeSettings.model_validate(data)
|
|
914
|
+
return TimerModeSettings.model_validate(data)
|
|
880
915
|
|
|
881
916
|
async def set_heat_pump_hot_water_schedule(self, settings: TimerModeSettings) -> TimerModeSettings:
|
|
882
917
|
"""Write an ASHW cylinder's schedule periods.
|
|
@@ -26,15 +26,24 @@ B2C_POLICY = "B2C_1A_DimplexControlSignupSignin"
|
|
|
26
26
|
# recovered from Dimplex Control APK 2.26.0.
|
|
27
27
|
# See ``docs/decompiled-api-reference.md``.
|
|
28
28
|
|
|
29
|
-
# The mode carousels (
|
|
29
|
+
# The mode carousels (Boost / Frost / Manual / Eco) offer 7–30 °C. Away shares
|
|
30
|
+
# the floor but *not* the ceiling — see AWAY_TEMP_MAX below.
|
|
30
31
|
MODE_TEMP_MIN = 7.0
|
|
31
32
|
MODE_TEMP_MAX = 30.0
|
|
32
33
|
|
|
34
|
+
# Away has its own, narrower ceiling. The app's Away picker will not offer above
|
|
35
|
+
# 18 °C, and a live test against a Quantum requesting 25 °C produced 18 °C in the
|
|
36
|
+
# cloud overview, the app and the appliance's own panel — so the earlier reading
|
|
37
|
+
# of ``UpdateTempRange`` that folded Away into the shared 7–30 carousel was
|
|
38
|
+
# over-generalised (dimplex-controller-py#98).
|
|
39
|
+
AWAY_TEMP_MIN = 7.0
|
|
40
|
+
AWAY_TEMP_MAX = 18.0
|
|
41
|
+
|
|
33
42
|
# Frost protection is always driven at the anti-freeze floor.
|
|
34
43
|
FROST_TEMPERATURE = 7.0
|
|
35
44
|
|
|
36
45
|
# Away defaults to the frost floor (it is an anti-freeze setback by default)
|
|
37
|
-
# but is user-settable across
|
|
46
|
+
# but is user-settable across AWAY_TEMP_MIN..AWAY_TEMP_MAX.
|
|
38
47
|
DEFAULT_AWAY_TEMPERATURE = FROST_TEMPERATURE
|
|
39
48
|
|
|
40
49
|
# Boost's default in the app's picker.
|
|
@@ -139,7 +139,7 @@ class ProductModel(BaseModel):
|
|
|
139
139
|
if not raw:
|
|
140
140
|
return None
|
|
141
141
|
try:
|
|
142
|
-
return AutomaticProvisioning.model_validate_json(raw)
|
|
142
|
+
return AutomaticProvisioning.model_validate_json(raw)
|
|
143
143
|
except (json.JSONDecodeError, ValueError):
|
|
144
144
|
return None
|
|
145
145
|
|
|
@@ -178,7 +178,7 @@ class Appliance(BaseModel):
|
|
|
178
178
|
if not raw:
|
|
179
179
|
return None
|
|
180
180
|
try:
|
|
181
|
-
return AutomaticProvisioning.model_validate_json(raw)
|
|
181
|
+
return AutomaticProvisioning.model_validate_json(raw)
|
|
182
182
|
except (json.JSONDecodeError, ValueError):
|
|
183
183
|
return None
|
|
184
184
|
|
|
@@ -425,7 +425,7 @@ class TsiEnergyReport(BaseModel):
|
|
|
425
425
|
"""
|
|
426
426
|
|
|
427
427
|
HubId: str
|
|
428
|
-
ApplianceTelemetryData: dict[str, list] = Field(default_factory=dict)
|
|
428
|
+
ApplianceTelemetryData: dict[str, list[Any]] = Field(default_factory=dict)
|
|
429
429
|
|
|
430
430
|
|
|
431
431
|
# `TsiReportType` integer values understood by the API. We do not know the
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "dimplex-controller"
|
|
3
|
-
version = "0.13.
|
|
4
|
-
description = "Python client for Dimplex
|
|
3
|
+
version = "0.13.1"
|
|
4
|
+
description = "Unofficial async Python client for Dimplex (GDHV IoT) heating appliances — not affiliated with Glen Dimplex"
|
|
5
5
|
authors = ["Kieran Roper"]
|
|
6
6
|
license = "MIT"
|
|
7
7
|
readme = "README.md"
|
|
@@ -55,11 +55,16 @@ ignore = ["E501"]
|
|
|
55
55
|
python_version = "3.10"
|
|
56
56
|
files = ["dimplex_controller"]
|
|
57
57
|
ignore_missing_imports = true
|
|
58
|
-
#
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
58
|
+
# `strict` rather than the four flags this used to carry (disallow_untyped_defs,
|
|
59
|
+
# warn_return_any, warn_unused_configs, warn_redundant_casts). The library is the
|
|
60
|
+
# layer the Home Assistant integration trusts for models, capabilities and error
|
|
61
|
+
# types, and that consumer runs strict mypy over its own code — so a library
|
|
62
|
+
# checked more loosely could hand it types that do not hold
|
|
63
|
+
# (dimplex-controller-hass#202).
|
|
64
|
+
#
|
|
65
|
+
# Raising it surfaced seven stale `# type: ignore` comments, all of which mypy
|
|
66
|
+
# reported as unused, plus one missing generic argument. No real type errors.
|
|
67
|
+
strict = true
|
|
63
68
|
|
|
64
69
|
[tool.pytest.ini_options]
|
|
65
70
|
# All async tests use asyncio; "auto" means new tests don't each need the
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|