feat: add convert_temperature function with validation and docstrings (#18)
This commit is contained in:
parent
31deaebb46
commit
1b2a544aaa
157
generated_code.py
Normal file
157
generated_code.py
Normal 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
|
||||||
Loading…
Reference in New Issue
Block a user