plugwise 0.37.1__tar.gz → 0.37.2__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.
- {plugwise-0.37.1 → plugwise-0.37.2}/PKG-INFO +1 -4
- {plugwise-0.37.1 → plugwise-0.37.2}/plugwise/constants.py +47 -44
- {plugwise-0.37.1 → plugwise-0.37.2}/plugwise/data.py +3 -3
- {plugwise-0.37.1 → plugwise-0.37.2}/plugwise/helper.py +15 -15
- {plugwise-0.37.1 → plugwise-0.37.2}/plugwise/legacy/data.py +3 -3
- {plugwise-0.37.1 → plugwise-0.37.2}/plugwise.egg-info/PKG-INFO +1 -4
- {plugwise-0.37.1 → plugwise-0.37.2}/plugwise.egg-info/requires.txt +0 -3
- {plugwise-0.37.1 → plugwise-0.37.2}/pyproject.toml +2 -5
- {plugwise-0.37.1 → plugwise-0.37.2}/tests/test_init.py +6 -7
- {plugwise-0.37.1 → plugwise-0.37.2}/LICENSE +0 -0
- {plugwise-0.37.1 → plugwise-0.37.2}/README.md +0 -0
- {plugwise-0.37.1 → plugwise-0.37.2}/plugwise/__init__.py +0 -0
- {plugwise-0.37.1 → plugwise-0.37.2}/plugwise/common.py +0 -0
- {plugwise-0.37.1 → plugwise-0.37.2}/plugwise/exceptions.py +0 -0
- {plugwise-0.37.1 → plugwise-0.37.2}/plugwise/legacy/helper.py +0 -0
- {plugwise-0.37.1 → plugwise-0.37.2}/plugwise/legacy/smile.py +0 -0
- {plugwise-0.37.1 → plugwise-0.37.2}/plugwise/py.typed +0 -0
- {plugwise-0.37.1 → plugwise-0.37.2}/plugwise/smile.py +0 -0
- {plugwise-0.37.1 → plugwise-0.37.2}/plugwise/util.py +0 -0
- {plugwise-0.37.1 → plugwise-0.37.2}/plugwise.egg-info/SOURCES.txt +0 -0
- {plugwise-0.37.1 → plugwise-0.37.2}/plugwise.egg-info/dependency_links.txt +0 -0
- {plugwise-0.37.1 → plugwise-0.37.2}/plugwise.egg-info/top_level.txt +0 -0
- {plugwise-0.37.1 → plugwise-0.37.2}/setup.cfg +0 -0
- {plugwise-0.37.1 → plugwise-0.37.2}/setup.py +0 -0
- {plugwise-0.37.1 → plugwise-0.37.2}/tests/test_adam.py +0 -0
- {plugwise-0.37.1 → plugwise-0.37.2}/tests/test_anna.py +0 -0
- {plugwise-0.37.1 → plugwise-0.37.2}/tests/test_generic.py +0 -0
- {plugwise-0.37.1 → plugwise-0.37.2}/tests/test_legacy_anna.py +0 -0
- {plugwise-0.37.1 → plugwise-0.37.2}/tests/test_legacy_generic.py +0 -0
- {plugwise-0.37.1 → plugwise-0.37.2}/tests/test_legacy_p1.py +0 -0
- {plugwise-0.37.1 → plugwise-0.37.2}/tests/test_legacy_stretch.py +0 -0
- {plugwise-0.37.1 → plugwise-0.37.2}/tests/test_p1.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: plugwise
|
3
|
-
Version: 0.37.
|
3
|
+
Version: 0.37.2
|
4
4
|
Summary: Plugwise Smile (Adam/Anna/P1) and Stretch module for Python 3.
|
5
5
|
Home-page: https://github.com/plugwise/python-plugwise
|
6
6
|
Author: Plugwise device owners
|
@@ -42,11 +42,8 @@ Requires-Python: >=3.11.0
|
|
42
42
|
Description-Content-Type: text/markdown
|
43
43
|
License-File: LICENSE
|
44
44
|
Requires-Dist: aiohttp
|
45
|
-
Requires-Dist: async_timeout
|
46
|
-
Requires-Dist: crcmod
|
47
45
|
Requires-Dist: defusedxml
|
48
46
|
Requires-Dist: munch
|
49
|
-
Requires-Dist: pyserial
|
50
47
|
Requires-Dist: python-dateutil
|
51
48
|
|
52
49
|
# Plugwise python module
|
@@ -121,21 +121,20 @@ P1_LEGACY_MEASUREMENTS: Final[dict[str, UOM]] = {
|
|
121
121
|
# radiator_valve: 'uncorrected_temperature', 'temperature_offset'
|
122
122
|
|
123
123
|
DEVICE_MEASUREMENTS: Final[dict[str, DATA | UOM]] = {
|
124
|
-
#
|
125
|
-
"
|
126
|
-
# HA Core thermostat
|
127
|
-
"thermostat": DATA("setpoint", TEMP_CELSIUS),
|
128
|
-
|
129
|
-
"illuminance": UOM(UNIT_LUMEN),
|
124
|
+
"humidity": UOM(PERCENTAGE), # Specific for a Jip
|
125
|
+
"illuminance": UOM(UNIT_LUMEN), # Specific for an Anna
|
126
|
+
"temperature": UOM(TEMP_CELSIUS), # HA Core thermostat current_temperature
|
127
|
+
"thermostat": DATA("setpoint", TEMP_CELSIUS), # HA Core thermostat setpoint
|
128
|
+
########################################################
|
130
129
|
# Specific for an Anna with heatpump extension installed
|
131
130
|
"cooling_activation_outdoor_temperature": UOM(TEMP_CELSIUS),
|
132
131
|
"cooling_deactivation_threshold": UOM(TEMP_CELSIUS),
|
133
|
-
|
132
|
+
##################################
|
133
|
+
# Specific for a Lisa or Tom/Floor
|
134
134
|
"battery": UOM(PERCENTAGE),
|
135
135
|
"temperature_difference": UOM(DEGREE),
|
136
136
|
"valve_position": UOM(PERCENTAGE),
|
137
|
-
|
138
|
-
"humidity": UOM(PERCENTAGE),
|
137
|
+
#####################
|
139
138
|
# Specific for a Plug
|
140
139
|
"electricity_consumed": UOM(POWER_WATT),
|
141
140
|
"electricity_produced": UOM(POWER_WATT),
|
@@ -144,39 +143,43 @@ DEVICE_MEASUREMENTS: Final[dict[str, DATA | UOM]] = {
|
|
144
143
|
|
145
144
|
# Heater Central related measurements
|
146
145
|
HEATER_CENTRAL_MEASUREMENTS: Final[dict[str, DATA | UOM]] = {
|
146
|
+
"boiler_state": DATA(
|
147
|
+
"flame_state", NONE
|
148
|
+
), # Legacy Anna: similar to flame-state on Anna/Adam
|
147
149
|
"boiler_temperature": DATA("water_temperature", TEMP_CELSIUS),
|
150
|
+
"central_heating_state": DATA(
|
151
|
+
"c_heating_state", NONE
|
152
|
+
), # For Elga (heatpump) use this instead of intended_central_heating_state
|
153
|
+
"central_heater_water_pressure": DATA("water_pressure", PRESSURE_BAR),
|
154
|
+
"compressor_state": UOM(NONE), # present with heatpump
|
155
|
+
"cooling_enabled": UOM(
|
156
|
+
NONE
|
157
|
+
), # Available with the Loria and Elga (newer Anna firmware) heatpumps
|
158
|
+
"cooling_state": UOM(NONE),
|
148
159
|
"domestic_hot_water_mode": DATA("select_dhw_mode", NONE),
|
149
160
|
"domestic_hot_water_setpoint": UOM(TEMP_CELSIUS),
|
150
161
|
"domestic_hot_water_state": DATA("dhw_state", NONE),
|
151
162
|
"domestic_hot_water_temperature": DATA("dhw_temperature", TEMP_CELSIUS),
|
152
163
|
"elga_status_code": UOM(NONE),
|
164
|
+
"intended_boiler_state": DATA(
|
165
|
+
"heating_state", NONE
|
166
|
+
), # Legacy Anna: shows when heating is active, we don't show dhw_state, cannot be determined reliably
|
167
|
+
"flame_state": UOM(
|
168
|
+
NONE
|
169
|
+
), # Also present when there is a single gas-heater
|
153
170
|
"intended_boiler_temperature": UOM(
|
154
171
|
TEMP_CELSIUS
|
155
172
|
), # Non-zero when heating, zero when dhw-heating
|
156
|
-
"central_heating_state": DATA(
|
157
|
-
"c_heating_state", NONE
|
158
|
-
), # For Elga (heatpump) use this instead of intended_central_heating_state
|
159
173
|
"intended_central_heating_state": DATA(
|
160
174
|
"heating_state", NONE
|
161
175
|
), # This key shows in general the heating-behavior better than c-h_state. except when connected to a heatpump
|
162
176
|
"modulation_level": UOM(PERCENTAGE),
|
163
177
|
"return_water_temperature": DATA("return_temperature", TEMP_CELSIUS),
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
"
|
168
|
-
#
|
169
|
-
"cooling_enabled": UOM(NONE),
|
170
|
-
# Next 2 keys are used to show the state of the gas-heater used next to the Elga heatpump - marcelveldt
|
171
|
-
"slave_boiler_state": UOM(NONE),
|
172
|
-
"flame_state": UOM(NONE), # Also present when there is a single gas-heater
|
173
|
-
"central_heater_water_pressure": DATA("water_pressure", PRESSURE_BAR),
|
174
|
-
# Legacy Anna: similar to flame-state on Anna/Adam
|
175
|
-
"boiler_state": DATA("flame_state", NONE),
|
176
|
-
# Legacy Anna: shows when heating is active, we don't show dhw_state, cannot be determined reliably
|
177
|
-
"intended_boiler_state": DATA("heating_state", NONE),
|
178
|
-
# Outdoor temperature from APPLIANCES - present for a heatpump
|
179
|
-
"outdoor_temperature": DATA("outdoor_air_temperature", TEMP_CELSIUS),
|
178
|
+
"outdoor_temperature": DATA(
|
179
|
+
"outdoor_air_temperature", TEMP_CELSIUS
|
180
|
+
), # Outdoor temperature from APPLIANCES - present for a heatpump
|
181
|
+
"slave_boiler_state": DATA("secondary_boiler_state", NONE),
|
182
|
+
"thermostat_supports_cooling": UOM(NONE), # present with heatpump
|
180
183
|
}
|
181
184
|
|
182
185
|
OBSOLETE_MEASUREMENTS: Final[tuple[str, ...]] = (
|
@@ -253,22 +256,22 @@ ApplianceType = Literal[
|
|
253
256
|
]
|
254
257
|
|
255
258
|
BinarySensorType = Literal[
|
256
|
-
"cooling_enabled",
|
257
259
|
"compressor_state",
|
260
|
+
"cooling_enabled",
|
258
261
|
"cooling_state",
|
259
262
|
"dhw_state",
|
260
263
|
"flame_state",
|
261
264
|
"heating_state",
|
262
265
|
"plugwise_notification",
|
263
|
-
"
|
266
|
+
"secondary_boiler_state",
|
264
267
|
]
|
265
268
|
BINARY_SENSORS: Final[tuple[str, ...]] = get_args(BinarySensorType)
|
266
269
|
|
267
270
|
LIMITS: Final[tuple[str, ...]] = (
|
271
|
+
"lower_bound",
|
268
272
|
"offset",
|
269
|
-
"setpoint",
|
270
273
|
"resolution",
|
271
|
-
"
|
274
|
+
"setpoint",
|
272
275
|
"upper_bound",
|
273
276
|
)
|
274
277
|
|
@@ -329,8 +332,8 @@ SENSORS: Final[tuple[str, ...]] = get_args(SensorType)
|
|
329
332
|
|
330
333
|
SPECIAL_PLUG_TYPES: Final[tuple[str, ...]] = (
|
331
334
|
"central_heating_pump",
|
332
|
-
"valve_actuator",
|
333
335
|
"heater_electric",
|
336
|
+
"valve_actuator",
|
334
337
|
)
|
335
338
|
|
336
339
|
SpecialType = Literal[
|
@@ -350,14 +353,14 @@ SwitchType = Literal[
|
|
350
353
|
]
|
351
354
|
SWITCHES: Final[tuple[str, ...]] = get_args(SwitchType)
|
352
355
|
|
353
|
-
SWITCH_GROUP_TYPES: Final[tuple[str, ...]] = ("
|
356
|
+
SWITCH_GROUP_TYPES: Final[tuple[str, ...]] = ("report", "switching")
|
354
357
|
|
355
358
|
THERMOSTAT_CLASSES: Final[tuple[str, ...]] = (
|
356
359
|
"thermostat",
|
360
|
+
"thermostatic_radiator_valve",
|
357
361
|
"thermo_sensor",
|
358
362
|
"zone_thermometer",
|
359
363
|
"zone_thermostat",
|
360
|
-
"thermostatic_radiator_valve",
|
361
364
|
)
|
362
365
|
|
363
366
|
ToggleNameType = Literal[
|
@@ -392,25 +395,25 @@ class ModelData(TypedDict):
|
|
392
395
|
"""The ModelData class."""
|
393
396
|
|
394
397
|
contents: bool
|
395
|
-
vendor_name: str | None
|
396
|
-
vendor_model: str | None
|
397
|
-
hardware_version: str | None
|
398
398
|
firmware_version: str | None
|
399
|
-
|
399
|
+
hardware_version: str | None
|
400
400
|
reachable: bool | None
|
401
|
+
vendor_model: str | None
|
402
|
+
vendor_name: str | None
|
403
|
+
zigbee_mac_address: str | None
|
401
404
|
|
402
405
|
|
403
406
|
class SmileBinarySensors(TypedDict, total=False):
|
404
407
|
"""Smile Binary Sensors class."""
|
405
408
|
|
406
|
-
cooling_enabled: bool
|
407
409
|
compressor_state: bool
|
410
|
+
cooling_enabled: bool
|
408
411
|
cooling_state: bool
|
409
412
|
dhw_state: bool
|
410
413
|
flame_state: bool
|
411
414
|
heating_state: bool
|
412
415
|
plugwise_notification: bool
|
413
|
-
|
416
|
+
secondary_boiler_state: bool
|
414
417
|
|
415
418
|
|
416
419
|
class SmileSensors(TypedDict, total=False):
|
@@ -482,9 +485,9 @@ class ThermoLoc(TypedDict, total=False):
|
|
482
485
|
"""Thermo Location class."""
|
483
486
|
|
484
487
|
name: str
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
+
primary: str | None
|
489
|
+
primary_prio: int
|
490
|
+
secondary: set[str]
|
488
491
|
|
489
492
|
|
490
493
|
class ActuatorData(TypedDict, total=False):
|
@@ -125,7 +125,7 @@ class SmileData(SmileHelper):
|
|
125
125
|
self._device_data_switching_group(device, data)
|
126
126
|
# Adam data
|
127
127
|
self._device_data_adam(device, data)
|
128
|
-
# Skip obtaining data for
|
128
|
+
# Skip obtaining data for (Adam) secondary thermostats
|
129
129
|
if device["dev_class"] not in ZONE_THERMOSTATS:
|
130
130
|
return data
|
131
131
|
|
@@ -164,7 +164,7 @@ class SmileData(SmileHelper):
|
|
164
164
|
):
|
165
165
|
data["binary_sensors"]["heating_state"] = self._heating_valves() != 0
|
166
166
|
|
167
|
-
# Show the allowed
|
167
|
+
# Show the allowed regulation_modes and gateway_modes
|
168
168
|
if device["dev_class"] == "gateway":
|
169
169
|
if self._reg_allowed_modes:
|
170
170
|
data["regulation_modes"] = self._reg_allowed_modes
|
@@ -173,7 +173,7 @@ class SmileData(SmileHelper):
|
|
173
173
|
data["gateway_modes"] = self._gw_allowed_modes
|
174
174
|
self._count += 1
|
175
175
|
|
176
|
-
# Control_state, only for Adam
|
176
|
+
# Control_state, only available for Adam primary thermostats
|
177
177
|
if device["dev_class"] in ZONE_THERMOSTATS:
|
178
178
|
loc_id = device["location"]
|
179
179
|
if ctrl_state := self._control_state(loc_id):
|
@@ -813,7 +813,7 @@ class SmileHelper(SmileCommon):
|
|
813
813
|
"""Helper-function for smile.py: get_all_devices().
|
814
814
|
|
815
815
|
Update locations with thermostat ranking results and use
|
816
|
-
the result to update the device_class of
|
816
|
+
the result to update the device_class of secondary thermostats.
|
817
817
|
"""
|
818
818
|
self._thermo_locs = self._match_locations()
|
819
819
|
|
@@ -828,11 +828,11 @@ class SmileHelper(SmileCommon):
|
|
828
828
|
for dev_id, device in self.gw_devices.items():
|
829
829
|
self._rank_thermostat(thermo_matching, loc_id, dev_id, device)
|
830
830
|
|
831
|
-
# Update
|
831
|
+
# Update secondary thermostat class where needed
|
832
832
|
for dev_id, device in self.gw_devices.items():
|
833
833
|
if (loc_id := device["location"]) in self._thermo_locs:
|
834
834
|
tl_loc_id = self._thermo_locs[loc_id]
|
835
|
-
if "
|
835
|
+
if "secondary" in tl_loc_id and dev_id in tl_loc_id["secondary"]:
|
836
836
|
device["dev_class"] = "thermo_sensor"
|
837
837
|
|
838
838
|
def _match_locations(self) -> dict[str, ThermoLoc]:
|
@@ -845,7 +845,7 @@ class SmileHelper(SmileCommon):
|
|
845
845
|
for appliance_details in self.gw_devices.values():
|
846
846
|
if appliance_details["location"] == location_id:
|
847
847
|
location_details.update(
|
848
|
-
{"
|
848
|
+
{"primary": None, "primary_prio": 0, "secondary": set()}
|
849
849
|
)
|
850
850
|
matched_locations[location_id] = location_details
|
851
851
|
|
@@ -860,29 +860,29 @@ class SmileHelper(SmileCommon):
|
|
860
860
|
) -> None:
|
861
861
|
"""Helper-function for _scan_thermostats().
|
862
862
|
|
863
|
-
Rank the thermostat based on appliance_details:
|
863
|
+
Rank the thermostat based on appliance_details: primary or secondary.
|
864
864
|
"""
|
865
865
|
appl_class = appliance_details["dev_class"]
|
866
866
|
appl_d_loc = appliance_details["location"]
|
867
867
|
if loc_id == appl_d_loc and appl_class in thermo_matching:
|
868
|
-
# Pre-elect new
|
869
|
-
if thermo_matching[appl_class] > self._thermo_locs[loc_id]["
|
870
|
-
# Demote former
|
871
|
-
if (
|
872
|
-
self._thermo_locs[loc_id]["
|
868
|
+
# Pre-elect new primary
|
869
|
+
if thermo_matching[appl_class] > self._thermo_locs[loc_id]["primary_prio"]:
|
870
|
+
# Demote former primary
|
871
|
+
if (tl_primary:= self._thermo_locs[loc_id]["primary"]) is not None:
|
872
|
+
self._thermo_locs[loc_id]["secondary"].add(tl_primary)
|
873
873
|
|
874
|
-
# Crown
|
875
|
-
self._thermo_locs[loc_id]["
|
876
|
-
self._thermo_locs[loc_id]["
|
874
|
+
# Crown primary
|
875
|
+
self._thermo_locs[loc_id]["primary_prio"] = thermo_matching[appl_class]
|
876
|
+
self._thermo_locs[loc_id]["primary"] = appliance_id
|
877
877
|
|
878
878
|
else:
|
879
|
-
self._thermo_locs[loc_id]["
|
879
|
+
self._thermo_locs[loc_id]["secondary"].add(appliance_id)
|
880
880
|
|
881
881
|
def _control_state(self, loc_id: str) -> str | bool:
|
882
882
|
"""Helper-function for _device_data_adam().
|
883
883
|
|
884
884
|
Adam: find the thermostat control_state of a location, from DOMAIN_OBJECTS.
|
885
|
-
Represents the heating/cooling demand-state of the local
|
885
|
+
Represents the heating/cooling demand-state of the local primary thermostat.
|
886
886
|
Note: heating or cooling can still be active when the setpoint has been reached.
|
887
887
|
"""
|
888
888
|
locator = f'location[@id="{loc_id}"]'
|
@@ -6,7 +6,7 @@ from __future__ import annotations
|
|
6
6
|
|
7
7
|
# Dict as class
|
8
8
|
# Version detection
|
9
|
-
from plugwise.constants import NONE,
|
9
|
+
from plugwise.constants import NONE, DeviceData
|
10
10
|
from plugwise.legacy.helper import SmileLegacyHelper
|
11
11
|
from plugwise.util import remove_empty_platform_dicts
|
12
12
|
|
@@ -57,8 +57,8 @@ class SmileLegacyData(SmileLegacyHelper):
|
|
57
57
|
# Switching groups data
|
58
58
|
self._device_data_switching_group(device, data)
|
59
59
|
|
60
|
-
# Skip obtaining data
|
61
|
-
if device["dev_class"]
|
60
|
+
# Skip obtaining data when not a thermostat
|
61
|
+
if device["dev_class"] != "thermostat":
|
62
62
|
return data
|
63
63
|
|
64
64
|
# Thermostat data (presets, temperatures etc)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: plugwise
|
3
|
-
Version: 0.37.
|
3
|
+
Version: 0.37.2
|
4
4
|
Summary: Plugwise Smile (Adam/Anna/P1) and Stretch module for Python 3.
|
5
5
|
Home-page: https://github.com/plugwise/python-plugwise
|
6
6
|
Author: Plugwise device owners
|
@@ -42,11 +42,8 @@ Requires-Python: >=3.11.0
|
|
42
42
|
Description-Content-Type: text/markdown
|
43
43
|
License-File: LICENSE
|
44
44
|
Requires-Dist: aiohttp
|
45
|
-
Requires-Dist: async_timeout
|
46
|
-
Requires-Dist: crcmod
|
47
45
|
Requires-Dist: defusedxml
|
48
46
|
Requires-Dist: munch
|
49
|
-
Requires-Dist: pyserial
|
50
47
|
Requires-Dist: python-dateutil
|
51
48
|
|
52
49
|
# Plugwise python module
|
@@ -1,10 +1,10 @@
|
|
1
1
|
[build-system]
|
2
|
-
requires = ["setuptools~=69.0", "wheel~=0.
|
2
|
+
requires = ["setuptools~=69.0", "wheel~=0.43.0"]
|
3
3
|
build-backend = "setuptools.build_meta"
|
4
4
|
|
5
5
|
[project]
|
6
6
|
name = "plugwise"
|
7
|
-
version = "0.37.
|
7
|
+
version = "0.37.2"
|
8
8
|
license = {file = "LICENSE"}
|
9
9
|
description = "Plugwise Smile (Adam/Anna/P1) and Stretch module for Python 3."
|
10
10
|
readme = "README.md"
|
@@ -28,11 +28,8 @@ maintainers = [
|
|
28
28
|
requires-python = ">=3.11.0"
|
29
29
|
dependencies = [
|
30
30
|
"aiohttp",
|
31
|
-
"async_timeout",
|
32
|
-
"crcmod",
|
33
31
|
"defusedxml",
|
34
32
|
"munch",
|
35
|
-
"pyserial",
|
36
33
|
"python-dateutil",
|
37
34
|
]
|
38
35
|
|
@@ -944,13 +944,12 @@ class TestPlugwise: # pylint: disable=attribute-defined-outside-init
|
|
944
944
|
log_msg = f" # Assert version matching '{smile_version}"
|
945
945
|
parent_logger.info(log_msg)
|
946
946
|
assert smile.smile_version == smile_version
|
947
|
-
|
948
|
-
|
949
|
-
|
950
|
-
|
951
|
-
|
952
|
-
|
953
|
-
assert not smile.smile_legacy
|
947
|
+
log_msg = f" # Assert legacy {smile_legacy}"
|
948
|
+
parent_logger.info(log_msg)
|
949
|
+
if smile_legacy:
|
950
|
+
assert smile.smile_legacy
|
951
|
+
else:
|
952
|
+
assert not smile.smile_legacy
|
954
953
|
|
955
954
|
class PlugwiseTestError(Exception):
|
956
955
|
"""Plugwise test exceptions class."""
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|