hass-core/homeassistant/components/bayesian/helpers.py
HarvsG 9d351a3c10
Improve typing and code quality in beyesian (#79603)
* strict typing

* Detail implication

* adds newline

* don't change indenting

* really dont change indenting

* Update homeassistant/components/bayesian/binary_sensor.py

Co-authored-by: epenet <6771947+epenet@users.noreply.github.com>

* typing in async_setup_platform() + remove arg

* less ambiguity

* mypy thinks Literal[False] otherwise

* clearer log

* don't use `and` assignments

* observations not values

* clarify can be None

* observation can't be none

* assert we have at least one

* make it clearer where we're using UUIDs

* remove unnecessary bool

Co-authored-by: epenet <6771947+epenet@users.noreply.github.com>

* Unnecessary None handling

Co-authored-by: epenet <6771947+epenet@users.noreply.github.com>

* Better type setting

Co-authored-by: epenet <6771947+epenet@users.noreply.github.com>

* Reccomended changes.

* remove if statement not needed

* Not strict until _TrackTemplateResultInfo fixed

Co-authored-by: epenet <6771947+epenet@users.noreply.github.com>
2022-10-07 22:23:25 +02:00

72 lines
2.2 KiB
Python

"""Helpers to deal with bayesian observations."""
from __future__ import annotations
from dataclasses import dataclass, field
import uuid
from homeassistant.const import (
CONF_ABOVE,
CONF_BELOW,
CONF_ENTITY_ID,
CONF_PLATFORM,
CONF_VALUE_TEMPLATE,
)
from homeassistant.helpers.template import Template
from .const import CONF_P_GIVEN_F, CONF_P_GIVEN_T, CONF_TO_STATE
@dataclass
class Observation:
"""Representation of a sensor or template observation.
Either entity_id or value_template should be non-None.
"""
entity_id: str | None
platform: str
prob_given_true: float
prob_given_false: float
to_state: str | None
above: float | None
below: float | None
value_template: Template | None
observed: bool | None = None
id: uuid.UUID = field(default_factory=uuid.uuid4)
def to_dict(self) -> dict[str, str | float | bool | None]:
"""Represent Class as a Dict for easier serialization."""
# Needed because dataclasses asdict() can't serialize Templates and ignores Properties.
dic = {
CONF_PLATFORM: self.platform,
CONF_ENTITY_ID: self.entity_id,
CONF_VALUE_TEMPLATE: self.template,
CONF_TO_STATE: self.to_state,
CONF_ABOVE: self.above,
CONF_BELOW: self.below,
CONF_P_GIVEN_T: self.prob_given_true,
CONF_P_GIVEN_F: self.prob_given_false,
"observed": self.observed,
}
for key, value in dic.copy().items():
if value is None:
del dic[key]
return dic
def is_mirror(self, other: Observation) -> bool:
"""Dectects whether given observation is a mirror of this one."""
return (
self.platform == other.platform
and round(self.prob_given_true + other.prob_given_true, 1) == 1
and round(self.prob_given_false + other.prob_given_false, 1) == 1
)
@property
def template(self) -> str | None:
"""Not all observations have templates and we want to get template strings."""
if self.value_template is not None:
return self.value_template.template
return None