diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 165c750b..8aa8efec 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,39 +5,20 @@ exclude: ^(fixtures/) repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.4.9 + rev: v0.6.1 hooks: - id: ruff args: - --fix - - repo: https://github.com/asottile/pyupgrade - rev: v3.16.0 - hooks: - - id: pyupgrade - args: [--py310-plus] - exclude: "external_src/int-tools" - - - repo: https://github.com/asottile/add-trailing-comma - rev: v3.1.0 - hooks: - - id: add-trailing-comma - args: [--py36-plus] - exclude: "external_src/int-tools" - - - repo: https://github.com/asottile/yesqa - rev: v1.5.0 - hooks: - - id: yesqa - - repo: https://github.com/psf/black - rev: 24.4.2 + rev: 24.8.0 hooks: - id: black language_version: python3 - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.10.0 + rev: v1.11.1 hooks: - id: mypy name: mypy diff --git a/pyproject.toml b/pyproject.toml index b5e0935e..30880cf0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,6 +7,9 @@ minversion = "7.0" asyncio_mode = "auto" [tool.ruff] +target-version = "py310" + +[tool.ruff.lint] select = [ "B002", # Python does not support the unary prefix increment "B007", # Loop control variable {name} not used within loop body @@ -23,17 +26,13 @@ select = [ "G", # flake8-logging-format "I", # isort "ICN001", # import concentions; {name} should be imported as {asname} - "ISC001", # Implicitly concatenated string literals on one line "N804", # First argument of a class method should be named cls "N805", # First argument of a method should be named self "N815", # Variable {name} in class scope should not be mixedCase - "PGH001", # No builtin eval() allowed + "S307", # No builtin eval() allowed "PGH004", # Use specific rule codes when using noqa "PLC0414", # Useless import alias. Import alias does not rename original package. - "PLC", # pylint - "PLE", # pylint - "PLR", # pylint - "PLW", # pylint + "PL", # pylint "Q000", # Double quotes found but single quotes preferred "RUF006", # Store a reference to the return value of asyncio.create_task "S102", # Use of exec detected @@ -66,7 +65,7 @@ select = [ "T20", # flake8-print "TID251", # Banned imports "TRY004", # Prefer TypeError exception for invalid type - "TRY200", # Use raise from to specify exception cause + "B904", # Use raise from to specify exception cause "TRY302", # Remove exception handler; error is immediately re-raised "UP", # pyupgrade "W", # pycodestyle @@ -94,25 +93,25 @@ ignore = [ "UP038", # Use `X | Y` in `isinstance` call instead of `(X, Y)` ] -[tool.ruff.flake8-pytest-style] +[tool.ruff.lint.flake8-pytest-style] fixture-parentheses = false -[tool.ruff.flake8-tidy-imports.banned-api] +[tool.ruff.lint.flake8-tidy-imports.banned-api] "pytz".msg = "use zoneinfo instead" -[tool.ruff.isort] +[tool.ruff.lint.isort] force-sort-within-sections = true combine-as-imports = true split-on-trailing-comma = false -[tool.ruff.per-file-ignores] +[tool.ruff.lint.per-file-ignores] # Allow for main entry & scripts to write to stdout "src/pyatmo/__main__.py" = ["T201"] # Exceptions for tests "tests/*" = ["D10"] -[tool.ruff.mccabe] +[tool.ruff.lint.mccabe] max-complexity = 25 [tool.setuptools_scm] diff --git a/src/pyatmo/modules/module.py b/src/pyatmo/modules/module.py index 2f5a0296..390d9a9b 100644 --- a/src/pyatmo/modules/module.py +++ b/src/pyatmo/modules/module.py @@ -653,7 +653,8 @@ class MeasureType(Enum): def compute_riemann_sum( - power_data: list[tuple[int, float]], conservative: bool = False + power_data: list[tuple[int, float]], + conservative: bool = False, ): """Compute energy from power with a rieman sum.""" @@ -710,7 +711,9 @@ def reset_measures(self, start_power_time, in_reset=True): self.sum_energy_elec_off_peak = 0 def get_sum_energy_elec_power_adapted( - self, to_ts: int | float | None = None, conservative: bool = False + self, + to_ts: int | float | None = None, + conservative: bool = False, ): """Compute proper energy value with adaptation from power.""" v = self.sum_energy_elec @@ -733,10 +736,13 @@ def get_sum_energy_elec_power_adapted( and isinstance(self, NetatmoBase) ): power_data = self.get_history_data( - "power", from_ts=from_ts, to_ts=to_ts + "power", + from_ts=from_ts, + to_ts=to_ts, ) if isinstance( - self, EnergyHistoryMixin + self, + EnergyHistoryMixin, ): # well to please the linter.... delta_energy = compute_riemann_sum(power_data, conservative) @@ -791,7 +797,10 @@ async def async_update_measures( filters, raw_data = await self._energy_API_calls(start_time, end_time, interval) hist_good_vals = await self._get_aligned_energy_values_and_mode( - start_time, end_time, delta_range, raw_data + start_time, + end_time, + delta_range, + raw_data, ) self.historical_data = [] @@ -920,7 +929,11 @@ async def _prepare_exported_historical_data( self._anchor_for_power_adjustment = computed_end_for_calculus async def _get_aligned_energy_values_and_mode( - self, start_time, end_time, delta_range, raw_data + self, + start_time, + end_time, + delta_range, + raw_data, ): hist_good_vals = [] values_lots = raw_data @@ -937,7 +950,7 @@ async def _get_aligned_energy_values_and_mode( ) raise ApiError( f"Energy badly formed resp beg_time missing: {values_lots} - " - f"module: {self.name}" + f"module: {self.name}", ) from None interval_sec = values_lot.get("step_time") @@ -997,12 +1010,15 @@ async def _energy_API_calls(self, start_time, end_time, interval): if rw_dt is None: self._log_energy_error( - start_time, end_time, msg=f"direct from {filters}", body=rw_dt_f + start_time, + end_time, + msg=f"direct from {filters}", + body=rw_dt_f, ) raise ApiError( f"Energy badly formed resp: {rw_dt_f} - " f"module: {self.name} - " - f"when accessing '{filters}'" + f"when accessing '{filters}'", ) raw_data = rw_dt diff --git a/tests/conftest.py b/tests/conftest.py index bd9bfdea..6b7c53a7 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -4,9 +4,10 @@ from contextlib import contextmanager from unittest.mock import AsyncMock, patch -import pyatmo import pytest +import pyatmo + from .common import fake_post_request, fake_post_request_multi @@ -27,12 +28,15 @@ async def async_account(async_auth): """AsyncAccount fixture.""" account = pyatmo.AsyncAccount(async_auth) - with patch( - "pyatmo.auth.AbstractAsyncAuth.async_post_api_request", - fake_post_request, - ), patch( - "pyatmo.auth.AbstractAsyncAuth.async_post_request", - fake_post_request, + with ( + patch( + "pyatmo.auth.AbstractAsyncAuth.async_post_api_request", + fake_post_request, + ), + patch( + "pyatmo.auth.AbstractAsyncAuth.async_post_request", + fake_post_request, + ), ): await account.async_update_topology() yield account @@ -51,15 +55,18 @@ async def async_account_multi(async_auth): """AsyncAccount fixture.""" account = pyatmo.AsyncAccount(async_auth) - with patch( - "pyatmo.auth.AbstractAsyncAuth.async_post_api_request", - fake_post_request_multi, - ), patch( - "pyatmo.auth.AbstractAsyncAuth.async_post_request", - fake_post_request_multi, + with ( + patch( + "pyatmo.auth.AbstractAsyncAuth.async_post_api_request", + fake_post_request_multi, + ), + patch( + "pyatmo.auth.AbstractAsyncAuth.async_post_request", + fake_post_request_multi, + ), ): await account.async_update_topology( - disabled_homes_ids=["eeeeeeeeeffffffffffaaaaa"] + disabled_homes_ids=["eeeeeeeeeffffffffffaaaaa"], ) yield account diff --git a/tests/test_camera.py b/tests/test_camera.py index d0d19100..79b7c01e 100644 --- a/tests/test_camera.py +++ b/tests/test_camera.py @@ -3,9 +3,9 @@ import json from unittest.mock import AsyncMock, patch -from pyatmo import DeviceType import pytest +from pyatmo import DeviceType from tests.common import MockResponse # pylint: disable=F6401 diff --git a/tests/test_climate.py b/tests/test_climate.py index 45f9d628..e0303840 100644 --- a/tests/test_climate.py +++ b/tests/test_climate.py @@ -3,11 +3,11 @@ import json from unittest.mock import AsyncMock, patch +import pytest + from pyatmo import DeviceType, NoSchedule from pyatmo.modules import NATherm1 from pyatmo.modules.device_types import DeviceCategory -import pytest - from tests.common import MockResponse, fake_post_request from tests.conftest import does_not_raise @@ -200,10 +200,13 @@ async def test_async_climate_switch_schedule( with open("fixtures/status_ok.json", encoding="utf-8") as json_file: response = json.load(json_file) - with patch( - "pyatmo.auth.AbstractAsyncAuth.async_post_api_request", - AsyncMock(return_value=MockResponse(response, 200)), - ), expected: + with ( + patch( + "pyatmo.auth.AbstractAsyncAuth.async_post_api_request", + AsyncMock(return_value=MockResponse(response, 200)), + ), + expected, + ): await async_home.async_switch_schedule( schedule_id=t_sched_id, ) @@ -351,10 +354,13 @@ async def test_async_climate_set_thermmode( with open(f"fixtures/{json_fixture}", encoding="utf-8") as json_file: response = json.load(json_file) - with patch( - "pyatmo.auth.AbstractAsyncAuth.async_post_api_request", - AsyncMock(return_value=MockResponse(response, 200)), - ), exception: + with ( + patch( + "pyatmo.auth.AbstractAsyncAuth.async_post_api_request", + AsyncMock(return_value=MockResponse(response, 200)), + ), + exception, + ): resp = await async_home.async_set_thermmode( mode=mode, end_time=end_time, diff --git a/tests/test_energy.py b/tests/test_energy.py index 511bf815..735d34f6 100644 --- a/tests/test_energy.py +++ b/tests/test_energy.py @@ -4,11 +4,11 @@ import json from unittest.mock import AsyncMock, patch -from pyatmo import ApiHomeReachabilityError, DeviceType -from pyatmo.modules.module import EnergyHistoryMixin, MeasureInterval import pytest import time_machine +from pyatmo import ApiHomeReachabilityError, DeviceType +from pyatmo.modules.module import EnergyHistoryMixin, MeasureInterval from tests.common import MockResponse # pylint: disable=F6401 @@ -139,7 +139,7 @@ async def test_disconnected_main_bridge(async_account_multi): with patch( "pyatmo.auth.AbstractAsyncAuth.async_post_api_request", AsyncMock(return_value=mock_home_status_resp), - ) as mock_request: + ): try: await async_account_multi.async_update_status(home_id) except ApiHomeReachabilityError: diff --git a/tests/test_fan.py b/tests/test_fan.py index 6c3a2c0c..a6e5535f 100644 --- a/tests/test_fan.py +++ b/tests/test_fan.py @@ -1,8 +1,9 @@ """Define tests for fan module.""" -from pyatmo import DeviceType import pytest +from pyatmo import DeviceType + # pylint: disable=F6401 diff --git a/tests/test_home.py b/tests/test_home.py index ac4a91c3..dc77d8cb 100644 --- a/tests/test_home.py +++ b/tests/test_home.py @@ -4,10 +4,10 @@ import json from unittest.mock import AsyncMock, patch -import pyatmo -from pyatmo import DeviceType, NoDevice import pytest +import pyatmo +from pyatmo import DeviceType, NoDevice from tests.common import MockResponse # pylint: disable=F6401 diff --git a/tests/test_shutter.py b/tests/test_shutter.py index f1a26ee3..004f9648 100644 --- a/tests/test_shutter.py +++ b/tests/test_shutter.py @@ -3,9 +3,9 @@ import json from unittest.mock import AsyncMock, patch -from pyatmo import DeviceType import pytest +from pyatmo import DeviceType from tests.common import MockResponse # pylint: disable=F6401 diff --git a/tests/test_switch.py b/tests/test_switch.py index af5034ce..846bd57f 100644 --- a/tests/test_switch.py +++ b/tests/test_switch.py @@ -1,8 +1,9 @@ """Define tests for switch module.""" -from pyatmo import DeviceType import pytest +from pyatmo import DeviceType + # pylint: disable=F6401 diff --git a/tests/test_weather.py b/tests/test_weather.py index fac69461..c83fb0d1 100644 --- a/tests/test_weather.py +++ b/tests/test_weather.py @@ -1,9 +1,10 @@ """Define tests for weaather module.""" +import pytest + import pyatmo from pyatmo import DeviceType from pyatmo.modules.base_class import Location, Place -import pytest # pylint: disable=F6401 diff --git a/tests/testing_main_template.py b/tests/testing_main_template.py index 5d17423a..329ace5b 100644 --- a/tests/testing_main_template.py +++ b/tests/testing_main_template.py @@ -1,6 +1,7 @@ import asyncio from aiohttp import ClientSession + import pyatmo from pyatmo.auth import AbstractAsyncAuth from pyatmo.modules.module import MeasureInterval @@ -9,9 +10,7 @@ class MyAuth(AbstractAsyncAuth): - async def async_get_access_token(self): - return MY_TOKEN_FROM_NETATMO @@ -42,7 +41,6 @@ async def main(): if __name__ == "__main__": - topology = asyncio.run(main()) # print(topology)