Prevent overriding cached attribute as property (#107657)
* Prevent overriding cached attribute as property * Remove debug
This commit is contained in:
parent
26da7402a2
commit
5b84e50dc0
2 changed files with 45 additions and 0 deletions
|
@ -13,6 +13,7 @@ import logging
|
||||||
import math
|
import math
|
||||||
import sys
|
import sys
|
||||||
from timeit import default_timer as timer
|
from timeit import default_timer as timer
|
||||||
|
from types import FunctionType
|
||||||
from typing import (
|
from typing import (
|
||||||
TYPE_CHECKING,
|
TYPE_CHECKING,
|
||||||
Any,
|
Any,
|
||||||
|
@ -374,6 +375,9 @@ class CachedProperties(type):
|
||||||
# Check if an _attr_ class attribute exits and move it to __attr_. We check
|
# Check if an _attr_ class attribute exits and move it to __attr_. We check
|
||||||
# __dict__ here because we don't care about _attr_ class attributes in parents.
|
# __dict__ here because we don't care about _attr_ class attributes in parents.
|
||||||
if attr_name in cls.__dict__:
|
if attr_name in cls.__dict__:
|
||||||
|
attr = getattr(cls, attr_name)
|
||||||
|
if isinstance(attr, (FunctionType, property)):
|
||||||
|
raise TypeError(f"Can't override {attr_name} in subclass")
|
||||||
setattr(cls, private_attr_name, getattr(cls, attr_name))
|
setattr(cls, private_attr_name, getattr(cls, attr_name))
|
||||||
annotations = cls.__annotations__
|
annotations = cls.__annotations__
|
||||||
if attr_name in annotations:
|
if attr_name in annotations:
|
||||||
|
|
|
@ -2039,6 +2039,47 @@ async def test_cached_entity_property_class_attribute(hass: HomeAssistant) -> No
|
||||||
assert getattr(ent[1], property) == values[0]
|
assert getattr(ent[1], property) == values[0]
|
||||||
|
|
||||||
|
|
||||||
|
async def test_cached_entity_property_override(hass: HomeAssistant) -> None:
|
||||||
|
"""Test overriding cached _attr_ raises."""
|
||||||
|
|
||||||
|
class EntityWithClassAttribute1(entity.Entity):
|
||||||
|
"""A derived class which overrides an _attr_ from a parent."""
|
||||||
|
|
||||||
|
_attr_attribution: str
|
||||||
|
|
||||||
|
class EntityWithClassAttribute2(entity.Entity):
|
||||||
|
"""A derived class which overrides an _attr_ from a parent."""
|
||||||
|
|
||||||
|
_attr_attribution = "blabla"
|
||||||
|
|
||||||
|
class EntityWithClassAttribute3(entity.Entity):
|
||||||
|
"""A derived class which overrides an _attr_ from a parent."""
|
||||||
|
|
||||||
|
_attr_attribution: str = "blabla"
|
||||||
|
|
||||||
|
class EntityWithClassAttribute4(entity.Entity):
|
||||||
|
@property
|
||||||
|
def _attr_not_cached(self):
|
||||||
|
return "blabla"
|
||||||
|
|
||||||
|
class EntityWithClassAttribute5(entity.Entity):
|
||||||
|
def _attr_not_cached(self):
|
||||||
|
return "blabla"
|
||||||
|
|
||||||
|
with pytest.raises(TypeError):
|
||||||
|
|
||||||
|
class EntityWithClassAttribute6(entity.Entity):
|
||||||
|
@property
|
||||||
|
def _attr_attribution(self):
|
||||||
|
return "🤡"
|
||||||
|
|
||||||
|
with pytest.raises(TypeError):
|
||||||
|
|
||||||
|
class EntityWithClassAttribute7(entity.Entity):
|
||||||
|
def _attr_attribution(self):
|
||||||
|
return "🤡"
|
||||||
|
|
||||||
|
|
||||||
async def test_entity_report_deprecated_supported_features_values(
|
async def test_entity_report_deprecated_supported_features_values(
|
||||||
caplog: pytest.LogCaptureFixture,
|
caplog: pytest.LogCaptureFixture,
|
||||||
) -> None:
|
) -> None:
|
||||||
|
|
Loading…
Add table
Reference in a new issue