Enable unit conversion for DATA_SIZE (#84699)
parent
e693ba17e0
commit
6261994fcf
homeassistant
components/sensor
tests/util
|
@ -88,6 +88,7 @@ from homeassistant.util.unit_conversion import (
|
||||||
BaseUnitConverter,
|
BaseUnitConverter,
|
||||||
DataRateConverter,
|
DataRateConverter,
|
||||||
DistanceConverter,
|
DistanceConverter,
|
||||||
|
InformationConverter,
|
||||||
MassConverter,
|
MassConverter,
|
||||||
PressureConverter,
|
PressureConverter,
|
||||||
SpeedConverter,
|
SpeedConverter,
|
||||||
|
@ -468,6 +469,7 @@ STATE_CLASSES: Final[list[str]] = [cls.value for cls in SensorStateClass]
|
||||||
# `entity-registry-settings.ts`
|
# `entity-registry-settings.ts`
|
||||||
UNIT_CONVERTERS: dict[SensorDeviceClass | str | None, type[BaseUnitConverter]] = {
|
UNIT_CONVERTERS: dict[SensorDeviceClass | str | None, type[BaseUnitConverter]] = {
|
||||||
SensorDeviceClass.DATA_RATE: DataRateConverter,
|
SensorDeviceClass.DATA_RATE: DataRateConverter,
|
||||||
|
SensorDeviceClass.DATA_SIZE: InformationConverter,
|
||||||
SensorDeviceClass.DISTANCE: DistanceConverter,
|
SensorDeviceClass.DISTANCE: DistanceConverter,
|
||||||
SensorDeviceClass.GAS: VolumeConverter,
|
SensorDeviceClass.GAS: VolumeConverter,
|
||||||
SensorDeviceClass.PRECIPITATION: DistanceConverter,
|
SensorDeviceClass.PRECIPITATION: DistanceConverter,
|
||||||
|
|
|
@ -5,6 +5,7 @@ from homeassistant.const import (
|
||||||
UNIT_NOT_RECOGNIZED_TEMPLATE,
|
UNIT_NOT_RECOGNIZED_TEMPLATE,
|
||||||
UnitOfDataRate,
|
UnitOfDataRate,
|
||||||
UnitOfEnergy,
|
UnitOfEnergy,
|
||||||
|
UnitOfInformation,
|
||||||
UnitOfLength,
|
UnitOfLength,
|
||||||
UnitOfMass,
|
UnitOfMass,
|
||||||
UnitOfPower,
|
UnitOfPower,
|
||||||
|
@ -155,6 +156,38 @@ class EnergyConverter(BaseUnitConverter):
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class InformationConverter(BaseUnitConverter):
|
||||||
|
"""Utility to convert information values."""
|
||||||
|
|
||||||
|
UNIT_CLASS = "information"
|
||||||
|
NORMALIZED_UNIT = UnitOfInformation.BITS
|
||||||
|
# Units in terms of bits
|
||||||
|
_UNIT_CONVERSION: dict[str, float] = {
|
||||||
|
UnitOfInformation.BITS: 1,
|
||||||
|
UnitOfInformation.KILOBITS: 1 / 1e3,
|
||||||
|
UnitOfInformation.MEGABITS: 1 / 1e6,
|
||||||
|
UnitOfInformation.GIGABITS: 1 / 1e9,
|
||||||
|
UnitOfInformation.BYTES: 1 / 8,
|
||||||
|
UnitOfInformation.KILOBYTES: 1 / 8e3,
|
||||||
|
UnitOfInformation.MEGABYTES: 1 / 8e6,
|
||||||
|
UnitOfInformation.GIGABYTES: 1 / 8e9,
|
||||||
|
UnitOfInformation.TERABYTES: 1 / 8e12,
|
||||||
|
UnitOfInformation.PETABYTES: 1 / 8e15,
|
||||||
|
UnitOfInformation.EXABYTES: 1 / 8e18,
|
||||||
|
UnitOfInformation.ZETTABYTES: 1 / 8e21,
|
||||||
|
UnitOfInformation.YOTTABYTES: 1 / 8e24,
|
||||||
|
UnitOfInformation.KIBIBYTES: 1 / 2**13,
|
||||||
|
UnitOfInformation.MEBIBYTES: 1 / 2**23,
|
||||||
|
UnitOfInformation.GIBIBYTES: 1 / 2**33,
|
||||||
|
UnitOfInformation.TEBIBYTES: 1 / 2**43,
|
||||||
|
UnitOfInformation.PEBIBYTES: 1 / 2**53,
|
||||||
|
UnitOfInformation.EXBIBYTES: 1 / 2**63,
|
||||||
|
UnitOfInformation.ZEBIBYTES: 1 / 2**73,
|
||||||
|
UnitOfInformation.YOBIBYTES: 1 / 2**83,
|
||||||
|
}
|
||||||
|
VALID_UNITS = set(UnitOfInformation)
|
||||||
|
|
||||||
|
|
||||||
class MassConverter(BaseUnitConverter):
|
class MassConverter(BaseUnitConverter):
|
||||||
"""Utility to convert mass values."""
|
"""Utility to convert mass values."""
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ import pytest
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
UnitOfDataRate,
|
UnitOfDataRate,
|
||||||
UnitOfEnergy,
|
UnitOfEnergy,
|
||||||
|
UnitOfInformation,
|
||||||
UnitOfLength,
|
UnitOfLength,
|
||||||
UnitOfMass,
|
UnitOfMass,
|
||||||
UnitOfPower,
|
UnitOfPower,
|
||||||
|
@ -19,6 +20,7 @@ from homeassistant.util.unit_conversion import (
|
||||||
DataRateConverter,
|
DataRateConverter,
|
||||||
DistanceConverter,
|
DistanceConverter,
|
||||||
EnergyConverter,
|
EnergyConverter,
|
||||||
|
InformationConverter,
|
||||||
MassConverter,
|
MassConverter,
|
||||||
PowerConverter,
|
PowerConverter,
|
||||||
PressureConverter,
|
PressureConverter,
|
||||||
|
@ -46,6 +48,7 @@ INVALID_SYMBOL = "bob"
|
||||||
(EnergyConverter, UnitOfEnergy.KILO_WATT_HOUR),
|
(EnergyConverter, UnitOfEnergy.KILO_WATT_HOUR),
|
||||||
(EnergyConverter, UnitOfEnergy.MEGA_WATT_HOUR),
|
(EnergyConverter, UnitOfEnergy.MEGA_WATT_HOUR),
|
||||||
(EnergyConverter, UnitOfEnergy.GIGA_JOULE),
|
(EnergyConverter, UnitOfEnergy.GIGA_JOULE),
|
||||||
|
(InformationConverter, UnitOfInformation.GIGABYTES),
|
||||||
(MassConverter, UnitOfMass.GRAMS),
|
(MassConverter, UnitOfMass.GRAMS),
|
||||||
(MassConverter, UnitOfMass.KILOGRAMS),
|
(MassConverter, UnitOfMass.KILOGRAMS),
|
||||||
(MassConverter, UnitOfMass.MICROGRAMS),
|
(MassConverter, UnitOfMass.MICROGRAMS),
|
||||||
|
@ -91,6 +94,7 @@ def test_convert_same_unit(converter: type[BaseUnitConverter], valid_unit: str)
|
||||||
(DataRateConverter, UnitOfDataRate.GIBIBYTES_PER_SECOND),
|
(DataRateConverter, UnitOfDataRate.GIBIBYTES_PER_SECOND),
|
||||||
(DistanceConverter, UnitOfLength.KILOMETERS),
|
(DistanceConverter, UnitOfLength.KILOMETERS),
|
||||||
(EnergyConverter, UnitOfEnergy.KILO_WATT_HOUR),
|
(EnergyConverter, UnitOfEnergy.KILO_WATT_HOUR),
|
||||||
|
(InformationConverter, UnitOfInformation.GIBIBYTES),
|
||||||
(MassConverter, UnitOfMass.GRAMS),
|
(MassConverter, UnitOfMass.GRAMS),
|
||||||
(PowerConverter, UnitOfPower.WATT),
|
(PowerConverter, UnitOfPower.WATT),
|
||||||
(PressureConverter, UnitOfPressure.PA),
|
(PressureConverter, UnitOfPressure.PA),
|
||||||
|
@ -122,6 +126,11 @@ def test_convert_invalid_unit(
|
||||||
),
|
),
|
||||||
(DistanceConverter, UnitOfLength.KILOMETERS, UnitOfLength.METERS),
|
(DistanceConverter, UnitOfLength.KILOMETERS, UnitOfLength.METERS),
|
||||||
(EnergyConverter, UnitOfEnergy.WATT_HOUR, UnitOfEnergy.KILO_WATT_HOUR),
|
(EnergyConverter, UnitOfEnergy.WATT_HOUR, UnitOfEnergy.KILO_WATT_HOUR),
|
||||||
|
(
|
||||||
|
InformationConverter,
|
||||||
|
UnitOfInformation.GIBIBYTES,
|
||||||
|
UnitOfInformation.GIGABYTES,
|
||||||
|
),
|
||||||
(MassConverter, UnitOfMass.GRAMS, UnitOfMass.KILOGRAMS),
|
(MassConverter, UnitOfMass.GRAMS, UnitOfMass.KILOGRAMS),
|
||||||
(PowerConverter, UnitOfPower.WATT, UnitOfPower.KILO_WATT),
|
(PowerConverter, UnitOfPower.WATT, UnitOfPower.KILO_WATT),
|
||||||
(PressureConverter, UnitOfPressure.HPA, UnitOfPressure.INHG),
|
(PressureConverter, UnitOfPressure.HPA, UnitOfPressure.INHG),
|
||||||
|
@ -149,6 +158,7 @@ def test_convert_nonnumeric_value(
|
||||||
),
|
),
|
||||||
(DistanceConverter, UnitOfLength.KILOMETERS, UnitOfLength.METERS, 1 / 1000),
|
(DistanceConverter, UnitOfLength.KILOMETERS, UnitOfLength.METERS, 1 / 1000),
|
||||||
(EnergyConverter, UnitOfEnergy.WATT_HOUR, UnitOfEnergy.KILO_WATT_HOUR, 1000),
|
(EnergyConverter, UnitOfEnergy.WATT_HOUR, UnitOfEnergy.KILO_WATT_HOUR, 1000),
|
||||||
|
(InformationConverter, UnitOfInformation.BITS, UnitOfInformation.BYTES, 8),
|
||||||
(PowerConverter, UnitOfPower.WATT, UnitOfPower.KILO_WATT, 1000),
|
(PowerConverter, UnitOfPower.WATT, UnitOfPower.KILO_WATT, 1000),
|
||||||
(
|
(
|
||||||
PressureConverter,
|
PressureConverter,
|
||||||
|
@ -364,6 +374,43 @@ def test_energy_convert(
|
||||||
assert EnergyConverter.convert(value, from_unit, to_unit) == expected
|
assert EnergyConverter.convert(value, from_unit, to_unit) == expected
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"value,from_unit,expected,to_unit",
|
||||||
|
[
|
||||||
|
(8e3, UnitOfInformation.BITS, 8, UnitOfInformation.KILOBITS),
|
||||||
|
(8e6, UnitOfInformation.BITS, 8, UnitOfInformation.MEGABITS),
|
||||||
|
(8e9, UnitOfInformation.BITS, 8, UnitOfInformation.GIGABITS),
|
||||||
|
(8, UnitOfInformation.BITS, 1, UnitOfInformation.BYTES),
|
||||||
|
(8e3, UnitOfInformation.BITS, 1, UnitOfInformation.KILOBYTES),
|
||||||
|
(8e6, UnitOfInformation.BITS, 1, UnitOfInformation.MEGABYTES),
|
||||||
|
(8e9, UnitOfInformation.BITS, 1, UnitOfInformation.GIGABYTES),
|
||||||
|
(8e12, UnitOfInformation.BITS, 1, UnitOfInformation.TERABYTES),
|
||||||
|
(8e15, UnitOfInformation.BITS, 1, UnitOfInformation.PETABYTES),
|
||||||
|
(8e18, UnitOfInformation.BITS, 1, UnitOfInformation.EXABYTES),
|
||||||
|
(8e21, UnitOfInformation.BITS, 1, UnitOfInformation.ZETTABYTES),
|
||||||
|
(8e24, UnitOfInformation.BITS, 1, UnitOfInformation.YOTTABYTES),
|
||||||
|
(8 * 2**10, UnitOfInformation.BITS, 1, UnitOfInformation.KIBIBYTES),
|
||||||
|
(8 * 2**20, UnitOfInformation.BITS, 1, UnitOfInformation.MEBIBYTES),
|
||||||
|
(8 * 2**30, UnitOfInformation.BITS, 1, UnitOfInformation.GIBIBYTES),
|
||||||
|
(8 * 2**40, UnitOfInformation.BITS, 1, UnitOfInformation.TEBIBYTES),
|
||||||
|
(8 * 2**50, UnitOfInformation.BITS, 1, UnitOfInformation.PEBIBYTES),
|
||||||
|
(8 * 2**60, UnitOfInformation.BITS, 1, UnitOfInformation.EXBIBYTES),
|
||||||
|
(8 * 2**70, UnitOfInformation.BITS, 1, UnitOfInformation.ZEBIBYTES),
|
||||||
|
(8 * 2**80, UnitOfInformation.BITS, 1, UnitOfInformation.YOBIBYTES),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
def test_information_convert(
|
||||||
|
value: float,
|
||||||
|
from_unit: str,
|
||||||
|
expected: float,
|
||||||
|
to_unit: str,
|
||||||
|
) -> None:
|
||||||
|
"""Test conversion to other units."""
|
||||||
|
assert InformationConverter.convert(value, from_unit, to_unit) == pytest.approx(
|
||||||
|
expected
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"value,from_unit,expected,to_unit",
|
"value,from_unit,expected,to_unit",
|
||||||
[
|
[
|
||||||
|
|
Loading…
Reference in New Issue