From d28896c7db1e63eb403a013b8a178d25846c3c85 Mon Sep 17 00:00:00 2001 From: nickzerjeski Date: Mon, 13 Apr 2026 10:45:06 +0200 Subject: [PATCH 1/6] feat(other): add grocery store cart model --- other/grocery_store_cart.py | 52 +++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 other/grocery_store_cart.py diff --git a/other/grocery_store_cart.py b/other/grocery_store_cart.py new file mode 100644 index 000000000000..eb2be39d0547 --- /dev/null +++ b/other/grocery_store_cart.py @@ -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 + """ + + 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") + 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") + remaining = current - quantity + if remaining > 0: + self.quantities[item] = remaining + else: + self.quantities.pop(item, None) + + def total_price(self) -> float: + return sum(self.price_catalog[item] * qty for item, qty in self.quantities.items()) + + +if __name__ == "__main__": + import doctest + + doctest.testmod() From 9611435dcf9cdbbadc2c0c8a11a1e246a6f1d04e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 13 Apr 2026 09:14:58 +0000 Subject: [PATCH 2/6] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- other/grocery_store_cart.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/other/grocery_store_cart.py b/other/grocery_store_cart.py index eb2be39d0547..eec34059a315 100644 --- a/other/grocery_store_cart.py +++ b/other/grocery_store_cart.py @@ -36,14 +36,15 @@ def remove_item(self, item: str, quantity: int = 1) -> None: current = self.quantities.get(item, 0) if current == 0: raise KeyError(f"{item!r} is not present in the cart") - remaining = current - quantity - if remaining > 0: + if (remaining := current - quantity) > 0: self.quantities[item] = remaining else: self.quantities.pop(item, None) def total_price(self) -> float: - return sum(self.price_catalog[item] * qty for item, qty in self.quantities.items()) + return sum( + self.price_catalog[item] * qty for item, qty in self.quantities.items() + ) if __name__ == "__main__": From 4e7fa49dfca40473d49b5edde1baeb6783b86cc3 Mon Sep 17 00:00:00 2001 From: nickzerjeski Date: Mon, 13 Apr 2026 12:14:29 +0200 Subject: [PATCH 3/6] Fix Ruff EM102 in grocery store cart exceptions --- other/grocery_store_cart.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/other/grocery_store_cart.py b/other/grocery_store_cart.py index eec34059a315..4a55c00e5f86 100644 --- a/other/grocery_store_cart.py +++ b/other/grocery_store_cart.py @@ -25,7 +25,8 @@ def __init__(self, price_catalog: dict[str, float]) -> None: 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") + msg = f"{item!r} is not in the catalog" + raise KeyError(msg) if quantity <= 0: raise ValueError("quantity must be positive") self.quantities[item] = self.quantities.get(item, 0) + quantity @@ -35,7 +36,8 @@ def remove_item(self, item: str, quantity: int = 1) -> None: 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") + msg = f"{item!r} is not present in the cart" + raise KeyError(msg) if (remaining := current - quantity) > 0: self.quantities[item] = remaining else: From eedcb1469f8becbb4c09b3ca2a89c9d891459fe8 Mon Sep 17 00:00:00 2001 From: nickzerjeski Date: Mon, 13 Apr 2026 12:16:55 +0200 Subject: [PATCH 4/6] Address review feedback for grocery cart edge cases --- other/grocery_store_cart.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/other/grocery_store_cart.py b/other/grocery_store_cart.py index 4a55c00e5f86..31a4545b84cd 100644 --- a/other/grocery_store_cart.py +++ b/other/grocery_store_cart.py @@ -15,6 +15,32 @@ class GroceryStoreCart: >>> cart.remove_item("apple") >>> round(cart.total_price(), 2) 3.5 + + >>> GroceryStoreCart({}) + Traceback (most recent call last): + ... + ValueError: price_catalog cannot be empty + + >>> cart.add_item("bread") + Traceback (most recent call last): + ... + KeyError: "'bread' is not in the catalog" + + >>> cart.add_item("apple", 0) + Traceback (most recent call last): + ... + ValueError: quantity must be positive + + >>> cart.remove_item("milk", 0) + Traceback (most recent call last): + ... + ValueError: quantity must be positive + + >>> empty_cart = GroceryStoreCart({"apple": 1.5}) + >>> empty_cart.remove_item("apple") + Traceback (most recent call last): + ... + KeyError: "'apple' is not present in the cart" """ def __init__(self, price_catalog: dict[str, float]) -> None: @@ -38,6 +64,8 @@ def remove_item(self, item: str, quantity: int = 1) -> None: if current == 0: msg = f"{item!r} is not present in the cart" raise KeyError(msg) + if quantity > current: + raise ValueError("quantity exceeds amount present in the cart") if (remaining := current - quantity) > 0: self.quantities[item] = remaining else: From d5e1fb057c8e6abcb32d3cc64608dc82b494e6e3 Mon Sep 17 00:00:00 2001 From: Nick Zerjeski <57059725+nickzerjeski@users.noreply.github.com> Date: Tue, 14 Apr 2026 09:29:33 +0200 Subject: [PATCH 5/6] Apply suggestions from code review Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- other/grocery_store_cart.py | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/other/grocery_store_cart.py b/other/grocery_store_cart.py index 31a4545b84cd..b8ba3ed2de1d 100644 --- a/other/grocery_store_cart.py +++ b/other/grocery_store_cart.py @@ -36,6 +36,32 @@ class GroceryStoreCart: ... ValueError: quantity must be positive + >>> empty_cart = GroceryStoreCart({"apple": 1.5}) + >>> empty_cart.remove_item("apple") + Traceback (most recent call last): + ... + KeyError: "'apple' is not present in the cart" + + >>> GroceryStoreCart({}) + Traceback (most recent call last): + ... + ValueError: price_catalog cannot be empty + + >>> cart.add_item("bread") + Traceback (most recent call last): + ... + KeyError: "'bread' is not in the catalog" + + >>> cart.add_item("apple", 0) + Traceback (most recent call last): + ... + ValueError: quantity must be positive + + >>> cart.remove_item("milk", 0) + Traceback (most recent call last): + ... + ValueError: quantity must be positive + >>> empty_cart = GroceryStoreCart({"apple": 1.5}) >>> empty_cart.remove_item("apple") Traceback (most recent call last): @@ -66,14 +92,17 @@ def remove_item(self, item: str, quantity: int = 1) -> None: raise KeyError(msg) if quantity > current: raise ValueError("quantity exceeds amount present in the cart") - if (remaining := current - quantity) > 0: - self.quantities[item] = remaining - else: + if quantity > current: + raise ValueError("quantity exceeds amount present in the cart") + if quantity == current: self.quantities.pop(item, None) + else: + self.quantities[item] = current - quantity def total_price(self) -> float: return sum( - self.price_catalog[item] * qty for item, qty in self.quantities.items() + self.price_catalog[item] * qty + for item, qty in self.quantities.items() ) From 206008548c04a1889c0d2434e08f5ea89a755f28 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 14 Apr 2026 07:29:46 +0000 Subject: [PATCH 6/6] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- other/grocery_store_cart.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/other/grocery_store_cart.py b/other/grocery_store_cart.py index b8ba3ed2de1d..978f8854ad81 100644 --- a/other/grocery_store_cart.py +++ b/other/grocery_store_cart.py @@ -101,8 +101,7 @@ def remove_item(self, item: str, quantity: int = 1) -> None: def total_price(self) -> float: return sum( - self.price_catalog[item] * qty - for item, qty in self.quantities.items() + self.price_catalog[item] * qty for item, qty in self.quantities.items() )