-
Notifications
You must be signed in to change notification settings - Fork 0
Jayden+aaron v2 3172025 #18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
aarondtrng
wants to merge
5
commits into
dev
Choose a base branch
from
jayden+aaron_V2_3172025
base: dev
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 4 commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
81612fa
exceptions.py file
aarondtrng f010970
Testing for Jayden
aarondtrng df296c1
Testing again
aarondtrng a024203
exception.py file and added some error handling to most
aarondtrng 5975a6f
updated db handling for most functions
aarondtrng File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,7 +11,9 @@ | |
| """ | ||
| import os | ||
| import sqlite3 | ||
| from typing import Type | ||
| from models.snack import Snack, SnackCreateSchema, SnackUpdateSchema | ||
| from exceptions import DatabaseError, ConnectionError, RecordNotFoundError, DuplicateRecordError, DatabaseInitError | ||
|
|
||
| def get_db_connection(db_file_path:str="data/db.sqlite3"): | ||
| """Creates and returns a SQLite database connection""" | ||
|
|
@@ -22,93 +24,131 @@ def get_db_connection(db_file_path:str="data/db.sqlite3"): | |
|
|
||
| def init_db(db_file_path: str = "data/db.sqlite3"): | ||
| """Initialize the database with schema""" | ||
| os.makedirs(os.path.dirname(db_file_path), exist_ok=True) | ||
| with open('data/schema.sql') as f: | ||
| schema = f.read() | ||
| with get_db_connection() as conn: | ||
| conn.executescript(schema) | ||
| try: | ||
| os.makedirs(os.path.dirname(db_file_path), exist_ok=True) | ||
| with open('data/schema.sql') as f: | ||
| schema = f.read() | ||
| with get_db_connection() as conn: | ||
| conn.executescript(schema) | ||
| except sqlite3.Error as e: | ||
| raise DatabaseInitError(f"Error when initializing database: {str(e)}") | ||
|
|
||
|
|
||
| def get_inventory() -> list[Snack]: | ||
| """Returns all snacks in the database""" | ||
| with get_db_connection() as conn: | ||
| cursor = conn.cursor() | ||
| cursor.execute("SELECT * FROM snacks") | ||
| records = cursor.fetchall() | ||
| return [Snack(**record) for record in records] | ||
| try: | ||
| with get_db_connection() as conn: | ||
| cursor = conn.cursor() | ||
| cursor.execute("SELECT * FROM snacks") | ||
| records = cursor.fetchall() | ||
| return [Snack(**record) for record in records] | ||
| except sqlite3.Error as e: | ||
| raise DatabaseError(f"Database error when fetching snacks: {str(e)}") | ||
|
|
||
|
|
||
| def get_snack(sku: str) -> Snack: | ||
| """Returns a single snack by SKU""" | ||
| with get_db_connection() as conn: | ||
| cursor = conn.cursor() | ||
| cursor.execute("SELECT * FROM snacks WHERE sku = ?", (sku,)) | ||
| record = cursor.fetchone() | ||
| return Snack(**record) | ||
|
|
||
| try: | ||
| with get_db_connection() as conn: | ||
| cursor = conn.cursor() | ||
| cursor.execute("SELECT * FROM snacks WHERE sku = ?", (sku,)) | ||
| record = cursor.fetchone() | ||
| if record is None: | ||
| raise RecordNotFoundError(f"No snack found with SKU: {sku}") | ||
| return Snack(**record) | ||
| except sqlite3.Error as e: | ||
| if(isinstance(e,ConnectionError)): | ||
| raise ConnectionError(f"Error when connecting to database: {str(e)}") | ||
| raise DatabaseError(f"Database error when fetching snack {sku}: {str(e)}") | ||
|
|
||
|
|
||
| def delete_snack(sku: str) -> Snack: | ||
| """Removes a snack from the database""" | ||
| with get_db_connection() as conn: | ||
| cursor = conn.cursor() | ||
| cursor.execute(""" | ||
| DELETE FROM snacks | ||
| WHERE sku = ? | ||
| RETURNING * | ||
| """, (sku,)) | ||
| record = cursor.fetchone() | ||
| return Snack(**record) | ||
|
|
||
|
|
||
| try: | ||
| with get_db_connection() as conn: | ||
| cursor = conn.cursor() | ||
| cursor.execute(""" | ||
| DELETE FROM snacks | ||
| WHERE sku = ? | ||
| RETURNING * | ||
| """, (sku,)) | ||
| record = cursor.fetchone() | ||
| return Snack(**record) | ||
| except sqlite3.Error as e: | ||
| raise DatabaseError(f"Database error when deleting snack {sku}: {str(e)}") | ||
|
|
||
|
|
||
| def create_snack(snack: SnackCreateSchema) -> Snack: | ||
| """Creates a new snack in the database""" | ||
| with get_db_connection() as conn: | ||
| cursor = conn.cursor() | ||
| cursor.execute(""" | ||
| INSERT INTO snacks | ||
| (sku, name, quantity, price, description, category, photo_url) | ||
| VALUES | ||
| (?, ?, ?, ?, ?, ?, ?) | ||
| RETURNING * | ||
| """, ( | ||
| snack.sku, | ||
| snack.name, | ||
| snack.quantity if snack.quantity is not None else 1, | ||
| snack.price, | ||
| snack.description, | ||
| snack.category, | ||
| snack.photo_url | ||
| )) | ||
| record = cursor.fetchone() | ||
| return Snack(**record) | ||
| try: | ||
| with get_db_connection() as conn: | ||
| cursor = conn.cursor() | ||
| cursor.execute(""" | ||
| INSERT INTO snacks | ||
| (sku, name, quantity, price, description, category, photo_url) | ||
| VALUES | ||
| (?, ?, ?, ?, ?, ?, ?) | ||
| RETURNING * | ||
| """, ( | ||
| snack.sku, | ||
| snack.name, | ||
| snack.quantity if snack.quantity is not None else 1, | ||
| snack.price, | ||
| snack.description, | ||
| snack.category, | ||
| snack.photo_url | ||
| )) | ||
| record = cursor.fetchone() | ||
| if not isinstance(snack.sku, str): | ||
| raise RecordNotFoundError(f"{snack.sku} is not a string") | ||
| if not isinstance(snack.name, str): | ||
| raise RecordNotFoundError(f"{snack.name} is not a string") | ||
| if not isinstance(snack.quantity, int): | ||
| raise RecordNotFoundError(f"{snack.quantity} is not an int") | ||
| if not isinstance(snack.price, float): | ||
| raise RecordNotFoundError(f"{snack.price} is not a float") | ||
| if not isinstance(snack.description, str): | ||
| raise RecordNotFoundError(f"{snack.description} is not a string") | ||
| if not isinstance(snack.category, str): | ||
| raise RecordNotFoundError(f"{snack.category} is not a string") | ||
| if not isinstance(snack.photo_url, str): | ||
| raise RecordNotFoundError(f"{snack.photo_url} is not a string") | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think we need to check the types here because the Pydantic models should be handling that for us. |
||
| return Snack(**record) | ||
| if record is none: | ||
| raise RecordNotFoundError(f"Error when creating snack: {str(e)}") | ||
| except sqlite3.Error as e: | ||
| raise DatabaseError(f"Database error when creating snack {snack.sku}: {str(e)}") | ||
|
|
||
|
|
||
| def update_snack(sku: str, updates: SnackUpdateSchema) -> Snack: | ||
| """Updates an existing snack in the database""" | ||
| with get_db_connection() as conn: | ||
| cursor = conn.cursor() | ||
| cursor.execute(""" | ||
| UPDATE snacks | ||
| SET | ||
| name = ?, | ||
| quantity = ?, | ||
| price = ?, | ||
| description = ?, | ||
| category = ?, | ||
| photo_url = ? | ||
| WHERE sku = ? | ||
| RETURNING * | ||
| """, ( | ||
| updates.name, | ||
| updates.quantity, | ||
| updates.price, | ||
| updates.description, | ||
| updates.category, | ||
| updates.photo_url, | ||
| sku | ||
| )) | ||
| record = cursor.fetchone() | ||
| return Snack(**record) | ||
| try: | ||
| with get_db_connection() as conn: | ||
| cursor = conn.cursor() | ||
| cursor.execute(""" | ||
| UPDATE snacks | ||
| SET | ||
| name = ?, | ||
| quantity = ?, | ||
| price = ?, | ||
| description = ?, | ||
| category = ?, | ||
| photo_url = ? | ||
| WHERE sku = ? | ||
| RETURNING * | ||
| """, ( | ||
| updates.name, | ||
| updates.quantity, | ||
| updates.price, | ||
| updates.description, | ||
| updates.category, | ||
| updates.photo_url, | ||
| sku | ||
| )) | ||
| record = cursor.fetchone() | ||
| return Snack(**record) | ||
| except sqlite3.Error as e: | ||
| raise DatabaseError(f"Database error when deleting snack {sku}: {str(e)}") | ||
|
|
||
|
|
||
| # Initialize the database and create tables | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| class DatabaseError(Exception): | ||
| """Base exception for database errors""" | ||
| pass | ||
|
|
||
| class ConnectionError(DatabaseError): | ||
| """Failed to connect to database""" | ||
| pass | ||
|
|
||
| class RecordNotFoundError(DatabaseError): | ||
| """Requested record does not exist""" | ||
| pass | ||
|
|
||
| class DuplicateRecordError(DatabaseError): | ||
| """Record with this identifier already exists""" | ||
| pass | ||
|
|
||
| class DatabaseInitError(DatabaseError): | ||
| """Failed to initialize database""" | ||
| pass |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can do something like this which makes it more readable