Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove unnecessary functools.cached_property backport #114239

Merged
merged 2 commits into from
Apr 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 2 additions & 7 deletions homeassistant/auth/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
from __future__ import annotations

from datetime import datetime, timedelta
from functools import cached_property
import secrets
from typing import TYPE_CHECKING, Any, NamedTuple
from typing import Any, NamedTuple
import uuid

import attr
Expand All @@ -18,12 +19,6 @@
from . import permissions as perm_mdl
from .const import GROUP_ID_ADMIN

if TYPE_CHECKING:
from functools import cached_property
else:
from homeassistant.backports.functools import cached_property


TOKEN_TYPE_NORMAL = "normal"
TOKEN_TYPE_SYSTEM = "system"
TOKEN_TYPE_LONG_LIVED_ACCESS_TOKEN = "long_lived_access_token"
Expand Down
85 changes: 11 additions & 74 deletions homeassistant/backports/functools.py
Original file line number Diff line number Diff line change
@@ -1,79 +1,16 @@
"""Functools backports from standard lib."""
"""Functools backports from standard lib.

# This file contains parts of Python's module wrapper
# for the _functools C module
# to allow utilities written in Python to be added
# to the functools module.
# Written by Nick Coghlan <ncoghlan at gmail.com>,
# Raymond Hettinger <python at rcn.com>,
# and Łukasz Langa <lukasz at langa.pl>.
# Copyright © 2001-2023 Python Software Foundation; All Rights Reserved
This file contained the backport of the cached_property implementation of Python 3.12.

from __future__ import annotations

from collections.abc import Callable
from types import GenericAlias
from typing import Any, Generic, Self, TypeVar, overload

_T = TypeVar("_T")


class cached_property(Generic[_T]):
"""Backport of Python 3.12's cached_property.
Since we have dropped support for Python 3.11, we can remove this backport.
This file is kept for now to avoid breaking custom components that might
import it.
"""

Includes https://github.com/python/cpython/pull/101890/files
"""

def __init__(self, func: Callable[[Any], _T]) -> None:
"""Initialize."""
self.func: Callable[[Any], _T] = func
self.attrname: str | None = None
self.__doc__ = func.__doc__

def __set_name__(self, owner: type[Any], 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})."
)

@overload
def __get__(self, instance: None, owner: type[Any] | None = None) -> Self: ...

@overload
def __get__(self, instance: Any, owner: type[Any] | None = None) -> _T: ...
from __future__ import annotations

Check warning on line 10 in homeassistant/backports/functools.py

View check run for this annotation

Codecov / codecov/patch

homeassistant/backports/functools.py#L10

Added line #L10 was not covered by tests

def __get__(
self, instance: Any | None, owner: type[Any] | None = None
) -> _T | Self:
"""Get."""
if instance is None:
return 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
from functools import cached_property

Check warning on line 12 in homeassistant/backports/functools.py

View check run for this annotation

Codecov / codecov/patch

homeassistant/backports/functools.py#L12

Added line #L12 was not covered by tests
Copy link
Contributor

@edenhaus edenhaus Mar 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we do something similar to the deprecated const?

_DEPRECATED_SUPPORT_ALARM_ARM_VACATION: Final = DeprecatedConstantEnum(

__getattr__ = partial(check_if_deprecated_constant, module_globals=globals())
__dir__ = partial(
dir_with_deprecated_constants, module_globals_keys=[*globals().keys()]
)
__all__ = all_with_deprecated_constants(globals())

Importing and using a deprecated const will create a log entry

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That might be possible. For now I've copied the way from backports.enum and added a new entry for the hass_imports pylint plugin.

from __future__ import annotations
from enum import StrEnum
__all__ = [
"StrEnum",
]

Would it be fine if we explore your idea after this is merged?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it's fine to add it after this PR is merged. Maybe we can also add it for the enum one.
So we can remove the files et all after the deprecation period


__class_getitem__ = classmethod(GenericAlias) # type: ignore[var-annotated]
__all__ = [

Check warning on line 14 in homeassistant/backports/functools.py

View check run for this annotation

Codecov / codecov/patch

homeassistant/backports/functools.py#L14

Added line #L14 was not covered by tests
"cached_property",
]
9 changes: 2 additions & 7 deletions homeassistant/components/alarm_control_panel/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
from __future__ import annotations

from datetime import timedelta
from functools import partial
from functools import cached_property, partial
import logging
from typing import TYPE_CHECKING, Any, Final, final
from typing import Any, Final, final

import voluptuous as vol

Expand Down Expand Up @@ -50,11 +50,6 @@
CodeFormat,
)

if TYPE_CHECKING:
from functools import cached_property
else:
from homeassistant.backports.functools import cached_property

_LOGGER: Final = logging.getLogger(__name__)

SCAN_INTERVAL: Final = timedelta(seconds=30)
Expand Down
10 changes: 2 additions & 8 deletions homeassistant/components/automation/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
import asyncio
from collections.abc import Callable, Mapping
from dataclasses import dataclass
from functools import partial
from functools import cached_property, partial
import logging
from typing import TYPE_CHECKING, Any, Protocol, cast
from typing import Any, Protocol, cast

import voluptuous as vol

Expand Down Expand Up @@ -112,12 +112,6 @@
from .helpers import async_get_blueprints
from .trace import trace_automation

if TYPE_CHECKING:
from functools import cached_property
else:
from homeassistant.backports.functools import cached_property


ENTITY_ID_FORMAT = DOMAIN + ".{}"


Expand Down
9 changes: 2 additions & 7 deletions homeassistant/components/binary_sensor/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@

from datetime import timedelta
from enum import StrEnum
from functools import partial
from functools import cached_property, partial
import logging
from typing import TYPE_CHECKING, Literal, final
from typing import Literal, final

import voluptuous as vol

Expand All @@ -28,11 +28,6 @@
from homeassistant.helpers.entity_component import EntityComponent
from homeassistant.helpers.typing import ConfigType

if TYPE_CHECKING:
from functools import cached_property
else:
from homeassistant.backports.functools import cached_property

_LOGGER = logging.getLogger(__name__)


Expand Down
8 changes: 2 additions & 6 deletions homeassistant/components/button/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@

from datetime import timedelta
from enum import StrEnum
from functools import cached_property
import logging
from typing import TYPE_CHECKING, final
from typing import final

import voluptuous as vol

Expand All @@ -24,11 +25,6 @@

from .const import DOMAIN, SERVICE_PRESS

if TYPE_CHECKING:
from functools import cached_property
else:
from homeassistant.backports.functools import cached_property

SCAN_INTERVAL = timedelta(seconds=30)

ENTITY_ID_FORMAT = DOMAIN + ".{}"
Expand Down
9 changes: 2 additions & 7 deletions homeassistant/components/camera/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@
from dataclasses import asdict
from datetime import datetime, timedelta
from enum import IntFlag
from functools import partial
from functools import cached_property, partial
import logging
import os
from random import SystemRandom
import time
from typing import TYPE_CHECKING, Any, Final, cast, final
from typing import Any, Final, cast, final

from aiohttp import hdrs, web
import attr
Expand Down Expand Up @@ -85,11 +85,6 @@
from .img_util import scale_jpeg_camera_image
from .prefs import CameraPreferences, DynamicStreamSettings # noqa: F401

if TYPE_CHECKING:
from functools import cached_property
else:
from homeassistant.backports.functools import cached_property

_LOGGER = logging.getLogger(__name__)

SERVICE_ENABLE_MOTION: Final = "enable_motion_detection"
Expand Down
8 changes: 2 additions & 6 deletions homeassistant/components/climate/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
import asyncio
from datetime import timedelta
import functools as ft
from functools import cached_property
import logging
from typing import TYPE_CHECKING, Any, Literal, final
from typing import Any, Literal, final

import voluptuous as vol

Expand Down Expand Up @@ -117,11 +118,6 @@
HVACMode,
)

if TYPE_CHECKING:
from functools import cached_property
else:
from homeassistant.backports.functools import cached_property

DEFAULT_MIN_TEMP = 7
DEFAULT_MAX_TEMP = 35
DEFAULT_MIN_HUMIDITY = 30
Expand Down
8 changes: 2 additions & 6 deletions homeassistant/components/cover/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
from datetime import timedelta
from enum import IntFlag, StrEnum
import functools as ft
from functools import cached_property
import logging
from typing import TYPE_CHECKING, Any, ParamSpec, TypeVar, final
from typing import Any, ParamSpec, TypeVar, final

import voluptuous as vol

Expand Down Expand Up @@ -46,11 +47,6 @@

from . import group as group_pre_import # noqa: F401

if TYPE_CHECKING:
from functools import cached_property
else:
from homeassistant.backports.functools import cached_property

_LOGGER = logging.getLogger(__name__)

DOMAIN = "cover"
Expand Down
9 changes: 2 additions & 7 deletions homeassistant/components/date/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
from __future__ import annotations

from datetime import date, timedelta
from functools import cached_property
import logging
from typing import TYPE_CHECKING, final
from typing import final

import voluptuous as vol

Expand All @@ -22,12 +23,6 @@

from .const import DOMAIN, SERVICE_SET_VALUE

if TYPE_CHECKING:
from functools import cached_property
else:
from homeassistant.backports.functools import cached_property


SCAN_INTERVAL = timedelta(seconds=30)

ENTITY_ID_FORMAT = DOMAIN + ".{}"
Expand Down
8 changes: 2 additions & 6 deletions homeassistant/components/datetime/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
from __future__ import annotations

from datetime import UTC, datetime, timedelta
from functools import cached_property
import logging
from typing import TYPE_CHECKING, final
from typing import final

import voluptuous as vol

Expand All @@ -22,11 +23,6 @@

from .const import ATTR_DATETIME, DOMAIN, SERVICE_SET_VALUE

if TYPE_CHECKING:
from functools import cached_property
else:
from homeassistant.backports.functools import cached_property

SCAN_INTERVAL = timedelta(seconds=30)

ENTITY_ID_FORMAT = DOMAIN + ".{}"
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/device_tracker/legacy.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import asyncio
from collections.abc import Callable, Coroutine, Sequence
from datetime import datetime, timedelta
from functools import cached_property
import hashlib
from types import ModuleType
from typing import Any, Final, Protocol, final
Expand All @@ -13,7 +14,6 @@
import voluptuous as vol

from homeassistant import util
from homeassistant.backports.functools import cached_property
from homeassistant.components import zone
from homeassistant.components.zone import ENTITY_ID_HOME
from homeassistant.config import (
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/dlna_dms/dms.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from dataclasses import dataclass
from enum import StrEnum
import functools
from functools import cached_property
from typing import Any, TypeVar, cast

from async_upnp_client.aiohttp import AiohttpSessionRequester
Expand All @@ -17,7 +18,6 @@
from async_upnp_client.profiles.dlna import ContentDirectoryErrorCode, DmsDevice
from didl_lite import didl_lite

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
Expand Down
9 changes: 2 additions & 7 deletions homeassistant/components/event/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
from dataclasses import asdict, dataclass
from datetime import datetime, timedelta
from enum import StrEnum
from functools import cached_property
import logging
from typing import TYPE_CHECKING, Any, Self, final
from typing import Any, Self, final

from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
Expand All @@ -22,12 +23,6 @@

from .const import ATTR_EVENT_TYPE, ATTR_EVENT_TYPES, DOMAIN

if TYPE_CHECKING:
from functools import cached_property
else:
from homeassistant.backports.functools import cached_property


SCAN_INTERVAL = timedelta(seconds=30)

ENTITY_ID_FORMAT = DOMAIN + ".{}"
Expand Down
Loading