Add new unit types for better type checking (#53124)

* Add new unit types
* Update helper functions
* Update components
* Update lcn climate
This commit is contained in:
Marc Mueller 2021-07-18 14:43:47 +02:00 committed by GitHub
parent 78f4a49b73
commit 71a8ae3016
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 254 additions and 152 deletions

View file

@ -18,6 +18,7 @@ from homeassistant.const import (
STATE_OFF, STATE_OFF,
STATE_ON, STATE_ON,
TEMP_CELSIUS, TEMP_CELSIUS,
UnitTemperatureT,
) )
from homeassistant.core import HomeAssistant, ServiceCall from homeassistant.core import HomeAssistant, ServiceCall
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
@ -195,7 +196,7 @@ class ClimateEntity(Entity):
_attr_target_temperature_low: float | None _attr_target_temperature_low: float | None
_attr_target_temperature_step: float | None = None _attr_target_temperature_step: float | None = None
_attr_target_temperature: float | None = None _attr_target_temperature: float | None = None
_attr_temperature_unit: str _attr_temperature_unit: UnitTemperatureT
@property @property
def state(self) -> str: def state(self) -> str:
@ -303,7 +304,7 @@ class ClimateEntity(Entity):
return data return data
@property @property
def temperature_unit(self) -> str: def temperature_unit(self) -> UnitTemperatureT:
"""Return the unit of measurement used by the platform.""" """Return the unit of measurement used by the platform."""
return self._attr_temperature_unit return self._attr_temperature_unit

View file

@ -19,6 +19,7 @@ from homeassistant.const import (
CONF_PLATFORM, CONF_PLATFORM,
CONF_TYPE, CONF_TYPE,
PERCENTAGE, PERCENTAGE,
UnitT,
) )
from homeassistant.core import CALLBACK_TYPE, HomeAssistant from homeassistant.core import CALLBACK_TYPE, HomeAssistant
from homeassistant.helpers import config_validation as cv, entity_registry from homeassistant.helpers import config_validation as cv, entity_registry
@ -172,6 +173,7 @@ async def async_get_trigger_capabilities(hass: HomeAssistant, config):
) )
} }
unit_of_measurement: UnitT
if trigger_type == "current_temperature_changed": if trigger_type == "current_temperature_changed":
unit_of_measurement = hass.config.units.temperature_unit unit_of_measurement = hass.config.units.temperature_unit
else: else:

View file

@ -11,7 +11,7 @@ from homeassistant.components.climate import (
ClimateEntity, ClimateEntity,
) )
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.const import PRECISION_HALVES, PRECISION_TENTHS from homeassistant.const import PRECISION_HALVES, PRECISION_TENTHS, UnitTemperatureT
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
@ -105,7 +105,7 @@ class DevoloClimateDeviceEntity(DevoloMultiLevelSwitchDeviceEntity, ClimateEntit
return SUPPORT_TARGET_TEMPERATURE return SUPPORT_TARGET_TEMPERATURE
@property @property
def temperature_unit(self) -> str: def temperature_unit(self) -> UnitTemperatureT:
"""Return the supported unit of temperature.""" """Return the supported unit of temperature."""
return TEMP_CELSIUS return TEMP_CELSIUS

View file

@ -65,6 +65,7 @@ from homeassistant.const import (
PRECISION_TENTHS, PRECISION_TENTHS,
PRECISION_WHOLE, PRECISION_WHOLE,
TEMP_CELSIUS, TEMP_CELSIUS,
UnitTemperatureT,
) )
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
@ -166,7 +167,7 @@ class EsphomeClimateEntity(EsphomeEntity[ClimateInfo, ClimateState], ClimateEnti
return PRECISION_TENTHS return PRECISION_TENTHS
@property @property
def temperature_unit(self) -> str: def temperature_unit(self) -> UnitTemperatureT:
"""Return the unit of measurement used by the platform.""" """Return the unit of measurement used by the platform."""
return TEMP_CELSIUS return TEMP_CELSIUS

View file

@ -23,6 +23,7 @@ from homeassistant.const import (
ATTR_UNIT_OF_MEASUREMENT, ATTR_UNIT_OF_MEASUREMENT,
PRECISION_HALVES, PRECISION_HALVES,
TEMP_CELSIUS, TEMP_CELSIUS,
UnitTemperatureT,
) )
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
@ -97,7 +98,7 @@ class FritzboxThermostat(FritzBoxEntity, ClimateEntity):
return self.device.present # type: ignore [no-any-return] return self.device.present # type: ignore [no-any-return]
@property @property
def temperature_unit(self) -> str: def temperature_unit(self) -> UnitTemperatureT:
"""Return the unit of measurement that is used.""" """Return the unit of measurement that is used."""
return TEMP_CELSIUS return TEMP_CELSIUS

View file

@ -18,6 +18,9 @@ from homeassistant.const import (
CONF_ENTITIES, CONF_ENTITIES,
CONF_SOURCE, CONF_SOURCE,
CONF_UNIT_OF_MEASUREMENT, CONF_UNIT_OF_MEASUREMENT,
TEMP_CELSIUS,
TEMP_FAHRENHEIT,
UnitTemperatureT,
) )
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import ConfigType, HomeAssistantType from homeassistant.helpers.typing import ConfigType, HomeAssistantType
@ -107,9 +110,12 @@ class LcnClimate(LcnEntity, ClimateEntity):
return const.SUPPORT_TARGET_TEMPERATURE return const.SUPPORT_TARGET_TEMPERATURE
@property @property
def temperature_unit(self) -> str: def temperature_unit(self) -> UnitTemperatureT:
"""Return the unit of measurement.""" """Return the unit of measurement."""
return cast(str, self.unit.value) # Config schema only allows for: TEMP_CELSIUS and TEMP_FAHRENHEIT
if self.unit == pypck.lcn_defs.VarUnit.FAHRENHEIT:
return TEMP_FAHRENHEIT
return TEMP_CELSIUS
@property @property
def current_temperature(self) -> float | None: def current_temperature(self) -> float | None:

View file

@ -19,7 +19,12 @@ from homeassistant.components.climate.const import (
) )
from homeassistant.components.mysensors.const import MYSENSORS_DISCOVERY, DiscoveryInfo from homeassistant.components.mysensors.const import MYSENSORS_DISCOVERY, DiscoveryInfo
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS, TEMP_FAHRENHEIT from homeassistant.const import (
ATTR_TEMPERATURE,
TEMP_CELSIUS,
TEMP_FAHRENHEIT,
UnitTemperatureT,
)
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
@ -91,7 +96,7 @@ class MySensorsHVAC(mysensors.device.MySensorsEntity, ClimateEntity):
return features return features
@property @property
def temperature_unit(self) -> str: def temperature_unit(self) -> UnitTemperatureT:
"""Return the unit of measurement.""" """Return the unit of measurement."""
return TEMP_CELSIUS if self.hass.config.units.is_metric else TEMP_FAHRENHEIT return TEMP_CELSIUS if self.hass.config.units.is_metric else TEMP_FAHRENHEIT

View file

@ -53,6 +53,7 @@ from homeassistant.const import (
PRECISION_TENTHS, PRECISION_TENTHS,
TEMP_CELSIUS, TEMP_CELSIUS,
TEMP_FAHRENHEIT, TEMP_FAHRENHEIT,
UnitTemperatureT,
) )
from homeassistant.core import HomeAssistant, callback from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.dispatcher import async_dispatcher_connect
@ -248,7 +249,7 @@ class ZWaveClimate(ZWaveBaseEntity, ClimateEntity):
return THERMOSTAT_MODE_SETPOINT_MAP.get(int(self._current_mode.value), []) # type: ignore return THERMOSTAT_MODE_SETPOINT_MAP.get(int(self._current_mode.value), []) # type: ignore
@property @property
def temperature_unit(self) -> str: def temperature_unit(self) -> UnitTemperatureT:
"""Return the unit of measurement used by the platform.""" """Return the unit of measurement used by the platform."""
if ( if (
self._unit_value self._unit_value

View file

@ -1,7 +1,7 @@
"""Constants used by Home Assistant components.""" """Constants used by Home Assistant components."""
from __future__ import annotations from __future__ import annotations
from typing import Final from typing import Final, NewType
MAJOR_VERSION: Final = 2021 MAJOR_VERSION: Final = 2021
MINOR_VERSION: Final = 8 MINOR_VERSION: Final = 8
@ -393,166 +393,212 @@ ATTR_DEVICE_CLASS: Final = "device_class"
# Temperature attribute # Temperature attribute
ATTR_TEMPERATURE: Final = "temperature" ATTR_TEMPERATURE: Final = "temperature"
# #### UNITS OF MEASUREMENT #### # #### UNITS OF MEASUREMENT ####
UnitT = NewType("UnitT", str)
# Power units # Power units
POWER_WATT: Final = "W" UnitPowerT = NewType("UnitPowerT", UnitT)
POWER_KILO_WATT: Final = "kW" POWER_WATT: Final[UnitPowerT] = UnitPowerT(UnitT("W"))
POWER_KILO_WATT: Final[UnitPowerT] = UnitPowerT(UnitT("kW"))
# Voltage units # Voltage units
VOLT: Final = "V" VOLT: Final[UnitT] = UnitT("V")
# Energy units # Energy units
ENERGY_WATT_HOUR: Final = "Wh" UnitEnergyT = NewType("UnitEnergyT", UnitT)
ENERGY_KILO_WATT_HOUR: Final = "kWh" ENERGY_WATT_HOUR: Final[UnitEnergyT] = UnitEnergyT(UnitT("Wh"))
ENERGY_KILO_WATT_HOUR: Final[UnitEnergyT] = UnitEnergyT(UnitT("kWh"))
# Electrical units # Electrical units
ELECTRICAL_CURRENT_AMPERE: Final = "A" ELECTRICAL_CURRENT_AMPERE: Final[UnitT] = UnitT("A")
ELECTRICAL_VOLT_AMPERE: Final = "VA" ELECTRICAL_VOLT_AMPERE: Final[UnitT] = UnitT("VA")
# Degree units # Degree units
DEGREE: Final = "°" DEGREE: Final[UnitT] = UnitT("°")
# Currency units # Currency units
CURRENCY_EURO: Final = "" UnitCurrencyT = NewType("UnitCurrencyT", UnitT)
CURRENCY_DOLLAR: Final = "$" CURRENCY_EURO: Final[UnitCurrencyT] = UnitCurrencyT(UnitT(""))
CURRENCY_CENT: Final = "¢" CURRENCY_DOLLAR: Final[UnitCurrencyT] = UnitCurrencyT(UnitT("$"))
CURRENCY_CENT: Final[UnitCurrencyT] = UnitCurrencyT(UnitT("¢"))
# Temperature units # Temperature units
TEMP_CELSIUS: Final = "°C" UnitTemperatureT = NewType("UnitTemperatureT", UnitT)
TEMP_FAHRENHEIT: Final = "°F" TEMP_CELSIUS: Final[UnitTemperatureT] = UnitTemperatureT(UnitT("°C"))
TEMP_KELVIN: Final = "K" TEMP_FAHRENHEIT: Final[UnitTemperatureT] = UnitTemperatureT(UnitT("°F"))
TEMP_KELVIN: Final[UnitTemperatureT] = UnitTemperatureT(UnitT("K"))
# Time units # Time units
TIME_MICROSECONDS: Final = "μs" UnitTimeT = NewType("UnitTimeT", UnitT)
TIME_MILLISECONDS: Final = "ms" TIME_MICROSECONDS: Final[UnitTimeT] = UnitTimeT(UnitT("μs"))
TIME_SECONDS: Final = "s" TIME_MILLISECONDS: Final[UnitTimeT] = UnitTimeT(UnitT("ms"))
TIME_MINUTES: Final = "min" TIME_SECONDS: Final[UnitTimeT] = UnitTimeT(UnitT("s"))
TIME_HOURS: Final = "h" TIME_MINUTES: Final[UnitTimeT] = UnitTimeT(UnitT("min"))
TIME_DAYS: Final = "d" TIME_HOURS: Final[UnitTimeT] = UnitTimeT(UnitT("h"))
TIME_WEEKS: Final = "w" TIME_DAYS: Final[UnitTimeT] = UnitTimeT(UnitT("d"))
TIME_MONTHS: Final = "m" TIME_WEEKS: Final[UnitTimeT] = UnitTimeT(UnitT("w"))
TIME_YEARS: Final = "y" TIME_MONTHS: Final[UnitTimeT] = UnitTimeT(UnitT("m"))
TIME_YEARS: Final[UnitTimeT] = UnitTimeT(UnitT("y"))
# Length units # Length units
LENGTH_MILLIMETERS: Final = "mm" UnitLengthT = NewType("UnitLengthT", UnitT)
LENGTH_CENTIMETERS: Final = "cm" LENGTH_MILLIMETERS: Final[UnitLengthT] = UnitLengthT(UnitT("mm"))
LENGTH_METERS: Final = "m" LENGTH_CENTIMETERS: Final[UnitLengthT] = UnitLengthT(UnitT("cm"))
LENGTH_KILOMETERS: Final = "km" LENGTH_METERS: Final[UnitLengthT] = UnitLengthT(UnitT("m"))
LENGTH_KILOMETERS: Final[UnitLengthT] = UnitLengthT(UnitT("km"))
LENGTH_INCHES: Final = "in" LENGTH_INCHES: Final[UnitLengthT] = UnitLengthT(UnitT("in"))
LENGTH_FEET: Final = "ft" LENGTH_FEET: Final[UnitLengthT] = UnitLengthT(UnitT("ft"))
LENGTH_YARD: Final = "yd" LENGTH_YARD: Final[UnitLengthT] = UnitLengthT(UnitT("yd"))
LENGTH_MILES: Final = "mi" LENGTH_MILES: Final[UnitLengthT] = UnitLengthT(UnitT("mi"))
# Frequency units # Frequency units
FREQUENCY_HERTZ: Final = "Hz" UnitFrequencyT = NewType("UnitFrequencyT", UnitT)
FREQUENCY_GIGAHERTZ: Final = "GHz" FREQUENCY_HERTZ: Final[UnitFrequencyT] = UnitFrequencyT(UnitT("Hz"))
FREQUENCY_GIGAHERTZ: Final[UnitFrequencyT] = UnitFrequencyT(UnitT("GHz"))
# Pressure units # Pressure units
PRESSURE_PA: Final = "Pa" UnitPressureT = NewType("UnitPressureT", UnitT)
PRESSURE_HPA: Final = "hPa" PRESSURE_PA: Final[UnitPressureT] = UnitPressureT(UnitT("Pa"))
PRESSURE_BAR: Final = "bar" PRESSURE_HPA: Final[UnitPressureT] = UnitPressureT(UnitT("hPa"))
PRESSURE_MBAR: Final = "mbar" PRESSURE_BAR: Final[UnitPressureT] = UnitPressureT(UnitT("bar"))
PRESSURE_INHG: Final = "inHg" PRESSURE_MBAR: Final[UnitPressureT] = UnitPressureT(UnitT("mbar"))
PRESSURE_PSI: Final = "psi" PRESSURE_INHG: Final[UnitPressureT] = UnitPressureT(UnitT("inHg"))
PRESSURE_PSI: Final[UnitPressureT] = UnitPressureT(UnitT("psi"))
# Volume units # Volume units
VOLUME_LITERS: Final = "L" UnitVolumeT = NewType("UnitVolumeT", UnitT)
VOLUME_MILLILITERS: Final = "mL" VOLUME_LITERS: Final[UnitVolumeT] = UnitVolumeT(UnitT("L"))
VOLUME_CUBIC_METERS: Final = "" VOLUME_MILLILITERS: Final[UnitVolumeT] = UnitVolumeT(UnitT("mL"))
VOLUME_CUBIC_FEET: Final = "ft³" VOLUME_CUBIC_METERS: Final[UnitVolumeT] = UnitVolumeT(UnitT(""))
VOLUME_CUBIC_FEET: Final[UnitVolumeT] = UnitVolumeT(UnitT("ft³"))
VOLUME_GALLONS: Final = "gal" VOLUME_GALLONS: Final[UnitVolumeT] = UnitVolumeT(UnitT("gal"))
VOLUME_FLUID_OUNCE: Final = "fl. oz." VOLUME_FLUID_OUNCE: Final[UnitVolumeT] = UnitVolumeT(UnitT("fl. oz."))
# Volume Flow Rate units # Volume Flow Rate units
VOLUME_FLOW_RATE_CUBIC_METERS_PER_HOUR: Final = "m³/h" UnitVolumeFlowT = NewType("UnitVolumeFlowT", UnitT)
VOLUME_FLOW_RATE_CUBIC_FEET_PER_MINUTE: Final = "ft³/m" VOLUME_FLOW_RATE_CUBIC_METERS_PER_HOUR: Final[UnitVolumeFlowT] = UnitVolumeFlowT(
UnitT("m³/h")
)
VOLUME_FLOW_RATE_CUBIC_FEET_PER_MINUTE: Final[UnitVolumeFlowT] = UnitVolumeFlowT(
UnitT("ft³/m")
)
# Area units # Area units
AREA_SQUARE_METERS: Final = "" UnitAreaT = NewType("UnitAreaT", UnitT)
AREA_SQUARE_METERS: Final[UnitAreaT] = UnitAreaT(UnitT(""))
# Mass units # Mass units
MASS_GRAMS: Final = "g" UnitMassT = NewType("UnitMassT", UnitT)
MASS_KILOGRAMS: Final = "kg" MASS_GRAMS: Final[UnitMassT] = UnitMassT(UnitT("g"))
MASS_MILLIGRAMS: Final = "mg" MASS_KILOGRAMS: Final[UnitMassT] = UnitMassT(UnitT("kg"))
MASS_MICROGRAMS: Final = "µg" MASS_MILLIGRAMS: Final[UnitMassT] = UnitMassT(UnitT("mg"))
MASS_MICROGRAMS: Final[UnitMassT] = UnitMassT(UnitT("µg"))
MASS_OUNCES: Final = "oz" MASS_OUNCES: Final[UnitMassT] = UnitMassT(UnitT("oz"))
MASS_POUNDS: Final = "lb" MASS_POUNDS: Final[UnitMassT] = UnitMassT(UnitT("lb"))
# Conductivity units # Conductivity units
CONDUCTIVITY: Final = "µS/cm" CONDUCTIVITY: Final[UnitT] = UnitT("µS/cm")
# Light units # Light units
LIGHT_LUX: Final = "lx" LIGHT_LUX: Final[UnitT] = UnitT("lx")
# UV Index units # UV Index units
UV_INDEX: Final = "UV index" UV_INDEX: Final[UnitT] = UnitT("UV index")
# Percentage units # Percentage units
PERCENTAGE: Final = "%" PERCENTAGE: Final[UnitT] = UnitT("%")
# Irradiation units # Irradiation units
IRRADIATION_WATTS_PER_SQUARE_METER: Final = "W/m²" UnitIrradiationT = NewType("UnitIrradiationT", UnitT)
IRRADIATION_BTUS_PER_HOUR_SQUARE_FOOT: Final = "BTU/(h×ft²)" IRRADIATION_WATTS_PER_SQUARE_METER: Final[UnitIrradiationT] = UnitIrradiationT(
UnitT("W/m²")
)
IRRADIATION_BTUS_PER_HOUR_SQUARE_FOOT: Final[UnitIrradiationT] = UnitIrradiationT(
UnitT("BTU/(h×ft²)")
)
# Precipitation units # Precipitation units
PRECIPITATION_MILLIMETERS_PER_HOUR: Final = "mm/h" PRECIPITATION_MILLIMETERS_PER_HOUR: Final[UnitT] = UnitT("mm/h")
# Concentration units # Concentration units
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER: Final = "µg/m³" UnitConcentrationT = NewType("UnitConcentrationT", UnitT)
CONCENTRATION_MILLIGRAMS_PER_CUBIC_METER: Final = "mg/m³" CONCENTRATION_MICROGRAMS_PER_CUBIC_METER: Final[
CONCENTRATION_MICROGRAMS_PER_CUBIC_FOOT: Final = "μg/ft³" UnitConcentrationT
CONCENTRATION_PARTS_PER_CUBIC_METER: Final = "p/m³" ] = UnitConcentrationT(UnitT("µg/m³"))
CONCENTRATION_PARTS_PER_MILLION: Final = "ppm" CONCENTRATION_MILLIGRAMS_PER_CUBIC_METER: Final[
CONCENTRATION_PARTS_PER_BILLION: Final = "ppb" UnitConcentrationT
] = UnitConcentrationT(UnitT("mg/m³"))
CONCENTRATION_MICROGRAMS_PER_CUBIC_FOOT: Final[UnitConcentrationT] = UnitConcentrationT(
UnitT("μg/ft³")
)
CONCENTRATION_PARTS_PER_CUBIC_METER: Final[UnitConcentrationT] = UnitConcentrationT(
UnitT("p/m³")
)
CONCENTRATION_PARTS_PER_MILLION: Final[UnitConcentrationT] = UnitConcentrationT(
UnitT("ppm")
)
CONCENTRATION_PARTS_PER_BILLION: Final[UnitConcentrationT] = UnitConcentrationT(
UnitT("ppb")
)
# Speed units # Speed units
SPEED_MILLIMETERS_PER_DAY: Final = "mm/d" UnitSpeedT = NewType("UnitSpeedT", UnitT)
SPEED_INCHES_PER_DAY: Final = "in/d" SPEED_MILLIMETERS_PER_DAY: Final[UnitSpeedT] = UnitSpeedT(UnitT("mm/d"))
SPEED_METERS_PER_SECOND: Final = "m/s" SPEED_INCHES_PER_DAY: Final[UnitSpeedT] = UnitSpeedT(UnitT("in/d"))
SPEED_INCHES_PER_HOUR: Final = "in/h" SPEED_METERS_PER_SECOND: Final[UnitSpeedT] = UnitSpeedT(UnitT("m/s"))
SPEED_KILOMETERS_PER_HOUR: Final = "km/h" SPEED_INCHES_PER_HOUR: Final[UnitSpeedT] = UnitSpeedT(UnitT("in/h"))
SPEED_MILES_PER_HOUR: Final = "mph" SPEED_KILOMETERS_PER_HOUR: Final[UnitSpeedT] = UnitSpeedT(UnitT("km/h"))
SPEED_MILES_PER_HOUR: Final[UnitSpeedT] = UnitSpeedT(UnitT("mph"))
# Signal_strength units # Signal_strength units
SIGNAL_STRENGTH_DECIBELS: Final = "dB" UnitSignalStrengthT = NewType("UnitSignalStrengthT", UnitT)
SIGNAL_STRENGTH_DECIBELS_MILLIWATT: Final = "dBm" SIGNAL_STRENGTH_DECIBELS: Final[UnitSignalStrengthT] = UnitSignalStrengthT(UnitT("dB"))
SIGNAL_STRENGTH_DECIBELS_MILLIWATT: Final[UnitSignalStrengthT] = UnitSignalStrengthT(
UnitT("dBm")
)
# Data units # Data units
DATA_BITS: Final = "bit" UnitDataT = NewType("UnitDataT", UnitT)
DATA_KILOBITS: Final = "kbit" DATA_BITS: Final[UnitDataT] = UnitDataT(UnitT("bit"))
DATA_MEGABITS: Final = "Mbit" DATA_KILOBITS: Final[UnitDataT] = UnitDataT(UnitT("kbit"))
DATA_GIGABITS: Final = "Gbit" DATA_MEGABITS: Final[UnitDataT] = UnitDataT(UnitT("Mbit"))
DATA_BYTES: Final = "B" DATA_GIGABITS: Final[UnitDataT] = UnitDataT(UnitT("Gbit"))
DATA_KILOBYTES: Final = "kB" DATA_BYTES: Final[UnitDataT] = UnitDataT(UnitT("B"))
DATA_MEGABYTES: Final = "MB" DATA_KILOBYTES: Final[UnitDataT] = UnitDataT(UnitT("kB"))
DATA_GIGABYTES: Final = "GB" DATA_MEGABYTES: Final[UnitDataT] = UnitDataT(UnitT("MB"))
DATA_TERABYTES: Final = "TB" DATA_GIGABYTES: Final[UnitDataT] = UnitDataT(UnitT("GB"))
DATA_PETABYTES: Final = "PB" DATA_TERABYTES: Final[UnitDataT] = UnitDataT(UnitT("TB"))
DATA_EXABYTES: Final = "EB" DATA_PETABYTES: Final[UnitDataT] = UnitDataT(UnitT("PB"))
DATA_ZETTABYTES: Final = "ZB" DATA_EXABYTES: Final[UnitDataT] = UnitDataT(UnitT("EB"))
DATA_YOTTABYTES: Final = "YB" DATA_ZETTABYTES: Final[UnitDataT] = UnitDataT(UnitT("ZB"))
DATA_KIBIBYTES: Final = "KiB" DATA_YOTTABYTES: Final[UnitDataT] = UnitDataT(UnitT("YB"))
DATA_MEBIBYTES: Final = "MiB" DATA_KIBIBYTES: Final[UnitDataT] = UnitDataT(UnitT("KiB"))
DATA_GIBIBYTES: Final = "GiB" DATA_MEBIBYTES: Final[UnitDataT] = UnitDataT(UnitT("MiB"))
DATA_TEBIBYTES: Final = "TiB" DATA_GIBIBYTES: Final[UnitDataT] = UnitDataT(UnitT("GiB"))
DATA_PEBIBYTES: Final = "PiB" DATA_TEBIBYTES: Final[UnitDataT] = UnitDataT(UnitT("TiB"))
DATA_EXBIBYTES: Final = "EiB" DATA_PEBIBYTES: Final[UnitDataT] = UnitDataT(UnitT("PiB"))
DATA_ZEBIBYTES: Final = "ZiB" DATA_EXBIBYTES: Final[UnitDataT] = UnitDataT(UnitT("EiB"))
DATA_YOBIBYTES: Final = "YiB" DATA_ZEBIBYTES: Final[UnitDataT] = UnitDataT(UnitT("ZiB"))
DATA_RATE_BITS_PER_SECOND: Final = "bit/s" DATA_YOBIBYTES: Final[UnitDataT] = UnitDataT(UnitT("YiB"))
DATA_RATE_KILOBITS_PER_SECOND: Final = "kbit/s"
DATA_RATE_MEGABITS_PER_SECOND: Final = "Mbit/s" # Data_rate units
DATA_RATE_GIGABITS_PER_SECOND: Final = "Gbit/s" UnitDataRateT = NewType("UnitDataRateT", UnitT)
DATA_RATE_BYTES_PER_SECOND: Final = "B/s" DATA_RATE_BITS_PER_SECOND: Final[UnitDataRateT] = UnitDataRateT(UnitT("bit/s"))
DATA_RATE_KILOBYTES_PER_SECOND: Final = "kB/s" DATA_RATE_KILOBITS_PER_SECOND: Final[UnitDataRateT] = UnitDataRateT(UnitT("kbit/s"))
DATA_RATE_MEGABYTES_PER_SECOND: Final = "MB/s" DATA_RATE_MEGABITS_PER_SECOND: Final[UnitDataRateT] = UnitDataRateT(UnitT("Mbit/s"))
DATA_RATE_GIGABYTES_PER_SECOND: Final = "GB/s" DATA_RATE_GIGABITS_PER_SECOND: Final[UnitDataRateT] = UnitDataRateT(UnitT("Gbit/s"))
DATA_RATE_KIBIBYTES_PER_SECOND: Final = "KiB/s" DATA_RATE_BYTES_PER_SECOND: Final[UnitDataRateT] = UnitDataRateT(UnitT("B/s"))
DATA_RATE_MEBIBYTES_PER_SECOND: Final = "MiB/s" DATA_RATE_KILOBYTES_PER_SECOND: Final[UnitDataRateT] = UnitDataRateT(UnitT("kB/s"))
DATA_RATE_GIBIBYTES_PER_SECOND: Final = "GiB/s" DATA_RATE_MEGABYTES_PER_SECOND: Final[UnitDataRateT] = UnitDataRateT(UnitT("MB/s"))
DATA_RATE_GIGABYTES_PER_SECOND: Final[UnitDataRateT] = UnitDataRateT(UnitT("GB/s"))
DATA_RATE_KIBIBYTES_PER_SECOND: Final[UnitDataRateT] = UnitDataRateT(UnitT("KiB/s"))
DATA_RATE_MEBIBYTES_PER_SECOND: Final[UnitDataRateT] = UnitDataRateT(UnitT("MiB/s"))
DATA_RATE_GIBIBYTES_PER_SECOND: Final[UnitDataRateT] = UnitDataRateT(UnitT("GiB/s"))
# #### SERVICES #### # #### SERVICES ####
SERVICE_HOMEASSISTANT_STOP: Final = "stop" SERVICE_HOMEASSISTANT_STOP: Final = "stop"
@ -653,13 +699,14 @@ RESTART_EXIT_CODE: Final = 100
UNIT_NOT_RECOGNIZED_TEMPLATE: Final = "{} is not a recognized {} unit." UNIT_NOT_RECOGNIZED_TEMPLATE: Final = "{} is not a recognized {} unit."
LENGTH: Final = "length" UnitTypeT = NewType("UnitTypeT", str)
MASS: Final = "mass" LENGTH: Final[UnitTypeT] = UnitTypeT("length")
PRESSURE: Final = "pressure" MASS: Final[UnitTypeT] = UnitTypeT("mass")
VOLUME: Final = "volume" PRESSURE: Final[UnitTypeT] = UnitTypeT("pressure")
TEMPERATURE: Final = "temperature" VOLUME: Final[UnitTypeT] = UnitTypeT("volume")
SPEED_MS: Final = "speed_ms" TEMPERATURE: Final[UnitTypeT] = UnitTypeT("temperature")
ILLUMINANCE: Final = "illuminance" SPEED_MS: Final[UnitTypeT] = UnitTypeT("speed_ms")
ILLUMINANCE: Final[UnitTypeT] = UnitTypeT("illuminance")
WEEKDAYS: Final[list[str]] = ["mon", "tue", "wed", "thu", "fri", "sat", "sun"] WEEKDAYS: Final[list[str]] = ["mon", "tue", "wed", "thu", "fri", "sat", "sun"]

View file

@ -3,13 +3,16 @@ from __future__ import annotations
from numbers import Number from numbers import Number
from homeassistant.const import PRECISION_HALVES, PRECISION_TENTHS from homeassistant.const import PRECISION_HALVES, PRECISION_TENTHS, UnitTemperatureT
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.util.temperature import convert as convert_temperature from homeassistant.util.temperature import convert as convert_temperature
def display_temp( def display_temp(
hass: HomeAssistant, temperature: float | None, unit: str, precision: float hass: HomeAssistant,
temperature: float | None,
unit: UnitTemperatureT,
precision: float,
) -> float | None: ) -> float | None:
"""Convert temperature into preferred units/precision for display.""" """Convert temperature into preferred units/precision for display."""
temperature_unit = unit temperature_unit = unit

View file

@ -15,9 +15,10 @@ from homeassistant.const import (
LENGTH_MILLIMETERS, LENGTH_MILLIMETERS,
LENGTH_YARD, LENGTH_YARD,
UNIT_NOT_RECOGNIZED_TEMPLATE, UNIT_NOT_RECOGNIZED_TEMPLATE,
UnitLengthT,
) )
VALID_UNITS = [ VALID_UNITS: tuple[UnitLengthT, ...] = (
LENGTH_KILOMETERS, LENGTH_KILOMETERS,
LENGTH_MILES, LENGTH_MILES,
LENGTH_FEET, LENGTH_FEET,
@ -26,9 +27,9 @@ VALID_UNITS = [
LENGTH_MILLIMETERS, LENGTH_MILLIMETERS,
LENGTH_INCHES, LENGTH_INCHES,
LENGTH_YARD, LENGTH_YARD,
] )
TO_METERS: dict[str, Callable[[float], float]] = { TO_METERS: dict[UnitLengthT, Callable[[float], float]] = {
LENGTH_METERS: lambda meters: meters, LENGTH_METERS: lambda meters: meters,
LENGTH_MILES: lambda miles: miles * 1609.344, LENGTH_MILES: lambda miles: miles * 1609.344,
LENGTH_YARD: lambda yards: yards * 0.9144, LENGTH_YARD: lambda yards: yards * 0.9144,
@ -39,7 +40,7 @@ TO_METERS: dict[str, Callable[[float], float]] = {
LENGTH_MILLIMETERS: lambda millimeters: millimeters * 0.001, LENGTH_MILLIMETERS: lambda millimeters: millimeters * 0.001,
} }
METERS_TO: dict[str, Callable[[float], float]] = { METERS_TO: dict[UnitLengthT, Callable[[float], float]] = {
LENGTH_METERS: lambda meters: meters, LENGTH_METERS: lambda meters: meters,
LENGTH_MILES: lambda meters: meters * 0.000621371, LENGTH_MILES: lambda meters: meters * 0.000621371,
LENGTH_YARD: lambda meters: meters * 1.09361, LENGTH_YARD: lambda meters: meters * 1.09361,
@ -51,7 +52,7 @@ METERS_TO: dict[str, Callable[[float], float]] = {
} }
def convert(value: float, unit_1: str, unit_2: str) -> float: def convert(value: float, unit_1: UnitLengthT, unit_2: UnitLengthT) -> float:
"""Convert one unit of measurement to another.""" """Convert one unit of measurement to another."""
if unit_1 not in VALID_UNITS: if unit_1 not in VALID_UNITS:
raise ValueError(UNIT_NOT_RECOGNIZED_TEMPLATE.format(unit_1, LENGTH)) raise ValueError(UNIT_NOT_RECOGNIZED_TEMPLATE.format(unit_1, LENGTH))

View file

@ -1,4 +1,6 @@
"""Pressure util functions.""" """Pressure util functions."""
from __future__ import annotations
from numbers import Number from numbers import Number
from homeassistant.const import ( from homeassistant.const import (
@ -9,11 +11,18 @@ from homeassistant.const import (
PRESSURE_PA, PRESSURE_PA,
PRESSURE_PSI, PRESSURE_PSI,
UNIT_NOT_RECOGNIZED_TEMPLATE, UNIT_NOT_RECOGNIZED_TEMPLATE,
UnitPressureT,
) )
VALID_UNITS = [PRESSURE_PA, PRESSURE_HPA, PRESSURE_MBAR, PRESSURE_INHG, PRESSURE_PSI] VALID_UNITS: tuple[UnitPressureT, ...] = (
PRESSURE_PA,
PRESSURE_HPA,
PRESSURE_MBAR,
PRESSURE_INHG,
PRESSURE_PSI,
)
UNIT_CONVERSION = { UNIT_CONVERSION: dict[UnitPressureT, float] = {
PRESSURE_PA: 1, PRESSURE_PA: 1,
PRESSURE_HPA: 1 / 100, PRESSURE_HPA: 1 / 100,
PRESSURE_MBAR: 1 / 100, PRESSURE_MBAR: 1 / 100,
@ -22,7 +31,7 @@ UNIT_CONVERSION = {
} }
def convert(value: float, unit_1: str, unit_2: str) -> float: def convert(value: float, unit_1: UnitPressureT, unit_2: UnitPressureT) -> float:
"""Convert one unit of measurement to another.""" """Convert one unit of measurement to another."""
if unit_1 not in VALID_UNITS: if unit_1 not in VALID_UNITS:
raise ValueError(UNIT_NOT_RECOGNIZED_TEMPLATE.format(unit_1, PRESSURE)) raise ValueError(UNIT_NOT_RECOGNIZED_TEMPLATE.format(unit_1, PRESSURE))

View file

@ -5,6 +5,7 @@ from homeassistant.const import (
TEMP_KELVIN, TEMP_KELVIN,
TEMPERATURE, TEMPERATURE,
UNIT_NOT_RECOGNIZED_TEMPLATE, UNIT_NOT_RECOGNIZED_TEMPLATE,
UnitTemperatureT,
) )
@ -37,7 +38,10 @@ def celsius_to_kelvin(celsius: float, interval: bool = False) -> float:
def convert( def convert(
temperature: float, from_unit: str, to_unit: str, interval: bool = False temperature: float,
from_unit: UnitTemperatureT,
to_unit: UnitTemperatureT,
interval: bool = False,
) -> float: ) -> float:
"""Convert a temperature from one unit to another.""" """Convert a temperature from one unit to another."""
if from_unit not in (TEMP_CELSIUS, TEMP_FAHRENHEIT, TEMP_KELVIN): if from_unit not in (TEMP_CELSIUS, TEMP_FAHRENHEIT, TEMP_KELVIN):

View file

@ -24,6 +24,13 @@ from homeassistant.const import (
VOLUME, VOLUME,
VOLUME_GALLONS, VOLUME_GALLONS,
VOLUME_LITERS, VOLUME_LITERS,
UnitLengthT,
UnitMassT,
UnitPressureT,
UnitT,
UnitTemperatureT,
UnitTypeT,
UnitVolumeT,
) )
from homeassistant.util import ( from homeassistant.util import (
distance as distance_util, distance as distance_util,
@ -36,17 +43,23 @@ from homeassistant.util import (
LENGTH_UNITS = distance_util.VALID_UNITS LENGTH_UNITS = distance_util.VALID_UNITS
MASS_UNITS = [MASS_POUNDS, MASS_OUNCES, MASS_KILOGRAMS, MASS_GRAMS] MASS_UNITS: tuple[UnitMassT, ...] = (
MASS_POUNDS,
MASS_OUNCES,
MASS_KILOGRAMS,
MASS_GRAMS,
)
PRESSURE_UNITS = pressure_util.VALID_UNITS PRESSURE_UNITS = pressure_util.VALID_UNITS
VOLUME_UNITS = volume_util.VALID_UNITS VOLUME_UNITS = volume_util.VALID_UNITS
TEMPERATURE_UNITS = [TEMP_FAHRENHEIT, TEMP_CELSIUS] TEMPERATURE_UNITS: tuple[UnitTemperatureT, ...] = (TEMP_FAHRENHEIT, TEMP_CELSIUS)
def is_valid_unit(unit: str, unit_type: str) -> bool: def is_valid_unit(unit: UnitT, unit_type: UnitTypeT) -> bool:
"""Check if the unit is valid for it's type.""" """Check if the unit is valid for it's type."""
units: tuple[UnitT, ...]
if unit_type == LENGTH: if unit_type == LENGTH:
units = LENGTH_UNITS units = LENGTH_UNITS
elif unit_type == TEMPERATURE: elif unit_type == TEMPERATURE:
@ -69,11 +82,11 @@ class UnitSystem:
def __init__( def __init__(
self, self,
name: str, name: str,
temperature: str, temperature: UnitTemperatureT,
length: str, length: UnitLengthT,
volume: str, volume: UnitVolumeT,
mass: str, mass: UnitMassT,
pressure: str, pressure: UnitPressureT,
) -> None: ) -> None:
"""Initialize the unit system object.""" """Initialize the unit system object."""
errors: str = ", ".join( errors: str = ", ".join(
@ -103,14 +116,14 @@ class UnitSystem:
"""Determine if this is the metric unit system.""" """Determine if this is the metric unit system."""
return self.name == CONF_UNIT_SYSTEM_METRIC return self.name == CONF_UNIT_SYSTEM_METRIC
def temperature(self, temperature: float, from_unit: str) -> float: def temperature(self, temperature: float, from_unit: UnitTemperatureT) -> float:
"""Convert the given temperature to this unit system.""" """Convert the given temperature to this unit system."""
if not isinstance(temperature, Number): if not isinstance(temperature, Number):
raise TypeError(f"{temperature!s} is not a numeric value.") raise TypeError(f"{temperature!s} is not a numeric value.")
return temperature_util.convert(temperature, from_unit, self.temperature_unit) return temperature_util.convert(temperature, from_unit, self.temperature_unit)
def length(self, length: float | None, from_unit: str) -> float: def length(self, length: float | None, from_unit: UnitLengthT) -> float:
"""Convert the given length to this unit system.""" """Convert the given length to this unit system."""
if not isinstance(length, Number): if not isinstance(length, Number):
raise TypeError(f"{length!s} is not a numeric value.") raise TypeError(f"{length!s} is not a numeric value.")
@ -120,7 +133,7 @@ class UnitSystem:
length, from_unit, self.length_unit length, from_unit, self.length_unit
) )
def pressure(self, pressure: float | None, from_unit: str) -> float: def pressure(self, pressure: float | None, from_unit: UnitPressureT) -> float:
"""Convert the given pressure to this unit system.""" """Convert the given pressure to this unit system."""
if not isinstance(pressure, Number): if not isinstance(pressure, Number):
raise TypeError(f"{pressure!s} is not a numeric value.") raise TypeError(f"{pressure!s} is not a numeric value.")
@ -130,7 +143,7 @@ class UnitSystem:
pressure, from_unit, self.pressure_unit pressure, from_unit, self.pressure_unit
) )
def volume(self, volume: float | None, from_unit: str) -> float: def volume(self, volume: float | None, from_unit: UnitVolumeT) -> float:
"""Convert the given volume to this unit system.""" """Convert the given volume to this unit system."""
if not isinstance(volume, Number): if not isinstance(volume, Number):
raise TypeError(f"{volume!s} is not a numeric value.") raise TypeError(f"{volume!s} is not a numeric value.")
@ -138,7 +151,7 @@ class UnitSystem:
# type ignore: https://github.com/python/mypy/issues/7207 # type ignore: https://github.com/python/mypy/issues/7207
return volume_util.convert(volume, from_unit, self.volume_unit) # type: ignore return volume_util.convert(volume, from_unit, self.volume_unit) # type: ignore
def as_dict(self) -> dict[str, str]: def as_dict(self) -> dict[str, UnitT]:
"""Convert the unit system to a dictionary.""" """Convert the unit system to a dictionary."""
return { return {
LENGTH: self.length_unit, LENGTH: self.length_unit,

View file

@ -1,4 +1,6 @@
"""Volume conversion util functions.""" """Volume conversion util functions."""
from __future__ import annotations
from numbers import Number from numbers import Number
from homeassistant.const import ( from homeassistant.const import (
@ -8,9 +10,15 @@ from homeassistant.const import (
VOLUME_GALLONS, VOLUME_GALLONS,
VOLUME_LITERS, VOLUME_LITERS,
VOLUME_MILLILITERS, VOLUME_MILLILITERS,
UnitVolumeT,
) )
VALID_UNITS = [VOLUME_LITERS, VOLUME_MILLILITERS, VOLUME_GALLONS, VOLUME_FLUID_OUNCE] VALID_UNITS: tuple[UnitVolumeT, ...] = (
VOLUME_LITERS,
VOLUME_MILLILITERS,
VOLUME_GALLONS,
VOLUME_FLUID_OUNCE,
)
def __liter_to_gallon(liter: float) -> float: def __liter_to_gallon(liter: float) -> float:
@ -23,7 +31,7 @@ def __gallon_to_liter(gallon: float) -> float:
return gallon * 3.785 return gallon * 3.785
def convert(volume: float, from_unit: str, to_unit: str) -> float: def convert(volume: float, from_unit: UnitVolumeT, to_unit: UnitVolumeT) -> float:
"""Convert a temperature from one unit to another.""" """Convert a temperature from one unit to another."""
if from_unit not in VALID_UNITS: if from_unit not in VALID_UNITS:
raise ValueError(UNIT_NOT_RECOGNIZED_TEMPLATE.format(from_unit, VOLUME)) raise ValueError(UNIT_NOT_RECOGNIZED_TEMPLATE.format(from_unit, VOLUME))