feat: add convert_temperature function with validation and docstrings (#18)

This commit is contained in:
CODER 2026-07-22 20:47:53 +00:00
parent 31deaebb46
commit 1b2a544aaa

157
generated_code.py Normal file
View File

@ -0,0 +1,157 @@
"""Temperature conversion utilities for SNS Network Solutions."""
from enum import Enum
class TemperatureUnit(str, Enum):
"""Supported temperature units."""
CELSIUS = "Celsius"
FAHRENHEIT = "Fahrenheit"
KELVIN = "Kelvin"
# Absolute zero in Celsius — used for Kelvin validation
_ABSOLUTE_ZERO_CELSIUS = -273.15
_ABSOLUTE_ZERO_FAHRENHEIT = -459.67
def convert_temperature(
value: float,
from_unit: str,
to_unit: str,
) -> float:
"""Convert a temperature value between Celsius, Fahrenheit, and Kelvin.
Validates that the input value is physically possible (i.e., not below
absolute zero for the given unit) and that both unit strings are
recognised before performing the conversion.
Args:
value: The numeric temperature to convert.
from_unit: The unit of the supplied value. Must be one of
``'Celsius'``, ``'Fahrenheit'``, or ``'Kelvin'``.
to_unit: The target unit for the result. Same allowed values as
*from_unit*.
Returns:
The converted temperature as a ``float``, rounded to six decimal
places to avoid floating-point noise.
Raises:
TypeError: If *value* is not an ``int`` or ``float``.
ValueError: If either unit string is not recognised, or if *value*
is below absolute zero for the given *from_unit*.
Examples:
>>> convert_temperature(100, 'Celsius', 'Fahrenheit')
212.0
>>> convert_temperature(32, 'Fahrenheit', 'Celsius')
0.0
>>> convert_temperature(0, 'Kelvin', 'Celsius')
-273.15
>>> convert_temperature(300, 'Kelvin', 'Fahrenheit')
80.33
"""
# --- type guard ---
if not isinstance(value, (int, float)):
raise TypeError(
f"'value' must be a numeric type (int or float), got {type(value).__name__!r}."
)
# --- unit validation (guard clauses) ---
valid_units = {u.value for u in TemperatureUnit}
if from_unit not in valid_units:
raise ValueError(
f"Unrecognised from_unit {from_unit!r}. "
f"Allowed values: {sorted(valid_units)}."
)
if to_unit not in valid_units:
raise ValueError(
f"Unrecognised to_unit {to_unit!r}. "
f"Allowed values: {sorted(valid_units)}."
)
# --- physical validity guard ---
_validate_above_absolute_zero(value, from_unit)
# --- trivial case ---
if from_unit == to_unit:
return float(value)
# --- convert to Celsius as the common intermediate ---
celsius = _to_celsius(value, from_unit)
# --- convert from Celsius to the target unit ---
result = _from_celsius(celsius, to_unit)
return round(result, 6)
# ---------------------------------------------------------------------------
# Private helpers
# ---------------------------------------------------------------------------
def _validate_above_absolute_zero(value: float, unit: str) -> None:
"""Raise ValueError if *value* is below absolute zero for *unit*.
Args:
value: The temperature value to check.
unit: The unit string (already validated as a recognised unit).
Raises:
ValueError: When *value* is physically impossible.
"""
if unit == TemperatureUnit.CELSIUS and value < _ABSOLUTE_ZERO_CELSIUS:
raise ValueError(
f"Temperature {value} °C is below absolute zero "
f"({_ABSOLUTE_ZERO_CELSIUS} °C)."
)
if unit == TemperatureUnit.FAHRENHEIT and value < _ABSOLUTE_ZERO_FAHRENHEIT:
raise ValueError(
f"Temperature {value} °F is below absolute zero "
f"({_ABSOLUTE_ZERO_FAHRENHEIT} °F)."
)
if unit == TemperatureUnit.KELVIN and value < 0:
raise ValueError(
f"Temperature {value} K is below absolute zero (0 K)."
)
def _to_celsius(value: float, from_unit: str) -> float:
"""Convert *value* (in *from_unit*) to degrees Celsius.
Args:
value: Source temperature.
from_unit: Source unit (pre-validated).
Returns:
Equivalent temperature in Celsius.
"""
if from_unit == TemperatureUnit.CELSIUS:
return float(value)
if from_unit == TemperatureUnit.FAHRENHEIT:
# °C = (°F 32) × 5/9
return (value - 32) * 5 / 9
# Kelvin → °C = K 273.15
return value - 273.15
def _from_celsius(celsius: float, to_unit: str) -> float:
"""Convert a Celsius value to *to_unit*.
Args:
celsius: Temperature in degrees Celsius.
to_unit: Target unit (pre-validated).
Returns:
Equivalent temperature in *to_unit*.
"""
if to_unit == TemperatureUnit.CELSIUS:
return celsius
if to_unit == TemperatureUnit.FAHRENHEIT:
# °F = °C × 9/5 + 32
return celsius * 9 / 5 + 32
# °C → K = °C + 273.15
return celsius + 273.15