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

View file

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

View file

@ -5,7 +5,6 @@ import asyncio
from collections import defaultdict
from collections.abc import Callable, Iterable
from datetime import timedelta
from functools import cached_property
from typing import Any, Generic, TypeVar
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.heatpump import HeatPump, Model, Series
from homeassistant.backports.functools import cached_property
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
CONF_IP_ADDRESS,

View file

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

View file

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

View file

@ -5,7 +5,6 @@ import asyncio
from collections.abc import Callable
from datetime import timedelta
from enum import Enum
from functools import cached_property
import logging
import random
import time
@ -23,6 +22,7 @@ from zigpy.zcl.clusters.general import Groups, Identify
from zigpy.zcl.foundation import Status as ZclStatus, ZCLCommandDef
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.core import HomeAssistant, callback
from homeassistant.exceptions import HomeAssistantError