stricter ruff formatting
This commit is contained in:
@@ -5,7 +5,6 @@
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
from bleak.exc import BleakError
|
from bleak.exc import BleakError
|
||||||
|
|
||||||
from homeassistant.components.bluetooth import async_ble_device_from_address
|
from homeassistant.components.bluetooth import async_ble_device_from_address
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import Platform
|
from homeassistant.const import Platform
|
||||||
|
|||||||
@@ -1,28 +1,27 @@
|
|||||||
"""Hunter Douglas PowerView BLE API."""
|
"""Hunter Douglas PowerView BLE API."""
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
|
import time
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
import time
|
|
||||||
from typing import Final
|
from typing import Final
|
||||||
|
|
||||||
from bleak import BleakClient
|
from bleak import BleakClient
|
||||||
from bleak.backends.device import BLEDevice
|
from bleak.backends.device import BLEDevice
|
||||||
from bleak.exc import BleakError
|
from bleak.exc import BleakError
|
||||||
from bleak.uuids import normalize_uuid_str
|
from bleak.uuids import normalize_uuid_str
|
||||||
from bleak_retry_connector import close_stale_connections, establish_connection
|
from bleak_retry_connector import establish_connection
|
||||||
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
|
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
|
||||||
|
|
||||||
from homeassistant.components.cover import ATTR_CURRENT_POSITION
|
from homeassistant.components.cover import ATTR_CURRENT_POSITION
|
||||||
|
|
||||||
from .const import LOGGER, TIMEOUT
|
from .const import LOGGER, TIMEOUT
|
||||||
|
|
||||||
UUID_COV_SERVICE: Final = normalize_uuid_str("fdc1")
|
UUID_COV_SERVICE: Final[str] = normalize_uuid_str("fdc1")
|
||||||
UUID_TX: Final = "cafe1001-c0ff-ee01-8000-a110ca7ab1e0"
|
UUID_TX: Final[str] = "cafe1001-c0ff-ee01-8000-a110ca7ab1e0"
|
||||||
UUID_DEV_SERVICE: Final = normalize_uuid_str("180a")
|
UUID_DEV_SERVICE: Final[str] = normalize_uuid_str("180a")
|
||||||
UUID_BAT_SERVICE: Final = normalize_uuid_str("180f")
|
UUID_BAT_SERVICE: Final[str] = normalize_uuid_str("180f")
|
||||||
|
|
||||||
ATTR_ACTIVITY: Final = "activity"
|
ATTR_ACTIVITY: Final[str] = "activity"
|
||||||
|
|
||||||
|
|
||||||
SHADE_TYPE: Final[dict[int, str]] = {
|
SHADE_TYPE: Final[dict[int, str]] = {
|
||||||
@@ -82,7 +81,15 @@ class PowerViewBLE:
|
|||||||
self._ble_device: Final[BLEDevice] = ble_device
|
self._ble_device: Final[BLEDevice] = ble_device
|
||||||
self.name: Final[str] = self._ble_device.name or "unknown"
|
self.name: Final[str] = self._ble_device.name or "unknown"
|
||||||
self._seqcnt: int = 1
|
self._seqcnt: int = 1
|
||||||
self._client: BleakClient | None = None
|
self._client: BleakClient = BleakClient(
|
||||||
|
self._ble_device,
|
||||||
|
disconnected_callback=self._on_disconnect,
|
||||||
|
services=[
|
||||||
|
UUID_COV_SERVICE,
|
||||||
|
# self.UUID_DEV_SERVICE,
|
||||||
|
# self.UUID_BAT_SERVICE,
|
||||||
|
],
|
||||||
|
)
|
||||||
self._data_event = asyncio.Event()
|
self._data_event = asyncio.Event()
|
||||||
self._data: bytearray
|
self._data: bytearray
|
||||||
self._info: PVDeviceInfo = PVDeviceInfo()
|
self._info: PVDeviceInfo = PVDeviceInfo()
|
||||||
@@ -106,7 +113,7 @@ class PowerViewBLE:
|
|||||||
@property
|
@property
|
||||||
def is_connected(self) -> bool:
|
def is_connected(self) -> bool:
|
||||||
"""Return whether remote device is connected."""
|
"""Return whether remote device is connected."""
|
||||||
return self._client is not None and self._client.is_connected
|
return self._client.is_connected
|
||||||
|
|
||||||
# general cmd: uint16_t cmd, uint8_t seqID, uint8_t data_len
|
# general cmd: uint16_t cmd, uint8_t seqID, uint8_t data_len
|
||||||
async def _cmd(
|
async def _cmd(
|
||||||
@@ -120,7 +127,6 @@ class PowerViewBLE:
|
|||||||
async with self._cmd_lock:
|
async with self._cmd_lock:
|
||||||
try:
|
try:
|
||||||
await self._connect()
|
await self._connect()
|
||||||
assert self._client is not None, "missing BT client"
|
|
||||||
cmd_run = self._cmd_next
|
cmd_run = self._cmd_next
|
||||||
tx_data = (
|
tx_data = (
|
||||||
bytearray(
|
bytearray(
|
||||||
@@ -156,7 +162,7 @@ class PowerViewBLE:
|
|||||||
LOGGER.debug("not a V2 record!")
|
LOGGER.debug("not a V2 record!")
|
||||||
return []
|
return []
|
||||||
pos = int.from_bytes(data[3:5], byteorder="little")
|
pos = int.from_bytes(data[3:5], byteorder="little")
|
||||||
pos2 = ((int(data[5]) << 4) + (int(data[4]) >> 4))
|
pos2 = (int(data[5]) << 4) + (int(data[4]) >> 4)
|
||||||
return [
|
return [
|
||||||
(ATTR_CURRENT_POSITION, ((pos >> 2) / 10)),
|
(ATTR_CURRENT_POSITION, ((pos >> 2) / 10)),
|
||||||
("position2", pos2 >> 2),
|
("position2", pos2 >> 2),
|
||||||
@@ -215,12 +221,12 @@ class PowerViewBLE:
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
def _verify_response(self, input: bytearray, seq_nr: int, cmd: ShadeCmd) -> bool:
|
def _verify_response(self, din: bytearray, seq_nr: int, cmd: ShadeCmd) -> bool:
|
||||||
"""Verify shade response data."""
|
"""Verify shade response data."""
|
||||||
data = input
|
data: bytearray = din
|
||||||
if self._cipher is not None:
|
if self._cipher is not None:
|
||||||
dec = self._cipher.decryptor()
|
dec = self._cipher.decryptor()
|
||||||
data = dec.update(input) + dec.finalize()
|
data = bytearray(dec.update(din) + dec.finalize())
|
||||||
if len(data) < 4:
|
if len(data) < 4:
|
||||||
LOGGER.error("Reponse message too short")
|
LOGGER.error("Reponse message too short")
|
||||||
return False
|
return False
|
||||||
@@ -229,14 +235,14 @@ class PowerViewBLE:
|
|||||||
return False
|
return False
|
||||||
if int(data[2]) != seq_nr:
|
if int(data[2]) != seq_nr:
|
||||||
LOGGER.warning(
|
LOGGER.warning(
|
||||||
f"Response sequence id {int(data[2])} wrong, expected {seq_nr}"
|
"Response sequence id %i wrong, expected %d", int(data[2]), seq_nr
|
||||||
)
|
)
|
||||||
return False
|
return False
|
||||||
if int(data[3]) != 1:
|
if int(data[3]) != 1:
|
||||||
LOGGER.error("Wrong response data length")
|
LOGGER.error("Wrong response data length")
|
||||||
return False
|
return False
|
||||||
if int(data[4] != 0):
|
if int(data[4] != 0):
|
||||||
LOGGER.error(f"Command {cmd.value} returned error #{int(data[4])}")
|
LOGGER.error("Command %d returned error #%d", cmd.value, int(data[4]))
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@@ -255,7 +261,6 @@ class PowerViewBLE:
|
|||||||
async with self._cmd_lock:
|
async with self._cmd_lock:
|
||||||
try:
|
try:
|
||||||
await self._connect()
|
await self._connect()
|
||||||
assert self._client is not None
|
|
||||||
|
|
||||||
for key, uuid in uuids.items():
|
for key, uuid in uuids.items():
|
||||||
LOGGER.debug("querying %s(%s)", key, uuid)
|
LOGGER.debug("querying %s(%s)", key, uuid)
|
||||||
@@ -265,7 +270,7 @@ class PowerViewBLE:
|
|||||||
.decode("UTF-8")
|
.decode("UTF-8")
|
||||||
)
|
)
|
||||||
finally:
|
finally:
|
||||||
await self._disconnect()
|
await self.disconnect()
|
||||||
LOGGER.debug("%s device data: %s", self.name, data)
|
LOGGER.debug("%s device data: %s", self.name, data)
|
||||||
return data.copy()
|
return data.copy()
|
||||||
|
|
||||||
@@ -289,8 +294,6 @@ class PowerViewBLE:
|
|||||||
return
|
return
|
||||||
|
|
||||||
start = time.time()
|
start = time.time()
|
||||||
await close_stale_connections(self._ble_device)
|
|
||||||
|
|
||||||
self._client = await establish_connection(
|
self._client = await establish_connection(
|
||||||
BleakClient,
|
BleakClient,
|
||||||
self._ble_device,
|
self._ble_device,
|
||||||
@@ -308,10 +311,10 @@ class PowerViewBLE:
|
|||||||
|
|
||||||
# await self._query_dev_info()
|
# await self._query_dev_info()
|
||||||
|
|
||||||
async def _disconnect(self) -> None:
|
async def disconnect(self) -> None:
|
||||||
"""Disconnect the device and stop notifications."""
|
"""Disconnect the device and stop notifications."""
|
||||||
|
|
||||||
if self._client is not None and self.is_connected:
|
if self.is_connected:
|
||||||
LOGGER.debug("Disconnecting device %s", self.name)
|
LOGGER.debug("Disconnecting device %s", self.name)
|
||||||
try:
|
try:
|
||||||
self._data_event.clear()
|
self._data_event.clear()
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ from dataclasses import dataclass
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant import config_entries
|
from homeassistant import config_entries
|
||||||
from homeassistant.components.bluetooth import (
|
from homeassistant.components.bluetooth import (
|
||||||
BluetoothServiceInfoBleak,
|
BluetoothServiceInfoBleak,
|
||||||
|
|||||||
@@ -3,9 +3,8 @@
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from bleak.backends.device import BLEDevice
|
from bleak.backends.device import BLEDevice
|
||||||
|
|
||||||
from homeassistant.components import bluetooth
|
from homeassistant.components import bluetooth
|
||||||
from homeassistant.components.bluetooth import DOMAIN as BLUETOOTH_DOMAIN
|
from homeassistant.components.bluetooth.const import DOMAIN as BLUETOOTH_DOMAIN
|
||||||
from homeassistant.components.bluetooth.passive_update_coordinator import (
|
from homeassistant.components.bluetooth.passive_update_coordinator import (
|
||||||
PassiveBluetoothDataUpdateCoordinator,
|
PassiveBluetoothDataUpdateCoordinator,
|
||||||
)
|
)
|
||||||
@@ -79,6 +78,12 @@ class PVCoordinator(PassiveBluetoothDataUpdateCoordinator):
|
|||||||
"""Check if a device is present."""
|
"""Check if a device is present."""
|
||||||
return bluetooth.async_address_present(self.hass, self._mac, connectable=True)
|
return bluetooth.async_address_present(self.hass, self._mac, connectable=True)
|
||||||
|
|
||||||
|
def _async_stop(self) -> None:
|
||||||
|
"""Shutdown coordinator and any connection."""
|
||||||
|
LOGGER.debug("%s: shuting down BMS device", self.name)
|
||||||
|
self.hass.async_create_task(self.api.disconnect())
|
||||||
|
super()._async_stop()
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _async_handle_bluetooth_event(
|
def _async_handle_bluetooth_event(
|
||||||
self,
|
self,
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
from typing import Any, Final
|
from typing import Any, Final
|
||||||
|
|
||||||
from bleak.exc import BleakError
|
from bleak.exc import BleakError
|
||||||
|
|
||||||
from homeassistant.components.bluetooth.passive_update_coordinator import (
|
from homeassistant.components.bluetooth.passive_update_coordinator import (
|
||||||
PassiveBluetoothCoordinatorEntity,
|
PassiveBluetoothCoordinatorEntity,
|
||||||
)
|
)
|
||||||
@@ -127,7 +126,10 @@ class PowerViewCover(PassiveBluetoothCoordinatorEntity[PVCoordinator], CoverEnti
|
|||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
except BleakError as err:
|
except BleakError as err:
|
||||||
LOGGER.error(
|
LOGGER.error(
|
||||||
f"Failed to move cover '{self.name}' to {target_position}%: {err}"
|
"Failed to move cover '%s' to %f%%: %s",
|
||||||
|
self.name,
|
||||||
|
target_position,
|
||||||
|
err,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _reset_target_position(self) -> None:
|
def _reset_target_position(self) -> None:
|
||||||
@@ -143,7 +145,7 @@ class PowerViewCover(PassiveBluetoothCoordinatorEntity[PVCoordinator], CoverEnti
|
|||||||
await self._coord.api.open()
|
await self._coord.api.open()
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
except BleakError as err:
|
except BleakError as err:
|
||||||
LOGGER.error(f"Failed to open cover '{self.name}': {err}")
|
LOGGER.error("Failed to open cover '%s': %s", self.name, err)
|
||||||
self._reset_target_position()
|
self._reset_target_position()
|
||||||
|
|
||||||
async def async_close_cover(self, **kwargs: Any) -> None:
|
async def async_close_cover(self, **kwargs: Any) -> None:
|
||||||
@@ -156,7 +158,7 @@ class PowerViewCover(PassiveBluetoothCoordinatorEntity[PVCoordinator], CoverEnti
|
|||||||
await self._coord.api.close()
|
await self._coord.api.close()
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
except BleakError as err:
|
except BleakError as err:
|
||||||
LOGGER.error(f"Failed to close cover '{self.name}': {err}")
|
LOGGER.error("Failed to close cover '%s': %s", self.name, err)
|
||||||
self._reset_target_position()
|
self._reset_target_position()
|
||||||
|
|
||||||
async def async_stop_cover(self, **kwargs: Any) -> None:
|
async def async_stop_cover(self, **kwargs: Any) -> None:
|
||||||
@@ -167,4 +169,4 @@ class PowerViewCover(PassiveBluetoothCoordinatorEntity[PVCoordinator], CoverEnti
|
|||||||
self._reset_target_position()
|
self._reset_target_position()
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
except BleakError as err:
|
except BleakError as err:
|
||||||
LOGGER.error(f"Failed to stop cover '{self.name}': {err}")
|
LOGGER.error("Failed to stop cover '%s': %s", self.name, err)
|
||||||
|
|||||||
@@ -4,9 +4,11 @@ from homeassistant.components.bluetooth.passive_update_coordinator import (
|
|||||||
PassiveBluetoothCoordinatorEntity,
|
PassiveBluetoothCoordinatorEntity,
|
||||||
)
|
)
|
||||||
from homeassistant.components.sensor import (
|
from homeassistant.components.sensor import (
|
||||||
SensorDeviceClass,
|
|
||||||
SensorEntity,
|
SensorEntity,
|
||||||
SensorEntityDescription,
|
SensorEntityDescription,
|
||||||
|
)
|
||||||
|
from homeassistant.components.sensor.const import (
|
||||||
|
SensorDeviceClass,
|
||||||
SensorStateClass,
|
SensorStateClass,
|
||||||
)
|
)
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
|
|||||||
155
pyproject.toml
155
pyproject.toml
@@ -1,12 +1,11 @@
|
|||||||
# pyproject.toml
|
# pyproject.toml
|
||||||
|
|
||||||
#[tool.setuptools.packages.find]
|
[project]
|
||||||
#where = ["custom_components/"]
|
requires-python = ">=3.12.0"
|
||||||
#include = ["bms_ble"]
|
|
||||||
|
|
||||||
[tool.pytest.ini_options]
|
[tool.pytest.ini_options]
|
||||||
minversion = "8.0"
|
minversion = "8.0"
|
||||||
addopts="--cov=custom_components.bms_ble --cov-report=term-missing --cov-fail-under=100"
|
addopts="--cov=custom_components.hunterdouglas_powerview_ble --cov-report=term-missing --cov-fail-under=100"
|
||||||
pythonpath = [
|
pythonpath = [
|
||||||
"custom_components.hunterdouglas_powerview_ble",
|
"custom_components.hunterdouglas_powerview_ble",
|
||||||
]
|
]
|
||||||
@@ -14,3 +13,151 @@ testpaths = [
|
|||||||
"tests",
|
"tests",
|
||||||
]
|
]
|
||||||
asyncio_mode = "auto"
|
asyncio_mode = "auto"
|
||||||
|
|
||||||
|
# ruff configuration taken from HA 2024.11.2 (less ignores)
|
||||||
|
[tool.ruff]
|
||||||
|
required-version = ">=0.6.8"
|
||||||
|
|
||||||
|
[tool.ruff.lint]
|
||||||
|
select = [
|
||||||
|
"A001", # Variable {name} is shadowing a Python builtin
|
||||||
|
"ASYNC210", # Async functions should not call blocking HTTP methods
|
||||||
|
"ASYNC220", # Async functions should not create subprocesses with blocking methods
|
||||||
|
"ASYNC221", # Async functions should not run processes with blocking methods
|
||||||
|
"ASYNC222", # Async functions should not wait on processes with blocking methods
|
||||||
|
"ASYNC230", # Async functions should not open files with blocking methods like open
|
||||||
|
"ASYNC251", # Async functions should not call time.sleep
|
||||||
|
"B002", # Python does not support the unary prefix increment
|
||||||
|
"B005", # Using .strip() with multi-character strings is misleading
|
||||||
|
"B007", # Loop control variable {name} not used within loop body
|
||||||
|
"B014", # Exception handler with duplicate exception
|
||||||
|
"B015", # Pointless comparison. Did you mean to assign a value? Otherwise, prepend assert or remove it.
|
||||||
|
"B017", # pytest.raises(BaseException) should be considered evil
|
||||||
|
"B018", # Found useless attribute access. Either assign it to a variable or remove it.
|
||||||
|
"B023", # Function definition does not bind loop variable {name}
|
||||||
|
"B026", # Star-arg unpacking after a keyword argument is strongly discouraged
|
||||||
|
"B032", # Possible unintentional type annotation (using :). Did you mean to assign (using =)?
|
||||||
|
"B904", # Use raise from to specify exception cause
|
||||||
|
"B905", # zip() without an explicit strict= parameter
|
||||||
|
"BLE",
|
||||||
|
"C", # complexity
|
||||||
|
"COM818", # Trailing comma on bare tuple prohibited
|
||||||
|
"D", # docstrings
|
||||||
|
"DTZ003", # Use datetime.now(tz=) instead of datetime.utcnow()
|
||||||
|
"DTZ004", # Use datetime.fromtimestamp(ts, tz=) instead of datetime.utcfromtimestamp(ts)
|
||||||
|
"E", # pycodestyle
|
||||||
|
"F", # pyflakes/autoflake
|
||||||
|
"F541", # f-string without any placeholders
|
||||||
|
"FLY", # flynt
|
||||||
|
"FURB", # refurb
|
||||||
|
"G", # flake8-logging-format
|
||||||
|
"I", # isort
|
||||||
|
"INP", # flake8-no-pep420
|
||||||
|
"ISC", # flake8-implicit-str-concat
|
||||||
|
"ICN001", # import concentions; {name} should be imported as {asname}
|
||||||
|
"LOG", # flake8-logging
|
||||||
|
"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
|
||||||
|
"PERF", # Perflint
|
||||||
|
"PGH", # pygrep-hooks
|
||||||
|
"PIE", # flake8-pie
|
||||||
|
"PL", # pylint
|
||||||
|
"PT", # flake8-pytest-style
|
||||||
|
"PTH", # flake8-pathlib
|
||||||
|
"PYI", # flake8-pyi
|
||||||
|
"RET", # flake8-return
|
||||||
|
"RSE", # flake8-raise
|
||||||
|
"RUF005", # Consider iterable unpacking instead of concatenation
|
||||||
|
"RUF006", # Store a reference to the return value of asyncio.create_task
|
||||||
|
"RUF010", # Use explicit conversion flag
|
||||||
|
"RUF013", # PEP 484 prohibits implicit Optional
|
||||||
|
"RUF017", # Avoid quadratic list summation
|
||||||
|
"RUF018", # Avoid assignment expressions in assert statements
|
||||||
|
"RUF019", # Unnecessary key check before dictionary access
|
||||||
|
# "RUF100", # Unused `noqa` directive; temporarily every now and then to clean them up
|
||||||
|
"S102", # Use of exec detected
|
||||||
|
"S103", # bad-file-permissions
|
||||||
|
"S108", # hardcoded-temp-file
|
||||||
|
"S306", # suspicious-mktemp-usage
|
||||||
|
"S307", # suspicious-eval-usage
|
||||||
|
"S313", # suspicious-xmlc-element-tree-usage
|
||||||
|
"S314", # suspicious-xml-element-tree-usage
|
||||||
|
"S315", # suspicious-xml-expat-reader-usage
|
||||||
|
"S316", # suspicious-xml-expat-builder-usage
|
||||||
|
"S317", # suspicious-xml-sax-usage
|
||||||
|
"S318", # suspicious-xml-mini-dom-usage
|
||||||
|
"S319", # suspicious-xml-pull-dom-usage
|
||||||
|
"S320", # suspicious-xmle-tree-usage
|
||||||
|
"S601", # paramiko-call
|
||||||
|
"S602", # subprocess-popen-with-shell-equals-true
|
||||||
|
"S604", # call-with-shell-equals-true
|
||||||
|
"S608", # hardcoded-sql-expression
|
||||||
|
"S609", # unix-command-wildcard-injection
|
||||||
|
"SIM", # flake8-simplify
|
||||||
|
"SLF", # flake8-self
|
||||||
|
"SLOT", # flake8-slots
|
||||||
|
"T100", # Trace found: {name} used
|
||||||
|
"T20", # flake8-print
|
||||||
|
"TCH", # flake8-type-checking
|
||||||
|
"TID", # Tidy imports
|
||||||
|
"TRY", # tryceratops
|
||||||
|
"UP", # pyupgrade
|
||||||
|
"UP031", # Use format specifiers instead of percent format
|
||||||
|
"UP032", # Use f-string instead of `format` call
|
||||||
|
"W", # pycodestyle
|
||||||
|
]
|
||||||
|
|
||||||
|
ignore = [
|
||||||
|
"D202", # No blank lines allowed after function docstring
|
||||||
|
"D203", # 1 blank line required before class docstring
|
||||||
|
"D213", # Multi-line docstring summary should start at the second line
|
||||||
|
"D406", # Section name should end with a newline
|
||||||
|
"D407", # Section name underlining
|
||||||
|
"E501", # line too long
|
||||||
|
|
||||||
|
# "PLC1901", # {existing} can be simplified to {replacement} as an empty string is falsey; too many false positives
|
||||||
|
# "PLR0911", # Too many return statements ({returns} > {max_returns})
|
||||||
|
# "PLR0912", # Too many branches ({branches} > {max_branches})
|
||||||
|
# "PLR0913", # Too many arguments to function call ({c_args} > {max_args})
|
||||||
|
# "PLR0915", # Too many statements ({statements} > {max_statements})
|
||||||
|
"PLR2004", # Magic value used in comparison, consider replacing {value} with a constant variable
|
||||||
|
# "PLW2901", # Outer {outer_kind} variable {name} overwritten by inner {inner_kind} target
|
||||||
|
# "PT004", # Fixture {fixture} does not return anything, add leading underscore
|
||||||
|
# "PT011", # pytest.raises({exception}) is too broad, set the `match` parameter or use a more specific exception
|
||||||
|
# "PT018", # Assertion should be broken down into multiple parts
|
||||||
|
# "RUF001", # String contains ambiguous unicode character.
|
||||||
|
# "RUF002", # Docstring contains ambiguous unicode character.
|
||||||
|
# "RUF003", # Comment contains ambiguous unicode character.
|
||||||
|
# "RUF015", # Prefer next(...) over single element slice
|
||||||
|
# "SIM102", # Use a single if statement instead of nested if statements
|
||||||
|
# "SIM103", # Return the condition {condition} directly
|
||||||
|
# "SIM108", # Use ternary operator {contents} instead of if-else-block
|
||||||
|
# "SIM115", # Use context handler for opening files
|
||||||
|
|
||||||
|
# Moving imports into type-checking blocks can mess with pytest.patch()
|
||||||
|
"TCH001", # Move application import {} into a type-checking block
|
||||||
|
"TCH002", # Move third-party import {} into a type-checking block
|
||||||
|
"TCH003", # Move standard library import {} into a type-checking block
|
||||||
|
|
||||||
|
"TRY003", # Avoid specifying long messages outside the exception class
|
||||||
|
"TRY400", # Use `logging.exception` instead of `logging.error`
|
||||||
|
# Ignored due to performance: https://github.com/charliermarsh/ruff/issues/2923
|
||||||
|
"UP038", # Use `X | Y` in `isinstance` call instead of `(X, Y)`
|
||||||
|
|
||||||
|
# May conflict with the formatter, https://docs.astral.sh/ruff/formatter/#conflicting-lint-rules
|
||||||
|
"W191",
|
||||||
|
"E111",
|
||||||
|
"E114",
|
||||||
|
"E117",
|
||||||
|
"D206",
|
||||||
|
"D300",
|
||||||
|
"Q",
|
||||||
|
"COM812",
|
||||||
|
"COM819",
|
||||||
|
"ISC001",
|
||||||
|
|
||||||
|
# Disabled because ruff does not understand type of __all__ generated by a function
|
||||||
|
"PLE0605"
|
||||||
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
homeassistant==2024.8.0
|
homeassistant==2024.8.0
|
||||||
pip>=21.3.1
|
pip>=21.3.1
|
||||||
ruff==0.4.2
|
ruff==0.6.8
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user