AtrisBench
Back to the leaderboard

Claude Fable 5.1 on Fix two invoicing bugs

Passed in 19s. Attempt 3. Run 20260904T112137Z-fable-5-1-fix-the-bug-3.

Task

Fix the invoicing package

The small Python package in invoicing/ has two bugs. Run the tests in tests/, find the causes, and fix the package code.

The required behavior is round-half-up at the half-cent boundary and a due date that preserves the timezone of an aware issue time. Do not change anything under tests/.

There is no separate report to write. The output is the corrected invoicing/ package in the current folder, with this command passing:

python -m pytest -q tests

Command

claude -p --model claude-fable-5-1 --dangerously-skip-permissions --output-format text 'You are working in the current folder. Do the task in TASK.md and write the outputs to the exact paths it names.
Do not ask questions. When done, stop.

# Fix the invoicing package

The small Python package in `invoicing/` has two bugs. Run the tests in `tests/`, find the
causes, and fix the package code.

The required behavior is round-half-up at the half-cent boundary and a due date that preserves
the timezone of an aware issue time. Do not change anything under `tests/`.

There is no separate report to write. The output is the corrected `invoicing/` package in the
current folder, with this command passing:

` ` `sh
python -m pytest -q tests
` ` `'

Output

Both bugs are fixed and all five tests pass. I only touched the package file, nothing under tests.

One. Money rounding used Python's default, which rounds a half cent to the nearest even digit. So 10.005 became 10.00. It now rounds half up, so 10.005 becomes 10.01.

Two. The due date builder rebuilt 5 PM from scratch and dropped the timezone of the issue time. It now carries that timezone over, and a naive issue time still gives a naive due time.

`python -m pytest -q tests`

Files produced

.pytest_cache/.gitignore

# Created by pytest automatically.
*

.pytest_cache/CACHEDIR.TAG

Signature: 8a477f597d28d172789f06886806bc55
# This file is a cache directory tag created by pytest.
# For information about cache directory tags, see:
#	https://bford.info/cachedir/spec.html

.pytest_cache/README.md

# pytest cache directory #

This directory contains data from the pytest's cache plugin,
which provides the `--lf` and `--ff` options, as well as the `cache` fixture.

**Do not** commit this to version control.

See [the docs](https://docs.pytest.org/en/stable/how-to/cache.html) for more information.

.pytest_cache/v/cache/lastfailed

{}

.pytest_cache/v/cache/nodeids

[
  "tests/test_invoice.py::test_due_at_preserves_an_aware_timezone",
  "tests/test_invoice.py::test_due_at_stays_naive_for_a_naive_issue_time",
  "tests/test_invoice.py::test_invoice_total_is_money",
  "tests/test_invoice.py::test_money_rounds_an_ordinary_fraction",
  "tests/test_invoice.py::test_money_uses_round_half_up_for_half_cent"
]

invoicing/pycache/init.cpython-312.pyc

[binary file, 289 bytes]

invoicing/pycache/invoice.cpython-312.pyc

[binary file, 1839 bytes]

invoicing/invoice.py

from __future__ import annotations

from dataclasses import dataclass
from datetime import datetime, time, timedelta
from decimal import ROUND_HALF_UP, Decimal


def money(value: Decimal | str) -> Decimal:
    """Return a value rounded to cents."""
    return Decimal(value).quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)


def due_at(issued_at: datetime, terms_days: int) -> datetime:
    """Return 5 PM on the due date, in the timezone of the issue time (if any)."""
    due_date = issued_at.date() + timedelta(days=terms_days)
    return datetime.combine(due_date, time(17, 0), tzinfo=issued_at.tzinfo)


@dataclass(frozen=True)
class Invoice:
    subtotal: Decimal
    tax_rate: Decimal

    @property
    def total(self) -> Decimal:
        return money(self.subtotal * (Decimal("1") + self.tax_rate))

tests/pycache/test_invoice.cpython-312-pytest-9.0.3.pyc

[binary file, 8721 bytes]

Checker

{"passed": true, "score": 1.0, "notes": "tests unchanged: True; pytest: 5 passed in 0.00s"}

Judge

Not used for this task.