Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions other/grocery_store_cart.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
"""
Console-free grocery cart logic.
"""


class GroceryStoreCart:
"""
Maintain cart item quantities and compute totals.

>>> cart = GroceryStoreCart({"apple": 1.5, "milk": 2.0})
>>> cart.add_item("apple", 2)
>>> cart.add_item("milk")
>>> round(cart.total_price(), 2)
5.0
>>> cart.remove_item("apple")
>>> round(cart.total_price(), 2)
3.5
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The doctest examples only cover the happy path. CONTRIBUTING.md asks for doctests that cover erroneous input values too; please add doctests for cases like empty price_catalog, unknown item in add_item(), and non-positive quantities to ensure exception behavior is tested and stays stable.

Suggested change
3.5
3.5
>>> GroceryStoreCart({})
Traceback (most recent call last):
...
ValueError: price_catalog cannot be empty
>>> cart = GroceryStoreCart({"apple": 1.5})
>>> cart.add_item("banana")
Traceback (most recent call last):
...
KeyError: "'banana' is not in the catalog"
>>> cart.add_item("apple", 0)
Traceback (most recent call last):
...
ValueError: quantity must be positive
>>> cart.add_item("apple", -1)
Traceback (most recent call last):
...
ValueError: quantity must be positive

Copilot uses AI. Check for mistakes.
"""

def __init__(self, price_catalog: dict[str, float]) -> None:
if not price_catalog:
raise ValueError("price_catalog cannot be empty")
self.price_catalog = dict(price_catalog)
self.quantities: dict[str, int] = {}

def add_item(self, item: str, quantity: int = 1) -> None:
if item not in self.price_catalog:
raise KeyError(f"{item!r} is not in the catalog")

Check failure on line 28 in other/grocery_store_cart.py

View workflow job for this annotation

GitHub Actions / ruff

ruff (EM102)

other/grocery_store_cart.py:28:28: EM102 Exception must not use an f-string literal, assign to variable first help: Assign to variable; remove f-string literal

Check failure on line 28 in other/grocery_store_cart.py

View workflow job for this annotation

GitHub Actions / ruff

ruff (EM102)

other/grocery_store_cart.py:28:28: EM102 Exception must not use an f-string literal, assign to variable first help: Assign to variable; remove f-string literal
if quantity <= 0:
raise ValueError("quantity must be positive")
self.quantities[item] = self.quantities.get(item, 0) + quantity

def remove_item(self, item: str, quantity: int = 1) -> None:
if quantity <= 0:
raise ValueError("quantity must be positive")
current = self.quantities.get(item, 0)
if current == 0:
raise KeyError(f"{item!r} is not present in the cart")

Check failure on line 38 in other/grocery_store_cart.py

View workflow job for this annotation

GitHub Actions / ruff

ruff (EM102)

other/grocery_store_cart.py:38:28: EM102 Exception must not use an f-string literal, assign to variable first help: Assign to variable; remove f-string literal

Check failure on line 38 in other/grocery_store_cart.py

View workflow job for this annotation

GitHub Actions / ruff

ruff (EM102)

other/grocery_store_cart.py:38:28: EM102 Exception must not use an f-string literal, assign to variable first help: Assign to variable; remove f-string literal
remaining = current - quantity
if remaining > 0:
self.quantities[item] = remaining
else:
self.quantities.pop(item, None)
Comment on lines +39 to +43
Copy link

Copilot AI Apr 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove_item() silently removes the item when quantity exceeds the current quantity (because remaining <= 0 falls into the pop() branch). This can hide caller mistakes; consider raising ValueError when quantity > current (or explicitly documenting/clamping the behavior) and add a doctest for the chosen behavior.

Copilot uses AI. Check for mistakes.

def total_price(self) -> float:
return sum(self.price_catalog[item] * qty for item, qty in self.quantities.items())

Check failure on line 46 in other/grocery_store_cart.py

View workflow job for this annotation

GitHub Actions / ruff

ruff (E501)

other/grocery_store_cart.py:46:89: E501 Line too long (91 > 88)

Check failure on line 46 in other/grocery_store_cart.py

View workflow job for this annotation

GitHub Actions / ruff

ruff (E501)

other/grocery_store_cart.py:46:89: E501 Line too long (91 > 88)


if __name__ == "__main__":
import doctest

doctest.testmod()
Loading