Source code for stravalib.unithelper
"""
Unit Helper
==============
Helpers for converting Strava's units to something more practical.
"""
from numbers import Number
from typing import Any, Protocol, Union, cast, runtime_checkable
import pint
from stravalib.exc import warn_units_deprecated
from stravalib.unit_registry import Q_
[docs]@runtime_checkable
class UnitsQuantity(Protocol):
"""
A type that represents the (deprecated) `units` Quantity. The `unit`
attribute in the units library consists of other classes, so this
representation may not be 100% backward compatible!
"""
num: float
unit: str
[docs]class Quantity(Q_): # type: ignore[valid-type, misc]
"""
Extension of `pint.Quantity` for temporary backward compatibility with
the legacy `units` package.
"""
@property
def num(self) -> pint._typing.Magnitude:
warn_units_deprecated()
return self.magnitude
@property
def unit(self) -> str:
warn_units_deprecated()
return str(self.units)
def __int__(self) -> int:
return int(self.magnitude)
def __float__(self) -> float:
return float(self.magnitude)
[docs]class UnitConverter:
[docs] def __init__(self, unit: str) -> None:
self.unit = unit
def __call__(
self, q: Union[Number, pint.Quantity, UnitsQuantity]
) -> Quantity:
if isinstance(q, Number):
# provided quantity is unitless, so mimic legacy `units` behavior:
converted_q = Quantity(q, self.unit)
else:
try:
converted_q = Quantity(
cast(pint.Quantity, q).to(self.unit).magnitude, self.unit
)
except AttributeError:
# unexpected type of quantity, maybe it's a legacy `units` Quantity
warn_units_deprecated()
computed_q = Quantity(q.num, q.unit)
converted_q = Quantity(
computed_q.to(self.unit).magnitude, self.unit
)
return converted_q
[docs]def is_quantity_type(obj: Any) -> bool:
if isinstance(obj, (pint.Quantity, Quantity)):
return True
elif isinstance(obj, UnitsQuantity): # check using Duck Typing
warn_units_deprecated()
return True
else:
return False
meter = meters = UnitConverter("m")
second = seconds = UnitConverter("s")
hour = hours = UnitConverter("hour")
foot = feet = UnitConverter("ft")
mile = miles = UnitConverter("mi")
kilometer = kilometers = UnitConverter("km")
meters_per_second = UnitConverter("m/s")
miles_per_hour = mph = UnitConverter("mi/hour")
kilometers_per_hour = kph = UnitConverter("km/hour")
kilogram = kilograms = kg = kgs = UnitConverter("kg")
pound = pounds = lb = lbs = UnitConverter("lb")
[docs]def c2f(celsius: float) -> float:
"""
Convert Celsius to Fahrenheit.
Parameters
----------
celsius :
Temperature in Celsius.
Returns
-------
float
Temperature in Fahrenheit.
"""
return (9.0 / 5.0) * celsius + 32