Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .github/workflows/pre-commit.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
name: pre-commit

on:
pull_request:
push:
branches: [main, dev]

jobs:
pre-commit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
- uses: pre-commit/action@v3.0.1
58 changes: 58 additions & 0 deletions .ruff.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# The contents of this file is based on https://github.com/home-assistant/core/blob/dev/pyproject.toml

target-version = "py310"
[lint]
select = ["ALL"]

# All the ones without a comment were the ones that are currently violated
# by the codebase. The plan is to fix them all (when sensible) and then enable them.
ignore = [
"ANN",
"ANN401", # Dynamically typed expressions (typing.Any) are disallowed in {name}
"D401", # First line of docstring should be in imperative mood
"E501", # line too long
"FBT001", # Boolean positional arg in function definition
"FBT002", # Boolean default value in function definition
"FIX004", # Line contains HACK, consider resolving the issue
"PD901", # df is a bad variable name. Be kinder to your future self.
"PERF203", # `try`-`except` within a loop incurs performance overhead
"PLR0913", # Too many arguments to function call (N > 5)
"PLR2004", # Magic value used in comparison, consider replacing X with a constant variable
"S101", # Use of assert detected
"SLF001", # Private member accessed
"RUF015", # Prefer `next(...)` over single element slices
]

[lint.per-file-ignores]
"tests/*.py" = [
"ARG001", # Unused function argument: `call`
"D100", # Missing docstring in public module
"D103", # Missing docstring in public function
"D205", # 1 blank line required between summary line and description
"D400", # First line should end with a period
"D415", # First line should end with a period, question mark, or
"DTZ001", # The use of `datetime.datetime()` without `tzinfo`
"ERA001", # Found commented-out code
"FBT003", # Boolean positional value in function call
"FIX002", # Line contains TODO, consider resolving the issue
"G004", # Logging statement uses f-string
"PLR0915", # Too many statements (94 > 50)
"PT004", # Fixture `cleanup` does not return anything, add leading underscore
"PT007", # Wrong values type in `@pytest.mark.parametrize` expected `list` of
"S311", # Standard pseudo-random generators are not suitable for cryptographic
"TD002", # Missing author in TODO; try: `# TODO(<author_name>): ...` or `# TODO
"TD003", # Missing issue link on the line following this TODO
]
".github/*py" = ["INP001"]
"webapp/homeassistant_util_color.py" = ["ALL"]
"webapp/app.py" = ["INP001", "DTZ011", "A002"]
"custom_components/adaptive_lighting/homeassistant_util_color.py" = ["ALL"]

[lint.flake8-pytest-style]
fixture-parentheses = false

[lint.pyupgrade]
keep-runtime-typing = true

[lint.mccabe]
max-complexity = 25
42 changes: 25 additions & 17 deletions custom_components/mass_queue/__init__.py
Original file line number Diff line number Diff line change
@@ -1,32 +1,33 @@
"""Initialize component."""

from __future__ import annotations

import asyncio
from dataclasses import dataclass
from typing import TYPE_CHECKING

from music_assistant_client import MusicAssistantClient
from music_assistant_client.exceptions import CannotConnect, InvalidServerVersion
from music_assistant_models.errors import ActionUnavailable, MusicAssistantError

from homeassistant.config_entries import ConfigEntry, ConfigEntryState
from homeassistant.const import CONF_URL, EVENT_HOMEASSISTANT_STOP
from homeassistant.core import Event, HomeAssistant
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers import config_validation as cv, device_registry as dr
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers import device_registry as dr
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.issue_registry import (
IssueSeverity,
async_create_issue,
async_delete_issue,
)
from music_assistant_client import MusicAssistantClient
from music_assistant_client.exceptions import CannotConnect, InvalidServerVersion
from music_assistant_models.errors import ActionUnavailable, MusicAssistantError

from .actions import get_music_assistant_client, setup_controller_and_actions
from .const import DOMAIN, LOGGER

if TYPE_CHECKING:
from homeassistant.helpers.typing import ConfigType
from homeassistant.core import HomeAssistant
from homeassistant.helpers.typing import ConfigType, Event

# PLATFORMS = [Platform.MEDIA_PLAYER]
PLATFORMS = []

CONNECT_TIMEOUT = 10
Expand All @@ -45,14 +46,15 @@ class MusicAssistantEntryData:
listen_task: asyncio.Task


async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: # noqa: ARG001
"""Set up the Music Assistant component."""
setup_controller_and_actions(hass)
return True


async def async_setup_entry(
hass: HomeAssistant, entry: MusicAssistantConfigEntry
hass: HomeAssistant,
entry: MusicAssistantConfigEntry,
) -> bool:
"""Set up Music Assistant from a config entry."""
http_session = async_get_clientsession(hass, verify_ssl=False)
Expand All @@ -63,8 +65,9 @@ async def async_setup_entry(
async with asyncio.timeout(CONNECT_TIMEOUT):
await mass.connect()
except (TimeoutError, CannotConnect) as err:
exc = f"Failed to connect to music assistant server {mass_url}"
raise ConfigEntryNotReady(
f"Failed to connect to music assistant server {mass_url}"
exc,
) from err
except InvalidServerVersion as err:
async_create_issue(
Expand All @@ -75,21 +78,23 @@ async def async_setup_entry(
severity=IssueSeverity.ERROR,
translation_key="invalid_server_version",
)
raise ConfigEntryNotReady(f"Invalid server version: {err}") from err
exc = f"Invalid server version: {err}"
raise ConfigEntryNotReady(exc) from err
except MusicAssistantError as err:
LOGGER.exception("Failed to connect to music assistant server", exc_info=err)
exc = f"Unknown error connecting to the Music Assistant server {mass_url}"
raise ConfigEntryNotReady(
f"Unknown error connecting to the Music Assistant server {mass_url}"
exc,
) from err

async_delete_issue(hass, DOMAIN, "invalid_server_version")

async def on_hass_stop(event: Event) -> None:
async def on_hass_stop(event: Event) -> None: # noqa: ARG001
"""Handle incoming stop event from Home Assistant."""
await mass.disconnect()

entry.async_on_unload(
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, on_hass_stop)
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, on_hass_stop),
)

# launch the music assistant client listen task in the background
Expand All @@ -102,7 +107,8 @@ async def on_hass_stop(event: Event) -> None:
await init_ready.wait()
except TimeoutError as err:
listen_task.cancel()
raise ConfigEntryNotReady("Music Assistant client not ready") from err
exc = "Music Assistant client not ready"
raise ConfigEntryNotReady(exc) from err

# store the listen task and mass client in the entry data
entry.runtime_data = MusicAssistantEntryData(mass, listen_task)
Expand Down Expand Up @@ -158,7 +164,9 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:


async def async_remove_config_entry_device(
hass: HomeAssistant, config_entry: ConfigEntry, device_entry: dr.DeviceEntry
hass: HomeAssistant,
config_entry: ConfigEntry,
device_entry: dr.DeviceEntry,
) -> bool:
"""Remove a config entry from a device."""
player_id = next(
Expand Down
Loading
Loading