From 692b07e79a7b72654db2af177bb9789b1fd52eec Mon Sep 17 00:00:00 2001 From: Kristofers Solo Date: Sun, 22 Oct 2023 19:40:01 +0300 Subject: [PATCH] feat(csv): read/write inventory from/to csv file --- src/main.py => main.py | 3 +++ src/bookstore/book.py | 6 +++++- src/bookstore/inventory.py | 20 ++++++++++++++++++-- 3 files changed, 26 insertions(+), 3 deletions(-) rename src/main.py => main.py (73%) mode change 100644 => 100755 diff --git a/src/main.py b/main.py old mode 100644 new mode 100755 similarity index 73% rename from src/main.py rename to main.py index 4693850..dec9a7d --- a/src/main.py +++ b/main.py @@ -1,3 +1,6 @@ +#!/usr/bin/env python3 + + def main() -> None: pass diff --git a/src/bookstore/book.py b/src/bookstore/book.py index be5e205..a73988a 100644 --- a/src/bookstore/book.py +++ b/src/bookstore/book.py @@ -13,10 +13,14 @@ def _check_stock_value(instance, attribute, value): raise ValueError("Stock must be larger or equal to 0!") +def _to_isbn(number: str): + return ISBN(number) + + @define class Book: title: str = field() author: str = field() # TODO: add default author as "Unknown" - isbn: ISBN = field(on_setattr=setters.frozen, repr=lambda value: f"'{value}'") + isbn: ISBN = field(converter=_to_isbn, validator=validators.instance_of(ISBN), on_setattr=setters.frozen, repr=lambda value: f"'{value}'") price: float = field(converter=float, validator=[validators.instance_of(float), _check_price_value]) stock: int = field(converter=int, validator=[validators.instance_of(int), _check_stock_value]) diff --git a/src/bookstore/inventory.py b/src/bookstore/inventory.py index 74777d1..1cc18fe 100644 --- a/src/bookstore/inventory.py +++ b/src/bookstore/inventory.py @@ -1,3 +1,4 @@ +import csv from pathlib import Path from .book import Book @@ -5,14 +6,29 @@ from .isbn import ISBN class Inventory: - def __init__(self, books: list[Book]) -> None: - self.books: dict[ISBN, Book] = {book.isbn: book for book in books} + def __init__(self, books: list[Book] | None) -> None: + self.books: dict[ISBN, Book] = {book.isbn: book for book in books} if books else {} def read_from_file(self, path: Path) -> None: """Read `Inventory` from `path` csv file.""" + with open(path, mode="r") as file: + reader = csv.reader(file) + + next(reader, None) # Skip header + + for title, author, isbn, price, stock in reader: + book = Book(title, author, isbn, price, stock) + self.add(book) def save_to_file(self, path: Path) -> None: """Save `Inventory` to `path` csv file.""" + with open(path, mode="w") as file: + writer = csv.writer(file) + + writer.writerow(["Title", "Auther", "ISBN", "Price", "Stock"]) + + for book in self.books.values(): + writer.writerow([book.title, book.author, book.isbn, book.price, book.stock]) def add(self, book: Book) -> None: """Add `Book` to the `Inventory`. `Book`s ISBN must be unique."""