Add abc.ABC to classes with abstract methods (#83546)

This commit is contained in:
Erik Montnemery 2022-12-08 17:50:36 +01:00 committed by GitHub
parent 7091781692
commit c4afc33fc5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 105 additions and 60 deletions

View File

@ -1,7 +1,7 @@
"""Base classes for HA Bluetooth scanners for bluetooth."""
from __future__ import annotations
from abc import abstractmethod
from abc import ABC, abstractmethod
from collections.abc import Callable, Generator
from contextlib import contextmanager
import datetime
@ -27,7 +27,7 @@ from .models import HaBluetoothConnector
MONOTONIC_TIME: Final = monotonic_time_coarse
class BaseHaScanner:
class BaseHaScanner(ABC):
"""Base class for Ha Scanners."""
__slots__ = ("hass", "source", "_connecting", "name", "scanning")

View File

@ -1,7 +1,7 @@
"""Update coordinator for the Bluetooth integration."""
from __future__ import annotations
from abc import abstractmethod
from abc import ABC, abstractmethod
import logging
from typing import cast
@ -19,7 +19,7 @@ from . import (
)
class BasePassiveBluetoothCoordinator:
class BasePassiveBluetoothCoordinator(ABC):
"""Base class for passive bluetooth coordinator for bluetooth advertisements.
The coordinator is responsible for tracking devices.

View File

@ -1,7 +1,7 @@
"""The dhcp integration."""
from __future__ import annotations
from abc import abstractmethod
from abc import ABC, abstractmethod
import asyncio
from collections.abc import Callable, Iterable
import contextlib
@ -115,7 +115,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
return True
class WatcherBase:
class WatcherBase(ABC):
"""Base class for dhcp and device tracker watching."""
def __init__(

View File

@ -1,7 +1,7 @@
"""Manage the Silicon Labs Multiprotocol add-on."""
from __future__ import annotations
from abc import abstractmethod
from abc import ABC, abstractmethod
import asyncio
import dataclasses
import logging
@ -71,7 +71,7 @@ def get_zigbee_socket(hass: HomeAssistant, addon_info: AddonInfo) -> str:
return f"socket://{addon_info.hostname}:9999"
class BaseMultiPanFlow(FlowHandler):
class BaseMultiPanFlow(FlowHandler, ABC):
"""Support configuring the Silicon Labs Multiprotocol add-on."""
def __init__(self) -> None:

View File

@ -1,5 +1,5 @@
"""Class to hold remote accessories."""
from abc import abstractmethod
from abc import ABC, abstractmethod
import logging
from pyhap.const import CATEGORY_TELEVISION
@ -75,7 +75,7 @@ REMOTE_KEYS = {
}
class RemoteInputSelectAccessory(HomeAccessory):
class RemoteInputSelectAccessory(HomeAccessory, ABC):
"""Generate a InputSelect accessory."""
def __init__(

View File

@ -1,7 +1,7 @@
"""Data update coordinator for the Jellyfin integration."""
from __future__ import annotations
from abc import abstractmethod
from abc import ABC, abstractmethod
from datetime import timedelta
from typing import Any, TypeVar, Union
@ -22,7 +22,7 @@ JellyfinDataT = TypeVar(
)
class JellyfinDataUpdateCoordinator(DataUpdateCoordinator[JellyfinDataT]):
class JellyfinDataUpdateCoordinator(DataUpdateCoordinator[JellyfinDataT], ABC):
"""Data update coordinator for the Jellyfin integration."""
config_entry: ConfigEntry

View File

@ -1,7 +1,7 @@
"""Data update coordinator for the Lidarr integration."""
from __future__ import annotations
from abc import abstractmethod
from abc import ABC, abstractmethod
from datetime import timedelta
from typing import Generic, TypeVar, Union, cast
@ -19,7 +19,7 @@ from .const import DEFAULT_MAX_RECORDS, DOMAIN, LOGGER
T = TypeVar("T", bound=Union[list[LidarrRootFolder], LidarrQueue, str, LidarrAlbum])
class LidarrDataUpdateCoordinator(DataUpdateCoordinator[T], Generic[T]):
class LidarrDataUpdateCoordinator(DataUpdateCoordinator[T], Generic[T], ABC):
"""Data update coordinator for the Lidarr integration."""
config_entry: ConfigEntry

View File

@ -1,7 +1,7 @@
"""MQTT component mixins and helpers."""
from __future__ import annotations
from abc import abstractmethod
from abc import ABC, abstractmethod
import asyncio
from collections.abc import Callable, Coroutine
from functools import partial
@ -662,7 +662,7 @@ async def async_clear_discovery_topic_if_entity_removed(
await async_remove_discovery_payload(hass, discovery_data)
class MqttDiscoveryDeviceUpdate:
class MqttDiscoveryDeviceUpdate(ABC):
"""Add support for auto discovery for platforms without an entity."""
def __init__(

View File

@ -1,7 +1,7 @@
"""The PrusaLink integration."""
from __future__ import annotations
from abc import abstractmethod
from abc import ABC, abstractmethod
from datetime import timedelta
import logging
from time import monotonic
@ -60,7 +60,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
T = TypeVar("T", PrinterInfo, JobInfo)
class PrusaLinkUpdateCoordinator(DataUpdateCoordinator, Generic[T]):
class PrusaLinkUpdateCoordinator(DataUpdateCoordinator, Generic[T], ABC):
"""Update coordinator for the printer."""
config_entry: ConfigEntry

View File

@ -1,7 +1,7 @@
"""Data update coordinator for the Radarr integration."""
from __future__ import annotations
from abc import abstractmethod
from abc import ABC, abstractmethod
from datetime import timedelta
from typing import Generic, TypeVar, Union, cast
@ -19,7 +19,7 @@ from .const import DOMAIN, LOGGER
T = TypeVar("T", bound=Union[SystemStatus, list[RootFolder], list[Health], int])
class RadarrDataUpdateCoordinator(DataUpdateCoordinator[T], Generic[T]):
class RadarrDataUpdateCoordinator(DataUpdateCoordinator[T], Generic[T], ABC):
"""Data update coordinator for the Radarr integration."""
config_entry: ConfigEntry

View File

@ -1,7 +1,7 @@
"""Provides the data update coordinators for SolarEdge."""
from __future__ import annotations
from abc import abstractmethod
from abc import ABC, abstractmethod
from datetime import date, datetime, timedelta
from typing import Any
@ -21,7 +21,7 @@ from .const import (
)
class SolarEdgeDataService:
class SolarEdgeDataService(ABC):
"""Get and update the latest data."""
coordinator: DataUpdateCoordinator

View File

@ -1,7 +1,7 @@
"""Config flow for Z-Wave JS integration."""
from __future__ import annotations
from abc import abstractmethod
from abc import ABC, abstractmethod
import asyncio
import logging
from typing import Any
@ -157,7 +157,7 @@ async def async_get_usb_ports(hass: HomeAssistant) -> dict[str, str]:
return await hass.async_add_executor_job(get_usb_ports)
class BaseZwaveJSFlow(FlowHandler):
class BaseZwaveJSFlow(FlowHandler, ABC):
"""Represent the base config flow for Z-Wave JS."""
def __init__(self) -> None:

View File

@ -211,7 +211,7 @@ class YamlCollection(ObservableCollection):
await self.notify_changes(change_sets)
class StorageCollection(ObservableCollection):
class StorageCollection(ObservableCollection, ABC):
"""Offer a CRUD interface on top of JSON storage."""
def __init__(

View File

@ -1,7 +1,7 @@
"""Support for restoring entity states on startup."""
from __future__ import annotations
from abc import abstractmethod
from abc import ABC, abstractmethod
import asyncio
from datetime import datetime, timedelta
import logging
@ -35,7 +35,7 @@ STATE_EXPIRATION = timedelta(days=7)
_StoredStateSelfT = TypeVar("_StoredStateSelfT", bound="StoredState")
class ExtraStoredData:
class ExtraStoredData(ABC):
"""Object to hold extra stored data."""
@abstractmethod

View File

@ -1,7 +1,7 @@
"""Helpers for creating schema based data entry flows."""
from __future__ import annotations
from abc import abstractmethod
from abc import ABC, abstractmethod
from collections.abc import Callable, Coroutine, Mapping
import copy
from dataclasses import dataclass
@ -250,7 +250,7 @@ class SchemaCommonFlowHandler:
)
class SchemaConfigFlowHandler(config_entries.ConfigFlow):
class SchemaConfigFlowHandler(config_entries.ConfigFlow, ABC):
"""Handle a schema based config flow."""
config_flow: Mapping[str, SchemaFlowStep]

View File

@ -17,6 +17,7 @@ from homeassistant.components.bluetooth import (
async_get_advertisement_callback,
models,
)
from homeassistant.components.bluetooth.base_scanner import BaseHaScanner
from homeassistant.components.bluetooth.manager import BluetoothManager
from homeassistant.core import HomeAssistant
from homeassistant.setup import async_setup_component
@ -223,3 +224,19 @@ class MockBleakClient(BleakClient):
async def clear_cache(self, *args, **kwargs):
"""Mock clear_cache."""
return True
class FakeScanner(BaseHaScanner):
"""Fake scanner."""
@property
def discovered_devices(self) -> list[BLEDevice]:
"""Return a list of discovered devices."""
return []
@property
def discovered_devices_and_advertisement_data(
self,
) -> dict[str, tuple[BLEDevice, AdvertisementData]]:
"""Return a list of discovered devices and their advertisement data."""
return {}

View File

@ -4,10 +4,9 @@ from datetime import timedelta
import time
from unittest.mock import patch
from bleak.backends.scanner import AdvertisementData, BLEDevice
from bleak.backends.scanner import BLEDevice
from homeassistant.components.bluetooth import (
BaseHaScanner,
async_register_scanner,
async_track_unavailable,
)
@ -22,6 +21,7 @@ from homeassistant.core import callback
from homeassistant.util import dt as dt_util
from . import (
FakeScanner,
generate_advertisement_data,
inject_advertisement_with_time_and_source,
inject_advertisement_with_time_and_source_connectable,
@ -304,16 +304,6 @@ async def test_advertisment_interval_longer_than_adapter_stack_timeout_adapter_c
)
switchbot_device_went_unavailable = False
class FakeScanner(BaseHaScanner):
"""Fake scanner."""
@property
def discovered_devices_and_advertisement_data(
self,
) -> dict[str, tuple[BLEDevice, AdvertisementData]]:
"""Return a list of discovered devices."""
return {}
scanner = FakeScanner(hass, "new", "fake_adapter")
cancel_scanner = async_register_scanner(hass, scanner, False)

View File

@ -2,13 +2,15 @@
from homeassistant.components import bluetooth
from homeassistant.components.bluetooth import BaseHaScanner, async_scanner_by_source
from homeassistant.components.bluetooth import async_scanner_by_source
from . import FakeScanner
async def test_scanner_by_source(hass, enable_bluetooth):
"""Test we can get a scanner by source."""
hci2_scanner = BaseHaScanner(hass, "hci2", "hci2")
hci2_scanner = FakeScanner(hass, "hci2", "hci2")
cancel_hci2 = bluetooth.async_register_scanner(hass, hci2_scanner, True)
assert async_scanner_by_source(hass, "hci2") is hci2_scanner

View File

@ -11,7 +11,6 @@ import pytest
from homeassistant.components import bluetooth
from homeassistant.components.bluetooth import (
BaseHaScanner,
BluetoothChange,
BluetoothScanningMode,
BluetoothServiceInfo,
@ -45,6 +44,7 @@ from homeassistant.setup import async_setup_component
from homeassistant.util import dt as dt_util
from . import (
FakeScanner,
_get_manager,
async_setup_with_default_adapter,
generate_advertisement_data,
@ -2649,7 +2649,7 @@ async def test_getting_the_scanner_returns_the_wrapped_instance(hass, enable_blu
async def test_scanner_count_connectable(hass, enable_bluetooth):
"""Test getting the connectable scanner count."""
scanner = BaseHaScanner(hass, "any", "any")
scanner = FakeScanner(hass, "any", "any")
cancel = bluetooth.async_register_scanner(hass, scanner, False)
assert bluetooth.async_scanner_count(hass, connectable=True) == 1
cancel()
@ -2657,7 +2657,7 @@ async def test_scanner_count_connectable(hass, enable_bluetooth):
async def test_scanner_count(hass, enable_bluetooth):
"""Test getting the connectable and non-connectable scanner count."""
scanner = BaseHaScanner(hass, "any", "any")
scanner = FakeScanner(hass, "any", "any")
cancel = bluetooth.async_register_scanner(hass, scanner, False)
assert bluetooth.async_scanner_count(hass, connectable=False) == 2
cancel()

View File

@ -8,7 +8,6 @@ from bluetooth_adapters import AdvertisementHistory
import pytest
from homeassistant.components import bluetooth
from homeassistant.components.bluetooth import BaseHaScanner
from homeassistant.components.bluetooth.manager import (
FALLBACK_MAXIMUM_STALE_ADVERTISEMENT_SECONDS,
)
@ -16,6 +15,7 @@ from homeassistant.core import HomeAssistant
from homeassistant.setup import async_setup_component
from . import (
FakeScanner,
generate_advertisement_data,
inject_advertisement_with_source,
inject_advertisement_with_time_and_source,
@ -26,7 +26,7 @@ from . import (
@pytest.fixture
def register_hci0_scanner(hass: HomeAssistant) -> None:
"""Register an hci0 scanner."""
hci0_scanner = BaseHaScanner(hass, "hci0", "hci0")
hci0_scanner = FakeScanner(hass, "hci0", "hci0")
cancel = bluetooth.async_register_scanner(hass, hci0_scanner, True)
yield
cancel()
@ -35,7 +35,7 @@ def register_hci0_scanner(hass: HomeAssistant) -> None:
@pytest.fixture
def register_hci1_scanner(hass: HomeAssistant) -> None:
"""Register an hci1 scanner."""
hci1_scanner = BaseHaScanner(hass, "hci1", "hci1")
hci1_scanner = FakeScanner(hass, "hci1", "hci1")
cancel = bluetooth.async_register_scanner(hass, hci1_scanner, True)
yield
cancel()
@ -418,7 +418,7 @@ async def test_switching_adapters_when_one_goes_away(
):
"""Test switching adapters when one goes away."""
cancel_hci2 = bluetooth.async_register_scanner(
hass, BaseHaScanner(hass, "hci2", "hci2"), True
hass, FakeScanner(hass, "hci2", "hci2"), True
)
address = "44:44:33:11:23:45"
@ -468,7 +468,7 @@ async def test_switching_adapters_when_one_stop_scanning(
hass, enable_bluetooth, register_hci0_scanner
):
"""Test switching adapters when stops scanning."""
hci2_scanner = BaseHaScanner(hass, "hci2", "hci2")
hci2_scanner = FakeScanner(hass, "hci2", "hci2")
cancel_hci2 = bluetooth.async_register_scanner(hass, hci2_scanner, True)
address = "44:44:33:11:23:45"

View File

@ -100,6 +100,11 @@ async def test_wrapped_bleak_client_set_disconnected_callback_after_connected(
)
class FakeScanner(BaseHaScanner):
@property
def discovered_devices(self) -> list[BLEDevice]:
"""Return a list of discovered devices."""
return []
@property
def discovered_devices_and_advertisement_data(
self,
@ -189,6 +194,11 @@ async def test_ble_device_with_proxy_clear_cache(hass, enable_bluetooth, one_ada
)
class FakeScanner(BaseHaScanner):
@property
def discovered_devices(self) -> list[BLEDevice]:
"""Return a list of discovered devices."""
return []
@property
def discovered_devices_and_advertisement_data(
self,
@ -290,6 +300,11 @@ async def test_ble_device_with_proxy_client_out_of_connections_uses_best_availab
)
class FakeScanner(BaseHaScanner):
@property
def discovered_devices(self) -> list[BLEDevice]:
"""Return a list of discovered devices."""
return []
@property
def discovered_devices_and_advertisement_data(
self,
@ -396,6 +411,11 @@ async def test_ble_device_with_proxy_client_out_of_connections_uses_best_availab
)
class FakeScanner(BaseHaScanner):
@property
def discovered_devices(self) -> list[BLEDevice]:
"""Return a list of discovered devices."""
return []
@property
def discovered_devices_and_advertisement_data(
self,

View File

@ -76,6 +76,10 @@ class TestOptionsFlow(silabs_multiprotocol_addon.OptionsFlowHandler):
"""Return the ZHA name."""
return "Test Multi-PAN"
def _hardware_name(self) -> str:
"""Return the name of the hardware."""
return "Test"
@pytest.fixture(autouse=True)
def config_flow_handler(

View File

@ -1,6 +1,7 @@
"""Tests for the schema based data entry flows."""
from __future__ import annotations
from collections.abc import Mapping
from typing import Any
from unittest.mock import patch
@ -8,7 +9,7 @@ import pytest
import voluptuous as vol
from homeassistant import config_entries, data_entry_flow
from homeassistant.core import HomeAssistant
from homeassistant.core import HomeAssistant, callback
from homeassistant.data_entry_flow import FlowResultType
from homeassistant.helpers import entity_registry as er
from homeassistant.helpers.schema_config_entry_flow import (
@ -27,6 +28,17 @@ from tests.common import MockConfigEntry, mock_platform
TEST_DOMAIN = "test"
class TestSchemaConfigFlowHandler(SchemaConfigFlowHandler):
"""Bare minimum SchemaConfigFlowHandler."""
config_flow = {}
@callback
def async_config_entry_title(self, options: Mapping[str, Any]) -> str:
"""Return config entry title."""
return "title"
@pytest.fixture(name="manager")
def manager_fixture():
"""Return a flow manager."""
@ -116,7 +128,7 @@ async def test_config_flow_advanced_option(
}
@manager.mock_reg_handler("test")
class TestFlow(SchemaConfigFlowHandler):
class TestFlow(TestSchemaConfigFlowHandler):
config_flow = CONFIG_FLOW
# Start flow in basic mode
@ -210,7 +222,7 @@ async def test_options_flow_advanced_option(
"init": SchemaFlowFormStep(OPTIONS_SCHEMA)
}
class TestFlow(SchemaConfigFlowHandler, domain="test"):
class TestFlow(TestSchemaConfigFlowHandler, domain="test"):
config_flow = {}
options_flow = OPTIONS_FLOW
@ -314,7 +326,7 @@ async def test_menu_step(hass: HomeAssistant) -> None:
"option4": SchemaFlowFormStep(vol.Schema({})),
}
class TestConfigFlow(SchemaConfigFlowHandler, domain=TEST_DOMAIN):
class TestConfigFlow(TestSchemaConfigFlowHandler, domain=TEST_DOMAIN):
"""Handle a config or options flow for Derivative."""
config_flow = CONFIG_FLOW
@ -363,7 +375,7 @@ async def test_schema_none(hass: HomeAssistant) -> None:
"option3": SchemaFlowFormStep(vol.Schema({})),
}
class TestConfigFlow(SchemaConfigFlowHandler, domain=TEST_DOMAIN):
class TestConfigFlow(TestSchemaConfigFlowHandler, domain=TEST_DOMAIN):
"""Handle a config or options flow for Derivative."""
config_flow = CONFIG_FLOW
@ -397,7 +409,7 @@ async def test_last_step(hass: HomeAssistant) -> None:
"step3": SchemaFlowFormStep(vol.Schema({}), next_step=None),
}
class TestConfigFlow(SchemaConfigFlowHandler, domain=TEST_DOMAIN):
class TestConfigFlow(TestSchemaConfigFlowHandler, domain=TEST_DOMAIN):
"""Handle a config or options flow for Derivative."""
config_flow = CONFIG_FLOW
@ -440,7 +452,7 @@ async def test_next_step_function(hass: HomeAssistant) -> None:
"step2": SchemaFlowFormStep(vol.Schema({}), next_step=_step2_next_step),
}
class TestConfigFlow(SchemaConfigFlowHandler, domain=TEST_DOMAIN):
class TestConfigFlow(TestSchemaConfigFlowHandler, domain=TEST_DOMAIN):
"""Handle a config or options flow for Derivative."""
config_flow = CONFIG_FLOW
@ -497,7 +509,7 @@ async def test_suggested_values(
),
}
class TestFlow(SchemaConfigFlowHandler, domain="test"):
class TestFlow(TestSchemaConfigFlowHandler, domain="test"):
config_flow = {}
options_flow = OPTIONS_FLOW
@ -608,7 +620,7 @@ async def test_options_flow_state(hass: HomeAssistant) -> None:
),
}
class TestFlow(SchemaConfigFlowHandler, domain="test"):
class TestFlow(TestSchemaConfigFlowHandler, domain="test"):
config_flow = {}
options_flow = OPTIONS_FLOW