wip
This commit is contained in:
parent
c238b9d757
commit
fcc0698aeb
12 changed files with 95 additions and 97 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -963,3 +963,5 @@ FodyWeavers.xsd
|
||||||
|
|
||||||
# End of https://www.toptal.com/developers/gitignore/api/vim,node,data,emacs,python,pycharm,executable,sublimetext,visualstudio,visualstudiocode
|
# End of https://www.toptal.com/developers/gitignore/api/vim,node,data,emacs,python,pycharm,executable,sublimetext,visualstudio,visualstudiocode
|
||||||
database.db
|
database.db
|
||||||
|
database.db
|
||||||
|
database.db
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ learn-sql-model hero get --id 0
|
||||||
## Use python to manage Heros
|
## Use python to manage Heros
|
||||||
|
|
||||||
```python
|
```python
|
||||||
from learn_sql_model.models import Hero
|
from learn_sql_model.models.hero import Hero
|
||||||
# create a hero
|
# create a hero
|
||||||
bruce = Hero(name="Batman", secret_name="Bruce Wayne")
|
bruce = Hero(name="Batman", secret_name="Bruce Wayne")
|
||||||
bruce.post()
|
bruce.post()
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,7 @@
|
||||||
from typing import Union
|
from typing import Union
|
||||||
|
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI
|
||||||
import httpx
|
|
||||||
|
|
||||||
from learn_sql_model.console import console
|
|
||||||
from learn_sql_model.models.hero import Hero
|
from learn_sql_model.models.hero import Hero
|
||||||
from learn_sql_model.models.pet import Pet
|
from learn_sql_model.models.pet import Pet
|
||||||
|
|
||||||
|
|
@ -13,53 +11,3 @@ models = Union[Hero, Pet]
|
||||||
# from learn_sql_model.models import Hero
|
# from learn_sql_model.models import Hero
|
||||||
|
|
||||||
app = FastAPI()
|
app = FastAPI()
|
||||||
|
|
||||||
|
|
||||||
app.post("/heroes/")
|
|
||||||
|
|
||||||
|
|
||||||
def post(self: models) -> None:
|
|
||||||
|
|
||||||
try:
|
|
||||||
httpx.post("http://localhost:5000/heroes/", json=self.dict())
|
|
||||||
except httpx.ConnectError:
|
|
||||||
console.log("local failover")
|
|
||||||
post_local(self)
|
|
||||||
|
|
||||||
|
|
||||||
def post_local(self: models) -> None:
|
|
||||||
from learn_sql_model.config import config
|
|
||||||
|
|
||||||
with config.session as session:
|
|
||||||
session.add(self)
|
|
||||||
session.commit()
|
|
||||||
|
|
||||||
|
|
||||||
def get(self: models, instance: models = None) -> list[models]:
|
|
||||||
"read all the heros"
|
|
||||||
from learn_sql_model.config import config
|
|
||||||
|
|
||||||
with config.session as session:
|
|
||||||
if instance is None:
|
|
||||||
heroes = session.exec(select(self)).all()
|
|
||||||
return heroes
|
|
||||||
else:
|
|
||||||
hero = session.exec(select(self).where(self.id == instance.id)).all().one()
|
|
||||||
return hero
|
|
||||||
|
|
||||||
|
|
||||||
@app.post("/heroes/")
|
|
||||||
def create_hero(hero: Hero):
|
|
||||||
post(hero)
|
|
||||||
|
|
||||||
|
|
||||||
@app.get("/heroes/")
|
|
||||||
def read_heroes() -> list[Hero]:
|
|
||||||
"read all the heros"
|
|
||||||
return get(Hero)
|
|
||||||
|
|
||||||
|
|
||||||
@app.get("/hero/")
|
|
||||||
def read_heroes(hero: Hero) -> list[Hero]:
|
|
||||||
"read all the heros"
|
|
||||||
return get(Hero, hero)
|
|
||||||
|
|
|
||||||
|
|
@ -28,4 +28,4 @@ def post_hero(hero: Hero) -> Hero:
|
||||||
@hero_router.get("/heros/")
|
@hero_router.get("/heros/")
|
||||||
def get_heros() -> list[Hero]:
|
def get_heros() -> list[Hero]:
|
||||||
"get all heros"
|
"get all heros"
|
||||||
return Hero.get()
|
return Hero().get()
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import typer
|
||||||
import uvicorn
|
import uvicorn
|
||||||
|
|
||||||
from learn_sql_model.cli.common import verbose_callback
|
from learn_sql_model.cli.common import verbose_callback
|
||||||
from learn_sql_model.config import config
|
from learn_sql_model.config import get_config
|
||||||
|
|
||||||
api_app = typer.Typer()
|
api_app = typer.Typer()
|
||||||
|
|
||||||
|
|
@ -26,4 +26,4 @@ def run(
|
||||||
help="show the log messages",
|
help="show the log messages",
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
uvicorn.run("learn_sql_model.api.app:app", port=config.port, log_level="info")
|
uvicorn.run("learn_sql_model.api.app:app", port=get_config().port, log_level="info")
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ from rich.console import Console
|
||||||
import typer
|
import typer
|
||||||
|
|
||||||
from learn_sql_model.cli.common import verbose_callback
|
from learn_sql_model.cli.common import verbose_callback
|
||||||
from learn_sql_model.config import config as configuration
|
from learn_sql_model.config import get_config
|
||||||
|
|
||||||
config_app = typer.Typer()
|
config_app = typer.Typer()
|
||||||
|
|
||||||
|
|
@ -26,4 +26,4 @@ def show(
|
||||||
help="show the log messages",
|
help="show the log messages",
|
||||||
),
|
),
|
||||||
):
|
):
|
||||||
Console().print(configuration)
|
Console().print(get_config())
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ def hero():
|
||||||
@hero_app.command()
|
@hero_app.command()
|
||||||
def get(id: int = None) -> Union[Hero, List[Hero]]:
|
def get(id: int = None) -> Union[Hero, List[Hero]]:
|
||||||
"get one hero"
|
"get one hero"
|
||||||
hero = Hero.get(item_id=id)
|
hero = Hero().get(item_id=id)
|
||||||
Console().print(hero)
|
Console().print(hero)
|
||||||
return hero
|
return hero
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,40 @@
|
||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from pydantic import BaseSettings
|
from pydantic import BaseSettings
|
||||||
from sqlmodel import SQLModel, Session, create_engine
|
from sqlalchemy import create_engine
|
||||||
|
from sqlmodel import SQLModel, Session
|
||||||
|
|
||||||
from learn_sql_model.models.hero import Hero
|
|
||||||
from learn_sql_model.models.pet import Pet
|
|
||||||
from learn_sql_model.standard_config import load
|
from learn_sql_model.standard_config import load
|
||||||
|
|
||||||
models = [Hero, Pet]
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from sqlalchemy import Engine
|
from sqlalchemy import Engine
|
||||||
|
|
||||||
|
|
||||||
|
class Database:
|
||||||
|
def __init__(self, config: "Config" = None) -> None:
|
||||||
|
if config is None:
|
||||||
|
|
||||||
|
self.config = get_config()
|
||||||
|
else:
|
||||||
|
self.config = config
|
||||||
|
self.create_db_and_tables()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def engine(self) -> "Engine":
|
||||||
|
return create_engine(self.config.database_url)
|
||||||
|
|
||||||
|
def session(self) -> "Session":
|
||||||
|
return Session(self.engine)
|
||||||
|
|
||||||
|
def create_db_and_tables(self) -> None:
|
||||||
|
from learn_sql_model.models.hero import Hero
|
||||||
|
from learn_sql_model.models.pet import Pet
|
||||||
|
|
||||||
|
__all__ = [Hero, Pet]
|
||||||
|
|
||||||
|
SQLModel.metadata.create_all(self.engine)
|
||||||
|
|
||||||
|
|
||||||
class Config(BaseSettings):
|
class Config(BaseSettings):
|
||||||
database_url: str = "sqlite:///database.db"
|
database_url: str = "sqlite:///database.db"
|
||||||
port: int = 5000
|
port: int = 5000
|
||||||
|
|
@ -21,27 +43,19 @@ class Config(BaseSettings):
|
||||||
env_prefix = "LEARN_SQL_MODEL_"
|
env_prefix = "LEARN_SQL_MODEL_"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def engine(self) -> "Engine":
|
def database(self) -> Database:
|
||||||
return create_engine(self.database_url)
|
return get_database(config=self)
|
||||||
|
|
||||||
@property
|
|
||||||
def session(self) -> "Session":
|
|
||||||
return Session(self.engine)
|
|
||||||
|
|
||||||
def create_db_and_tables(self) -> None:
|
def get_database(config: Config = None) -> Database:
|
||||||
SQLModel.metadata.create_all(self.engine)
|
|
||||||
|
|
||||||
# def create_endpoints(self) -> None:
|
if config is None:
|
||||||
# for model in models:
|
config = get_config()
|
||||||
# app.post("/heroes/")(Hero.post_local)
|
|
||||||
# app.get("/heroes/")(Hero.read_heroes)
|
return Database(config)
|
||||||
|
|
||||||
|
|
||||||
def get_config(overrides: dict = {}) -> Config:
|
def get_config(overrides: dict = {}) -> Config:
|
||||||
raw_config = load("learn_sql_model")
|
raw_config = load("learn_sql_model")
|
||||||
config = Config(**raw_config, **overrides)
|
config = Config(**raw_config, **overrides)
|
||||||
config.create_db_and_tables()
|
|
||||||
return config
|
return config
|
||||||
|
|
||||||
|
|
||||||
config = get_config()
|
|
||||||
|
|
|
||||||
0
learn_sql_model/database.py
Normal file
0
learn_sql_model/database.py
Normal file
15
learn_sql_model/models.py
Normal file
15
learn_sql_model/models.py
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import Optional
|
||||||
|
|
||||||
|
from learn_sql_model.models.fast_model import FastModel
|
||||||
|
from sqlmodel import Field
|
||||||
|
|
||||||
|
|
||||||
|
class Hero(FastModel, table=True):
|
||||||
|
id: Optional[int] = Field(default=None, primary_key=True)
|
||||||
|
name: str
|
||||||
|
secret_name: str
|
||||||
|
age: Optional[int] = None
|
||||||
|
# new_attribute: Optional[str] = None
|
||||||
|
# pets: List["Pet"] = Relationship(back_populates="hero")
|
||||||
|
|
@ -2,6 +2,8 @@ from typing import Optional, TYPE_CHECKING
|
||||||
|
|
||||||
from sqlmodel import SQLModel, select
|
from sqlmodel import SQLModel, select
|
||||||
|
|
||||||
|
from learn_sql_model.config import get_config
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from learn_sql_model.config import Config
|
from learn_sql_model.config import Config
|
||||||
|
|
||||||
|
|
@ -19,28 +21,36 @@ class FastModel(SQLModel):
|
||||||
|
|
||||||
def post(self, config: "Config" = None) -> None:
|
def post(self, config: "Config" = None) -> None:
|
||||||
if config is None:
|
if config is None:
|
||||||
from learn_sql_model.config import get_config
|
|
||||||
|
|
||||||
config = get_config()
|
config = get_config()
|
||||||
|
|
||||||
self.pre_post()
|
self.pre_post()
|
||||||
|
|
||||||
with config.session as session:
|
instance = self.__class__(**self.dict())
|
||||||
|
|
||||||
|
with config.database.session() as session:
|
||||||
session.add(self)
|
session.add(self)
|
||||||
session.commit()
|
session.commit()
|
||||||
|
return instance
|
||||||
|
|
||||||
@classmethod
|
def get(self, id: int = None, config: "Config" = None) -> Optional["FastModel"]:
|
||||||
def get(
|
|
||||||
self, item_id: int = None, config: "Config" = None
|
|
||||||
) -> Optional["FastModel"]:
|
|
||||||
if config is None:
|
if config is None:
|
||||||
from learn_sql_model.config import get_config
|
|
||||||
|
|
||||||
config = get_config()
|
config = get_config()
|
||||||
|
|
||||||
self.pre_get()
|
self.pre_get()
|
||||||
|
|
||||||
with config.session as session:
|
with config.database.session() as session:
|
||||||
if item_id is None:
|
if id is None:
|
||||||
return session.exec(select(self)).all()
|
print("get all")
|
||||||
return session.exec(select(self).where(self.id == item_id)).one()
|
statement = select(self.__class__)
|
||||||
|
results = session.exec(statement).all()
|
||||||
|
else:
|
||||||
|
print("get by id")
|
||||||
|
statement = select(self.__class__).where(self.__class__.id == id)
|
||||||
|
results = session.exec(statement).one()
|
||||||
|
return results
|
||||||
|
|
||||||
|
# TODO
|
||||||
|
# update
|
||||||
|
# delete
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
import tempfile
|
import tempfile
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from sqlmodel import Session
|
|
||||||
|
|
||||||
from learn_sql_model.config import Config, get_config
|
from learn_sql_model.config import Config, get_config
|
||||||
from learn_sql_model.factories.hero import HeroFactory
|
from learn_sql_model.factories.hero import HeroFactory
|
||||||
|
|
@ -11,15 +10,25 @@ Hero
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def config() -> Session:
|
def config() -> Config:
|
||||||
tmp_db = tempfile.NamedTemporaryFile(suffix=".db")
|
tmp_db = tempfile.NamedTemporaryFile(suffix=".db")
|
||||||
config = get_config({"database_url": f"sqlite:///{tmp_db.name}"})
|
config = get_config({"database_url": f"sqlite:///{tmp_db.name}"})
|
||||||
config.create_db_and_tables()
|
|
||||||
return config
|
return config
|
||||||
|
|
||||||
|
|
||||||
def test_post_hero(config: Config) -> None:
|
def test_post_hero(config: Config) -> None:
|
||||||
hero = HeroFactory().build(name="Batman", age=50)
|
hero = HeroFactory().build(name="Batman", age=50, id=1)
|
||||||
hero.post(config=config)
|
hero = hero.post(config=config)
|
||||||
assert hero.get(hero.id) == hero
|
db_hero = Hero().get(hero.id, config=config)
|
||||||
breakpoint()
|
assert db_hero == hero
|
||||||
|
|
||||||
|
|
||||||
|
def test_update_hero(config: Config) -> None:
|
||||||
|
hero = HeroFactory().build(name="Batman", age=50, id=1)
|
||||||
|
hero = hero.post(config=config)
|
||||||
|
db_hero = Hero().get(id=hero.id, config=config)
|
||||||
|
assert db_hero.dict() == hero.dict()
|
||||||
|
db_hero.name = "Superman"
|
||||||
|
hero = db_hero.post(config=config)
|
||||||
|
db_hero = Hero().get(id=hero.id, config=config)
|
||||||
|
assert db_hero.dict() == hero.dict()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue