Add more type hints to pylint plugin (#118319)

This commit is contained in:
epenet 2024-05-28 18:37:38 +02:00 committed by GitHub
parent 0b2aac8f4c
commit a59621bf9e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
22 changed files with 179 additions and 43 deletions

View file

@ -98,6 +98,7 @@ _METHOD_MATCH: list[TypeHintMatch] = [
_TEST_FIXTURES: dict[str, list[str] | str] = {
"aioclient_mock": "AiohttpClientMocker",
"aiohttp_client": "ClientSessionGenerator",
"aiohttp_server": "Callable[[], TestServer]",
"area_registry": "AreaRegistry",
"async_setup_recorder_instance": "RecorderInstanceGenerator",
"caplog": "pytest.LogCaptureFixture",
@ -110,6 +111,7 @@ _TEST_FIXTURES: dict[str, list[str] | str] = {
"enable_schema_validation": "bool",
"entity_registry": "EntityRegistry",
"entity_registry_enabled_by_default": "None",
"event_loop": "AbstractEventLoop",
"freezer": "FrozenDateTimeFactory",
"hass_access_token": "str",
"hass_admin_credential": "Credentials",
@ -146,9 +148,12 @@ _TEST_FIXTURES: dict[str, list[str] | str] = {
"recorder_mock": "Recorder",
"requests_mock": "requests_mock.Mocker",
"snapshot": "SnapshotAssertion",
"socket_enabled": "None",
"stub_blueprint_populate": "None",
"tmp_path": "Path",
"tmpdir": "py.path.local",
"unused_tcp_port_factory": "Callable[[], int]",
"unused_udp_port_factory": "Callable[[], int]",
}
_TEST_FUNCTION_MATCH = TypeHintMatch(
function_name="test_*",

View file

@ -1,15 +1,19 @@
"""The tests for the Alexa component."""
from asyncio import AbstractEventLoop
import datetime
from http import HTTPStatus
from aiohttp.test_utils import TestClient
import pytest
from homeassistant.components import alexa
from homeassistant.components.alexa import const
from homeassistant.core import callback
from homeassistant.core import HomeAssistant, callback
from homeassistant.setup import async_setup_component
from tests.typing import ClientSessionGenerator
SESSION_ID = "amzn1.echo-api.session.0000000-0000-0000-0000-00000000000"
APPLICATION_ID = "amzn1.echo-sdk-ams.app.000000-d0ed-0000-ad00-000000d00ebe"
REQUEST_ID = "amzn1.echo-api.request.0000000-0000-0000-0000-00000000000"
@ -20,7 +24,11 @@ NPR_NEWS_MP3_URL = "https://pd.npr.org/anon.npr-mp3/npr/news/newscast.mp3"
@pytest.fixture
def alexa_client(event_loop, hass, hass_client):
def alexa_client(
event_loop: AbstractEventLoop,
hass: HomeAssistant,
hass_client: ClientSessionGenerator,
) -> TestClient:
"""Initialize a Home Assistant server for testing this module."""
loop = event_loop

View file

@ -1,8 +1,10 @@
"""The tests for the Alexa component."""
from asyncio import AbstractEventLoop
from http import HTTPStatus
import json
from aiohttp.test_utils import TestClient
import pytest
from homeassistant.components import alexa
@ -11,6 +13,8 @@ from homeassistant.const import CONTENT_TYPE_JSON
from homeassistant.core import HomeAssistant, callback
from homeassistant.setup import async_setup_component
from tests.typing import ClientSessionGenerator
SESSION_ID = "amzn1.echo-api.session.0000000-0000-0000-0000-00000000000"
APPLICATION_ID = "amzn1.echo-sdk-ams.app.000000-d0ed-0000-ad00-000000d00ebe"
APPLICATION_ID_SESSION_OPEN = (
@ -26,7 +30,11 @@ NPR_NEWS_MP3_URL = "https://pd.npr.org/anon.npr-mp3/npr/news/newscast.mp3"
@pytest.fixture
def alexa_client(event_loop, hass, hass_client):
def alexa_client(
event_loop: AbstractEventLoop,
hass: HomeAssistant,
hass_client: ClientSessionGenerator,
) -> TestClient:
"""Initialize a Home Assistant server for testing this module."""
loop = event_loop

View file

@ -1,9 +1,17 @@
"""Test configuration for auth."""
from asyncio import AbstractEventLoop
import pytest
from tests.typing import ClientSessionGenerator
@pytest.fixture
def aiohttp_client(event_loop, aiohttp_client, socket_enabled):
def aiohttp_client(
event_loop: AbstractEventLoop,
aiohttp_client: ClientSessionGenerator,
socket_enabled: None,
) -> ClientSessionGenerator:
"""Return aiohttp_client and allow opening sockets."""
return aiohttp_client

View file

@ -1,5 +1,6 @@
"""The tests for the emulated Hue component."""
from asyncio import AbstractEventLoop
from http import HTTPStatus
import json
import unittest
@ -16,6 +17,7 @@ from homeassistant.const import CONTENT_TYPE_JSON
from homeassistant.core import HomeAssistant
from tests.common import get_test_instance_port
from tests.typing import ClientSessionGenerator
BRIDGE_SERVER_PORT = get_test_instance_port()
@ -33,7 +35,11 @@ class MockTransport:
@pytest.fixture
def aiohttp_client(event_loop, aiohttp_client, socket_enabled):
def aiohttp_client(
event_loop: AbstractEventLoop,
aiohttp_client: ClientSessionGenerator,
socket_enabled: None,
) -> ClientSessionGenerator:
"""Return aiohttp_client and allow opening sockets."""
return aiohttp_client

View file

@ -1,6 +1,7 @@
"""Test ESPHome voice assistant server."""
import asyncio
from collections.abc import Callable
import io
import socket
from unittest.mock import Mock, patch
@ -174,8 +175,8 @@ async def test_pipeline_events(
async def test_udp_server(
hass: HomeAssistant,
socket_enabled,
unused_udp_port_factory,
socket_enabled: None,
unused_udp_port_factory: Callable[[], int],
voice_assistant_udp_pipeline_v1: VoiceAssistantUDPPipeline,
) -> None:
"""Test the UDP server runs and queues incoming data."""
@ -301,8 +302,8 @@ async def test_error_calls_handle_finished(
async def test_udp_server_multiple(
hass: HomeAssistant,
socket_enabled,
unused_udp_port_factory,
socket_enabled: None,
unused_udp_port_factory: Callable[[], int],
voice_assistant_udp_pipeline_v1: VoiceAssistantUDPPipeline,
) -> None:
"""Test that the UDP server raises an error if started twice."""
@ -324,8 +325,8 @@ async def test_udp_server_multiple(
async def test_udp_server_after_stopped(
hass: HomeAssistant,
socket_enabled,
unused_udp_port_factory,
socket_enabled: None,
unused_udp_port_factory: Callable[[], int],
voice_assistant_udp_pipeline_v1: VoiceAssistantUDPPipeline,
) -> None:
"""Test that the UDP server raises an error if started after stopped."""

View file

@ -1,5 +1,6 @@
"""The tests for Home Assistant frontend."""
from asyncio import AbstractEventLoop
from http import HTTPStatus
import re
from typing import Any
@ -25,7 +26,11 @@ from homeassistant.loader import async_get_integration
from homeassistant.setup import async_setup_component
from tests.common import MockUser, async_capture_events, async_fire_time_changed
from tests.typing import MockHAClientWebSocket, WebSocketGenerator
from tests.typing import (
ClientSessionGenerator,
MockHAClientWebSocket,
WebSocketGenerator,
)
MOCK_THEMES = {
"happy": {"primary-color": "red", "app-header-background-color": "blue"},
@ -84,7 +89,11 @@ async def frontend_themes(hass):
@pytest.fixture
def aiohttp_client(event_loop, aiohttp_client, socket_enabled):
def aiohttp_client(
event_loop: AbstractEventLoop,
aiohttp_client: ClientSessionGenerator,
socket_enabled: None,
) -> ClientSessionGenerator:
"""Return aiohttp_client and allow opening sockets."""
return aiohttp_client

View file

@ -1,10 +1,12 @@
"""The tests for the Google Assistant component."""
from asyncio import AbstractEventLoop
from http import HTTPStatus
import json
from unittest.mock import patch
from aiohttp.hdrs import AUTHORIZATION
from aiohttp.test_utils import TestClient
import pytest
from homeassistant import const, core, setup
@ -24,6 +26,8 @@ from homeassistant.helpers import entity_registry as er
from . import DEMO_DEVICES
from tests.typing import ClientSessionGenerator
API_PASSWORD = "test1234"
PROJECT_ID = "hasstest-1234"
@ -38,7 +42,11 @@ def auth_header(hass_access_token):
@pytest.fixture
def assistant_client(event_loop, hass, hass_client_no_auth):
def assistant_client(
event_loop: AbstractEventLoop,
hass: core.HomeAssistant,
hass_client_no_auth: ClientSessionGenerator,
) -> TestClient:
"""Create web client for the Google Assistant API."""
loop = event_loop
loop.run_until_complete(
@ -83,7 +91,9 @@ async def wanted_platforms_only() -> None:
@pytest.fixture
def hass_fixture(event_loop, hass):
def hass_fixture(
event_loop: AbstractEventLoop, hass: core.HomeAssistant
) -> core.HomeAssistant:
"""Set up a Home Assistant instance for these tests."""
loop = event_loop

View file

@ -322,8 +322,8 @@ async def test_api_ingress_panels(
)
async def test_api_headers(
aiohttp_raw_server, # 'aiohttp_raw_server' must be before 'hass'!
hass,
socket_enabled,
hass: HomeAssistant,
socket_enabled: None,
api_call: str,
method: Literal["GET", "POST"],
payload: Any,

View file

@ -1,7 +1,10 @@
"""HomeKit session fixtures."""
from asyncio import AbstractEventLoop
from collections.abc import Generator
from contextlib import suppress
import os
from typing import Any
from unittest.mock import patch
import pytest
@ -10,6 +13,7 @@ from homeassistant.components.device_tracker.legacy import YAML_DEVICES
from homeassistant.components.homekit.accessories import HomeDriver
from homeassistant.components.homekit.const import BRIDGE_NAME, EVENT_HOMEKIT_CHANGED
from homeassistant.components.homekit.iidmanager import AccessoryIIDStorage
from homeassistant.core import HomeAssistant
from tests.common import async_capture_events
@ -22,7 +26,9 @@ def iid_storage(hass):
@pytest.fixture
def run_driver(hass, event_loop, iid_storage):
def run_driver(
hass: HomeAssistant, event_loop: AbstractEventLoop, iid_storage: AccessoryIIDStorage
) -> Generator[HomeDriver, Any, None]:
"""Return a custom AccessoryDriver instance for HomeKit accessory init.
This mock does not mock async_stop, so the driver will not be stopped
@ -49,7 +55,9 @@ def run_driver(hass, event_loop, iid_storage):
@pytest.fixture
def hk_driver(hass, event_loop, iid_storage):
def hk_driver(
hass: HomeAssistant, event_loop: AbstractEventLoop, iid_storage: AccessoryIIDStorage
) -> Generator[HomeDriver, Any, None]:
"""Return a custom AccessoryDriver instance for HomeKit accessory init."""
with (
patch("pyhap.accessory_driver.AsyncZeroconf"),
@ -76,7 +84,12 @@ def hk_driver(hass, event_loop, iid_storage):
@pytest.fixture
def mock_hap(hass, event_loop, iid_storage, mock_zeroconf):
def mock_hap(
hass: HomeAssistant,
event_loop: AbstractEventLoop,
iid_storage: AccessoryIIDStorage,
mock_zeroconf: None,
) -> Generator[HomeDriver, Any, None]:
"""Return a custom AccessoryDriver instance for HomeKit accessory init."""
with (
patch("pyhap.accessory_driver.AsyncZeroconf"),

View file

@ -1,9 +1,17 @@
"""Test configuration for http."""
from asyncio import AbstractEventLoop
import pytest
from tests.typing import ClientSessionGenerator
@pytest.fixture
def aiohttp_client(event_loop, aiohttp_client, socket_enabled):
def aiohttp_client(
event_loop: AbstractEventLoop,
aiohttp_client: ClientSessionGenerator,
socket_enabled: None,
) -> ClientSessionGenerator:
"""Return aiohttp_client and allow opening sockets."""
return aiohttp_client

View file

@ -1,5 +1,6 @@
"""Test cors for the HTTP component."""
from asyncio import AbstractEventLoop
from http import HTTPStatus
from pathlib import Path
from unittest.mock import patch
@ -13,6 +14,7 @@ from aiohttp.hdrs import (
AUTHORIZATION,
ORIGIN,
)
from aiohttp.test_utils import TestClient
import pytest
from homeassistant.components.http.cors import setup_cors
@ -54,7 +56,9 @@ async def mock_handler(request):
@pytest.fixture
def client(event_loop, aiohttp_client):
def client(
event_loop: AbstractEventLoop, aiohttp_client: ClientSessionGenerator
) -> TestClient:
"""Fixture to set up a web.Application."""
app = web.Application()
setup_cors(app, [TRUSTED_ORIGIN])

View file

@ -1,6 +1,7 @@
"""The tests for the Home Assistant HTTP component."""
import asyncio
from collections.abc import Callable
from datetime import timedelta
from http import HTTPStatus
from ipaddress import ip_network
@ -85,7 +86,9 @@ class TestView(http.HomeAssistantView):
async def test_registering_view_while_running(
hass: HomeAssistant, aiohttp_client: ClientSessionGenerator, unused_tcp_port_factory
hass: HomeAssistant,
aiohttp_client: ClientSessionGenerator,
unused_tcp_port_factory: Callable[[], int],
) -> None:
"""Test that we can register a view while the server is running."""
await async_setup_component(
@ -465,7 +468,9 @@ async def test_cors_defaults(hass: HomeAssistant) -> None:
async def test_storing_config(
hass: HomeAssistant, aiohttp_client: ClientSessionGenerator, unused_tcp_port_factory
hass: HomeAssistant,
aiohttp_client: ClientSessionGenerator,
unused_tcp_port_factory: Callable[[], int],
) -> None:
"""Test that we store last working config."""
config = {

View file

@ -1,5 +1,7 @@
"""The tests for the image_processing component."""
from asyncio import AbstractEventLoop
from collections.abc import Callable
from unittest.mock import PropertyMock, patch
import pytest
@ -24,7 +26,11 @@ async def setup_homeassistant(hass: HomeAssistant):
@pytest.fixture
def aiohttp_unused_port_factory(event_loop, unused_tcp_port_factory, socket_enabled):
def aiohttp_unused_port_factory(
event_loop: AbstractEventLoop,
unused_tcp_port_factory: Callable[[], int],
socket_enabled: None,
) -> Callable[[], int]:
"""Return aiohttp_unused_port and allow opening sockets."""
return unused_tcp_port_factory

View file

@ -1,8 +1,10 @@
"""The tests the for Meraki device tracker."""
from asyncio import AbstractEventLoop
from http import HTTPStatus
import json
from aiohttp.test_utils import TestClient
import pytest
from homeassistant.components import device_tracker
@ -16,9 +18,15 @@ from homeassistant.const import CONF_PLATFORM
from homeassistant.core import HomeAssistant
from homeassistant.setup import async_setup_component
from tests.typing import ClientSessionGenerator
@pytest.fixture
def meraki_client(event_loop, hass, hass_client):
def meraki_client(
event_loop: AbstractEventLoop,
hass: HomeAssistant,
hass_client: ClientSessionGenerator,
) -> TestClient:
"""Meraki mock client."""
loop = event_loop

View file

@ -1,10 +1,13 @@
"""Test the motionEye camera."""
from asyncio import AbstractEventLoop
from collections.abc import Callable
import copy
from typing import Any, cast
from typing import cast
from unittest.mock import AsyncMock, Mock, call
from aiohttp import web
from aiohttp.test_utils import TestServer
from aiohttp.web_exceptions import HTTPBadGateway
from motioneye_client.client import (
MotionEyeClientError,
@ -63,7 +66,11 @@ from tests.common import async_fire_time_changed
@pytest.fixture
def aiohttp_server(event_loop, aiohttp_server, socket_enabled):
def aiohttp_server(
event_loop: AbstractEventLoop,
aiohttp_server: Callable[[], TestServer],
socket_enabled: None,
) -> Callable[[], TestServer]:
"""Return aiohttp_server and allow opening sockets."""
return aiohttp_server
@ -220,7 +227,7 @@ async def test_unload_camera(hass: HomeAssistant) -> None:
async def test_get_still_image_from_camera(
aiohttp_server: Any, hass: HomeAssistant
aiohttp_server: Callable[[], TestServer], hass: HomeAssistant
) -> None:
"""Test getting a still image."""
@ -261,7 +268,9 @@ async def test_get_still_image_from_camera(
assert image_handler.called
async def test_get_stream_from_camera(aiohttp_server: Any, hass: HomeAssistant) -> None:
async def test_get_stream_from_camera(
aiohttp_server: Callable[[], TestServer], hass: HomeAssistant
) -> None:
"""Test getting a stream."""
stream_handler = AsyncMock(return_value="")
@ -344,7 +353,7 @@ async def test_device_info(
async def test_camera_option_stream_url_template(
aiohttp_server: Any, hass: HomeAssistant
aiohttp_server: Callable[[], TestServer], hass: HomeAssistant
) -> None:
"""Verify camera with a stream URL template option."""
client = create_mock_motioneye_client()
@ -384,7 +393,7 @@ async def test_camera_option_stream_url_template(
async def test_get_stream_from_camera_with_broken_host(
aiohttp_server: Any, hass: HomeAssistant
aiohttp_server: Callable[[], TestServer], hass: HomeAssistant
) -> None:
"""Test getting a stream with a broken URL (no host)."""

View file

@ -2,6 +2,7 @@
from __future__ import annotations
from asyncio import AbstractEventLoop
from collections.abc import Generator
import copy
import shutil
@ -37,6 +38,7 @@ from .common import (
)
from tests.common import MockConfigEntry
from tests.typing import ClientSessionGenerator
FAKE_TOKEN = "some-token"
FAKE_REFRESH_TOKEN = "some-refresh-token"
@ -86,7 +88,11 @@ class FakeAuth(AbstractAuth):
@pytest.fixture
def aiohttp_client(event_loop, aiohttp_client, socket_enabled):
def aiohttp_client(
event_loop: AbstractEventLoop,
aiohttp_client: ClientSessionGenerator,
socket_enabled: None,
) -> ClientSessionGenerator:
"""Return aiohttp_client and allow opening sockets."""
return aiohttp_client

View file

@ -1,16 +1,24 @@
"""The tests for the rss_feed_api component."""
from asyncio import AbstractEventLoop
from http import HTTPStatus
from aiohttp.test_utils import TestClient
from defusedxml import ElementTree
import pytest
from homeassistant.core import HomeAssistant
from homeassistant.setup import async_setup_component
from tests.typing import ClientSessionGenerator
@pytest.fixture
def mock_http_client(event_loop, hass, hass_client):
def mock_http_client(
event_loop: AbstractEventLoop,
hass: HomeAssistant,
hass_client: ClientSessionGenerator,
) -> TestClient:
"""Set up test fixture."""
loop = event_loop
config = {

View file

@ -9,7 +9,7 @@ from homeassistant.components import voip
from homeassistant.core import HomeAssistant
async def test_create_sip_server(hass: HomeAssistant, socket_enabled) -> None:
async def test_create_sip_server(hass: HomeAssistant, socket_enabled: None) -> None:
"""Tests starting/stopping SIP server."""
result = await hass.config_entries.flow.async_init(
voip.DOMAIN, context={"source": config_entries.SOURCE_USER}

View file

@ -1,5 +1,6 @@
"""Test the auth script to manage local users."""
from asyncio import AbstractEventLoop
import logging
from typing import Any
from unittest.mock import Mock, patch
@ -125,7 +126,7 @@ async def test_change_password_invalid_user(
data.validate_login("invalid-user", "new-pass")
def test_parsing_args(event_loop) -> None:
def test_parsing_args(event_loop: AbstractEventLoop) -> None:
"""Test we parse args correctly."""
called = False

View file

@ -1,5 +1,6 @@
"""Test check_config script."""
from asyncio import AbstractEventLoop
import logging
from unittest.mock import patch
@ -55,7 +56,9 @@ def normalize_yaml_files(check_dict):
@pytest.mark.parametrize("hass_config_yaml", [BAD_CORE_CONFIG])
def test_bad_core_config(mock_is_file, event_loop, mock_hass_config_yaml: None) -> None:
def test_bad_core_config(
mock_is_file: None, event_loop: AbstractEventLoop, mock_hass_config_yaml: None
) -> None:
"""Test a bad core config setup."""
res = check_config.check(get_test_config_dir())
assert res["except"].keys() == {"homeassistant"}
@ -65,7 +68,7 @@ def test_bad_core_config(mock_is_file, event_loop, mock_hass_config_yaml: None)
@pytest.mark.parametrize("hass_config_yaml", [BASE_CONFIG + "light:\n platform: demo"])
def test_config_platform_valid(
mock_is_file, event_loop, mock_hass_config_yaml: None
mock_is_file: None, event_loop: AbstractEventLoop, mock_hass_config_yaml: None
) -> None:
"""Test a valid platform setup."""
res = check_config.check(get_test_config_dir())
@ -97,7 +100,11 @@ def test_config_platform_valid(
],
)
def test_component_platform_not_found(
mock_is_file, event_loop, mock_hass_config_yaml: None, platforms, error
mock_is_file: None,
event_loop: AbstractEventLoop,
mock_hass_config_yaml: None,
platforms: set[str],
error: str,
) -> None:
"""Test errors if component or platform not found."""
# Make sure they don't exist
@ -122,7 +129,9 @@ def test_component_platform_not_found(
}
],
)
def test_secrets(mock_is_file, event_loop, mock_hass_config_yaml: None) -> None:
def test_secrets(
mock_is_file: None, event_loop: AbstractEventLoop, mock_hass_config_yaml: None
) -> None:
"""Test secrets config checking method."""
res = check_config.check(get_test_config_dir(), True)
@ -151,7 +160,9 @@ def test_secrets(mock_is_file, event_loop, mock_hass_config_yaml: None) -> None:
@pytest.mark.parametrize(
"hass_config_yaml", [BASE_CONFIG + ' packages:\n p1:\n group: ["a"]']
)
def test_package_invalid(mock_is_file, event_loop, mock_hass_config_yaml: None) -> None:
def test_package_invalid(
mock_is_file: None, event_loop: AbstractEventLoop, mock_hass_config_yaml: None
) -> None:
"""Test an invalid package."""
res = check_config.check(get_test_config_dir())
@ -167,7 +178,9 @@ def test_package_invalid(mock_is_file, event_loop, mock_hass_config_yaml: None)
@pytest.mark.parametrize(
"hass_config_yaml", [BASE_CONFIG + "automation: !include no.yaml"]
)
def test_bootstrap_error(event_loop, mock_hass_config_yaml: None) -> None:
def test_bootstrap_error(
event_loop: AbstractEventLoop, mock_hass_config_yaml: None
) -> None:
"""Test a valid platform setup."""
res = check_config.check(get_test_config_dir(YAML_CONFIG_FILE))
err = res["except"].pop(check_config.ERROR_STR)

View file

@ -20,7 +20,7 @@ def test_sockets_disabled() -> None:
socket.socket()
def test_sockets_enabled(socket_enabled) -> None:
def test_sockets_enabled(socket_enabled: None) -> None:
"""Test we can't connect to an address different from 127.0.0.1."""
mysocket = socket.socket()
with pytest.raises(pytest_socket.SocketConnectBlockedError):