Skip to content

Round numbers

round_numbers

Round-numbers strategy — reduce float precision.

RoundNumbersStrategy

Bases: SmeltStrategy

Recursively round floats to precision decimal places.

Source code in packages/axm-smelt/src/axm_smelt/strategies/round_numbers.py
Python
class RoundNumbersStrategy(SmeltStrategy):
    """Recursively round floats to *precision* decimal places."""

    def __init__(self, precision: int = 2) -> None:
        self._precision = precision

    @property
    def name(self) -> str:
        return "round_numbers"

    @property
    def category(self) -> str:
        return "cosmetic"

    def _round_text(self, text: str) -> str:
        """Round float literals found in plain text (e.g. tabular output)."""
        return _round_in_str(text, self._precision)

    def apply(self, ctx: SmeltContext) -> SmeltContext:
        """Round float values to the configured precision.

        Uses ``ctx.parsed`` for the JSON path and falls back to
        regex-based rounding on plain text (e.g. post-tabular output).
        Propagates the rounded object as ``parsed`` on the returned
        context.
        """
        parsed = ctx.parsed
        if parsed is not None:
            rounded = _round_walk(parsed, self._precision)
            result = json.dumps(rounded, separators=(",", ":"), ensure_ascii=False)
            new_ctx = SmeltContext(text=result, format=ctx.format)
            new_ctx._parsed = rounded
            return new_ctx

        text = ctx.text
        stripped = text.strip()
        if not stripped:
            return ctx

        if stripped[0] in ("{", "["):
            try:
                data = json.loads(stripped)
                rounded = _round_walk(data, self._precision)
                result = json.dumps(rounded, separators=(",", ":"), ensure_ascii=False)
                new_ctx = SmeltContext(text=result, format=ctx.format)
                new_ctx._parsed = rounded
                return new_ctx
            except (json.JSONDecodeError, ValueError):
                pass

        # Fallback: round floats in plain text (post-tabular output, etc.)
        result = self._round_text(text)
        if result != text:
            new_ctx = SmeltContext(text=result, format=ctx.format)
            new_ctx._parsed = None  # non-JSON text, prevent reparsing
            return new_ctx
        return ctx
apply(ctx)

Round float values to the configured precision.

Uses ctx.parsed for the JSON path and falls back to regex-based rounding on plain text (e.g. post-tabular output). Propagates the rounded object as parsed on the returned context.

Source code in packages/axm-smelt/src/axm_smelt/strategies/round_numbers.py
Python
def apply(self, ctx: SmeltContext) -> SmeltContext:
    """Round float values to the configured precision.

    Uses ``ctx.parsed`` for the JSON path and falls back to
    regex-based rounding on plain text (e.g. post-tabular output).
    Propagates the rounded object as ``parsed`` on the returned
    context.
    """
    parsed = ctx.parsed
    if parsed is not None:
        rounded = _round_walk(parsed, self._precision)
        result = json.dumps(rounded, separators=(",", ":"), ensure_ascii=False)
        new_ctx = SmeltContext(text=result, format=ctx.format)
        new_ctx._parsed = rounded
        return new_ctx

    text = ctx.text
    stripped = text.strip()
    if not stripped:
        return ctx

    if stripped[0] in ("{", "["):
        try:
            data = json.loads(stripped)
            rounded = _round_walk(data, self._precision)
            result = json.dumps(rounded, separators=(",", ":"), ensure_ascii=False)
            new_ctx = SmeltContext(text=result, format=ctx.format)
            new_ctx._parsed = rounded
            return new_ctx
        except (json.JSONDecodeError, ValueError):
            pass

    # Fallback: round floats in plain text (post-tabular output, etc.)
    result = self._round_text(text)
    if result != text:
        new_ctx = SmeltContext(text=result, format=ctx.format)
        new_ctx._parsed = None  # non-JSON text, prevent reparsing
        return new_ctx
    return ctx