diff --git a/.flake8.ini b/.flake8 similarity index 81% rename from .flake8.ini rename to .flake8 index d4476aa..b53e755 100644 --- a/.flake8.ini +++ b/.flake8 @@ -1,4 +1,5 @@ [flake8] exclude = .git,.tox,__pycache__ +max-line-length = 120 select = C,E,F,W,B,B950 ignore = E501,W503,E203,D202,W504 diff --git a/.hound.yml b/.hound.yml index 0b51966..5076dae 100644 --- a/.hound.yml +++ b/.hound.yml @@ -1,3 +1,3 @@ python: enabled: true - config_file: .flake8.ini + config_file: .flake8 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a7b4ff9..c1fa6b5 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,21 +1,14 @@ - repos: -- repo: https://github.com/psf/black - rev: 19.3b0 + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.4.5 hooks: - - id: black + - id: ruff args: - - --safe - - --quiet -- repo: https://gitlab.com/pycqa/flake8 - rev: 3.7.8 - hooks: - - id: flake8 - additional_dependencies: - - flake8-docstrings==1.3.1 - - pydocstyle==4.0.0 + - --fix + - id: ruff-format -- repo: https://github.com/pre-commit/mirrors-isort - rev: v4.3.21 + - repo: https://github.com/pycqa/flake8 + rev: 7.0.0 hooks: - - id: isort + - id: flake8 + additional_dependencies: [flake8-docstrings, flake8-bugbear, flake8-builtins, flake8-print, flake8-pytest-style, flake8-return, flake8-simplify, flake8-annotations] diff --git a/custom_components/xiaomi_miio_airpurifier/climate.py b/custom_components/xiaomi_miio_airpurifier/climate.py index 81742f1..4dc17c9 100644 --- a/custom_components/xiaomi_miio_airpurifier/climate.py +++ b/custom_components/xiaomi_miio_airpurifier/climate.py @@ -1,4 +1,5 @@ """Support for Xiaomi Mi Air Dehumidifier.""" + import asyncio from enum import Enum from functools import partial diff --git a/custom_components/xiaomi_miio_airpurifier/fan.py b/custom_components/xiaomi_miio_airpurifier/fan.py index de83c89..d84df75 100644 --- a/custom_components/xiaomi_miio_airpurifier/fan.py +++ b/custom_components/xiaomi_miio_airpurifier/fan.py @@ -1,4 +1,5 @@ """Support for Xiaomi Mi Air Purifier and Xiaomi Mi Air Humidifier.""" + import asyncio from enum import Enum from functools import partial @@ -74,11 +75,7 @@ ) import voluptuous as vol -from homeassistant.components.fan import ( - PLATFORM_SCHEMA, - FanEntity, - FanEntityFeature -) +from homeassistant.components.fan import PLATFORM_SCHEMA, FanEntity, FanEntityFeature from homeassistant.const import ( ATTR_ENTITY_ID, ATTR_MODE, @@ -1266,7 +1263,11 @@ def __init__(self, name, device, model, unique_id, retries=0): @property def supported_features(self): """Flag supported features.""" - return FanEntityFeature.PRESET_MODE + return ( + FanEntityFeature.PRESET_MODE + | FanEntityFeature.TURN_OFF + | FanEntityFeature.TURN_ON + ) @property def should_poll(self): @@ -1899,9 +1900,12 @@ def __init__(self, name, device, model, unique_id): self._device_features = FEATURE_FLAGS_AIRHUMIDIFIER_MJJSQ self._available_attributes = AVAILABLE_ATTRIBUTES_AIRHUMIDIFIER_MJJSQ - self._preset_modes = [mode.name for mode in AirhumidifierMjjsqOperationMode - if self._device_features & FEATURE_SET_WET_PROTECTION != 0 - or mode != AirhumidifierMjjsqOperationMode.WetAndProtect] + self._preset_modes = [ + mode.name + for mode in AirhumidifierMjjsqOperationMode + if self._device_features & FEATURE_SET_WET_PROTECTION != 0 + or mode != AirhumidifierMjjsqOperationMode.WetAndProtect + ] self._state_attrs = {ATTR_MODEL: self._model} self._state_attrs.update( {attribute: None for attribute in self._available_attributes} @@ -2400,6 +2404,8 @@ def supported_features(self) -> int: | FanEntityFeature.PRESET_MODE | FanEntityFeature.OSCILLATE | FanEntityFeature.DIRECTION + | FanEntityFeature.TURN_OFF + | FanEntityFeature.TURN_ON ) async def async_update(self): @@ -2410,7 +2416,7 @@ async def async_update(self): return try: - state = await self.hass.async_add_job(self._device.status) + state = await self.hass.async_add_executor_job(self._device.status) _LOGGER.debug("Got new state: %s", state) self._available = True @@ -2626,7 +2632,7 @@ async def async_update(self): return try: - state = await self.hass.async_add_job(self._device.status) + state = await self.hass.async_add_executor_job(self._device.status) _LOGGER.debug("Got new state: %s", state) self._available = True @@ -2749,7 +2755,13 @@ def __init__(self, name, device, model, unique_id, retries): @property def supported_features(self) -> int: """Supported features.""" - return FanEntityFeature.SET_SPEED | FanEntityFeature.PRESET_MODE | FanEntityFeature.OSCILLATE + return ( + FanEntityFeature.SET_SPEED + | FanEntityFeature.PRESET_MODE + | FanEntityFeature.OSCILLATE + | FanEntityFeature.TURN_OFF + | FanEntityFeature.TURN_ON + ) async def async_update(self): """Fetch state from the device.""" @@ -2759,7 +2771,7 @@ async def async_update(self): return try: - state = await self.hass.async_add_job(self._device.status) + state = await self.hass.async_add_executor_job(self._device.status) _LOGGER.debug("Got new state: %s", state) self._available = True @@ -2882,7 +2894,13 @@ def __init__(self, name, device, model, unique_id, retries): @property def supported_features(self) -> int: """Supported features.""" - return FanEntityFeature.SET_SPEED | FanEntityFeature.PRESET_MODE | FanEntityFeature.OSCILLATE + return ( + FanEntityFeature.SET_SPEED + | FanEntityFeature.PRESET_MODE + | FanEntityFeature.OSCILLATE + | FanEntityFeature.TURN_OFF + | FanEntityFeature.TURN_ON + ) async def async_update(self): """Fetch state from the device.""" @@ -2892,7 +2910,7 @@ async def async_update(self): return try: - state = await self.hass.async_add_job(self._device.status) + state = await self.hass.async_add_executor_job(self._device.status) _LOGGER.debug("Got new state: %s", state) self._available = True @@ -3141,12 +3159,14 @@ async def async_set_preset_mode(self, preset_mode: str) -> None: self._preset_modes_to_mode_speed[preset_mode], ) - # Following is true on AirDogX5 with firmware 1.3.5_0005. Maybe this is different for other models. Needs testing + # Following is true on AirDogX5 with firmware 1.3.5_0005. + # Maybe this is different for other models. Needs testing # It looks like the device was not designed to switch from any arbitrary mode to any other mode. # Some of the combinations produce unexpected results # - # For example, switching from 'Auto' to 'Speed X' switches to Manual mode, but always sets speed to 1, regardless of the speed parameter. + # For example, switching from 'Auto' to 'Speed X' switches to Manual mode, + # but always sets speed to 1, regardless of the speed parameter. # # Switching from 'Night mode' to 'Speed X' sets device in Auto mode with speed X. # Tihs 'Auto X' state is quite strange and does not seem to be useful. @@ -3157,31 +3177,32 @@ async def async_set_preset_mode(self, preset_mode: str) -> None: # Here is a full table of device behaviour # FROM TO RESULT - #'Night mode' -> + # 'Night mode' -> # 'Auto' Good # 'Speed 1' 'Auto 1' + repeat -> Good # 'Speed 2' 'Auto 2' + repeat -> Good # 'Speed 3' 'Auto 3' + repeat -> Good # 'Speed 4' 'Auto 4' + repeat -> Good - #'Speed 1' + # 'Speed 1' # 'Night mode' Good # 'Auto' Good - #'Speed 2' -> + # 'Speed 2' -> # 'Night mode' Good # 'Auto' Good - #'Speed 3' -> + # 'Speed 3' -> # 'Night mode' Good # 'Auto' Good - #'Speed 4' -> + # 'Speed 4' -> # 'Night mode' Good - #'Auto'-> + # 'Auto'-> # 'Night mode' Good # 'Speed 1' Good # 'Speed 2' 'Speed 1' + repeat -> Good # 'Speed 3' 'Speed 1' + repeat -> Good # 'Speed 4' 'Speed 1' + repeat -> Good - # To allow switching from any mode to any other mode command is repeated twice when switching is from 'Night mode' or 'Auto' to 'Speed X'. + # To allow switching from any mode to any other mode command is repeated + # twice when switching is from 'Night mode' or 'Auto' to 'Speed X'. await self._try_command( "Setting preset mode of the miio device failed.", diff --git a/custom_components/xiaomi_miio_airpurifier/manifest.json b/custom_components/xiaomi_miio_airpurifier/manifest.json index 55a8a14..93bc5f0 100644 --- a/custom_components/xiaomi_miio_airpurifier/manifest.json +++ b/custom_components/xiaomi_miio_airpurifier/manifest.json @@ -13,5 +13,5 @@ "construct==2.10.68", "python-miio>=0.5.12" ], - "version": "2024.7.0.0" + "version": "2024.8.0.0" } diff --git a/tox.ini b/tox.ini deleted file mode 100644 index 973cb7b..0000000 --- a/tox.ini +++ /dev/null @@ -1,36 +0,0 @@ - -[flake8] -exclude = .venv,.git,.tox,docs,venv,bin,lib,deps,build -# To work with Black -max-line-length = 88 -# E501: line too long -# W503: Line break occurred before a binary operator -# E203: Whitespace before ':' -# D202 No blank lines allowed after function docstring -# W504 line break after binary operator -ignore = - E501, - W503, - E203, - D202, - W504 - -[isort] -# https://github.com/timothycrosley/isort -# https://github.com/timothycrosley/isort/wiki/isort-Settings -# splits long import on multiple lines indented by 4 spaces -multi_line_output = 3 -include_trailing_comma=True -force_grid_wrap=0 -use_parentheses=True -line_length=88 -indent = " " -# by default isort don't check module indexes -not_skip = __init__.py -# will group `import x` and `from x import` of the same module. -force_sort_within_sections = true -sections = FUTURE,STDLIB,INBETWEENS,THIRDPARTY,FIRSTPARTY,LOCALFOLDER -default_section = THIRDPARTY -known_first_party = homeassistant,tests -forced_separate = tests -combine_as_imports = true