Use PEP 695 for decorator typing with type aliases (2) (#117663)
This commit is contained in:
parent
d65437e347
commit
907b9c42e5
6 changed files with 41 additions and 55 deletions
|
@ -5,7 +5,7 @@ from __future__ import annotations
|
||||||
from collections.abc import Awaitable, Callable, Coroutine
|
from collections.abc import Awaitable, Callable, Coroutine
|
||||||
import functools
|
import functools
|
||||||
import logging
|
import logging
|
||||||
from typing import Any, Concatenate, ParamSpec, TypeVar
|
from typing import Any, Concatenate
|
||||||
|
|
||||||
import aiohttp
|
import aiohttp
|
||||||
from async_upnp_client.client import UpnpError
|
from async_upnp_client.client import UpnpError
|
||||||
|
@ -28,10 +28,6 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
from .const import ATTR_PIN_INDEX, DOMAIN, SERVICE_INVOKE_PIN
|
from .const import ATTR_PIN_INDEX, DOMAIN, SERVICE_INVOKE_PIN
|
||||||
|
|
||||||
_OpenhomeDeviceT = TypeVar("_OpenhomeDeviceT", bound="OpenhomeDevice")
|
|
||||||
_R = TypeVar("_R")
|
|
||||||
_P = ParamSpec("_P")
|
|
||||||
|
|
||||||
SUPPORT_OPENHOME = (
|
SUPPORT_OPENHOME = (
|
||||||
MediaPlayerEntityFeature.SELECT_SOURCE
|
MediaPlayerEntityFeature.SELECT_SOURCE
|
||||||
| MediaPlayerEntityFeature.TURN_OFF
|
| MediaPlayerEntityFeature.TURN_OFF
|
||||||
|
@ -65,13 +61,13 @@ async def async_setup_entry(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
_FuncType = Callable[Concatenate[_OpenhomeDeviceT, _P], Awaitable[_R]]
|
type _FuncType[_T, **_P, _R] = Callable[Concatenate[_T, _P], Awaitable[_R]]
|
||||||
_ReturnFuncType = Callable[
|
type _ReturnFuncType[_T, **_P, _R] = Callable[
|
||||||
Concatenate[_OpenhomeDeviceT, _P], Coroutine[Any, Any, _R | None]
|
Concatenate[_T, _P], Coroutine[Any, Any, _R | None]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def catch_request_errors() -> (
|
def catch_request_errors[_OpenhomeDeviceT: OpenhomeDevice, **_P, _R]() -> (
|
||||||
Callable[
|
Callable[
|
||||||
[_FuncType[_OpenhomeDeviceT, _P, _R]], _ReturnFuncType[_OpenhomeDeviceT, _P, _R]
|
[_FuncType[_OpenhomeDeviceT, _P, _R]], _ReturnFuncType[_OpenhomeDeviceT, _P, _R]
|
||||||
]
|
]
|
||||||
|
|
|
@ -12,7 +12,7 @@ from itertools import islice
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
from typing import TYPE_CHECKING, Any, Concatenate, NoReturn, ParamSpec, TypeVar
|
from typing import TYPE_CHECKING, Any, Concatenate, NoReturn
|
||||||
|
|
||||||
from awesomeversion import (
|
from awesomeversion import (
|
||||||
AwesomeVersion,
|
AwesomeVersion,
|
||||||
|
@ -61,9 +61,6 @@ if TYPE_CHECKING:
|
||||||
|
|
||||||
from . import Recorder
|
from . import Recorder
|
||||||
|
|
||||||
_RecorderT = TypeVar("_RecorderT", bound="Recorder")
|
|
||||||
_P = ParamSpec("_P")
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
RETRIES = 3
|
RETRIES = 3
|
||||||
|
@ -628,18 +625,20 @@ def _is_retryable_error(instance: Recorder, err: OperationalError) -> bool:
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
_FuncType = Callable[Concatenate[_RecorderT, _P], bool]
|
type _FuncType[_T, **_P, _R] = Callable[Concatenate[_T, _P], _R]
|
||||||
|
|
||||||
|
|
||||||
def retryable_database_job(
|
def retryable_database_job[_RecorderT: Recorder, **_P](
|
||||||
description: str,
|
description: str,
|
||||||
) -> Callable[[_FuncType[_RecorderT, _P]], _FuncType[_RecorderT, _P]]:
|
) -> Callable[[_FuncType[_RecorderT, _P, bool]], _FuncType[_RecorderT, _P, bool]]:
|
||||||
"""Try to execute a database job.
|
"""Try to execute a database job.
|
||||||
|
|
||||||
The job should return True if it finished, and False if it needs to be rescheduled.
|
The job should return True if it finished, and False if it needs to be rescheduled.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def decorator(job: _FuncType[_RecorderT, _P]) -> _FuncType[_RecorderT, _P]:
|
def decorator(
|
||||||
|
job: _FuncType[_RecorderT, _P, bool],
|
||||||
|
) -> _FuncType[_RecorderT, _P, bool]:
|
||||||
@functools.wraps(job)
|
@functools.wraps(job)
|
||||||
def wrapper(instance: _RecorderT, *args: _P.args, **kwargs: _P.kwargs) -> bool:
|
def wrapper(instance: _RecorderT, *args: _P.args, **kwargs: _P.kwargs) -> bool:
|
||||||
try:
|
try:
|
||||||
|
@ -664,12 +663,9 @@ def retryable_database_job(
|
||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
_WrappedFuncType = Callable[Concatenate[_RecorderT, _P], None]
|
def database_job_retry_wrapper[_RecorderT: Recorder, **_P](
|
||||||
|
|
||||||
|
|
||||||
def database_job_retry_wrapper(
|
|
||||||
description: str, attempts: int = 5
|
description: str, attempts: int = 5
|
||||||
) -> Callable[[_WrappedFuncType[_RecorderT, _P]], _WrappedFuncType[_RecorderT, _P]]:
|
) -> Callable[[_FuncType[_RecorderT, _P, None]], _FuncType[_RecorderT, _P, None]]:
|
||||||
"""Try to execute a database job multiple times.
|
"""Try to execute a database job multiple times.
|
||||||
|
|
||||||
This wrapper handles InnoDB deadlocks and lock timeouts.
|
This wrapper handles InnoDB deadlocks and lock timeouts.
|
||||||
|
@ -679,8 +675,8 @@ def database_job_retry_wrapper(
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def decorator(
|
def decorator(
|
||||||
job: _WrappedFuncType[_RecorderT, _P],
|
job: _FuncType[_RecorderT, _P, None],
|
||||||
) -> _WrappedFuncType[_RecorderT, _P]:
|
) -> _FuncType[_RecorderT, _P, None]:
|
||||||
@functools.wraps(job)
|
@functools.wraps(job)
|
||||||
def wrapper(instance: _RecorderT, *args: _P.args, **kwargs: _P.kwargs) -> None:
|
def wrapper(instance: _RecorderT, *args: _P.args, **kwargs: _P.kwargs) -> None:
|
||||||
for attempt in range(attempts):
|
for attempt in range(attempts):
|
||||||
|
|
|
@ -4,7 +4,7 @@ from __future__ import annotations
|
||||||
|
|
||||||
from collections.abc import Awaitable, Callable, Coroutine
|
from collections.abc import Awaitable, Callable, Coroutine
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
from typing import Any, Concatenate, ParamSpec, TypeVar
|
from typing import Any, Concatenate
|
||||||
|
|
||||||
from rokuecp import RokuConnectionError, RokuConnectionTimeoutError, RokuError
|
from rokuecp import RokuConnectionError, RokuConnectionTimeoutError, RokuError
|
||||||
|
|
||||||
|
@ -12,11 +12,10 @@ from homeassistant.exceptions import HomeAssistantError
|
||||||
|
|
||||||
from .entity import RokuEntity
|
from .entity import RokuEntity
|
||||||
|
|
||||||
_RokuEntityT = TypeVar("_RokuEntityT", bound=RokuEntity)
|
type _FuncType[_T, **_P] = Callable[Concatenate[_T, _P], Awaitable[Any]]
|
||||||
_P = ParamSpec("_P")
|
type _ReturnFuncType[_T, **_P] = Callable[
|
||||||
|
Concatenate[_T, _P], Coroutine[Any, Any, None]
|
||||||
_FuncType = Callable[Concatenate[_RokuEntityT, _P], Awaitable[Any]]
|
]
|
||||||
_ReturnFuncType = Callable[Concatenate[_RokuEntityT, _P], Coroutine[Any, Any, None]]
|
|
||||||
|
|
||||||
|
|
||||||
def format_channel_name(channel_number: str, channel_name: str | None = None) -> str:
|
def format_channel_name(channel_number: str, channel_name: str | None = None) -> str:
|
||||||
|
@ -27,7 +26,7 @@ def format_channel_name(channel_number: str, channel_name: str | None = None) ->
|
||||||
return channel_number
|
return channel_number
|
||||||
|
|
||||||
|
|
||||||
def roku_exception_handler(
|
def roku_exception_handler[_RokuEntityT: RokuEntity, **_P](
|
||||||
ignore_timeout: bool = False,
|
ignore_timeout: bool = False,
|
||||||
) -> Callable[[_FuncType[_RokuEntityT, _P]], _ReturnFuncType[_RokuEntityT, _P]]:
|
) -> Callable[[_FuncType[_RokuEntityT, _P]], _ReturnFuncType[_RokuEntityT, _P]]:
|
||||||
"""Decorate Roku calls to handle Roku exceptions."""
|
"""Decorate Roku calls to handle Roku exceptions."""
|
||||||
|
|
|
@ -4,7 +4,7 @@ from __future__ import annotations
|
||||||
|
|
||||||
from collections.abc import Callable
|
from collections.abc import Callable
|
||||||
import logging
|
import logging
|
||||||
from typing import TYPE_CHECKING, Any, Concatenate, ParamSpec, TypeVar, overload
|
from typing import TYPE_CHECKING, Any, Concatenate, overload
|
||||||
|
|
||||||
from requests.exceptions import Timeout
|
from requests.exceptions import Timeout
|
||||||
from soco import SoCo
|
from soco import SoCo
|
||||||
|
@ -26,29 +26,26 @@ UID_POSTFIX = "01400"
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
_T = TypeVar(
|
type _SonosEntitiesType = (
|
||||||
"_T", bound="SonosSpeaker | SonosMedia | SonosEntity | SonosHouseholdCoordinator"
|
SonosSpeaker | SonosMedia | SonosEntity | SonosHouseholdCoordinator
|
||||||
)
|
)
|
||||||
_R = TypeVar("_R")
|
type _FuncType[_T, **_P, _R] = Callable[Concatenate[_T, _P], _R]
|
||||||
_P = ParamSpec("_P")
|
type _ReturnFuncType[_T, **_P, _R] = Callable[Concatenate[_T, _P], _R | None]
|
||||||
|
|
||||||
_FuncType = Callable[Concatenate[_T, _P], _R]
|
|
||||||
_ReturnFuncType = Callable[Concatenate[_T, _P], _R | None]
|
|
||||||
|
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def soco_error(
|
def soco_error[_T: _SonosEntitiesType, **_P, _R](
|
||||||
errorcodes: None = ...,
|
errorcodes: None = ...,
|
||||||
) -> Callable[[_FuncType[_T, _P, _R]], _FuncType[_T, _P, _R]]: ...
|
) -> Callable[[_FuncType[_T, _P, _R]], _FuncType[_T, _P, _R]]: ...
|
||||||
|
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def soco_error(
|
def soco_error[_T: _SonosEntitiesType, **_P, _R](
|
||||||
errorcodes: list[str],
|
errorcodes: list[str],
|
||||||
) -> Callable[[_FuncType[_T, _P, _R]], _ReturnFuncType[_T, _P, _R]]: ...
|
) -> Callable[[_FuncType[_T, _P, _R]], _ReturnFuncType[_T, _P, _R]]: ...
|
||||||
|
|
||||||
|
|
||||||
def soco_error(
|
def soco_error[_T: _SonosEntitiesType, **_P, _R](
|
||||||
errorcodes: list[str] | None = None,
|
errorcodes: list[str] | None = None,
|
||||||
) -> Callable[[_FuncType[_T, _P, _R]], _ReturnFuncType[_T, _P, _R]]:
|
) -> Callable[[_FuncType[_T, _P, _R]], _ReturnFuncType[_T, _P, _R]]:
|
||||||
"""Filter out specified UPnP errors and raise exceptions for service calls."""
|
"""Filter out specified UPnP errors and raise exceptions for service calls."""
|
||||||
|
|
|
@ -7,7 +7,7 @@ import contextlib
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
import functools
|
import functools
|
||||||
import logging
|
import logging
|
||||||
from typing import TYPE_CHECKING, Any, ParamSpec, TypedDict
|
from typing import TYPE_CHECKING, Any, TypedDict
|
||||||
|
|
||||||
import zigpy.exceptions
|
import zigpy.exceptions
|
||||||
import zigpy.util
|
import zigpy.util
|
||||||
|
@ -51,10 +51,8 @@ _LOGGER = logging.getLogger(__name__)
|
||||||
RETRYABLE_REQUEST_DECORATOR = zigpy.util.retryable_request(tries=3)
|
RETRYABLE_REQUEST_DECORATOR = zigpy.util.retryable_request(tries=3)
|
||||||
UNPROXIED_CLUSTER_METHODS = {"general_command"}
|
UNPROXIED_CLUSTER_METHODS = {"general_command"}
|
||||||
|
|
||||||
|
type _FuncType[**_P] = Callable[_P, Awaitable[Any]]
|
||||||
_P = ParamSpec("_P")
|
type _ReturnFuncType[**_P] = Callable[_P, Coroutine[Any, Any, Any]]
|
||||||
_FuncType = Callable[_P, Awaitable[Any]]
|
|
||||||
_ReturnFuncType = Callable[_P, Coroutine[Any, Any, Any]]
|
|
||||||
|
|
||||||
|
|
||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
|
@ -75,7 +73,7 @@ def wrap_zigpy_exceptions() -> Iterator[None]:
|
||||||
raise HomeAssistantError(message) from exc
|
raise HomeAssistantError(message) from exc
|
||||||
|
|
||||||
|
|
||||||
def retry_request(func: _FuncType[_P]) -> _ReturnFuncType[_P]:
|
def retry_request[**_P](func: _FuncType[_P]) -> _ReturnFuncType[_P]:
|
||||||
"""Send a request with retries and wrap expected zigpy exceptions."""
|
"""Send a request with retries and wrap expected zigpy exceptions."""
|
||||||
|
|
||||||
@functools.wraps(func)
|
@functools.wraps(func)
|
||||||
|
|
|
@ -5,26 +5,26 @@ from __future__ import annotations
|
||||||
import asyncio
|
import asyncio
|
||||||
from collections.abc import Callable
|
from collections.abc import Callable
|
||||||
import functools
|
import functools
|
||||||
from typing import Any, TypeVar, cast, overload
|
from typing import Any, cast, overload
|
||||||
|
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.loader import bind_hass
|
from homeassistant.loader import bind_hass
|
||||||
from homeassistant.util.hass_dict import HassKey
|
from homeassistant.util.hass_dict import HassKey
|
||||||
|
|
||||||
_T = TypeVar("_T")
|
type _FuncType[_T] = Callable[[HomeAssistant], _T]
|
||||||
|
|
||||||
_FuncType = Callable[[HomeAssistant], _T]
|
|
||||||
|
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def singleton(data_key: HassKey[_T]) -> Callable[[_FuncType[_T]], _FuncType[_T]]: ...
|
def singleton[_T](
|
||||||
|
data_key: HassKey[_T],
|
||||||
|
) -> Callable[[_FuncType[_T]], _FuncType[_T]]: ...
|
||||||
|
|
||||||
|
|
||||||
@overload
|
@overload
|
||||||
def singleton(data_key: str) -> Callable[[_FuncType[_T]], _FuncType[_T]]: ...
|
def singleton[_T](data_key: str) -> Callable[[_FuncType[_T]], _FuncType[_T]]: ...
|
||||||
|
|
||||||
|
|
||||||
def singleton(data_key: Any) -> Callable[[_FuncType[_T]], _FuncType[_T]]:
|
def singleton[_T](data_key: Any) -> Callable[[_FuncType[_T]], _FuncType[_T]]:
|
||||||
"""Decorate a function that should be called once per instance.
|
"""Decorate a function that should be called once per instance.
|
||||||
|
|
||||||
Result will be cached and simultaneous calls will be handled.
|
Result will be cached and simultaneous calls will be handled.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue