Skip to content
Open
Show file tree
Hide file tree
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
44 changes: 44 additions & 0 deletions .github/workflows/main.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: CIBeerLog
on:
push:
branches:
- "*"
pull_request:
branches:
- "*"
workflow_dispatch:

jobs:
test:
strategy:
fail-fast: true
matrix:
python-version: ['3.8', '3.10']
os: [ubuntu-latest]
runs-on: ${{matrix.os}}
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: ${{matrix.python-version}}
- name: Install Poetry
run: pip install --upgrade pip && pip install poetry

- name: Install Project
run: poetry install

- name: Look for style errors
run: poetry run flake8 beerlog

- name: Look for auto format errors
run: poetry run black -l 79 --check --diff beerlog tests

- name: Run tests
run: poetry run pytest -v --junitxml=test-result.xml

- name: publish junit results
uses: EnricoMi/publish-unit-test-result-action@v1
if: always()
with:
files: test-result.xml
check_name: Test Result (Python ${{matrix.python-version}})
25 changes: 14 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
# python-week-2022
Template Para a Python Week 2002 - 25 a 29 de Abril na Linux Tips

Template Para a Python Week 2022 - 25 a 29 de Abril na Linux Tips

## Instruções

Este repositório é um template de um projeto Python minimo
O programa se chama `beerlog` e está organizado com pastas
O programa se chama `beerlog` e está organizado com pastas
e módulos, porém a maioria dos arquivos encontra-se vazio.

A apartir deste template você poderá acompanhar as lives
Expand All @@ -22,14 +23,14 @@ da Python week e programar junto com o Bruno e o Jeferson.
> **OBS** substitua `SEUNOME` pelo seu nome de usuário do github.

- Você pode rodar localmente em seu computador desde que tenha o Python 3.8+
- Para rodar localmente faça o clone com `git clone https://github.com/SEUNOME/python-week-2022`
- Acesse a pasta `cd python-week-2022`
- Para rodar localmente faça o clone com `git clone https://github.com/SEUNOME/python-week-2022`
- Acesse a pasta `cd python-week-2022`
- Você pode rodar no [https://gitpod.io](https://gitpod.io) **recomendado**
- Para rodar no gitpod acesse no navegador `https://gitpod.io/#https://github.com/SEUNOME/python-week-2022`
- **OBS** O plano free do github permite o uso de 40 horas do ambiente.
- Para rodar no gitpod acesse no navegador `https://gitpod.io/#https://github.com/SEUNOME/python-week-2022`
- **OBS** O plano free do gitpod permite o uso de 40 horas do ambiente.
- Você pode rodar no [https://replit.com/](https://replit.com/) diretamente no browser
- Para rodar no replit, crie um replit e escolha a opção `importar do github` e informe o repositório
- **OBS** O replit.com tem limite de consumo de memória e CPU
- Para rodar no replit, crie um replit e escolha a opção `importar do github` e informe o repositório
- **OBS** O replit.com tem limite de consumo de memória e CPU
- Ou em qualquer plataforma que permita executar Python 3.8

## Requisitos
Expand All @@ -39,16 +40,18 @@ Este template utiliza o gerenciador de pacotes **poetry**
### Se estiver rodando no Linux no seu ambiente local

`execute o comando abaixo para instalar o Poetry no Linux`

```bash
curl -sSL https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py | python -
```

`Em outros ambientes pode instalar com `
`Em outros ambientes pode instalar com`

```bash
pip install --user poetry
```

> No replit.com o poetry já está disponível e no gitpod será instalado assim que o ambiente iniciar.
> No replit.com o poetry já está disponível e no gitpod será instalado assim que o ambiente iniciar.

## Instalando o ambiente

Expand All @@ -57,8 +60,8 @@ poetry install
poetry shell
```


Executando

```bash
beerlog
# ou
Expand Down
Binary file added beerlog.db
Binary file not shown.
29 changes: 29 additions & 0 deletions beerlog/api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from typing import List, Optional

from fastapi import FastAPI, Response, status

from beerlog.core import get_beers_from_database
from beerlog.database import get_session
from beerlog.models import Beer
from beerlog.serializers import BeerIn, BeerOut

api = FastAPI(title="beerlog")


@api.get("/beers", response_model=List[BeerOut])
async def list_beers(style: Optional[str] = None):
"""Lists beers from the database"""
beers = get_beers_from_database(style)
return beers


@api.post("/beers", response_model=BeerOut)
async def add_beer(beer_in: BeerIn, response: Response):
beer = Beer(**beer_in.dict())
with get_session() as session:
session.add(beer)
session.commit()
session.refresh(beer)

response.status_code = status.HTTP_201_CREATED
return beer
56 changes: 53 additions & 3 deletions beerlog/cli.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,55 @@
from .config import settings
from typing import Optional

import typer
from rich import print # NEW
from rich.console import Console # NEW
from rich.table import Table # NEW

def main():
print("Hello from", settings.NAME)
from beerlog.core import add_beer_to_database, get_beers_from_database

main = typer.Typer(help="Beer Management Application")
console = Console()


@main.command()
def add(
name: str,
style: str,
flavor: int = typer.Option(...),
image: int = typer.Option(...),
cost: int = typer.Option(...),
):
"""Adds a new beer to the database"""
if add_beer_to_database(name, style, flavor, image, cost):
print(":beer_mug: Beer added!!!") # NEW
else:
print(":no_entry: - Cannot add beer.") # NEW


# NEW
@main.command("list")
def list_beers(style: Optional[str] = None):
"""Lists beers from the database"""
beers = get_beers_from_database(style)
table = Table(
title="Beerlog Database :beer_mug:"
if not style
else f"Beerlog {style}"
)
headers = [
"id",
"name",
"style",
"flavor",
"image",
"cost",
"rate",
"date",
]
for header in headers:
table.add_column(header, style="magenta")
for beer in beers:
beer.date = beer.date.strftime("%Y-%m-%d")
values = [str(getattr(beer, header)) for header in headers]
table.add_row(*values)
console.print(table)
2 changes: 1 addition & 1 deletion beerlog/config.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import os
from dynaconf import Dynaconf

from dynaconf import Dynaconf

settings = Dynaconf(
envvar_prefix="BEERLOG",
Expand Down
29 changes: 29 additions & 0 deletions beerlog/core.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from typing import List, Optional

from sqlmodel import select

from beerlog.database import get_session
from beerlog.models import Beer


def add_beer_to_database(
name: str,
style: str,
flavor: int,
image: int,
cost: int,
) -> bool:
with get_session() as session:
beer = Beer(**locals())
session.add(beer)
session.commit()

return True


def get_beers_from_database(style: Optional[str] = None) -> List[Beer]:
with get_session() as session:
sql = select(Beer)
if style:
sql = sql.where(Beer.style == style)
return list(session.exec(sql))
18 changes: 18 additions & 0 deletions beerlog/database.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import warnings
from sqlmodel import Session, create_engine
from beerlog import models
from beerlog.config import settings # NEW
from sqlalchemy.exc import SAWarning
from sqlmodel.sql.expression import Select, SelectOfScalar

warnings.filterwarnings("ignore", category=SAWarning)
SelectOfScalar.inherit_cache = True
Select.inherit_cache = True

engine = create_engine(settings.database.url) # NEW
models.SQLModel.metadata.create_all(engine)


# NEW
def get_session():
return Session(engine)
30 changes: 30 additions & 0 deletions beerlog/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from datetime import datetime
from statistics import mean # NEW
from typing import Optional

from pydantic import validator # NEW
from sqlmodel import Field, SQLModel


class Beer(SQLModel, table=True):
id: Optional[int] = Field(primary_key=True, default=None, index=True)
name: str
style: str
flavor: int
image: int
cost: int
rate: int = 0
date: datetime = Field(default_factory=datetime.now)

# NEW
@validator("image", "flavor", "cost")
def validate_ratings(cls, v, field):
if v < 1 or v > 10:
raise RuntimeError(f"{field.name} must be between 1 and 10")
return v

# NEW
@validator("rate", always=True)
def calculate_rate(cls, v, values):
rate = mean([values["flavor"], values["image"], values["cost"]])
return int(rate)
32 changes: 32 additions & 0 deletions beerlog/serializers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from datetime import datetime

from fastapi import HTTPException, status
from pydantic import BaseModel, validator


class BeerOut(BaseModel):
id: int
name: str
style: str
flavor: int
image: int
cost: int
rate: int
date: datetime


class BeerIn(BaseModel):
name: str
style: str
flavor: int
image: int
cost: int

@validator("image", "flavor", "cost")
def validate_ratings(cls, v, field):
if v < 1 or v > 10:
raise HTTPException(
detail=f"{field.name} must be between 1 and 10",
status_code=status.HTTP_400_BAD_REQUEST,
)
return v
3 changes: 3 additions & 0 deletions beerlog/settings.toml
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
name = "beerlog"

[database]
url = "sqlite:///beerlog.db"
14 changes: 14 additions & 0 deletions conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import pytest
from unittest.mock import patch
from sqlmodel import create_engine
from beerlog import models


@pytest.fixture(autouse=True, scope="function")
def each_test_uses_separate_database(request):
tmpdir = request.getfixturevalue("tmpdir")
test_db = tmpdir.join("beerlog.test.db")
engine = create_engine(f"sqlite:///{test_db}")
models.SQLModel.metadata.create_all(bind=engine)
with patch("beerlog.database.engine", engine):
yield
Loading