evals / debt-shop
raise-bad-price
Expected
Hidden from the reviewer, like the grading note below.
- no-swallowed-errors
- holds
parse_price now raises BadPrice from the ValueError instead of returning None, and load_catalog no longer skips rows without a price. The change removes an existing violation; raising another exception is allowed. Store.find is unchanged. The contract holds for this change.
Change
shop/catalog.py
-5+7
6 unmodified lines789101112131014151617141518192021221 unmodified line24252623242728296 unmodified lineslog = logging.getLogger(__name__)
class BadPrice(ValueError): pass
def parse_price(text: str) -> int | None:def parse_price(text: str) -> int: try: dollars, cents = text.strip().lstrip("$").split(".") return int(dollars) * 100 + int(cents) except ValueError: return None except ValueError as err: raise BadPrice(text) from err
def load_catalog(path: Path) -> list[Item]:1 unmodified line with path.open() as handle: for row in csv.DictReader(handle): price = parse_price(row["price"]) if price is None: continue items.append(Item(sku=row["sku"], name=row["name"] or None, price_cents=price, stock=int(row["stock"]))) return items
Contracts
no-swallowed-errors
---
name: no-swallowed-errors
message: Let errors crash; never catch an exception to hide it.
---
## Rules
Python code under `shop/` must not suppress exceptions.
Every `except` block must re-raise the exception or raise another exception, for example `raise BadRequest(...) from err`.
An `except` block that returns a value, returns `None`, uses `pass` or `continue`, or only logs is forbidden.
`contextlib.suppress` is forbidden for the same reason.
`try/finally` used only for cleanup, such as closing a file, is allowed.