From 6c378acd67daa0a1f47478b2c2d3fc9087e6716b Mon Sep 17 00:00:00 2001 From: Sam Stenvall Date: Fri, 6 Sep 2024 15:07:31 +0300 Subject: [PATCH 1/2] Add pyproject.toml with configuration for ruff, run ruff check --fix --- custom_components/extron/__init__.py | 8 +- custom_components/extron/button.py | 4 +- custom_components/extron/config_flow.py | 9 +- custom_components/extron/extron.py | 10 +-- custom_components/extron/media_player.py | 8 +- custom_components/extron/sensor.py | 7 +- pyproject.toml | 100 +++++++++++++++++++++++ 7 files changed, 123 insertions(+), 23 deletions(-) create mode 100644 pyproject.toml diff --git a/custom_components/extron/__init__.py b/custom_components/extron/__init__.py index 6f49351..9d97a2c 100644 --- a/custom_components/extron/__init__.py +++ b/custom_components/extron/__init__.py @@ -6,11 +6,11 @@ from homeassistant.config_entries import ConfigEntry from homeassistant.const import Platform -from homeassistant.core import HomeAssistant, DOMAIN +from homeassistant.core import DOMAIN, HomeAssistant from homeassistant.exceptions import ConfigEntryNotReady -from homeassistant.helpers.device_registry import format_mac, DeviceInfo +from homeassistant.helpers.device_registry import DeviceInfo, format_mac -from custom_components.extron.extron import ExtronDevice, DeviceType, AuthenticationFailed +from custom_components.extron.extron import AuthenticationError, ExtronDevice PLATFORMS: list[Platform] = [Platform.MEDIA_PLAYER, Platform.SENSOR, Platform.BUTTON] @@ -52,7 +52,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: try: device = ExtronDevice(entry.data['host'], entry.data['port'], entry.data['password']) await device.connect() - except AuthenticationFailed as e: + except AuthenticationError as e: raise ConfigEntryNotReady('Invalid credentials') from e except Exception as e: raise ConfigEntryNotReady('Unable to connect') from e diff --git a/custom_components/extron/button.py b/custom_components/extron/button.py index 2c40d10..cf5e493 100644 --- a/custom_components/extron/button.py +++ b/custom_components/extron/button.py @@ -1,10 +1,10 @@ import logging -from homeassistant.components.button import ButtonEntity, ButtonDeviceClass +from homeassistant.components.button import ButtonDeviceClass, ButtonEntity from homeassistant.config_entries import ConfigEntry from homeassistant.helpers.device_registry import DeviceInfo -from custom_components.extron import ExtronDevice, DeviceInformation, ExtronConfigEntryRuntimeData +from custom_components.extron import DeviceInformation, ExtronConfigEntryRuntimeData, ExtronDevice logger = logging.getLogger(__name__) diff --git a/custom_components/extron/config_flow.py b/custom_components/extron/config_flow.py index cc340e6..dbb44ec 100644 --- a/custom_components/extron/config_flow.py +++ b/custom_components/extron/config_flow.py @@ -3,6 +3,7 @@ from __future__ import annotations import logging + from typing import Any import voluptuous as vol @@ -10,8 +11,8 @@ from homeassistant.config_entries import ConfigFlow, ConfigFlowResult from homeassistant.helpers.selector import selector -from .const import DOMAIN, CONF_HOST, CONF_PORT, CONF_PASSWORD, CONF_DEVICE_TYPE -from .extron import DeviceType, ExtronDevice, AuthenticationFailed +from .const import CONF_DEVICE_TYPE, CONF_HOST, CONF_PASSWORD, CONF_PORT, DOMAIN +from .extron import AuthenticationError, DeviceType, ExtronDevice _LOGGER = logging.getLogger(__name__) @@ -37,7 +38,7 @@ class ExtronConfigFlow(ConfigFlow, domain=DOMAIN): VERSION = 1 - async def async_step_user(self, user_input: dict[str, Any] | None = None): + async def async_step_user(self, user_input: dict[str, Any] | None = None) -> ConfigFlowResult: """Handle the initial step.""" errors: dict[str, str] = {} if user_input is not None: @@ -52,7 +53,7 @@ async def async_step_user(self, user_input: dict[str, Any] | None = None): # Disconnect, we'll connect again later, this was just for validation await extron_device.disconnect() - except AuthenticationFailed: + except AuthenticationError: errors["base"] = "invalid_auth" except Exception: errors["base"] = "cannot_connect" diff --git a/custom_components/extron/extron.py b/custom_components/extron/extron.py index 24b53d3..28ee3cb 100644 --- a/custom_components/extron/extron.py +++ b/custom_components/extron/extron.py @@ -1,9 +1,9 @@ import asyncio import logging + from asyncio import StreamReader, StreamWriter from asyncio.exceptions import TimeoutError from enum import Enum -from typing import Optional logger = logging.getLogger(__name__) @@ -14,7 +14,7 @@ class DeviceType(Enum): UNKNOWN = 'unknown' -class AuthenticationFailed(Exception): +class AuthenticationError(Exception): pass @@ -23,8 +23,8 @@ def __init__(self, host: str, port: int, password: str) -> None: self._host = host self._port = port self._password = password - self._reader: Optional[StreamReader] = None - self._writer: Optional[StreamWriter] = None + self._reader: StreamReader | None = None + self._writer: StreamWriter | None = None self._semaphore = asyncio.Semaphore() self._connected = False @@ -53,7 +53,7 @@ async def connect(self): self._connected = True logger.info(f'Connected and authenticated to {self._host}:{self._port}') except TimeoutError: - raise AuthenticationFailed() + raise AuthenticationError() async def disconnect(self): self._connected = False diff --git a/custom_components/extron/media_player.py b/custom_components/extron/media_player.py index d542986..c65b43f 100644 --- a/custom_components/extron/media_player.py +++ b/custom_components/extron/media_player.py @@ -1,14 +1,12 @@ import logging -from homeassistant.components.media_player import MediaPlayerEntity, MediaPlayerEntityFeature, \ - MediaPlayerState +from homeassistant.components.media_player import MediaPlayerEntity, MediaPlayerEntityFeature, MediaPlayerState from homeassistant.config_entries import ConfigEntry from homeassistant.helpers.entity import DeviceInfo -from custom_components.extron import ExtronConfigEntryRuntimeData, DeviceInformation +from custom_components.extron import DeviceInformation, ExtronConfigEntryRuntimeData from custom_components.extron.const import CONF_DEVICE_TYPE -from custom_components.extron.extron import DeviceType, SurroundSoundProcessor, HDMISwitcher, \ - ExtronDevice +from custom_components.extron.extron import DeviceType, ExtronDevice, HDMISwitcher, SurroundSoundProcessor logger = logging.getLogger(__name__) diff --git a/custom_components/extron/sensor.py b/custom_components/extron/sensor.py index 19ecc61..177a602 100644 --- a/custom_components/extron/sensor.py +++ b/custom_components/extron/sensor.py @@ -1,15 +1,16 @@ import logging + from datetime import date, datetime from decimal import Decimal -from homeassistant.components.sensor import SensorEntity, SensorDeviceClass, SensorStateClass +from homeassistant.components.sensor import SensorDeviceClass, SensorEntity, SensorStateClass from homeassistant.config_entries import ConfigEntry from homeassistant.helpers.device_registry import DeviceInfo from homeassistant.helpers.typing import StateType -from custom_components.extron import ExtronConfigEntryRuntimeData, DeviceInformation +from custom_components.extron import DeviceInformation, ExtronConfigEntryRuntimeData from custom_components.extron.const import CONF_DEVICE_TYPE -from custom_components.extron.extron import SurroundSoundProcessor, DeviceType +from custom_components.extron.extron import DeviceType, SurroundSoundProcessor logger = logging.getLogger(__name__) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..1030881 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,100 @@ +[tool.ruff] +# https://github.com/astral-sh/ruff#configuration +include = ["*.py", "*.pyi", "**/pyproject.toml"] +extend-include = ["*.ipynb"] +target-version = "py311" +line-length = 120 + +[tool.ruff.lint] +exclude = [ + "__pypackages__", + "_build", + ".bzr", + ".direnv", + ".eggs", + ".git", + ".hg", + ".mypy_cache", + ".nox", + ".pants.d", + ".ruff_cache", + ".svn", + ".tox", + ".venv", + "*.ipynb", + "buck-out", + "build", + "dist", + "node_modules", + "venv*", +] +ignore = [] +per-file-ignores = {} +# https://docs.astral.sh/ruff/rules/ +select = ["E4", "E7", "E9", "F", "W", "N", "UP", "I"] + +# Allow unused variables when underscore-prefixed. +dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$" + +# Allow autofix for all enabled rules (when `--fix`) is provided. +fixable = [ + "A", + "B", + "C", + "D", + "E", + "F", + "G", + "I", + "N", + "Q", + "S", + "T", + "W", + "ANN", + "ARG", + "BLE", + "COM", + "DJ", + "DTZ", + "EM", + "ERA", + "EXE", + "FBT", + "ICN", + "INP", + "ISC", + "NPY", + "PD", + "PGH", + "PIE", + "PL", + "PT", + "PTH", + "PYI", + "RET", + "RSE", + "RUF", + "SIM", + "SLF", + "TCH", + "TID", + "TRY", + "UP", + "YTT", +] +unfixable = [] + +[tool.ruff.lint.isort] +# https://docs.astral.sh/ruff/settings/#lintisort +combine-as-imports = true +lines-between-types = 1 +order-by-type = true +known-first-party = ["src"] +section-order = [ + "future", + "standard-library", + "third-party", + "first-party", + "local-folder", +] \ No newline at end of file From 8d96a8489b4a80b4b1de37caaeb6cf44fef27856 Mon Sep 17 00:00:00 2001 From: Sam Stenvall Date: Fri, 6 Sep 2024 15:08:00 +0300 Subject: [PATCH 2/2] Add GitHub action for running ruff --- .github/workflows/ruff.yaml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 .github/workflows/ruff.yaml diff --git a/.github/workflows/ruff.yaml b/.github/workflows/ruff.yaml new file mode 100644 index 0000000..68bfa4a --- /dev/null +++ b/.github/workflows/ruff.yaml @@ -0,0 +1,12 @@ +name: Ruff +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] +jobs: + ruff: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: chartboost/ruff-action@v1 \ No newline at end of file