Add additional rules for converting distances (#80940)

* Add additional rules for converting distances

* Convert in to mm

* Adjust existing tests

* Add test
This commit is contained in:
Erik Montnemery 2022-10-25 12:51:23 +02:00 committed by GitHub
parent fe7402375d
commit aea0067e49
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 60 additions and 16 deletions

View File

@ -9,8 +9,14 @@ import voluptuous as vol
from homeassistant.const import ( from homeassistant.const import (
ACCUMULATED_PRECIPITATION, ACCUMULATED_PRECIPITATION,
LENGTH, LENGTH,
LENGTH_CENTIMETERS,
LENGTH_FEET,
LENGTH_INCHES,
LENGTH_KILOMETERS, LENGTH_KILOMETERS,
LENGTH_METERS,
LENGTH_MILES, LENGTH_MILES,
LENGTH_MILLIMETERS,
LENGTH_YARD,
MASS, MASS,
MASS_GRAMS, MASS_GRAMS,
MASS_KILOGRAMS, MASS_KILOGRAMS,
@ -92,8 +98,8 @@ class UnitSystem:
name: str, name: str,
*, *,
accumulated_precipitation: str, accumulated_precipitation: str,
conversions: dict[tuple[str | None, str | None], str],
length: str, length: str,
length_conversions: dict[str | None, str],
mass: str, mass: str,
pressure: str, pressure: str,
temperature: str, temperature: str,
@ -126,7 +132,7 @@ class UnitSystem:
self.pressure_unit = pressure self.pressure_unit = pressure
self.volume_unit = volume self.volume_unit = volume
self.wind_speed_unit = wind_speed self.wind_speed_unit = wind_speed
self._length_conversions = length_conversions self._conversions = conversions
@property @property
def name(self) -> str: def name(self) -> str:
@ -226,10 +232,7 @@ class UnitSystem:
original_unit: str | None, original_unit: str | None,
) -> str | None: ) -> str | None:
"""Return converted unit given a device class or an original unit.""" """Return converted unit given a device class or an original unit."""
if device_class == "distance": return self._conversions.get((device_class, original_unit))
return self._length_conversions.get(original_unit)
return None
def get_unit_system(key: str) -> UnitSystem: def get_unit_system(key: str) -> UnitSystem:
@ -259,8 +262,14 @@ validate_unit_system = vol.All(
METRIC_SYSTEM = UnitSystem( METRIC_SYSTEM = UnitSystem(
_CONF_UNIT_SYSTEM_METRIC, _CONF_UNIT_SYSTEM_METRIC,
accumulated_precipitation=PRECIPITATION_MILLIMETERS, accumulated_precipitation=PRECIPITATION_MILLIMETERS,
conversions={
# Convert non-metric distances
("distance", LENGTH_FEET): LENGTH_METERS,
("distance", LENGTH_INCHES): LENGTH_MILLIMETERS,
("distance", LENGTH_MILES): LENGTH_KILOMETERS,
("distance", LENGTH_YARD): LENGTH_METERS,
},
length=LENGTH_KILOMETERS, length=LENGTH_KILOMETERS,
length_conversions={LENGTH_MILES: LENGTH_KILOMETERS},
mass=MASS_GRAMS, mass=MASS_GRAMS,
pressure=PRESSURE_PA, pressure=PRESSURE_PA,
temperature=TEMP_CELSIUS, temperature=TEMP_CELSIUS,
@ -271,8 +280,14 @@ METRIC_SYSTEM = UnitSystem(
US_CUSTOMARY_SYSTEM = UnitSystem( US_CUSTOMARY_SYSTEM = UnitSystem(
_CONF_UNIT_SYSTEM_US_CUSTOMARY, _CONF_UNIT_SYSTEM_US_CUSTOMARY,
accumulated_precipitation=PRECIPITATION_INCHES, accumulated_precipitation=PRECIPITATION_INCHES,
conversions={
# Convert non-USCS distances
("distance", LENGTH_CENTIMETERS): LENGTH_INCHES,
("distance", LENGTH_KILOMETERS): LENGTH_MILES,
("distance", LENGTH_METERS): LENGTH_FEET,
("distance", LENGTH_MILLIMETERS): LENGTH_INCHES,
},
length=LENGTH_MILES, length=LENGTH_MILES,
length_conversions={LENGTH_KILOMETERS: LENGTH_MILES},
mass=MASS_POUNDS, mass=MASS_POUNDS,
pressure=PRESSURE_PSI, pressure=PRESSURE_PSI,
temperature=TEMP_FAHRENHEIT, temperature=TEMP_FAHRENHEIT,

View File

@ -44,8 +44,8 @@ def _set_up_units(hass):
hass.config.units = UnitSystem( hass.config.units = UnitSystem(
"custom", "custom",
accumulated_precipitation=LENGTH_MILLIMETERS, accumulated_precipitation=LENGTH_MILLIMETERS,
conversions={},
length=LENGTH_METERS, length=LENGTH_METERS,
length_conversions={},
mass=MASS_GRAMS, mass=MASS_GRAMS,
pressure=PRESSURE_PA, pressure=PRESSURE_PA,
temperature=TEMP_CELSIUS, temperature=TEMP_CELSIUS,

View File

@ -4,9 +4,14 @@ import pytest
from homeassistant.const import ( from homeassistant.const import (
ACCUMULATED_PRECIPITATION, ACCUMULATED_PRECIPITATION,
LENGTH, LENGTH,
LENGTH_CENTIMETERS,
LENGTH_FEET,
LENGTH_INCHES,
LENGTH_KILOMETERS, LENGTH_KILOMETERS,
LENGTH_METERS, LENGTH_METERS,
LENGTH_MILES,
LENGTH_MILLIMETERS, LENGTH_MILLIMETERS,
LENGTH_YARD,
MASS, MASS,
MASS_GRAMS, MASS_GRAMS,
PRESSURE, PRESSURE,
@ -40,8 +45,8 @@ def test_invalid_units():
UnitSystem( UnitSystem(
SYSTEM_NAME, SYSTEM_NAME,
accumulated_precipitation=LENGTH_MILLIMETERS, accumulated_precipitation=LENGTH_MILLIMETERS,
conversions={},
length=LENGTH_METERS, length=LENGTH_METERS,
length_conversions={},
mass=MASS_GRAMS, mass=MASS_GRAMS,
pressure=PRESSURE_PA, pressure=PRESSURE_PA,
temperature=INVALID_UNIT, temperature=INVALID_UNIT,
@ -53,8 +58,8 @@ def test_invalid_units():
UnitSystem( UnitSystem(
SYSTEM_NAME, SYSTEM_NAME,
accumulated_precipitation=LENGTH_MILLIMETERS, accumulated_precipitation=LENGTH_MILLIMETERS,
conversions={},
length=INVALID_UNIT, length=INVALID_UNIT,
length_conversions={},
mass=MASS_GRAMS, mass=MASS_GRAMS,
pressure=PRESSURE_PA, pressure=PRESSURE_PA,
temperature=TEMP_CELSIUS, temperature=TEMP_CELSIUS,
@ -66,8 +71,8 @@ def test_invalid_units():
UnitSystem( UnitSystem(
SYSTEM_NAME, SYSTEM_NAME,
accumulated_precipitation=LENGTH_MILLIMETERS, accumulated_precipitation=LENGTH_MILLIMETERS,
conversions={},
length=LENGTH_METERS, length=LENGTH_METERS,
length_conversions={},
mass=MASS_GRAMS, mass=MASS_GRAMS,
pressure=PRESSURE_PA, pressure=PRESSURE_PA,
temperature=TEMP_CELSIUS, temperature=TEMP_CELSIUS,
@ -79,8 +84,8 @@ def test_invalid_units():
UnitSystem( UnitSystem(
SYSTEM_NAME, SYSTEM_NAME,
accumulated_precipitation=LENGTH_MILLIMETERS, accumulated_precipitation=LENGTH_MILLIMETERS,
conversions={},
length=LENGTH_METERS, length=LENGTH_METERS,
length_conversions={},
mass=MASS_GRAMS, mass=MASS_GRAMS,
pressure=PRESSURE_PA, pressure=PRESSURE_PA,
temperature=TEMP_CELSIUS, temperature=TEMP_CELSIUS,
@ -92,8 +97,8 @@ def test_invalid_units():
UnitSystem( UnitSystem(
SYSTEM_NAME, SYSTEM_NAME,
accumulated_precipitation=LENGTH_MILLIMETERS, accumulated_precipitation=LENGTH_MILLIMETERS,
conversions={},
length=LENGTH_METERS, length=LENGTH_METERS,
length_conversions={},
mass=INVALID_UNIT, mass=INVALID_UNIT,
pressure=PRESSURE_PA, pressure=PRESSURE_PA,
temperature=TEMP_CELSIUS, temperature=TEMP_CELSIUS,
@ -105,8 +110,8 @@ def test_invalid_units():
UnitSystem( UnitSystem(
SYSTEM_NAME, SYSTEM_NAME,
accumulated_precipitation=LENGTH_MILLIMETERS, accumulated_precipitation=LENGTH_MILLIMETERS,
conversions={},
length=LENGTH_METERS, length=LENGTH_METERS,
length_conversions={},
mass=MASS_GRAMS, mass=MASS_GRAMS,
pressure=INVALID_UNIT, pressure=INVALID_UNIT,
temperature=TEMP_CELSIUS, temperature=TEMP_CELSIUS,
@ -118,8 +123,8 @@ def test_invalid_units():
UnitSystem( UnitSystem(
SYSTEM_NAME, SYSTEM_NAME,
accumulated_precipitation=INVALID_UNIT, accumulated_precipitation=INVALID_UNIT,
conversions={},
length=LENGTH_METERS, length=LENGTH_METERS,
length_conversions={},
mass=MASS_GRAMS, mass=MASS_GRAMS,
pressure=PRESSURE_PA, pressure=PRESSURE_PA,
temperature=TEMP_CELSIUS, temperature=TEMP_CELSIUS,
@ -374,3 +379,27 @@ def test_get_unit_system_invalid(key: str) -> None:
"""Test get_unit_system with an invalid key.""" """Test get_unit_system with an invalid key."""
with pytest.raises(ValueError, match=f"`{key}` is not a valid unit system key"): with pytest.raises(ValueError, match=f"`{key}` is not a valid unit system key"):
_ = get_unit_system(key) _ = get_unit_system(key)
@pytest.mark.parametrize(
"unit_system, device_class, original_unit, state_unit",
(
(METRIC_SYSTEM, "distance", LENGTH_FEET, LENGTH_METERS),
(METRIC_SYSTEM, "distance", LENGTH_INCHES, LENGTH_MILLIMETERS),
(METRIC_SYSTEM, "distance", LENGTH_MILES, LENGTH_KILOMETERS),
(METRIC_SYSTEM, "distance", LENGTH_YARD, LENGTH_METERS),
(METRIC_SYSTEM, "distance", LENGTH_KILOMETERS, None),
(METRIC_SYSTEM, "distance", "very_long", None),
(US_CUSTOMARY_SYSTEM, "distance", LENGTH_CENTIMETERS, LENGTH_INCHES),
(US_CUSTOMARY_SYSTEM, "distance", LENGTH_KILOMETERS, LENGTH_MILES),
(US_CUSTOMARY_SYSTEM, "distance", LENGTH_METERS, LENGTH_FEET),
(US_CUSTOMARY_SYSTEM, "distance", LENGTH_MILLIMETERS, LENGTH_INCHES),
(US_CUSTOMARY_SYSTEM, "distance", LENGTH_MILES, None),
(US_CUSTOMARY_SYSTEM, "distance", "very_long", None),
),
)
def test_get_converted_unit(
unit_system, device_class, original_unit, state_unit
) -> None:
"""Test unit conversion rules."""
assert unit_system.get_converted_unit(device_class, original_unit) == state_unit