Skip to content

Commit 9fa577c

Browse files
committed
day1
1 parent 10cca67 commit 9fa577c

10 files changed

Lines changed: 800 additions & 5 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,3 +127,4 @@ dmypy.json
127127

128128
# Pyre type checker
129129
.pyre/
130+
*.db

.vscode/settings.json

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,14 @@
1919
"coverage.xml": true,
2020
".pytest_cache": true
2121
},
22-
"editor.mouseWheelZoom": true
22+
"editor.mouseWheelZoom": true,
23+
"python.testing.pytestArgs": [
24+
"tests"
25+
],
26+
"python.testing.unittestEnabled": false,
27+
"python.testing.pytestEnabled": true,
28+
"sqlite.logLevel": "DEBUG",
29+
"python.formatting.provider": "black",
30+
"editor.renderWhitespace": "boundary",
31+
"workbench.tree.renderIndentGuides": "always"
2332
}

beerlog/cli.py

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,52 @@
1-
from .config import settings
1+
import typer
2+
from typing import Optional
3+
from rich.console import Console
4+
from rich.table import Table
5+
from rich import print
26

7+
from beerlog.core import add_beer_to_database, get_beers_from_database
38

4-
def main():
5-
print("Hello from", settings.NAME)
9+
10+
main = typer.Typer(help="Beer Management Application")
11+
console = Console()
12+
13+
14+
@main.command()
15+
def add(
16+
name: str,
17+
style: str,
18+
flavor: int = typer.Option(...),
19+
image: int = typer.Option(...),
20+
cost: int = typer.Option(...),
21+
):
22+
"""Adds a new beer to the database"""
23+
if add_beer_to_database(name, style, flavor, image, cost):
24+
print(":beer_mug: Beer added!!!")
25+
else:
26+
print(":no_entry: - Cannot add beer.")
27+
28+
29+
@main.command("list")
30+
def list_beers(style: Optional[str] = None):
31+
"""Lists beers from the database"""
32+
beers = get_beers_from_database(style)
33+
table = Table(
34+
title="Beerlog Database" if not style else f"Beerlog {style}"
35+
)
36+
headers = [
37+
"id",
38+
"name",
39+
"style",
40+
"flavor",
41+
"image",
42+
"cost",
43+
"rate",
44+
"date",
45+
]
46+
for header in headers:
47+
table.add_column(header, style="magenta")
48+
for beer in beers:
49+
beer.date = beer.date.strftime("%Y-%m-%d")
50+
values = [str(getattr(beer, header)) for header in headers]
51+
table.add_row(*values)
52+
console.print(table)

beerlog/core.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
from typing import Optional, List
2+
from sqlmodel import select
3+
from beerlog.database import get_session
4+
from beerlog.models import Beer
5+
6+
7+
def add_beer_to_database(
8+
name: str,
9+
style: str,
10+
flavor: int,
11+
image: int,
12+
cost: int,
13+
) -> bool:
14+
with get_session() as session:
15+
beer = Beer(**locals())
16+
session.add(beer)
17+
session.commit()
18+
19+
return True
20+
21+
22+
def get_beers_from_database(style: Optional[str] = None) -> List[Beer]:
23+
with get_session() as session:
24+
sql = select(Beer)
25+
if style:
26+
sql = sql.where(Beer.style == style)
27+
return list(session.exec(sql))

beerlog/database.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import warnings
2+
from sqlalchemy.exc import SAWarning
3+
from sqlmodel.sql.expression import Select, SelectOfScalar
4+
5+
warnings.filterwarnings("ignore", category=SAWarning)
6+
SelectOfScalar.inherit_cache = True
7+
Select.inherit_cache = True
8+
9+
10+
from sqlmodel import create_engine, Session
11+
12+
from beerlog import models
13+
from beerlog.config import settings
14+
15+
engine = create_engine(settings.database.url, echo=False)
16+
models.SQLModel.metadata.create_all(engine)
17+
18+
19+
def get_session():
20+
return Session(engine)

beerlog/models.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
from sqlmodel import SQLModel, Field
2+
from datetime import datetime
3+
from typing import Optional
4+
from pydantic import validator # NEW
5+
from statistics import mean # NEW
6+
7+
8+
class Beer(SQLModel, table=True):
9+
id: Optional[int] = Field(primary_key=True, default=None, index=True)
10+
name: str
11+
style: str
12+
flavor: int
13+
image: int
14+
cost: int
15+
rate: int = 0
16+
date: datetime = Field(default_factory=datetime.now)
17+
18+
# NEW
19+
@validator("image", "flavor", "cost")
20+
def validate_ratings(cls, v, field):
21+
if v < 1 or v > 10:
22+
raise RuntimeError(f"{field.name} must be between 1 and 10")
23+
return v
24+
25+
@validator("rate", always=True)
26+
def calculate_rate(cls, v, values):
27+
rate = mean([values["flavor"], values["image"], values["cost"]])
28+
return int(rate)
29+
30+
31+
beer = Beer(name="Lagunitas", style="IPA", flavor=3, image=6, cost=8)

beerlog/settings.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
11
name = "beerlog"
2+
3+
[database]
4+
url = "sqlite:///beerlog.db"

0 commit comments

Comments
 (0)