From 31e62852a5124c66c8d06ac31949d93efc364bf7 Mon Sep 17 00:00:00 2001 From: Emmanuel Levijarvi Date: Fri, 6 Feb 2026 23:25:03 -0800 Subject: [PATCH 1/6] feat: configure hypothesis fuzzing and bandit security scanning - Add hypothesis to testing requirements in setup.cfg - Add property-based fuzz tests for DeviceStatus model in tests/test_mqtt_hypothesis.py - Add bandit environment to tox.ini for security linting - Add security job to GitHub Actions workflow to run bandit --- .github/workflows/ci.yml | 19 ++++ setup.cfg | 1 + tests/test_mqtt_hypothesis.py | 173 ++++++++++++++++++++++++++++++++++ tox.ini | 9 +- 4 files changed, 201 insertions(+), 1 deletion(-) create mode 100644 tests/test_mqtt_hypothesis.py diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a383012..0341451 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,6 +28,25 @@ jobs: - name: Run tox lint run: tox -e lint + security: + name: Security Check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.13' + + - name: Install tox + run: | + python -m pip install --upgrade pip + python -m pip install tox + + - name: Run bandit + run: tox -e bandit + test: name: Test on Python ${{ matrix.python-version }} runs-on: ubuntu-latest diff --git a/setup.cfg b/setup.cfg index 256c2f1..89dee02 100644 --- a/setup.cfg +++ b/setup.cfg @@ -77,6 +77,7 @@ testing = pytest pytest-cov pytest-asyncio + hypothesis # Development tools dev = diff --git a/tests/test_mqtt_hypothesis.py b/tests/test_mqtt_hypothesis.py new file mode 100644 index 0000000..ed2dac5 --- /dev/null +++ b/tests/test_mqtt_hypothesis.py @@ -0,0 +1,173 @@ + +import pytest +from hypothesis import given, strategies as st +from nwp500.models import DeviceStatus +from nwp500.enums import TemperatureType + +# Base payload matching required fields in DeviceStatus +BASE_PAYLOAD = { + "command": 0, + "outsideTemperature": 0.0, + "specialFunctionStatus": 0, + "errorCode": 0, + "subErrorCode": 0, + "smartDiagnostic": 0, + "faultStatus1": 0, + "faultStatus2": 0, + "wifiRssi": 0, + "dhwChargePer": 0.0, + "drEventStatus": 0, + "vacationDaySetting": 0, + "vacationDayElapsed": 0, + "antiLegionellaPeriod": 0, + "programReservationType": 0, + "tempFormulaType": 0, + "currentStatenum": 0, + "targetFanRpm": 0, + "currentFanRpm": 0, + "fanPwm": 0, + "mixingRate": 0.0, + "eevStep": 0, + "airFilterAlarmPeriod": 0, + "airFilterAlarmElapsed": 0, + "cumulatedOpTimeEvaFan": 0, + "cumulatedDhwFlowRate": 0.0, + "touStatus": 0, + "drOverrideStatus": 0, + "touOverrideStatus": 0, + "totalEnergyCapacity": 0.0, + "availableEnergyCapacity": 0.0, + "recircOperationMode": 0, + "recircPumpOperationStatus": 0, + "recircHotBtnReady": 0, + "recircOperationReason": 0, + "recircErrorStatus": 0, + "currentInstPower": 0.0, + "didReload": 0, + "operationBusy": 0, + "freezeProtectionUse": 0, + "dhwUse": 0, + "dhwUseSustained": 0, + "dhwOperationBusy": 0, + "programReservationUse": 0, + "ecoUse": 0, + "compUse": 0, + "eevUse": 0, + "evaFanUse": 0, + "shutOffValveUse": 0, + "conOvrSensorUse": 0, + "wtrOvrSensorUse": 0, + "antiLegionellaUse": 0, + "antiLegionellaOperationBusy": 0, + "errorBuzzerUse": 0, + "currentHeatUse": 0, + "heatUpperUse": 0, + "heatLowerUse": 0, + "scaldUse": 0, + "airFilterAlarmUse": 0, + "recircOperationBusy": 0, + "recircReservationUse": 0, + "dhwTemperature": 0, + "dhwTemperatureSetting": 0, + "dhwTargetTemperatureSetting": 0, + "freezeProtectionTemperature": 0, + "dhwTemperature2": 0, + "hpUpperOnTempSetting": 0, + "hpUpperOffTempSetting": 0, + "hpLowerOnTempSetting": 0, + "hpLowerOffTempSetting": 0, + "heUpperOnTempSetting": 0, + "heUpperOffTempSetting": 0, + "heLowerOnTempSetting": 0, + "heLowerOffTempSetting": 0, + "heatMinOpTemperature": 0, + "recircTempSetting": 0, + "recircTemperature": 0, + "recircFaucetTemperature": 0, + "currentInletTemperature": 0, + "currentDhwFlowRate": 0, + "hpUpperOnDiffTempSetting": 0, + "hpUpperOffDiffTempSetting": 0, + "hpLowerOnDiffTempSetting": 0, + "hpLowerOffDiffTempSetting": 0, + "heUpperOnDiffTempSetting": 0, + "heUpperOffDiffTempSetting": 0, + "heLowerOnTDiffempSetting": 0, + "heLowerOffDiffTempSetting": 0, + "recircDhwFlowRate": 0, + "tankUpperTemperature": 0, + "tankLowerTemperature": 0, + "dischargeTemperature": 0, + "suctionTemperature": 0, + "evaporatorTemperature": 0, + "ambientTemperature": 0, + "targetSuperHeat": 0, + "currentSuperHeat": 0, + "operationMode": 0, + "dhwOperationSetting": 3, + "temperatureType": 2, + "freezeProtectionTempMin": 43.0, + "freezeProtectionTempMax": 65.0, +} + +@given( + temperature_type_int=st.sampled_from([1, 2]), + dhw_temp_raw=st.integers(min_value=0, max_value=200), # 0 to 100°C + tank_temp_raw=st.integers(min_value=0, max_value=1000), # 0 to 100°C (deci) + flow_rate_raw=st.integers(min_value=0, max_value=500), # 0 to 50 LPM +) +def test_device_status_fuzzing(temperature_type_int, dhw_temp_raw, tank_temp_raw, flow_rate_raw): + """ + Fuzz test parsing of DeviceStatus with varying temperature types and values. + """ + # Create a copy of the base payload + payload = BASE_PAYLOAD.copy() + + # Update with fuzzed values + payload["temperatureType"] = temperature_type_int + payload["dhwTemperature"] = dhw_temp_raw + payload["tankUpperTemperature"] = tank_temp_raw + payload["currentDhwFlowRate"] = flow_rate_raw + + # Parse the model + status = DeviceStatus.model_validate(payload) + + # Assertions based on temperature type + is_celsius = (temperature_type_int == 1) # 1=Celsius, 2=Fahrenheit + + # 1. Check Temperature Type parsing + if is_celsius: + assert status.temperature_type == TemperatureType.CELSIUS + else: + assert status.temperature_type == TemperatureType.FAHRENHEIT + + # 2. Check DHW Temperature (HalfCelsius) + # Raw value is half-celsius. + celsius_val = dhw_temp_raw / 2.0 + if is_celsius: + assert status.dhw_temperature == pytest.approx(celsius_val) + else: + fahrenheit_val = (celsius_val * 9/5) + 32 + assert status.dhw_temperature == pytest.approx(fahrenheit_val) + + # 3. Check Tank Temperature (DeciCelsius) + # Raw value is deci-celsius. + tank_celsius_val = tank_temp_raw / 10.0 + if is_celsius: + assert status.tank_upper_temperature == pytest.approx(tank_celsius_val) + else: + tank_fahrenheit_val = (tank_celsius_val * 9/5) + 32 + # Note: DeciCelsiusToPreferred in models calls DeciCelsius(raw).to_preferred(is_celsius) + # to_preferred -> to_fahrenheit -> standard conversion + # We need to match the exact logic if there's rounding involved, but simple math should match approx. + assert status.tank_upper_temperature == pytest.approx(tank_fahrenheit_val) + + # 4. Check Flow Rate (LPM * 10) + lpm_val = flow_rate_raw / 10.0 + if is_celsius: + assert status.current_dhw_flow_rate == pytest.approx(lpm_val) + else: + # Imperial: LPM to GPM + gpm_val = round(lpm_val * 0.264172, 2) + assert status.current_dhw_flow_rate == pytest.approx(gpm_val) + diff --git a/tox.ini b/tox.ini index 9047447..6982214 100644 --- a/tox.ini +++ b/tox.ini @@ -4,7 +4,7 @@ [tox] minversion = 3.24 -envlist = default,lint +envlist = default,lint,bandit isolated_build = True @@ -41,6 +41,13 @@ commands = pyright src/nwp500 {posargs} +[testenv:bandit] +description = Run bandit to check for security issues +skip_install = True +deps = bandit +commands = bandit -r src/ {posargs} + + [testenv:format] description = Format code with ruff skip_install = True From e035a431f9b71c74ab67939dc3786a72e7ad266a Mon Sep 17 00:00:00 2001 From: Emmanuel Levijarvi Date: Mon, 9 Feb 2026 10:28:57 -0800 Subject: [PATCH 2/6] fix: resolve linting issues in test_mqtt_hypothesis.py - Fix import sorting and remove duplicate imports - Fix line length violations (>80 characters) - Remove trailing whitespace and blank line whitespace - Ensure proper code formatting for CI compliance --- tests/test_mqtt_hypothesis.py | 41 ++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/tests/test_mqtt_hypothesis.py b/tests/test_mqtt_hypothesis.py index ed2dac5..6aa111d 100644 --- a/tests/test_mqtt_hypothesis.py +++ b/tests/test_mqtt_hypothesis.py @@ -1,8 +1,8 @@ - import pytest + from hypothesis import given, strategies as st -from nwp500.models import DeviceStatus from nwp500.enums import TemperatureType +from nwp500.models import DeviceStatus # Base payload matching required fields in DeviceStatus BASE_PAYLOAD = { @@ -110,31 +110,34 @@ "freezeProtectionTempMax": 65.0, } + @given( temperature_type_int=st.sampled_from([1, 2]), dhw_temp_raw=st.integers(min_value=0, max_value=200), # 0 to 100°C - tank_temp_raw=st.integers(min_value=0, max_value=1000), # 0 to 100°C (deci) - flow_rate_raw=st.integers(min_value=0, max_value=500), # 0 to 50 LPM + tank_temp_raw=st.integers(min_value=0, max_value=1000), # 0 to 100°C (deci) + flow_rate_raw=st.integers(min_value=0, max_value=500), # 0 to 50 LPM ) -def test_device_status_fuzzing(temperature_type_int, dhw_temp_raw, tank_temp_raw, flow_rate_raw): +def test_device_status_fuzzing( + temperature_type_int, dhw_temp_raw, tank_temp_raw, flow_rate_raw +): """ Fuzz test parsing of DeviceStatus with varying temperature types and values. """ # Create a copy of the base payload payload = BASE_PAYLOAD.copy() - + # Update with fuzzed values payload["temperatureType"] = temperature_type_int payload["dhwTemperature"] = dhw_temp_raw payload["tankUpperTemperature"] = tank_temp_raw payload["currentDhwFlowRate"] = flow_rate_raw - + # Parse the model status = DeviceStatus.model_validate(payload) - + # Assertions based on temperature type - is_celsius = (temperature_type_int == 1) # 1=Celsius, 2=Fahrenheit - + is_celsius = temperature_type_int == 1 # 1=Celsius, 2=Fahrenheit + # 1. Check Temperature Type parsing if is_celsius: assert status.temperature_type == TemperatureType.CELSIUS @@ -142,12 +145,12 @@ def test_device_status_fuzzing(temperature_type_int, dhw_temp_raw, tank_temp_raw assert status.temperature_type == TemperatureType.FAHRENHEIT # 2. Check DHW Temperature (HalfCelsius) - # Raw value is half-celsius. + # Raw value is half-celsius. celsius_val = dhw_temp_raw / 2.0 if is_celsius: assert status.dhw_temperature == pytest.approx(celsius_val) else: - fahrenheit_val = (celsius_val * 9/5) + 32 + fahrenheit_val = (celsius_val * 9 / 5) + 32 assert status.dhw_temperature == pytest.approx(fahrenheit_val) # 3. Check Tank Temperature (DeciCelsius) @@ -156,11 +159,14 @@ def test_device_status_fuzzing(temperature_type_int, dhw_temp_raw, tank_temp_raw if is_celsius: assert status.tank_upper_temperature == pytest.approx(tank_celsius_val) else: - tank_fahrenheit_val = (tank_celsius_val * 9/5) + 32 - # Note: DeciCelsiusToPreferred in models calls DeciCelsius(raw).to_preferred(is_celsius) - # to_preferred -> to_fahrenheit -> standard conversion - # We need to match the exact logic if there's rounding involved, but simple math should match approx. - assert status.tank_upper_temperature == pytest.approx(tank_fahrenheit_val) + tank_fahrenheit_val = (tank_celsius_val * 9 / 5) + 32 + # Note: DeciCelsiusToPreferred in models calls DeciCelsius(raw).to_preferred( + # is_celsius) to_preferred -> to_fahrenheit -> standard conversion + # We need to match the exact logic if there's rounding involved, but simple + # math should match approx. + assert status.tank_upper_temperature == pytest.approx( + tank_fahrenheit_val + ) # 4. Check Flow Rate (LPM * 10) lpm_val = flow_rate_raw / 10.0 @@ -170,4 +176,3 @@ def test_device_status_fuzzing(temperature_type_int, dhw_temp_raw, tank_temp_raw # Imperial: LPM to GPM gpm_val = round(lpm_val * 0.264172, 2) assert status.current_dhw_flow_rate == pytest.approx(gpm_val) - From 22d4e715188f01d9cf361e329f03364e5ccf621d Mon Sep 17 00:00:00 2001 From: Emmanuel Levijarvi Date: Mon, 9 Feb 2026 10:43:47 -0800 Subject: [PATCH 3/6] fix: resolve remaining linting issues in test_mqtt_hypothesis.py - Fix line length violations in comments (>80 characters) - Ensure all ruff linting checks pass - All tests continue to pass locally --- tests/test_mqtt_hypothesis.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/tests/test_mqtt_hypothesis.py b/tests/test_mqtt_hypothesis.py index 6aa111d..72b308c 100644 --- a/tests/test_mqtt_hypothesis.py +++ b/tests/test_mqtt_hypothesis.py @@ -1,6 +1,7 @@ import pytest +from hypothesis import given +from hypothesis import strategies as st -from hypothesis import given, strategies as st from nwp500.enums import TemperatureType from nwp500.models import DeviceStatus @@ -160,10 +161,11 @@ def test_device_status_fuzzing( assert status.tank_upper_temperature == pytest.approx(tank_celsius_val) else: tank_fahrenheit_val = (tank_celsius_val * 9 / 5) + 32 - # Note: DeciCelsiusToPreferred in models calls DeciCelsius(raw).to_preferred( - # is_celsius) to_preferred -> to_fahrenheit -> standard conversion - # We need to match the exact logic if there's rounding involved, but simple - # math should match approx. + # Note: DeciCelsiusToPreferred calls DeciCelsius(raw).to_preferred( + # is_celsius) + # to_preferred -> to_fahrenheit -> standard conversion + # We need to match the exact logic if there's rounding involved, but + # simple math should match approx. assert status.tank_upper_temperature == pytest.approx( tank_fahrenheit_val ) From 8c91ffe88ef32541d5c119e9e41e02bf397e7e75 Mon Sep 17 00:00:00 2001 From: Emmanuel Levijarvi Date: Mon, 9 Feb 2026 10:54:13 -0800 Subject: [PATCH 4/6] fix: configure bandit to ignore low-severity assert usage issues - Add .bandit configuration file to skip B101 (assert_used) warnings - Update tox.ini bandit environment to use configuration file - Security check now passes while maintaining security scanning for actual vulnerabilities - Assert statements in CLI rich output are low-severity and acceptable for this use case --- .bandit | 1 + tox.ini | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 .bandit diff --git a/.bandit b/.bandit new file mode 100644 index 0000000..ec2e3a9 --- /dev/null +++ b/.bandit @@ -0,0 +1 @@ +skips: ['B101'] \ No newline at end of file diff --git a/tox.ini b/tox.ini index 6982214..550546e 100644 --- a/tox.ini +++ b/tox.ini @@ -45,7 +45,7 @@ commands = description = Run bandit to check for security issues skip_install = True deps = bandit -commands = bandit -r src/ {posargs} +commands = bandit -c .bandit -r src/ {posargs} [testenv:format] From bca42551d7442bbe17d3331d4e0bd10f19436606 Mon Sep 17 00:00:00 2001 From: Emmanuel Levijarvi Date: Mon, 9 Feb 2026 11:58:52 -0800 Subject: [PATCH 5/6] fix: address pull request review comments - Fix flow rate test to use lenient tolerance (abs=0.01) instead of manual rounding This avoids brittle assumptions about the converter's rounding behavior and instead relies on pytest.approx() to account for the model's 2-decimal rounding - Improve bandit security scanning configuration Replaced global B101 skip with file-specific skip for src/nwp500/cli/rich_output.py This maintains security scanning rigor while acknowledging that assert statements are acceptable for type-narrowing checks in CLI optional feature code - Note: 'heLowerOnTDiffempSetting' field name retains the API's existing typo as documented in the model's alias - this is the correct key expected by the DeviceStatus model validation All 403 tests passing, security and linting checks passing --- .bandit | 4 +++- .hypothesis/constants/05044b0e70ef42ab | 4 ++++ .hypothesis/constants/13db13a7b2178134 | 4 ++++ .hypothesis/constants/1b534f211836d036 | 4 ++++ .hypothesis/constants/22cdb7ce598358e5 | 4 ++++ .hypothesis/constants/30373286342e9c2d | 4 ++++ .hypothesis/constants/351307d9f52e5712 | 4 ++++ .hypothesis/constants/38e5a0ee4c20c2fa | 4 ++++ .hypothesis/constants/3cd888b2fda940ce | 4 ++++ .hypothesis/constants/3e41f6e2dac7d711 | 4 ++++ .hypothesis/constants/43960b0ace50254c | 4 ++++ .hypothesis/constants/47db797441adc9da | 4 ++++ .hypothesis/constants/523206edf9bd1235 | 4 ++++ .hypothesis/constants/67b0a8ccf18bf5d2 | 4 ++++ .hypothesis/constants/74e6edbaadef1e50 | 4 ++++ .hypothesis/constants/767fac7418bf21ee | 4 ++++ .hypothesis/constants/7b14ae8dd875b280 | 4 ++++ .hypothesis/constants/7d39af6d962efa3c | 4 ++++ .hypothesis/constants/89a580be14782398 | 4 ++++ .hypothesis/constants/8f1254dc32667f86 | 4 ++++ .hypothesis/constants/9e0fd89dbf206808 | 4 ++++ .hypothesis/constants/9eab8fc57863e41e | 4 ++++ .hypothesis/constants/a3f229c898281d19 | 4 ++++ .hypothesis/constants/b00985cd3c10a1f8 | 4 ++++ .hypothesis/constants/b294530e090203ba | 4 ++++ .hypothesis/constants/b5232deb51bddc9a | 4 ++++ .hypothesis/constants/bd643e9276a6173b | 4 ++++ .hypothesis/constants/c7a31c6dc0068cbd | 4 ++++ .hypothesis/constants/ca0b70aa93535c1f | 4 ++++ .hypothesis/constants/cd91fc95eade0457 | 4 ++++ .hypothesis/constants/d0ea67d716f83a90 | 4 ++++ .hypothesis/constants/dae78f4d97fdd43b | 4 ++++ .hypothesis/constants/dcfcf6e03af72a1c | 4 ++++ .hypothesis/constants/dfc00db7cf73d63c | 4 ++++ .hypothesis/constants/e4b0f73ee49546d6 | 4 ++++ .../examples/04e6b3400353b141/b04e33f1dccbdab0 | 2 ++ .../examples/04e6b3400353b141/e2ebc17191359b9b | 2 ++ .../examples/b04e33f1dccbdab0/3e1706876c4d4240 | Bin 0 -> 8 bytes .../examples/e2ebc17191359b9b/06e8e5454ebe80d4 | Bin 0 -> 9 bytes .../examples/e2ebc17191359b9b/6fe30320955145d3 | Bin 0 -> 9 bytes .../examples/e2ebc17191359b9b/97091e146329faa6 | Bin 0 -> 9 bytes tests/test_mqtt_hypothesis.py | 8 +++++--- 42 files changed, 148 insertions(+), 4 deletions(-) create mode 100644 .hypothesis/constants/05044b0e70ef42ab create mode 100644 .hypothesis/constants/13db13a7b2178134 create mode 100644 .hypothesis/constants/1b534f211836d036 create mode 100644 .hypothesis/constants/22cdb7ce598358e5 create mode 100644 .hypothesis/constants/30373286342e9c2d create mode 100644 .hypothesis/constants/351307d9f52e5712 create mode 100644 .hypothesis/constants/38e5a0ee4c20c2fa create mode 100644 .hypothesis/constants/3cd888b2fda940ce create mode 100644 .hypothesis/constants/3e41f6e2dac7d711 create mode 100644 .hypothesis/constants/43960b0ace50254c create mode 100644 .hypothesis/constants/47db797441adc9da create mode 100644 .hypothesis/constants/523206edf9bd1235 create mode 100644 .hypothesis/constants/67b0a8ccf18bf5d2 create mode 100644 .hypothesis/constants/74e6edbaadef1e50 create mode 100644 .hypothesis/constants/767fac7418bf21ee create mode 100644 .hypothesis/constants/7b14ae8dd875b280 create mode 100644 .hypothesis/constants/7d39af6d962efa3c create mode 100644 .hypothesis/constants/89a580be14782398 create mode 100644 .hypothesis/constants/8f1254dc32667f86 create mode 100644 .hypothesis/constants/9e0fd89dbf206808 create mode 100644 .hypothesis/constants/9eab8fc57863e41e create mode 100644 .hypothesis/constants/a3f229c898281d19 create mode 100644 .hypothesis/constants/b00985cd3c10a1f8 create mode 100644 .hypothesis/constants/b294530e090203ba create mode 100644 .hypothesis/constants/b5232deb51bddc9a create mode 100644 .hypothesis/constants/bd643e9276a6173b create mode 100644 .hypothesis/constants/c7a31c6dc0068cbd create mode 100644 .hypothesis/constants/ca0b70aa93535c1f create mode 100644 .hypothesis/constants/cd91fc95eade0457 create mode 100644 .hypothesis/constants/d0ea67d716f83a90 create mode 100644 .hypothesis/constants/dae78f4d97fdd43b create mode 100644 .hypothesis/constants/dcfcf6e03af72a1c create mode 100644 .hypothesis/constants/dfc00db7cf73d63c create mode 100644 .hypothesis/constants/e4b0f73ee49546d6 create mode 100644 .hypothesis/examples/04e6b3400353b141/b04e33f1dccbdab0 create mode 100644 .hypothesis/examples/04e6b3400353b141/e2ebc17191359b9b create mode 100644 .hypothesis/examples/b04e33f1dccbdab0/3e1706876c4d4240 create mode 100644 .hypothesis/examples/e2ebc17191359b9b/06e8e5454ebe80d4 create mode 100644 .hypothesis/examples/e2ebc17191359b9b/6fe30320955145d3 create mode 100644 .hypothesis/examples/e2ebc17191359b9b/97091e146329faa6 diff --git a/.bandit b/.bandit index ec2e3a9..2113d89 100644 --- a/.bandit +++ b/.bandit @@ -1 +1,3 @@ -skips: ['B101'] \ No newline at end of file +assert_used: + skips: + - src/nwp500/cli/rich_output.py diff --git a/.hypothesis/constants/05044b0e70ef42ab b/.hypothesis/constants/05044b0e70ef42ab new file mode 100644 index 0000000..813a1ee --- /dev/null +++ b/.hypothesis/constants/05044b0e70ef42ab @@ -0,0 +1,4 @@ +# file: /home/emmanuel/Projects/nwp500-python/src/nwp500/unit_system.py +# hypothesis_version: 6.151.5 + +['Emmanuel Levijarvi', 'MIT', 'metric', 'unit_system', 'us_customary'] \ No newline at end of file diff --git a/.hypothesis/constants/13db13a7b2178134 b/.hypothesis/constants/13db13a7b2178134 new file mode 100644 index 0000000..d1c91a4 --- /dev/null +++ b/.hypothesis/constants/13db13a7b2178134 @@ -0,0 +1,4 @@ +# file: /home/emmanuel/Projects/nwp500-python/src/nwp500/utils.py +# hypothesis_version: 6.151.5 + +['Emmanuel Levijarvi', 'MIT'] \ No newline at end of file diff --git a/.hypothesis/constants/1b534f211836d036 b/.hypothesis/constants/1b534f211836d036 new file mode 100644 index 0000000..dfdb5a4 --- /dev/null +++ b/.hypothesis/constants/1b534f211836d036 @@ -0,0 +1,4 @@ +# file: /home/emmanuel/Projects/nwp500-python/src/nwp500/enums.py +# hypothesis_version: 6.151.5 + +[257, 326, 407, 445, 480, 481, 513, 515, 517, 593, 594, 595, 596, 598, 615, 781, 798, 799, 901, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 920, 940, 990, 16777217, 16777219, 16777222, 16777225, 16777226, 33554433, 33554434, 33554437, 33554438, 33554439, 33554440, 33554441, 33554442, 33554443, 33554444, 33554445, 33554446, 33554447, 33554451, 33554455, 33554464, 33554466, 33554467, 33554468, 33554469, 33554470, 33554471, 33554472, 33554473, 33554474, 33554475, 33554476, '0.5°C', '1°C', '3 Stage', '50 gallons', '65 gallons', '80 gallons', 'Abnormal DIP Switch', 'Abnormal EEPROM', 'Abnormal Feedback', 'Abnormal Panel Key', 'Abnormal Power Meter', 'Advance Load Up', 'Always', 'Button', 'C', 'Commercial', 'Customer Peak Event', 'Dry Fire', 'Electric', 'Energy Saver', 'Heat Element', 'Heat Pump', 'Heat Pump Active', 'High Demand', 'Hybrid Boost', 'Hybrid Efficiency', 'Load Up', 'Mid Peak', 'No Error', 'Normal Operation', 'Not Applied', 'OFF', 'Off Peak', 'On Peak', 'Power Off', 'R', 'Relay Fault', 'Replacement Needed', 'Residential', 'Run Normal', 'Schedule', 'Shed', 'Standby', 'Temperature', 'Unknown', 'Vacation', 'Water Leak Detected'] \ No newline at end of file diff --git a/.hypothesis/constants/22cdb7ce598358e5 b/.hypothesis/constants/22cdb7ce598358e5 new file mode 100644 index 0000000..77e3851 --- /dev/null +++ b/.hypothesis/constants/22cdb7ce598358e5 @@ -0,0 +1,4 @@ +# file: /home/emmanuel/Projects/nwp500-python/src/nwp500/mqtt/diagnostics.py +# hypothesis_version: 6.151.5 + +[0.0, 1000, '-', '1', '11+', '2-5', '6-10', '=', 'Emmanuel Levijarvi', 'MIT', 'aws_error_counts', 'code', 'connected', 'inf', 'metrics', 'name', 'recent_connections', 'recent_drops', 'sample_durations', 'timestamp', 'total_sessions'] \ No newline at end of file diff --git a/.hypothesis/constants/30373286342e9c2d b/.hypothesis/constants/30373286342e9c2d new file mode 100644 index 0000000..a3db196 --- /dev/null +++ b/.hypothesis/constants/30373286342e9c2d @@ -0,0 +1,4 @@ +# file: /home/emmanuel/Projects/nwp500-python/src/nwp500/mqtt_events.py +# hypothesis_version: 6.151.5 + +['CurrentOperationMode', 'DeviceFeature', 'DeviceStatus', 'ErrorCode', '_', 'connection_resumed', 'error_cleared', 'error_detected', 'feature_received', 'heating_started', 'heating_stopped', 'mode_changed', 'power_changed', 'status_received', 'temperature_changed'] \ No newline at end of file diff --git a/.hypothesis/constants/351307d9f52e5712 b/.hypothesis/constants/351307d9f52e5712 new file mode 100644 index 0000000..4e168f8 --- /dev/null +++ b/.hypothesis/constants/351307d9f52e5712 @@ -0,0 +1,4 @@ +# file: /home/emmanuel/Projects/nwp500-python/src/nwp500/mqtt/client.py +# hypothesis_version: 6.151.5 + +[30.0, 300.0, 'Already connected', 'Emmanuel Levijarvi', 'MIT', 'Not connected', 'connected', 'connection failure', 'connection_resumed', 'name', 'resumed'] \ No newline at end of file diff --git a/.hypothesis/constants/38e5a0ee4c20c2fa b/.hypothesis/constants/38e5a0ee4c20c2fa new file mode 100644 index 0000000..799f638 --- /dev/null +++ b/.hypothesis/constants/38e5a0ee4c20c2fa @@ -0,0 +1,4 @@ +# file: /home/emmanuel/Projects/nwp500-python/src/nwp500/encoding.py +# hypothesis_version: 6.151.5 + +[150, 'Friday', 'Monday', 'Saturday', 'Sunday', 'Thursday', 'Tuesday', 'Wednesday', 'day_index', 'decimalPoint', 'decimal_point', 'enable', 'enabled', 'endHour', 'endMinute', 'end_hour', 'end_minute', 'hour', 'min', 'minute', 'mode', 'mode_id', 'month', 'param', 'priceMax', 'priceMin', 'season', 'startHour', 'startMinute', 'start_hour', 'start_minute', 'temperature', 'week', 'weekday'] \ No newline at end of file diff --git a/.hypothesis/constants/3cd888b2fda940ce b/.hypothesis/constants/3cd888b2fda940ce new file mode 100644 index 0000000..e49b057 --- /dev/null +++ b/.hypothesis/constants/3cd888b2fda940ce @@ -0,0 +1,4 @@ +# file: /home/emmanuel/Projects/nwp500-python/src/nwp500/mqtt/reconnection.py +# hypothesis_version: 6.151.5 + +['Emmanuel Levijarvi', 'MIT', 'deep', 'quick', 'reconnection_failed'] \ No newline at end of file diff --git a/.hypothesis/constants/3e41f6e2dac7d711 b/.hypothesis/constants/3e41f6e2dac7d711 new file mode 100644 index 0000000..1a2b4cf --- /dev/null +++ b/.hypothesis/constants/3e41f6e2dac7d711 @@ -0,0 +1,4 @@ +# file: /home/emmanuel/Projects/nwp500-python/src/nwp500/converters.py +# hypothesis_version: 6.151.5 + +[0.0, 0.264172, 10.0, 'Celsius', 'Fahrenheit', 'div_10', 'enum_validator', 'metric', 'mul_10', 'str_enum_validator', 'temp_formula_type', 'temperatureType', 'temperature_type', 'volume_to_preferred'] \ No newline at end of file diff --git a/.hypothesis/constants/43960b0ace50254c b/.hypothesis/constants/43960b0ace50254c new file mode 100644 index 0000000..06ac08d --- /dev/null +++ b/.hypothesis/constants/43960b0ace50254c @@ -0,0 +1,4 @@ +# file: /home/emmanuel/Projects/nwp500-python/venv/bin/pytest +# hypothesis_version: 6.151.5 + +['__main__'] \ No newline at end of file diff --git a/.hypothesis/constants/47db797441adc9da b/.hypothesis/constants/47db797441adc9da new file mode 100644 index 0000000..d2339be --- /dev/null +++ b/.hypothesis/constants/47db797441adc9da @@ -0,0 +1,4 @@ +# file: /home/emmanuel/Projects/nwp500-python/src/nwp500/topic_builder.py +# hypothesis_version: 6.151.5 + +['ctrl'] \ No newline at end of file diff --git a/.hypothesis/constants/523206edf9bd1235 b/.hypothesis/constants/523206edf9bd1235 new file mode 100644 index 0000000..1430a33 --- /dev/null +++ b/.hypothesis/constants/523206edf9bd1235 @@ -0,0 +1,4 @@ +# file: /home/emmanuel/Projects/nwp500-python/src/nwp500/mqtt/periodic.py +# hypothesis_version: 6.151.5 + +[300.0, 'DEVICE_ID_REDACTED', 'Emmanuel Levijarvi', 'name', 's'] \ No newline at end of file diff --git a/.hypothesis/constants/67b0a8ccf18bf5d2 b/.hypothesis/constants/67b0a8ccf18bf5d2 new file mode 100644 index 0000000..ae885fc --- /dev/null +++ b/.hypothesis/constants/67b0a8ccf18bf5d2 @@ -0,0 +1,4 @@ +# file: /usr/lib/python3.13/sitecustomize.py +# hypothesis_version: 6.151.5 + +[] \ No newline at end of file diff --git a/.hypothesis/constants/74e6edbaadef1e50 b/.hypothesis/constants/74e6edbaadef1e50 new file mode 100644 index 0000000..e3ee4a3 --- /dev/null +++ b/.hypothesis/constants/74e6edbaadef1e50 @@ -0,0 +1,4 @@ +# file: /home/emmanuel/Projects/nwp500-python/src/nwp500/events.py +# hypothesis_version: 6.151.5 + +['Emmanuel Levijarvi', 'MIT'] \ No newline at end of file diff --git a/.hypothesis/constants/767fac7418bf21ee b/.hypothesis/constants/767fac7418bf21ee new file mode 100644 index 0000000..003f527 --- /dev/null +++ b/.hypothesis/constants/767fac7418bf21ee @@ -0,0 +1,4 @@ +# file: /home/emmanuel/Projects/nwp500-python/src/nwp500/device_info_cache.py +# hypothesis_version: 6.151.5 + +['Device info cached', 'DeviceFeature', 'DeviceFeature | None', 'Emmanuel Levijarvi', 'cached_at', 'device_count', 'devices', 'expires_at', 'is_expired', 'mac'] \ No newline at end of file diff --git a/.hypothesis/constants/7b14ae8dd875b280 b/.hypothesis/constants/7b14ae8dd875b280 new file mode 100644 index 0000000..392872d --- /dev/null +++ b/.hypothesis/constants/7b14ae8dd875b280 @@ -0,0 +1,4 @@ +# file: /home/emmanuel/Projects/nwp500-python/src/nwp500/temperature.py +# hypothesis_version: 6.151.5 + +[2.0, 10.0] \ No newline at end of file diff --git a/.hypothesis/constants/7d39af6d962efa3c b/.hypothesis/constants/7d39af6d962efa3c new file mode 100644 index 0000000..72de7f5 --- /dev/null +++ b/.hypothesis/constants/7d39af6d962efa3c @@ -0,0 +1,4 @@ +# file: /home/emmanuel/Projects/nwp500-python/src/nwp500/mqtt/command_queue.py +# hypothesis_version: 6.151.5 + +['Emmanuel Levijarvi', 'MIT'] \ No newline at end of file diff --git a/.hypothesis/constants/89a580be14782398 b/.hypothesis/constants/89a580be14782398 new file mode 100644 index 0000000..0e3aa82 --- /dev/null +++ b/.hypothesis/constants/89a580be14782398 @@ -0,0 +1,4 @@ +# file: /home/emmanuel/Projects/nwp500-python/src/nwp500/auth.py +# hypothesis_version: 6.151.5 + +[200, 401, 3600, '/', 'AuthTokens', 'Content-Type', 'Emmanuel Levijarvi', 'MIT', 'NavienAuthClient', 'SUCCESS', 'Token expires in: %s', 'User-Agent', 'UserInfo', 'accessKeyId', 'accessToken', 'access_key_id', 'access_token', 'application/json', 'authenticate', 'authorization', 'before', 'code', 'data', 'idToken', 'id_token', 'ignore', 'invalid', 'json', 'legal', 'metric', 'msg', 'password', 'refreshToken', 'refresh_access_token', 'refresh_token', 'secretKey', 'secret_key', 'sessionToken', 'session_token', 'token', 'tokens', 'unauthorized', 'us_customary', 'userId', 'userInfo'] \ No newline at end of file diff --git a/.hypothesis/constants/8f1254dc32667f86 b/.hypothesis/constants/8f1254dc32667f86 new file mode 100644 index 0000000..a35cac6 --- /dev/null +++ b/.hypothesis/constants/8f1254dc32667f86 @@ -0,0 +1,4 @@ +# file: /home/emmanuel/Projects/nwp500-python/src/nwp500/mqtt/control.py +# hypothesis_version: 6.151.5 + +[5.0, 365, '+00:00', 'Emmanuel Levijarvi', 'MqttDeviceInfoCache', 'Z', 'additionalValue', 'air-filter-reset', 'anti-leg-off', 'anti-leg-on', 'app-connection', 'clientID', 'command', 'ctrl', 'ctrl/rsv/rd', 'ctrl/tou/rd', 'days', 'deviceType', 'device_info', 'dhw-mode', 'dhw-temperature', 'dhw_use', 'dr-off', 'dr-on', 'goout-day', 'holiday_use', 'macAddress', 'mode', 'period_days', 'periods', 'power-off', 'power-on', 'power_use', 'protocolVersion', 'recirc-hotbtn', 'recirc-mode', 'recirculation_use', 'request', 'requestTopic', 'reservation-mode', 'responseTopic', 'rsv/rd', 'sessionID', 'st', 'st/did', 'st/rsv/rd', 'temperature', 'timestamp', 'tou-off', 'tou-on', 'tou/rd', 'vacation_days'] \ No newline at end of file diff --git a/.hypothesis/constants/9e0fd89dbf206808 b/.hypothesis/constants/9e0fd89dbf206808 new file mode 100644 index 0000000..8877f5f --- /dev/null +++ b/.hypothesis/constants/9e0fd89dbf206808 @@ -0,0 +1,4 @@ +# file: /home/emmanuel/Projects/nwp500-python/src/nwp500/mqtt/__init__.py +# hypothesis_version: 6.151.5 + +['ConnectionDropEvent', 'ConnectionEvent', 'MqttConnectionConfig', 'MqttMetrics', 'NavienMqttClient', 'PeriodicRequestType'] \ No newline at end of file diff --git a/.hypothesis/constants/9eab8fc57863e41e b/.hypothesis/constants/9eab8fc57863e41e new file mode 100644 index 0000000..c0ed3a3 --- /dev/null +++ b/.hypothesis/constants/9eab8fc57863e41e @@ -0,0 +1,4 @@ +# file: /home/emmanuel/Projects/nwp500-python/src/nwp500/mqtt/subscriptions.py +# hypothesis_version: 6.151.5 + +['#', 'Emmanuel Levijarvi', 'Heating started', 'Heating stopped', 'error_cleared', 'error_detected', 'feature', 'feature_received', 'heating_started', 'heating_stopped', 'metric', 'mode_changed', 'power_changed', 'response', 'status', 'status_received', 'temperature_changed', 'utf-8', '°C', '°F'] \ No newline at end of file diff --git a/.hypothesis/constants/a3f229c898281d19 b/.hypothesis/constants/a3f229c898281d19 new file mode 100644 index 0000000..02efcd7 --- /dev/null +++ b/.hypothesis/constants/a3f229c898281d19 @@ -0,0 +1,4 @@ +# file: /home/emmanuel/Projects/nwp500-python/src/nwp500/mqtt/utils.py +# hypothesis_version: 6.151.5 + +[1.0, 2.0, 120.0, 100, 256, 512, 1200, '#', '([0-9A-Fa-f]{12})', '+', '......', '/', '', '', 'Emmanuel Levijarvi', 'MIT', 'REDACTED', '[0-9A-Fa-f]{8,}', '\\1REDACTED', '\\b[0-9a-fA-F]{12}\\b', 'access_key_id', 'auth', 'clientID', 'clientId', 'client_id', 'device_info', 'device_status', 'email', 'macAddress', 'mac_address', 'navilink-', 'password', 'pushToken', 'push_token', 'secret_access_key', 'secret_key', 'sessionID', 'sessionToken', 'session_token', 'token'] \ No newline at end of file diff --git a/.hypothesis/constants/b00985cd3c10a1f8 b/.hypothesis/constants/b00985cd3c10a1f8 new file mode 100644 index 0000000..7638f16 --- /dev/null +++ b/.hypothesis/constants/b00985cd3c10a1f8 @@ -0,0 +1,4 @@ +# file: /home/emmanuel/Projects/nwp500-python/src/nwp500/models.py +# hypothesis_version: 6.151.5 + +[0.0, 43.0, 65.0, 100.0, ' GPM', ' L', ' LPM', ' gal', ' °C', ' °F', '%', '...', 'Current fan RPM', 'Current state number', 'Fan PWM value', 'GPM', 'RPM', 'Target fan RPM', 'Unknown', 'Vacation day setting', 'W', 'Wh', 'before', 'clientID', 'days', 'device_class', 'device_info', 'energy', 'flow_rate', 'gal', 'h', 'heTime', 'heUsage', 'hours', 'hpTime', 'hpUsage', 'ignore', 'interval', 'json_schema_extra', 'metric', 'mixingValveUse', 'mode', 'power', 'python', 'sessionID', 'temperature', 'touInfo', 'unit_of_measurement', 'water', '°F'] \ No newline at end of file diff --git a/.hypothesis/constants/b294530e090203ba b/.hypothesis/constants/b294530e090203ba new file mode 100644 index 0000000..f1e3487 --- /dev/null +++ b/.hypothesis/constants/b294530e090203ba @@ -0,0 +1,4 @@ +# file: /home/emmanuel/Projects/nwp500-python/.tox/default/bin/pytest +# hypothesis_version: 6.151.5 + +['.exe', '__main__'] \ No newline at end of file diff --git a/.hypothesis/constants/b5232deb51bddc9a b/.hypothesis/constants/b5232deb51bddc9a new file mode 100644 index 0000000..716dc25 --- /dev/null +++ b/.hypothesis/constants/b5232deb51bddc9a @@ -0,0 +1,4 @@ +# file: /home/emmanuel/Projects/nwp500-python/src/nwp500/__init__.py +# hypothesis_version: 6.151.5 + +['APIError', 'AuthTokens', 'AuthenticationError', 'CommandCode', 'ConnectionDropEvent', 'ConnectionEvent', 'CurrentOperationMode', 'DREvent', 'Device', 'DeviceError', 'DeviceFeature', 'DeviceInfo', 'DeviceNotFoundError', 'DeviceOfflineError', 'DeviceOperationError', 'DeviceStatus', 'DhwOperationSetting', 'EnergyUsageDay', 'EnergyUsageResponse', 'EnergyUsageTotal', 'ErrorCode', 'EventEmitter', 'EventListener', 'FilterChange', 'FirmwareInfo', 'HeatSource', 'InstallType', 'Location', 'MonthlyEnergyData', 'MqttClientEvents', 'MqttCommand', 'MqttConnectionConfig', 'MqttConnectionError', 'MqttCredentialsError', 'MqttDeviceInfoCache', 'MqttError', 'MqttMetrics', 'MqttPublishError', 'MqttRequest', 'NavienAPIClient', 'NavienAuthClient', 'NavienMqttClient', 'Nwp500Error', 'OnOffFlag', 'Operation', 'PeriodicRequestType', 'RangeValidationError', 'RecirculationMode', 'TOUInfo', 'TOUSchedule', 'TempFormulaType', 'TemperatureType', 'TokenExpiredError', 'TokenRefreshError', 'TouRateType', 'TouWeekType', 'UnitType', 'UserInfo', 'ValidationError', 'VolumeCode', '__version__', 'authenticate', 'build_tou_period', 'decode_price', 'decode_week_bitfield', 'encode_price', 'encode_week_bitfield', 'get_unit_system', 'log_performance', 'nwp500-python', 'refresh_access_token', 'requires_capability', 'reset_unit_system', 'set_unit_system', 'unknown'] \ No newline at end of file diff --git a/.hypothesis/constants/bd643e9276a6173b b/.hypothesis/constants/bd643e9276a6173b new file mode 100644 index 0000000..b7ddc3b --- /dev/null +++ b/.hypothesis/constants/bd643e9276a6173b @@ -0,0 +1,4 @@ +# file: /home/emmanuel/Projects/nwp500-python/src/nwp500/api_client.py +# hypothesis_version: 6.151.5 + +[200, 401, '/', '/device/info', '/device/list', '/device/tou', '1.0.0', '3.8+', 'Emmanuel Levijarvi', 'GET', 'MIT', 'NavienAPIClient', 'O', 'POST', 'Python', 'Python Client', '_session', 'additionalValue', 'appVersion', 'code', 'controllerId', 'count', 'data', 'firmwares', 'macAddress', 'metric', 'modelName', 'msg', 'offset', 'os', 'osVersion', 'pushToken', 'us_customary', 'userId', 'userType'] \ No newline at end of file diff --git a/.hypothesis/constants/c7a31c6dc0068cbd b/.hypothesis/constants/c7a31c6dc0068cbd new file mode 100644 index 0000000..9c1bad7 --- /dev/null +++ b/.hypothesis/constants/c7a31c6dc0068cbd @@ -0,0 +1,4 @@ +# file: /home/emmanuel/Projects/nwp500-python/.venv/bin/pytest +# hypothesis_version: 6.151.5 + +['.exe', '__main__'] \ No newline at end of file diff --git a/.hypothesis/constants/ca0b70aa93535c1f b/.hypothesis/constants/ca0b70aa93535c1f new file mode 100644 index 0000000..8b48a82 --- /dev/null +++ b/.hypothesis/constants/ca0b70aa93535c1f @@ -0,0 +1,4 @@ +# file: /home/emmanuel/Projects/nwp500-python/src/nwp500/config.py +# hypothesis_version: 6.151.5 + +['/auth/refresh', '/user/sign-in', 'us-east-1'] \ No newline at end of file diff --git a/.hypothesis/constants/cd91fc95eade0457 b/.hypothesis/constants/cd91fc95eade0457 new file mode 100644 index 0000000..e26e9c1 --- /dev/null +++ b/.hypothesis/constants/cd91fc95eade0457 @@ -0,0 +1,4 @@ +# file: /home/emmanuel/Projects/nwp500-python/src/nwp500/mqtt/connection.py +# hypothesis_version: 6.151.5 + +['Already connected', 'Emmanuel Levijarvi', 'MIT', 'MqttConnectionConfig', 'NavienAuthClient', 'Not connected', 'name', 'utf-8'] \ No newline at end of file diff --git a/.hypothesis/constants/d0ea67d716f83a90 b/.hypothesis/constants/d0ea67d716f83a90 new file mode 100644 index 0000000..e5e78f7 --- /dev/null +++ b/.hypothesis/constants/d0ea67d716f83a90 @@ -0,0 +1,4 @@ +# file: /home/emmanuel/Projects/nwp500-python/src/nwp500/device_capabilities.py +# hypothesis_version: 6.151.5 + +[', ', 'DeviceFeature', 'Emmanuel Levijarvi', 'dhw_use', 'holiday_use', 'power_use', 'recirculation_use'] \ No newline at end of file diff --git a/.hypothesis/constants/dae78f4d97fdd43b b/.hypothesis/constants/dae78f4d97fdd43b new file mode 100644 index 0000000..66ceb5c --- /dev/null +++ b/.hypothesis/constants/dae78f4d97fdd43b @@ -0,0 +1,4 @@ +# file: /home/emmanuel/Projects/nwp500-python/src/nwp500/field_factory.py +# hypothesis_version: 6.151.5 + +['W', 'dBm', 'device_class', 'energy', 'energy_field', 'json_schema_extra', 'kWh', 'power', 'power_field', 'signal_strength', 'temperature', 'temperature_field', 'unit_of_measurement', '°F'] \ No newline at end of file diff --git a/.hypothesis/constants/dcfcf6e03af72a1c b/.hypothesis/constants/dcfcf6e03af72a1c new file mode 100644 index 0000000..208b51b --- /dev/null +++ b/.hypothesis/constants/dcfcf6e03af72a1c @@ -0,0 +1,4 @@ +# file: /home/emmanuel/Projects/nwp500-python/src/nwp500/factory.py +# hypothesis_version: 6.151.5 + +[] \ No newline at end of file diff --git a/.hypothesis/constants/dfc00db7cf73d63c b/.hypothesis/constants/dfc00db7cf73d63c new file mode 100644 index 0000000..7445afd --- /dev/null +++ b/.hypothesis/constants/dfc00db7cf73d63c @@ -0,0 +1,4 @@ +# file: /home/emmanuel/Projects/nwp500-python/src/nwp500/exceptions.py +# hypothesis_version: 6.151.5 + +['(retriable)', 'Emmanuel Levijarvi', 'MIT', 'details', 'error_code', 'error_type', 'message', 'retriable'] \ No newline at end of file diff --git a/.hypothesis/constants/e4b0f73ee49546d6 b/.hypothesis/constants/e4b0f73ee49546d6 new file mode 100644 index 0000000..d63695f --- /dev/null +++ b/.hypothesis/constants/e4b0f73ee49546d6 @@ -0,0 +1,4 @@ +# file: /home/emmanuel/Projects/nwp500-python/src/nwp500/command_decorators.py +# hypothesis_version: 6.151.5 + +['Emmanuel Levijarvi', 'F'] \ No newline at end of file diff --git a/.hypothesis/examples/04e6b3400353b141/b04e33f1dccbdab0 b/.hypothesis/examples/04e6b3400353b141/b04e33f1dccbdab0 new file mode 100644 index 0000000..1a20869 --- /dev/null +++ b/.hypothesis/examples/04e6b3400353b141/b04e33f1dccbdab0 @@ -0,0 +1,2 @@ +[#¾…©sÒ^Þ·HÜü`ÊŒv2l¬°úŒ¼Õ4Šä‰ +¤>4›¢»¾¨œ»Ù/Á \ No newline at end of file diff --git a/.hypothesis/examples/04e6b3400353b141/e2ebc17191359b9b b/.hypothesis/examples/04e6b3400353b141/e2ebc17191359b9b new file mode 100644 index 0000000..a632899 --- /dev/null +++ b/.hypothesis/examples/04e6b3400353b141/e2ebc17191359b9b @@ -0,0 +1,2 @@ +[#¾…©sÒ^Þ·HÜü`ÊŒv2l¬°úŒ¼Õ4Šä‰ +¤>4›¢»¾¨œ»Ù/Á.secondary \ No newline at end of file diff --git a/.hypothesis/examples/b04e33f1dccbdab0/3e1706876c4d4240 b/.hypothesis/examples/b04e33f1dccbdab0/3e1706876c4d4240 new file mode 100644 index 0000000000000000000000000000000000000000..b275563e306ac76b2c9401e5e2fa51c00476bcd4 GIT binary patch literal 8 NcmZ={bYuWRMgRpQ0S5p8 literal 0 HcmV?d00001 diff --git a/.hypothesis/examples/e2ebc17191359b9b/06e8e5454ebe80d4 b/.hypothesis/examples/e2ebc17191359b9b/06e8e5454ebe80d4 new file mode 100644 index 0000000000000000000000000000000000000000..015dfb79237e266cdc3fc138315a520a7a5588e2 GIT binary patch literal 9 QcmZ={bX0KEb7J@a00@)(^b literal 0 HcmV?d00001 diff --git a/tests/test_mqtt_hypothesis.py b/tests/test_mqtt_hypothesis.py index 72b308c..7a31647 100644 --- a/tests/test_mqtt_hypothesis.py +++ b/tests/test_mqtt_hypothesis.py @@ -175,6 +175,8 @@ def test_device_status_fuzzing( if is_celsius: assert status.current_dhw_flow_rate == pytest.approx(lpm_val) else: - # Imperial: LPM to GPM - gpm_val = round(lpm_val * 0.264172, 2) - assert status.current_dhw_flow_rate == pytest.approx(gpm_val) + # Imperial: LPM to GPM (rounded to 2 decimals in the converter) + gpm_val = lpm_val * 0.264172 + assert status.current_dhw_flow_rate == pytest.approx( + gpm_val, abs=0.01 + ) From 0850051ceaeca6be365758eae0e5cd114ce1c3bc Mon Sep 17 00:00:00 2001 From: Emmanuel Levijarvi Date: Mon, 9 Feb 2026 12:03:50 -0800 Subject: [PATCH 6/6] Fix formatting in test_mqtt_hypothesis.py --- tests/test_mqtt_hypothesis.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/test_mqtt_hypothesis.py b/tests/test_mqtt_hypothesis.py index 7a31647..f660781 100644 --- a/tests/test_mqtt_hypothesis.py +++ b/tests/test_mqtt_hypothesis.py @@ -177,6 +177,4 @@ def test_device_status_fuzzing( else: # Imperial: LPM to GPM (rounded to 2 decimals in the converter) gpm_val = lpm_val * 0.264172 - assert status.current_dhw_flow_rate == pytest.approx( - gpm_val, abs=0.01 - ) + assert status.current_dhw_flow_rate == pytest.approx(gpm_val, abs=0.01)