Functional Weave
Code in Python

energy.carbon-emissions@1.0.1

impl/python.py

1,373 bytes · the Python implementation · view raw

Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.

from .energy_carbon_emissions_data import CONVERSION_FACTORS  ← this capability’s own data, compiled from data/conversion-factors.json into the same file by fune build
from .energy_carbon_emissions_types import CarbonEmissions
from .math_round_div import round_div  ← from math.round-div ^1.0.0 · built alongside by fune

# quantity (thousandths of a unit) x factor (hundred-thousandths of a kg)
# / 100000 is grams.
DIVISOR = 100_000
MAX_SAFE = 9007199254740991


def carbon_emissions(fuel: str, quantity: int, year: int) -> CarbonEmissions:
    """kgCO2e, as whole grams, for an amount of a fuel, from the UK government
    conversion factor set for ``year``.
    """
    if not isinstance(quantity, int) or isinstance(quantity, bool) or quantity < 0:
        raise ValueError(
            "quantity must be a whole number of thousandths of a unit, 0 or more, received %s" % (quantity,)
        )
    if not any(f.fuel == fuel for f in CONVERSION_FACTORS):
        raise ValueError('unknown fuel "%s"' % (fuel,))
    row = next((f for f in CONVERSION_FACTORS if f.fuel == fuel and f.year == year), None)
    if row is None:
        raise ValueError("no conversion factor for %s in %s" % (fuel, year))
    whole, rest = divmod(quantity, DIVISOR)
    grams = whole * row.factor + round_div(rest * row.factor, DIVISOR, "half-up")
    if grams > MAX_SAFE:
        raise ValueError("emissions too large to calculate exactly")
    return CarbonEmissions(fuel=fuel, unit=row.unit, year=year, scope=row.scope, factor=row.factor, grams=grams)