Add backport of cached_property from CPython 3.12 (#95292)

This commit is contained in:
Erik Montnemery 2023-06-26 23:23:07 +02:00 committed by GitHub
parent b02cb56988
commit a568885ad2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 70 additions and 7 deletions

View file

@ -0,0 +1,62 @@
"""Functools backports from standard lib."""
from __future__ import annotations
from collections.abc import Callable
from types import GenericAlias
from typing import Any, Generic, TypeVar, cast
_T = TypeVar("_T")
_R = TypeVar("_R")
class cached_property(Generic[_T, _R]): # pylint: disable=invalid-name
"""Backport of Python 3.12's cached_property.
Includes https://github.com/python/cpython/pull/101890/files
"""
def __init__(self, func: Callable[[_T], _R]) -> None:
"""Initialize."""
self.func = func
self.attrname: Any = None
self.__doc__ = func.__doc__
def __set_name__(self, owner: type[_T], name: str) -> None:
"""Set name."""
if self.attrname is None:
self.attrname = name
elif name != self.attrname:
raise TypeError(
"Cannot assign the same cached_property to two different names "
f"({self.attrname!r} and {name!r})."
)
def __get__(self, instance: _T | None, owner: type[_T] | None = None) -> _R:
"""Get."""
if instance is None:
return cast(_R, self)
if self.attrname is None:
raise TypeError(
"Cannot use cached_property instance without calling __set_name__ on it."
)
try:
cache = instance.__dict__
# not all objects have __dict__ (e.g. class defines slots)
except AttributeError:
msg = (
f"No '__dict__' attribute on {type(instance).__name__!r} "
f"instance to cache {self.attrname!r} property."
)
raise TypeError(msg) from None
val = self.func(instance)
try:
cache[self.attrname] = val
except TypeError:
msg = (
f"The '__dict__' attribute on {type(instance).__name__!r} instance "
f"does not support item assignment for caching {self.attrname!r} property."
)
raise TypeError(msg) from None
return val
__class_getitem__ = classmethod(GenericAlias)

View file

@ -16,6 +16,7 @@ from async_upnp_client.profiles.dlna import ContentDirectoryErrorCode, DmsDevice
from didl_lite import didl_lite from didl_lite import didl_lite
from homeassistant.backports.enum import StrEnum from homeassistant.backports.enum import StrEnum
from homeassistant.backports.functools import cached_property
from homeassistant.components import ssdp from homeassistant.components import ssdp
from homeassistant.components.media_player import BrowseError, MediaClass from homeassistant.components.media_player import BrowseError, MediaClass
from homeassistant.components.media_source.error import Unresolvable from homeassistant.components.media_source.error import Unresolvable
@ -619,7 +620,7 @@ class DmsDeviceSource:
"""Make an identifier for BrowseMediaSource.""" """Make an identifier for BrowseMediaSource."""
return f"{self.source_id}/{action}{object_id}" return f"{self.source_id}/{action}{object_id}"
@functools.cached_property @cached_property
def _sort_criteria(self) -> list[str]: def _sort_criteria(self) -> list[str]:
"""Return criteria to be used for sorting results. """Return criteria to be used for sorting results.

View file

@ -3,7 +3,6 @@ from __future__ import annotations
from collections import namedtuple from collections import namedtuple
from datetime import timedelta from datetime import timedelta
from functools import cached_property
import logging import logging
from typing import Any from typing import Any
@ -11,6 +10,7 @@ from fints.client import FinTS3PinTanClient
from fints.models import SEPAAccount from fints.models import SEPAAccount
import voluptuous as vol import voluptuous as vol
from homeassistant.backports.functools import cached_property
from homeassistant.components.sensor import PLATFORM_SCHEMA, SensorEntity from homeassistant.components.sensor import PLATFORM_SCHEMA, SensorEntity
from homeassistant.const import CONF_NAME, CONF_PIN, CONF_URL, CONF_USERNAME from homeassistant.const import CONF_NAME, CONF_PIN, CONF_URL, CONF_USERNAME
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant

View file

@ -5,7 +5,6 @@ import asyncio
from collections import defaultdict from collections import defaultdict
from collections.abc import Callable, Iterable from collections.abc import Callable, Iterable
from datetime import timedelta from datetime import timedelta
from functools import cached_property
from typing import Any, Generic, TypeVar from typing import Any, Generic, TypeVar
from nibe.coil import Coil, CoilData from nibe.coil import Coil, CoilData
@ -15,6 +14,7 @@ from nibe.connection.nibegw import NibeGW, ProductInfo
from nibe.exceptions import CoilNotFoundException, ReadException from nibe.exceptions import CoilNotFoundException, ReadException
from nibe.heatpump import HeatPump, Model, Series from nibe.heatpump import HeatPump, Model, Series
from homeassistant.backports.functools import cached_property
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ( from homeassistant.const import (
CONF_IP_ADDRESS, CONF_IP_ADDRESS,

View file

@ -3,13 +3,13 @@ from __future__ import annotations
import dataclasses import dataclasses
from datetime import datetime from datetime import datetime
from functools import cached_property
import logging import logging
from typing import Any, cast from typing import Any, cast
from python_otbr_api import tlv_parser from python_otbr_api import tlv_parser
from python_otbr_api.tlv_parser import MeshcopTLVType from python_otbr_api.tlv_parser import MeshcopTLVType
from homeassistant.backports.functools import cached_property
from homeassistant.core import HomeAssistant, callback from homeassistant.core import HomeAssistant, callback
from homeassistant.exceptions import HomeAssistantError from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.singleton import singleton from homeassistant.helpers.singleton import singleton

View file

@ -1,10 +1,10 @@
"""Lighting cluster handlers module for Zigbee Home Automation.""" """Lighting cluster handlers module for Zigbee Home Automation."""
from __future__ import annotations from __future__ import annotations
from functools import cached_property
from zigpy.zcl.clusters import lighting from zigpy.zcl.clusters import lighting
from homeassistant.backports.functools import cached_property
from .. import registries from .. import registries
from ..const import REPORT_CONFIG_DEFAULT from ..const import REPORT_CONFIG_DEFAULT
from . import AttrReportConfig, ClientClusterHandler, ClusterHandler from . import AttrReportConfig, ClientClusterHandler, ClusterHandler

View file

@ -5,7 +5,6 @@ import asyncio
from collections.abc import Callable from collections.abc import Callable
from datetime import timedelta from datetime import timedelta
from enum import Enum from enum import Enum
from functools import cached_property
import logging import logging
import random import random
import time import time
@ -23,6 +22,7 @@ from zigpy.zcl.clusters.general import Groups, Identify
from zigpy.zcl.foundation import Status as ZclStatus, ZCLCommandDef from zigpy.zcl.foundation import Status as ZclStatus, ZCLCommandDef
import zigpy.zdo.types as zdo_types import zigpy.zdo.types as zdo_types
from homeassistant.backports.functools import cached_property
from homeassistant.const import ATTR_COMMAND, ATTR_DEVICE_ID, ATTR_NAME from homeassistant.const import ATTR_COMMAND, ATTR_DEVICE_ID, ATTR_NAME
from homeassistant.core import HomeAssistant, callback from homeassistant.core import HomeAssistant, callback
from homeassistant.exceptions import HomeAssistantError from homeassistant.exceptions import HomeAssistantError