Move attribution attribute to Entity base class (#57492)

pull/57503/head
Franck Nijhof 2021-10-11 23:15:32 +02:00 committed by GitHub
parent d10b1d9fe0
commit 13db867c1d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 47 additions and 46 deletions

View File

@ -5,7 +5,7 @@ from typing import Any, cast
from homeassistant.components.sensor import SensorEntity
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ATTR_ATTRIBUTION, CONF_NAME, DEVICE_CLASS_TEMPERATURE
from homeassistant.const import CONF_NAME, DEVICE_CLASS_TEMPERATURE
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import StateType
@ -59,6 +59,7 @@ async def async_setup_entry(
class AccuWeatherSensor(CoordinatorEntity, SensorEntity):
"""Define an AccuWeather entity."""
_attr_attribution = ATTRIBUTION
coordinator: AccuWeatherDataUpdateCoordinator
entity_description: AccuWeatherSensorDescription
@ -75,7 +76,7 @@ class AccuWeatherSensor(CoordinatorEntity, SensorEntity):
self._sensor_data = _get_sensor_data(
coordinator.data, forecast_day, description.key
)
self._attrs = {ATTR_ATTRIBUTION: ATTRIBUTION}
self._attrs: dict[str, Any] = {}
if forecast_day is not None:
self._attr_name = f"{name} {description.name} {forecast_day}d"
self._attr_unique_id = (

View File

@ -6,10 +6,7 @@ import logging
from typing import Final, final
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
ATTR_ATTRIBUTION,
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
)
from homeassistant.const import CONCENTRATION_MICROGRAMS_PER_CUBIC_METER
from homeassistant.core import HomeAssistant
from homeassistant.helpers.config_validation import ( # noqa: F401
PLATFORM_SCHEMA,
@ -41,7 +38,6 @@ SCAN_INTERVAL: Final = timedelta(seconds=30)
PROP_TO_ATTR: Final[dict[str, str]] = {
"air_quality_index": ATTR_AQI,
"attribution": ATTR_ATTRIBUTION,
"carbon_dioxide": ATTR_CO2,
"carbon_monoxide": ATTR_CO,
"nitrogen_oxide": ATTR_N2O,
@ -114,11 +110,6 @@ class AirQualityEntity(Entity):
"""Return the CO2 (carbon dioxide) level."""
return None
@property
def attribution(self) -> StateType:
"""Return the attribution."""
return None
@property
def sulphur_dioxide(self) -> StateType:
"""Return the SO2 (sulphur dioxide) level."""

View File

@ -18,7 +18,6 @@ from homeassistant.components.weather import (
ATTR_FORECAST_TIME,
ATTR_FORECAST_WIND_BEARING,
ATTR_FORECAST_WIND_SPEED,
ATTR_WEATHER_ATTRIBUTION,
ATTR_WEATHER_HUMIDITY,
ATTR_WEATHER_PRESSURE,
ATTR_WEATHER_TEMPERATURE,
@ -184,7 +183,6 @@ FORECAST_MAP = {
}
ATTR_MAP = {
ATTR_WEATHER_ATTRIBUTION: "attribution",
ATTR_WEATHER_HUMIDITY: "humidity",
ATTR_WEATHER_PRESSURE: "pressure",
ATTR_WEATHER_TEMPERATURE: "temperature",

View File

@ -47,7 +47,6 @@ ATTR_FORECAST_TEMP_LOW: Final = "templow"
ATTR_FORECAST_TIME: Final = "datetime"
ATTR_FORECAST_WIND_BEARING: Final = "wind_bearing"
ATTR_FORECAST_WIND_SPEED: Final = "wind_speed"
ATTR_WEATHER_ATTRIBUTION = "attribution"
ATTR_WEATHER_HUMIDITY = "humidity"
ATTR_WEATHER_OZONE = "ozone"
ATTR_WEATHER_PRESSURE = "pressure"
@ -107,7 +106,6 @@ class WeatherEntity(Entity):
"""ABC for weather data."""
entity_description: WeatherEntityDescription
_attr_attribution: str | None = None
_attr_condition: str | None
_attr_forecast: list[Forecast] | None = None
_attr_humidity: float | None = None
@ -156,11 +154,6 @@ class WeatherEntity(Entity):
"""Return the ozone level."""
return self._attr_ozone
@property
def attribution(self) -> str | None:
"""Return the attribution."""
return self._attr_attribution
@property
def visibility(self) -> float | None:
"""Return the visibility."""
@ -216,10 +209,6 @@ class WeatherEntity(Entity):
if visibility is not None:
data[ATTR_WEATHER_VISIBILITY] = visibility
attribution = self.attribution
if attribution is not None:
data[ATTR_WEATHER_ATTRIBUTION] = attribution
if self.forecast is not None:
forecast = []
for forecast_entry in self.forecast:

View File

@ -16,6 +16,7 @@ from typing import Any, TypedDict, final
from homeassistant.config import DATA_CUSTOMIZE
from homeassistant.const import (
ATTR_ASSUMED_STATE,
ATTR_ATTRIBUTION,
ATTR_DEVICE_CLASS,
ATTR_ENTITY_PICTURE,
ATTR_FRIENDLY_NAME,
@ -232,6 +233,7 @@ class Entity(ABC):
# Entity Properties
_attr_assumed_state: bool = False
_attr_attribution: str | None = None
_attr_available: bool = True
_attr_context_recent_time: timedelta = timedelta(seconds=5)
_attr_device_class: str | None
@ -397,6 +399,11 @@ class Entity(ABC):
return self.entity_description.entity_registry_enabled_default
return True
@property
def attribution(self) -> str | None:
"""Return the attribution."""
return self._attr_attribution
# DO NOT OVERWRITE
# These properties and methods are either managed by Home Assistant or they
# are used to perform a very specific function. Overwriting these may
@ -520,6 +527,9 @@ class Entity(ABC):
if (device_class := self.device_class) is not None:
attr[ATTR_DEVICE_CLASS] = str(device_class)
if (attribution := self.attribution) is not None:
attr[ATTR_ATTRIBUTION] = attribution
end = timer()
if end - start > 0.4 and not self._slow_reported:

View File

@ -1,11 +1,7 @@
"""The tests for the Air Quality component."""
from homeassistant.components.air_quality import (
ATTR_ATTRIBUTION,
ATTR_N2O,
ATTR_OZONE,
ATTR_PM_10,
)
from homeassistant.components.air_quality import ATTR_N2O, ATTR_OZONE, ATTR_PM_10
from homeassistant.const import (
ATTR_ATTRIBUTION,
ATTR_UNIT_OF_MEASUREMENT,
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
)

View File

@ -1,13 +1,13 @@
"""Tests for HomematicIP Cloud weather."""
from homeassistant.components.homematicip_cloud import DOMAIN as HMIPC_DOMAIN
from homeassistant.components.weather import (
ATTR_WEATHER_ATTRIBUTION,
ATTR_WEATHER_HUMIDITY,
ATTR_WEATHER_TEMPERATURE,
ATTR_WEATHER_WIND_BEARING,
ATTR_WEATHER_WIND_SPEED,
DOMAIN as WEATHER_DOMAIN,
)
from homeassistant.const import ATTR_ATTRIBUTION
from homeassistant.setup import async_setup_component
from .helper import async_manipulate_test_data, get_and_check_entity_basics
@ -38,7 +38,7 @@ async def test_hmip_weather_sensor(hass, default_mock_hap_factory):
assert ha_state.attributes[ATTR_WEATHER_TEMPERATURE] == 4.3
assert ha_state.attributes[ATTR_WEATHER_HUMIDITY] == 97
assert ha_state.attributes[ATTR_WEATHER_WIND_SPEED] == 15.0
assert ha_state.attributes[ATTR_WEATHER_ATTRIBUTION] == "Powered by Homematic IP"
assert ha_state.attributes[ATTR_ATTRIBUTION] == "Powered by Homematic IP"
await async_manipulate_test_data(hass, hmip_device, "actualTemperature", 12.1)
ha_state = hass.states.get(entity_id)
@ -63,7 +63,7 @@ async def test_hmip_weather_sensor_pro(hass, default_mock_hap_factory):
assert ha_state.attributes[ATTR_WEATHER_HUMIDITY] == 65
assert ha_state.attributes[ATTR_WEATHER_WIND_SPEED] == 2.6
assert ha_state.attributes[ATTR_WEATHER_WIND_BEARING] == 295.0
assert ha_state.attributes[ATTR_WEATHER_ATTRIBUTION] == "Powered by Homematic IP"
assert ha_state.attributes[ATTR_ATTRIBUTION] == "Powered by Homematic IP"
await async_manipulate_test_data(hass, hmip_device, "actualTemperature", 12.1)
ha_state = hass.states.get(entity_id)
@ -86,7 +86,7 @@ async def test_hmip_home_weather(hass, default_mock_hap_factory):
assert ha_state.attributes[ATTR_WEATHER_HUMIDITY] == 54
assert ha_state.attributes[ATTR_WEATHER_WIND_SPEED] == 8.6
assert ha_state.attributes[ATTR_WEATHER_WIND_BEARING] == 294
assert ha_state.attributes[ATTR_WEATHER_ATTRIBUTION] == "Powered by Homematic IP"
assert ha_state.attributes[ATTR_ATTRIBUTION] == "Powered by Homematic IP"
await async_manipulate_test_data(
hass, mock_hap.home.weather, "temperature", 28.3, fire_device=mock_hap.home

View File

@ -19,7 +19,6 @@ from homeassistant.components.weather import (
ATTR_FORECAST_TEMP,
ATTR_FORECAST_TEMP_LOW,
ATTR_FORECAST_TIME,
ATTR_WEATHER_ATTRIBUTION,
ATTR_WEATHER_HUMIDITY,
ATTR_WEATHER_PRESSURE,
ATTR_WEATHER_TEMPERATURE,
@ -27,7 +26,7 @@ from homeassistant.components.weather import (
ATTR_WEATHER_WIND_BEARING,
ATTR_WEATHER_WIND_SPEED,
)
from homeassistant.const import STATE_UNKNOWN
from homeassistant.const import ATTR_ATTRIBUTION, STATE_UNKNOWN
from homeassistant.core import HomeAssistant
from homeassistant.util.dt import utcnow
@ -60,7 +59,7 @@ async def test_setup_hass(
assert state.attributes[ATTR_SMHI_CLOUDINESS] == 50
assert state.attributes[ATTR_SMHI_THUNDER_PROBABILITY] == 33
assert state.attributes[ATTR_SMHI_WIND_GUST_SPEED] == 17
assert state.attributes[ATTR_WEATHER_ATTRIBUTION].find("SMHI") >= 0
assert state.attributes[ATTR_ATTRIBUTION].find("SMHI") >= 0
assert state.attributes[ATTR_WEATHER_HUMIDITY] == 55
assert state.attributes[ATTR_WEATHER_PRESSURE] == 1024
assert state.attributes[ATTR_WEATHER_TEMPERATURE] == 17
@ -94,9 +93,7 @@ async def test_properties_no_data(hass: HomeAssistant) -> None:
assert state
assert state.name == "test"
assert state.state == STATE_UNKNOWN
assert (
state.attributes[ATTR_WEATHER_ATTRIBUTION] == "Swedish weather institute (SMHI)"
)
assert state.attributes[ATTR_ATTRIBUTION] == "Swedish weather institute (SMHI)"
assert ATTR_WEATHER_HUMIDITY not in state.attributes
assert ATTR_WEATHER_PRESSURE not in state.attributes
assert ATTR_WEATHER_TEMPERATURE not in state.attributes

View File

@ -2,7 +2,6 @@
import pytest
from homeassistant.components.weather import (
ATTR_WEATHER_ATTRIBUTION,
ATTR_WEATHER_HUMIDITY,
ATTR_WEATHER_OZONE,
ATTR_WEATHER_PRESSURE,
@ -12,6 +11,7 @@ from homeassistant.components.weather import (
ATTR_WEATHER_WIND_SPEED,
DOMAIN,
)
from homeassistant.const import ATTR_ATTRIBUTION
@pytest.mark.parametrize("count,domain", [(1, DOMAIN)])
@ -44,7 +44,7 @@ async def test_template_state_text(hass, start_ha):
for attr, v_attr, value in [
(
"sensor.attribution",
ATTR_WEATHER_ATTRIBUTION,
ATTR_ATTRIBUTION,
"The custom attribution",
),
("sensor.temperature", ATTR_WEATHER_TEMPERATURE, 22.3),

View File

@ -7,7 +7,6 @@ from homeassistant.components.weather import (
ATTR_FORECAST_PRECIPITATION_PROBABILITY,
ATTR_FORECAST_TEMP,
ATTR_FORECAST_TEMP_LOW,
ATTR_WEATHER_ATTRIBUTION,
ATTR_WEATHER_HUMIDITY,
ATTR_WEATHER_OZONE,
ATTR_WEATHER_PRESSURE,
@ -15,6 +14,7 @@ from homeassistant.components.weather import (
ATTR_WEATHER_WIND_BEARING,
ATTR_WEATHER_WIND_SPEED,
)
from homeassistant.const import ATTR_ATTRIBUTION
from homeassistant.setup import async_setup_component
from homeassistant.util.unit_system import METRIC_SYSTEM
@ -39,7 +39,7 @@ async def test_attributes(hass):
assert data.get(ATTR_WEATHER_WIND_SPEED) == 0.5
assert data.get(ATTR_WEATHER_WIND_BEARING) is None
assert data.get(ATTR_WEATHER_OZONE) is None
assert data.get(ATTR_WEATHER_ATTRIBUTION) == "Powered by Home Assistant"
assert data.get(ATTR_ATTRIBUTION) == "Powered by Home Assistant"
assert data.get(ATTR_FORECAST)[0].get(ATTR_FORECAST_CONDITION) == "rainy"
assert data.get(ATTR_FORECAST)[0].get(ATTR_FORECAST_PRECIPITATION) == 1
assert data.get(ATTR_FORECAST)[0].get(ATTR_FORECAST_PRECIPITATION_PROBABILITY) == 60

View File

@ -7,7 +7,12 @@ from unittest.mock import MagicMock, PropertyMock, patch
import pytest
from homeassistant.const import ATTR_DEVICE_CLASS, STATE_UNAVAILABLE, STATE_UNKNOWN
from homeassistant.const import (
ATTR_ATTRIBUTION,
ATTR_DEVICE_CLASS,
STATE_UNAVAILABLE,
STATE_UNKNOWN,
)
from homeassistant.core import Context, HomeAssistantError
from homeassistant.helpers import entity, entity_registry
@ -790,3 +795,17 @@ async def test_float_conversion(hass):
state = hass.states.get("hello.world")
assert state is not None
assert state.state == "3.6"
async def test_attribution_attribute(hass):
"""Test attribution attribute."""
mock_entity = entity.Entity()
mock_entity.hass = hass
mock_entity.entity_id = "hello.world"
mock_entity._attr_attribution = "Home Assistant"
mock_entity.async_schedule_update_ha_state(True)
await hass.async_block_till_done()
state = hass.states.get(mock_entity.entity_id)
assert state.attributes.get(ATTR_ATTRIBUTION) == "Home Assistant"