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
2 changes: 1 addition & 1 deletion .github/workflows/builder.yml
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ jobs:
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0

- name: Install Cosign
uses: sigstore/cosign-installer@d58896d6a1865668819e1d91763c7751a165e159 # v3.9.2
uses: sigstore/cosign-installer@d7543c93d881b35a8faa02e8e3605f69b7a1ce62 # v3.10.0
with:
cosign-release: "v2.2.3"

Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/eq3btsmart/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: Eq3ConfigEntry) -> bool:
f"[{eq3_config.mac_address}] Device could not be found"
)

thermostat = Thermostat(mac_address=device) # type: ignore[arg-type]
thermostat = Thermostat(device)

entry.runtime_data = Eq3ConfigEntryData(
eq3_config=eq3_config, thermostat=thermostat
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/eq3btsmart/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,5 @@
"integration_type": "device",
"iot_class": "local_polling",
"loggers": ["eq3btsmart"],
"requirements": ["eq3btsmart==2.1.0", "bleak-esphome==3.3.0"]
"requirements": ["eq3btsmart==2.2.0"]
}
2 changes: 1 addition & 1 deletion homeassistant/components/imeon_inverter/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"integration_type": "device",
"iot_class": "local_polling",
"quality_scale": "bronze",
"requirements": ["imeon_inverter_api==0.3.16"],
"requirements": ["imeon_inverter_api==0.4.0"],
"ssdp": [
{
"manufacturer": "IMEON",
Expand Down
68 changes: 29 additions & 39 deletions homeassistant/components/openweathermap/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,24 @@
)
from .utils import build_data_and_options, validate_api_key

USER_SCHEMA = vol.Schema(
{
vol.Optional(CONF_NAME, default=DEFAULT_NAME): str,
vol.Optional(CONF_LATITUDE): cv.latitude,
vol.Optional(CONF_LONGITUDE): cv.longitude,
vol.Optional(CONF_LANGUAGE, default=DEFAULT_LANGUAGE): vol.In(LANGUAGES),
vol.Required(CONF_API_KEY): str,
vol.Optional(CONF_MODE, default=DEFAULT_OWM_MODE): vol.In(OWM_MODES),
}
)

OPTIONS_SCHEMA = vol.Schema(
{
vol.Optional(CONF_LANGUAGE, default=DEFAULT_LANGUAGE): vol.In(LANGUAGES),
vol.Optional(CONF_MODE, default=DEFAULT_OWM_MODE): vol.In(OWM_MODES),
}
)


class OpenWeatherMapConfigFlow(ConfigFlow, domain=DOMAIN):
"""Config flow for OpenWeatherMap."""
Expand Down Expand Up @@ -68,31 +86,21 @@ async def async_step_user(self, user_input=None) -> ConfigFlowResult:
return self.async_create_entry(
title=user_input[CONF_NAME], data=data, options=options
)
schema_data = user_input
else:
schema_data = {
CONF_LATITUDE: self.hass.config.latitude,
CONF_LONGITUDE: self.hass.config.longitude,
CONF_LANGUAGE: self.hass.config.language,
}

description_placeholders["doc_url"] = (
"https://www.home-assistant.io/integrations/openweathermap/"
)

schema = vol.Schema(
{
vol.Required(CONF_API_KEY): str,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): str,
vol.Optional(
CONF_LATITUDE, default=self.hass.config.latitude
): cv.latitude,
vol.Optional(
CONF_LONGITUDE, default=self.hass.config.longitude
): cv.longitude,
vol.Optional(CONF_MODE, default=DEFAULT_OWM_MODE): vol.In(OWM_MODES),
vol.Optional(CONF_LANGUAGE, default=DEFAULT_LANGUAGE): vol.In(
LANGUAGES
),
}
)

return self.async_show_form(
step_id="user",
data_schema=schema,
data_schema=self.add_suggested_values_to_schema(USER_SCHEMA, schema_data),
errors=errors,
description_placeholders=description_placeholders,
)
Expand All @@ -108,25 +116,7 @@ async def async_step_init(self, user_input: dict | None = None) -> ConfigFlowRes

return self.async_show_form(
step_id="init",
data_schema=self._get_options_schema(),
)

def _get_options_schema(self):
return vol.Schema(
{
vol.Optional(
CONF_MODE,
default=self.config_entry.options.get(
CONF_MODE,
self.config_entry.data.get(CONF_MODE, DEFAULT_OWM_MODE),
),
): vol.In(OWM_MODES),
vol.Optional(
CONF_LANGUAGE,
default=self.config_entry.options.get(
CONF_LANGUAGE,
self.config_entry.data.get(CONF_LANGUAGE, DEFAULT_LANGUAGE),
),
): vol.In(LANGUAGES),
}
data_schema=self.add_suggested_values_to_schema(
OPTIONS_SCHEMA, self.config_entry.options
),
)
12 changes: 12 additions & 0 deletions homeassistant/components/openweathermap/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@
"mode": "[%key:common::config_flow::data::mode%]",
"name": "[%key:common::config_flow::data::name%]"
},
"data_description": {
"api_key": "API key for the OpenWeatherMap integration",
"language": "Language for the OpenWeatherMap content",
"latitude": "Latitude of the location",
"longitude": "Longitude of the location",
"mode": "Mode for the OpenWeatherMap API",
"name": "Name for this OpenWeatherMap location"
},
"description": "To generate an API key, please refer to the [integration documentation]({doc_url})"
}
}
Expand All @@ -27,6 +35,10 @@
"data": {
"language": "[%key:common::config_flow::data::language%]",
"mode": "[%key:common::config_flow::data::mode%]"
},
"data_description": {
"language": "[%key:component::openweathermap::config::step::user::data_description::language%]",
"mode": "[%key:component::openweathermap::config::step::user::data_description::mode%]"
}
}
}
Expand Down
8 changes: 8 additions & 0 deletions pylint/plugins/hass_enforce_type_hints.py
Original file line number Diff line number Diff line change
Expand Up @@ -3425,6 +3425,14 @@ def _check_function(
# Check that all positional arguments are correctly annotated.
if match.arg_types:
for key, expected_type in match.arg_types.items():
if key > len(node.args.args) - 1:
# The number of arguments is less than expected
self.add_message(
"hass-argument-type",
node=node,
args=(key + 1, expected_type, node.name),
)
continue
if node.args.args[key].name in _COMMON_ARGUMENTS:
# It has already been checked, avoid double-message
continue
Expand Down
5 changes: 2 additions & 3 deletions requirements_all.txt

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 2 additions & 3 deletions requirements_test_all.txt

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions tests/components/zha/conftest.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Test configuration for the ZHA component."""

from collections.abc import Generator
from collections.abc import Callable, Coroutine, Generator
import itertools
import time
from typing import Any
Expand Down Expand Up @@ -241,11 +241,11 @@ def setup_zha(
hass: HomeAssistant,
config_entry: MockConfigEntry,
mock_zigpy_connect: ControllerApplication,
):
) -> Callable[..., Coroutine[None]]:
"""Set up ZHA component."""
zha_config = {zha_const.CONF_ENABLE_QUIRKS: False}

async def _setup(config=None):
async def _setup(config=None) -> None:
config_entry.add_to_hass(hass)
config = config or {}

Expand Down Expand Up @@ -353,7 +353,7 @@ def network_backup() -> zigpy.backups.NetworkBackup:


@pytest.fixture
def zigpy_device_mock(zigpy_app_controller):
def zigpy_device_mock(zigpy_app_controller) -> Callable[..., zigpy.device.Device]:
"""Make a fake device using the specified cluster classes."""

def _mock_dev(
Expand Down
6 changes: 5 additions & 1 deletion tests/components/zha/test_alarm_control_panel.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
"""Test ZHA alarm control panel."""

from collections.abc import Callable, Coroutine
from unittest.mock import AsyncMock, call, patch, sentinel

import pytest
from zigpy.device import Device
from zigpy.profiles import zha
from zigpy.zcl import Cluster
from zigpy.zcl.clusters import security
Expand Down Expand Up @@ -45,7 +47,9 @@ def alarm_control_panel_platform_only():
new=AsyncMock(return_value=[sentinel.data, zcl_f.Status.SUCCESS]),
)
async def test_alarm_control_panel(
hass: HomeAssistant, setup_zha, zigpy_device_mock
hass: HomeAssistant,
setup_zha: Callable[..., Coroutine[None]],
zigpy_device_mock: Callable[..., Device],
) -> None:
"""Test ZHA alarm control panel platform."""

Expand Down
27 changes: 20 additions & 7 deletions tests/components/zha/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from __future__ import annotations

from collections.abc import Callable, Coroutine
from typing import TYPE_CHECKING
from unittest.mock import AsyncMock, MagicMock, call, patch

Expand All @@ -26,7 +27,7 @@ def required_platform_only():


async def test_async_get_network_settings_active(
hass: HomeAssistant, setup_zha
hass: HomeAssistant, setup_zha: Callable[..., Coroutine[None]]
) -> None:
"""Test reading settings with an active ZHA installation."""
await setup_zha()
Expand All @@ -36,7 +37,9 @@ async def test_async_get_network_settings_active(


async def test_async_get_network_settings_inactive(
hass: HomeAssistant, setup_zha, zigpy_app_controller: ControllerApplication
hass: HomeAssistant,
setup_zha: Callable[..., Coroutine[None]],
zigpy_app_controller: ControllerApplication,
) -> None:
"""Test reading settings with an inactive ZHA installation."""
await setup_zha()
Expand All @@ -63,7 +66,9 @@ async def test_async_get_network_settings_inactive(


async def test_async_get_network_settings_missing(
hass: HomeAssistant, setup_zha, zigpy_app_controller: ControllerApplication
hass: HomeAssistant,
setup_zha: Callable[..., Coroutine[None]],
zigpy_app_controller: ControllerApplication,
) -> None:
"""Test reading settings with an inactive ZHA installation, no valid channel."""
await setup_zha()
Expand All @@ -86,15 +91,19 @@ async def test_async_get_network_settings_failure(hass: HomeAssistant) -> None:
await api.async_get_network_settings(hass)


async def test_async_get_radio_type_active(hass: HomeAssistant, setup_zha) -> None:
async def test_async_get_radio_type_active(
hass: HomeAssistant, setup_zha: Callable[..., Coroutine[None]]
) -> None:
"""Test reading the radio type with an active ZHA installation."""
await setup_zha()

radio_type = api.async_get_radio_type(hass)
assert radio_type == RadioType.ezsp


async def test_async_get_radio_path_active(hass: HomeAssistant, setup_zha) -> None:
async def test_async_get_radio_path_active(
hass: HomeAssistant, setup_zha: Callable[..., Coroutine[None]]
) -> None:
"""Test reading the radio path with an active ZHA installation."""
await setup_zha()

Expand All @@ -103,7 +112,9 @@ async def test_async_get_radio_path_active(hass: HomeAssistant, setup_zha) -> No


async def test_change_channel(
hass: HomeAssistant, setup_zha, zigpy_app_controller: ControllerApplication
hass: HomeAssistant,
setup_zha: Callable[..., Coroutine[None]],
zigpy_app_controller: ControllerApplication,
) -> None:
"""Test changing the channel."""
await setup_zha()
Expand All @@ -113,7 +124,9 @@ async def test_change_channel(


async def test_change_channel_auto(
hass: HomeAssistant, setup_zha, zigpy_app_controller: ControllerApplication
hass: HomeAssistant,
setup_zha: Callable[..., Coroutine[None]],
zigpy_app_controller: ControllerApplication,
) -> None:
"""Test changing the channel automatically using an energy scan."""
await setup_zha()
Expand Down
13 changes: 10 additions & 3 deletions tests/components/zha/test_backup.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"""Unit tests for ZHA backup platform."""

from collections.abc import Callable, Coroutine
from unittest.mock import AsyncMock, patch

from zigpy.application import ControllerApplication
Expand All @@ -9,7 +10,9 @@


async def test_pre_backup(
hass: HomeAssistant, zigpy_app_controller: ControllerApplication, setup_zha
hass: HomeAssistant,
zigpy_app_controller: ControllerApplication,
setup_zha: Callable[..., Coroutine[None]],
) -> None:
"""Test backup creation when `async_pre_backup` is called."""
await setup_zha()
Expand All @@ -23,13 +26,17 @@ async def test_pre_backup(


@patch("homeassistant.components.zha.backup.get_zha_gateway", side_effect=ValueError())
async def test_pre_backup_no_gateway(hass: HomeAssistant, setup_zha) -> None:
async def test_pre_backup_no_gateway(
hass: HomeAssistant, setup_zha: Callable[..., Coroutine[None]]
) -> None:
"""Test graceful backup failure when no gateway exists."""
await setup_zha()
await async_pre_backup(hass)


async def test_post_backup(hass: HomeAssistant, setup_zha) -> None:
async def test_post_backup(
hass: HomeAssistant, setup_zha: Callable[..., Coroutine[None]]
) -> None:
"""Test no-op `async_post_backup`."""
await setup_zha()
await async_post_backup(hass)
Loading
Loading