#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
-from numbers import Number
-from typing import Callable
+# © Copyright 2021-2022, Scott Gasch
+
+"""Utilities involving converting between different units."""
+
+from typing import Callable, SupportsFloat
import constants
category: str,
to_canonical: Callable, # convert to canonical unit
from_canonical: Callable, # convert from canonical unit
- unit: str,
+ suffix: str,
) -> None:
+ """Construct a converter.
+
+ Args:
+ name: the unit name
+ category: the converter category
+ to_canonical: a Callable to convert this unit into the
+ canonical unit of the category.
+ from_canonical: a Callable to convert from the canonical
+ unit of this category into this unit.
+ suffix: the abbreviation of the unit name.
+ """
+
self.name = name
self.category = category
self.to_canonical_f = to_canonical
self.from_canonical_f = from_canonical
- self.unit = unit
+ self.suffix = suffix
- def to_canonical(self, n: Number) -> Number:
+ def to_canonical(self, n: SupportsFloat) -> SupportsFloat:
+ """Convert into the canonical unit of this caregory by using the
+ Callable provided during construction."""
return self.to_canonical_f(n)
- def from_canonical(self, n: Number) -> Number:
+ def from_canonical(self, n: SupportsFloat) -> SupportsFloat:
+ """Convert from the canonical unit of this category by using the
+ Callable provided during construction."""
return self.from_canonical_f(n)
def unit_suffix(self) -> str:
- return self.unit
+ """Get this unit's suffix abbreviation."""
+ return self.suffix
# A catalog of converters.
}
-def convert(magnitude: Number, from_thing: str, to_thing: str) -> float:
+def convert(magnitude: SupportsFloat, from_thing: str, to_thing: str) -> float:
+ """Convert between units using the internal catalog.
+
+ Args:
+ magnitude: the quantity from which to convert
+ from_thing: the quantity's source unit we're coverting from
+ to_thing: the unit we are coverting to
+
+ Returns:
+ The converted magnitude. Raises on error.
+ """
src = conversion_catalog.get(from_thing, None)
dst = conversion_catalog.get(to_thing, None)
if src is None or dst is None:
return _convert(magnitude, src, dst)
-def _convert(magnitude: Number, from_unit: Converter, to_unit: Converter) -> float:
+def _convert(magnitude: SupportsFloat, from_unit: Converter, to_unit: Converter) -> float:
+ """Internal conversion code."""
canonical = from_unit.to_canonical(magnitude)
converted = to_unit.from_canonical(canonical)
return float(converted)