From 342b406dc01a97d9aa65af55f251ba4d71bd6129 Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Tue, 7 Feb 2023 05:29:47 +0100 Subject: [PATCH] Add Self typing (1) [mypy 1.0] (#87598) --- homeassistant/backports/enum.py | 8 +++----- homeassistant/components/esphome/domain_data.py | 9 ++++----- homeassistant/components/recorder/db_schema.py | 11 ++++------- homeassistant/config_entries.py | 7 +++---- homeassistant/core.py | 6 ++---- homeassistant/helpers/restore_state.py | 8 ++++---- tests/components/recorder/db_schema_30.py | 9 +++------ 7 files changed, 23 insertions(+), 35 deletions(-) diff --git a/homeassistant/backports/enum.py b/homeassistant/backports/enum.py index bba54c51634..35562877bab 100644 --- a/homeassistant/backports/enum.py +++ b/homeassistant/backports/enum.py @@ -2,17 +2,15 @@ from __future__ import annotations from enum import Enum -from typing import Any, TypeVar +from typing import Any -_StrEnumSelfT = TypeVar("_StrEnumSelfT", bound="StrEnum") +from typing_extensions import Self class StrEnum(str, Enum): """Partial backport of Python 3.11's StrEnum for our basic use cases.""" - def __new__( - cls: type[_StrEnumSelfT], value: str, *args: Any, **kwargs: Any - ) -> _StrEnumSelfT: + def __new__(cls, value: str, *args: Any, **kwargs: Any) -> Self: """Create a new StrEnum instance.""" if not isinstance(value, str): raise TypeError(f"{value!r} is not a string") diff --git a/homeassistant/components/esphome/domain_data.py b/homeassistant/components/esphome/domain_data.py index 07029e2610a..32d2d1effff 100644 --- a/homeassistant/components/esphome/domain_data.py +++ b/homeassistant/components/esphome/domain_data.py @@ -3,10 +3,11 @@ from __future__ import annotations from collections.abc import MutableMapping from dataclasses import dataclass, field -from typing import TypeVar, cast +from typing import cast from bleak.backends.service import BleakGATTServiceCollection from lru import LRU # pylint: disable=no-name-in-module +from typing_extensions import Self from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant @@ -19,8 +20,6 @@ from .entry_data import RuntimeEntryData STORAGE_VERSION = 1 MAX_CACHED_SERVICES = 128 -_DomainDataSelfT = TypeVar("_DomainDataSelfT", bound="DomainData") - @dataclass class DomainData: @@ -94,10 +93,10 @@ class DomainData: ) @classmethod - def get(cls: type[_DomainDataSelfT], hass: HomeAssistant) -> _DomainDataSelfT: + def get(cls, hass: HomeAssistant) -> Self: """Get the global DomainData instance stored in hass.data.""" # Don't use setdefault - this is a hot code path if DOMAIN in hass.data: - return cast(_DomainDataSelfT, hass.data[DOMAIN]) + return cast(Self, hass.data[DOMAIN]) ret = hass.data[DOMAIN] = cls() return ret diff --git a/homeassistant/components/recorder/db_schema.py b/homeassistant/components/recorder/db_schema.py index dfbb83c495a..73f3c46f81a 100644 --- a/homeassistant/components/recorder/db_schema.py +++ b/homeassistant/components/recorder/db_schema.py @@ -5,7 +5,7 @@ from collections.abc import Callable from datetime import datetime, timedelta import logging import time -from typing import Any, TypeVar, cast +from typing import Any, cast import ciso8601 from fnvhash import fnv1a_32 @@ -30,6 +30,7 @@ from sqlalchemy.dialects import mysql, oracle, postgresql, sqlite from sqlalchemy.ext.declarative import declared_attr from sqlalchemy.orm import aliased, declarative_base, relationship from sqlalchemy.orm.session import Session +from typing_extensions import Self from homeassistant.const import ( MAX_LENGTH_EVENT_CONTEXT_ID, @@ -57,8 +58,6 @@ Base = declarative_base() SCHEMA_VERSION = 33 -_StatisticsBaseSelfT = TypeVar("_StatisticsBaseSelfT", bound="StatisticsBase") - _LOGGER = logging.getLogger(__name__) TABLE_EVENTS = "events" @@ -472,9 +471,7 @@ class StatisticsBase: sum = Column(DOUBLE_TYPE) @classmethod - def from_stats( - cls: type[_StatisticsBaseSelfT], metadata_id: int, stats: StatisticData - ) -> _StatisticsBaseSelfT: + def from_stats(cls, metadata_id: int, stats: StatisticData) -> Self: """Create object from a statistics.""" return cls( # type: ignore[call-arg,misc] metadata_id=metadata_id, @@ -576,7 +573,7 @@ class RecorderRuns(Base): # type: ignore[misc,valid-type] return [row[0] for row in query] - def to_native(self, validate_entity_id: bool = True) -> RecorderRuns: + def to_native(self, validate_entity_id: bool = True) -> Self: """Return self, native format is this model.""" return self diff --git a/homeassistant/config_entries.py b/homeassistant/config_entries.py index e127476073d..9ffd5afa478 100644 --- a/homeassistant/config_entries.py +++ b/homeassistant/config_entries.py @@ -14,6 +14,8 @@ from types import MappingProxyType, MethodType from typing import TYPE_CHECKING, Any, TypeVar, cast import weakref +from typing_extensions import Self + from . import data_entry_flow, loader from .backports.enum import StrEnum from .components import persistent_notification @@ -86,7 +88,6 @@ PATH_CONFIG = ".config_entries.json" SAVE_DELAY = 1 -_ConfigEntryStateSelfT = TypeVar("_ConfigEntryStateSelfT", bound="ConfigEntryState") _R = TypeVar("_R") @@ -110,9 +111,7 @@ class ConfigEntryState(Enum): _recoverable: bool - def __new__( - cls: type[_ConfigEntryStateSelfT], value: str, recoverable: bool - ) -> _ConfigEntryStateSelfT: + def __new__(cls, value: str, recoverable: bool) -> Self: """Create new ConfigEntryState.""" obj = object.__new__(cls) obj._value_ = value diff --git a/homeassistant/core.py b/homeassistant/core.py index ea3a57afe59..34d3dabc9a9 100644 --- a/homeassistant/core.py +++ b/homeassistant/core.py @@ -37,6 +37,7 @@ from typing import ( ) from urllib.parse import urlparse +from typing_extensions import Self import voluptuous as vol import yarl @@ -1075,9 +1076,6 @@ class EventBus: ) -_StateT = TypeVar("_StateT", bound="State") - - class State: """Object to represent a state within the state machine. @@ -1200,7 +1198,7 @@ class State: return compressed_state @classmethod - def from_dict(cls: type[_StateT], json_dict: dict[str, Any]) -> _StateT | None: + def from_dict(cls, json_dict: dict[str, Any]) -> Self | None: """Initialize a state from a dict. Async friendly. diff --git a/homeassistant/helpers/restore_state.py b/homeassistant/helpers/restore_state.py index 073d1879a82..d7e30661b38 100644 --- a/homeassistant/helpers/restore_state.py +++ b/homeassistant/helpers/restore_state.py @@ -5,7 +5,9 @@ from abc import ABC, abstractmethod import asyncio from datetime import datetime, timedelta import logging -from typing import Any, TypeVar, cast +from typing import Any, cast + +from typing_extensions import Self from homeassistant.const import ATTR_RESTORED, EVENT_HOMEASSISTANT_STOP from homeassistant.core import HomeAssistant, State, callback, valid_entity_id @@ -32,8 +34,6 @@ STATE_DUMP_INTERVAL = timedelta(minutes=15) # How long should a saved state be preserved if the entity no longer exists STATE_EXPIRATION = timedelta(days=7) -_StoredStateSelfT = TypeVar("_StoredStateSelfT", bound="StoredState") - class ExtraStoredData(ABC): """Object to hold extra stored data.""" @@ -82,7 +82,7 @@ class StoredState: return result @classmethod - def from_dict(cls: type[_StoredStateSelfT], json_dict: dict) -> _StoredStateSelfT: + def from_dict(cls, json_dict: dict) -> Self: """Initialize a stored state from a dict.""" extra_data_dict = json_dict.get("extra_data") extra_data = RestoredExtraData(extra_data_dict) if extra_data_dict else None diff --git a/tests/components/recorder/db_schema_30.py b/tests/components/recorder/db_schema_30.py index 01c31807ff7..451cc94d9fa 100644 --- a/tests/components/recorder/db_schema_30.py +++ b/tests/components/recorder/db_schema_30.py @@ -8,7 +8,7 @@ from __future__ import annotations from collections.abc import Callable from datetime import datetime, timedelta import logging -from typing import Any, TypedDict, TypeVar, cast, overload +from typing import Any, TypedDict, cast, overload import ciso8601 from fnvhash import fnv1a_32 @@ -33,6 +33,7 @@ from sqlalchemy.dialects import mysql, oracle, postgresql, sqlite from sqlalchemy.ext.declarative import declared_attr from sqlalchemy.orm import aliased, declarative_base, relationship from sqlalchemy.orm.session import Session +from typing_extensions import Self from homeassistant.components.recorder.const import SupportedDialect from homeassistant.const import ( @@ -62,8 +63,6 @@ Base = declarative_base() SCHEMA_VERSION = 30 -_StatisticsBaseSelfT = TypeVar("_StatisticsBaseSelfT", bound="StatisticsBase") - _LOGGER = logging.getLogger(__name__) TABLE_EVENTS = "events" @@ -497,9 +496,7 @@ class StatisticsBase: sum = Column(DOUBLE_TYPE) @classmethod - def from_stats( - cls: type[_StatisticsBaseSelfT], metadata_id: int, stats: StatisticData - ) -> _StatisticsBaseSelfT: + def from_stats(cls, metadata_id: int, stats: StatisticData) -> Self: """Create object from a statistics.""" return cls( # type: ignore[call-arg,misc] metadata_id=metadata_id,