diff --git a/tests/test_dryer.py b/tests/test_dryer.py index 35e4a04..7d98c78 100644 --- a/tests/test_dryer.py +++ b/tests/test_dryer.py @@ -1,5 +1,6 @@ import json import unittest +from unittest import mock from wideq.client import Client, DeviceInfo from wideq.dryer import ( @@ -48,6 +49,8 @@ class DryerStatusTest(unittest.TestCase): def test_properties(self): status = DryerStatus(self.dryer, POLL_DATA) + self.assertEqual(self.dryer, status.dryer) + self.assertEqual(POLL_DATA, status.data) self.assertEqual(DryerState.DRYING, status.state) self.assertEqual(DryerState.INITIAL, status.previous_state) self.assertEqual(DryLevel.NORMAL, status.dry_level) @@ -61,3 +64,17 @@ class DryerStatusTest(unittest.TestCase): self.assertEqual('No Error', status.error) self.assertEqual(TempControl.MID_HIGH, status.temperature_control) self.assertEqual(TimeDry.OFF, status.time_dry) + + @mock.patch('wideq.client.logging') + def test_properties_unknown_enum_value(self, mock_logging): + """ + This should not raise an error for an invalid enum value and instead + use the `UNKNOWN` enum value. + """ + data = dict(POLL_DATA, State='5000') + status = DryerStatus(self.dryer, data) + self.assertEqual(DryerState.UNKNOWN, status.state) + expected_call = mock.call( + 'Value `%s` for key `%s` not in options: %s. Values from API: %s', + '5000', 'State', mock.ANY, mock.ANY) + self.assertEqual(expected_call, mock_logging.warning.call_args) diff --git a/wideq/client.py b/wideq/client.py index 987cbb9..3ab371c 100644 --- a/wideq/client.py +++ b/wideq/client.py @@ -3,6 +3,7 @@ SmartThinQ API for most use cases. """ import json import enum +import logging import requests import base64 from collections import namedtuple @@ -12,6 +13,8 @@ from . import core DEFAULT_COUNTRY = 'US' DEFAULT_LANGUAGE = 'en-US' +#: Represents an unknown enum value. +_UNKNOWN = 'Unknown' class Monitor(object): @@ -350,6 +353,11 @@ class ModelInfo(object): """Look up the friendly enum name for an encoded value. """ options = self.value(key).options + if value not in options: + logging.warning( + 'Value `%s` for key `%s` not in options: %s. Values from API: ' + '%s', value, key, options, self.data['Value'][key]['option']) + return _UNKNOWN return options[value] def reference_name(self, key: str, value: Any) -> str: diff --git a/wideq/dryer.py b/wideq/dryer.py index 191e8c0..2a19121 100644 --- a/wideq/dryer.py +++ b/wideq/dryer.py @@ -1,7 +1,7 @@ import enum from typing import Optional -from .client import Device +from .client import Device, _UNKNOWN class DryerState(enum.Enum): @@ -17,6 +17,7 @@ class DryerState(enum.Enum): RUNNING = '@WM_STATE_RUNNING_W' SMART_DIAGNOSIS = '@WM_STATE_SMART_DIAGNOSIS_W' WRINKLE_CARE = '@WM_STATE_WRINKLECARE_W' + UNKNOWN = _UNKNOWN class DryLevel(enum.Enum): @@ -31,6 +32,7 @@ class DryLevel(enum.Enum): NORMAL = '@WM_DRY27_DRY_LEVEL_NORMAL_W' OFF = '-' VERY = '@WM_DRY27_DRY_LEVEL_VERY_W' + UNKNOWN = _UNKNOWN class DryerError(enum.Enum): @@ -52,6 +54,7 @@ class DryerError(enum.Enum): ERROR_TE2 = '@WM_US_DRYER_ERROR_TE2_W' ERROR_TE5 = '@WM_US_DRYER_ERROR_TE5_W' ERROR_TE6 = '@WM_US_DRYER_ERROR_TE6_W' + UNKNOWN = _UNKNOWN class TempControl(enum.Enum): @@ -63,6 +66,7 @@ class TempControl(enum.Enum): MEDIUM = '@WM_DRY27_TEMP_MEDIUM_W' MID_HIGH = '@WM_DRY27_TEMP_MID_HIGH_W' HIGH = '@WM_DRY27_TEMP_HIGH_W' + UNKNOWN = _UNKNOWN class TimeDry(enum.Enum): @@ -74,6 +78,7 @@ class TimeDry(enum.Enum): FOURTY = '40' FIFTY = '50' SIXTY = '60' + UNKNOWN = _UNKNOWN class DryerDevice(Device):