mirror of
https://github.com/ijaric/voice_assistant.git
synced 2025-05-24 14:33:26 +00:00
Merge pull request #34 from ijaric/test/try_postgres
Пример: Handler, Service & Repository
This commit is contained in:
commit
eab9177c00
43
package-lock.json
generated
43
package-lock.json
generated
|
@ -11,7 +11,7 @@
|
||||||
"husky": "^8.0.1",
|
"husky": "^8.0.1",
|
||||||
"lint-staged": "^13.0.3",
|
"lint-staged": "^13.0.3",
|
||||||
"prettier": "2.8.3",
|
"prettier": "2.8.3",
|
||||||
"pyright": "^1.1.299"
|
"pyright": "^1.1.329"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/code-frame": {
|
"node_modules/@babel/code-frame": {
|
||||||
|
@ -1063,6 +1063,20 @@
|
||||||
"node": ">=14.14"
|
"node": ">=14.14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/fsevents": {
|
||||||
|
"version": "2.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
||||||
|
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
|
||||||
|
"dev": true,
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"optional": true,
|
||||||
|
"os": [
|
||||||
|
"darwin"
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/function-bind": {
|
"node_modules/function-bind": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
||||||
|
@ -2215,9 +2229,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/pyright": {
|
"node_modules/pyright": {
|
||||||
"version": "1.1.299",
|
"version": "1.1.329",
|
||||||
"resolved": "https://registry.npmjs.org/pyright/-/pyright-1.1.299.tgz",
|
"resolved": "https://registry.npmjs.org/pyright/-/pyright-1.1.329.tgz",
|
||||||
"integrity": "sha512-37agqu0oNRsftFHNyGtaN3SBJJ+Qe2pembdgIpif9iL0VNqCU7j3wauSm8j0peXg1uNHFcS8UMrft4hT7w2XvQ==",
|
"integrity": "sha512-5AT98Mi0OYcDiQ5lD1nPJ3cq8gX/HHaXrQ5WjJ/QZkaJtGqnEdrUp5Gq5wBPipWgOnv/l5e50YScaaNDMjoy9Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"pyright": "index.js",
|
"pyright": "index.js",
|
||||||
|
@ -2225,6 +2239,9 @@
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12.0.0"
|
"node": ">=12.0.0"
|
||||||
|
},
|
||||||
|
"optionalDependencies": {
|
||||||
|
"fsevents": "~2.3.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/q": {
|
"node_modules/q": {
|
||||||
|
@ -3883,6 +3900,13 @@
|
||||||
"universalify": "^2.0.0"
|
"universalify": "^2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"fsevents": {
|
||||||
|
"version": "2.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
||||||
|
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
|
||||||
|
"dev": true,
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
"function-bind": {
|
"function-bind": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
||||||
|
@ -4702,10 +4726,13 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"pyright": {
|
"pyright": {
|
||||||
"version": "1.1.299",
|
"version": "1.1.329",
|
||||||
"resolved": "https://registry.npmjs.org/pyright/-/pyright-1.1.299.tgz",
|
"resolved": "https://registry.npmjs.org/pyright/-/pyright-1.1.329.tgz",
|
||||||
"integrity": "sha512-37agqu0oNRsftFHNyGtaN3SBJJ+Qe2pembdgIpif9iL0VNqCU7j3wauSm8j0peXg1uNHFcS8UMrft4hT7w2XvQ==",
|
"integrity": "sha512-5AT98Mi0OYcDiQ5lD1nPJ3cq8gX/HHaXrQ5WjJ/QZkaJtGqnEdrUp5Gq5wBPipWgOnv/l5e50YScaaNDMjoy9Q==",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"fsevents": "~2.3.2"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"q": {
|
"q": {
|
||||||
"version": "1.5.1",
|
"version": "1.5.1",
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
"husky": "^8.0.1",
|
"husky": "^8.0.1",
|
||||||
"lint-staged": "^13.0.3",
|
"lint-staged": "^13.0.3",
|
||||||
"prettier": "2.8.3",
|
"prettier": "2.8.3",
|
||||||
"pyright": "^1.1.299"
|
"pyright": "^1.1.329"
|
||||||
},
|
},
|
||||||
"hooks": {
|
"hooks": {
|
||||||
"commit-msg": "commitlint"
|
"commit-msg": "commitlint"
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
"""Added initial table
|
||||||
|
|
||||||
|
Revision ID: 9749b063b095
|
||||||
|
Revises:
|
||||||
|
Create Date: 2023-10-02 19:46:05.078494
|
||||||
|
|
||||||
|
"""
|
||||||
|
from typing import Sequence, Union
|
||||||
|
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
from alembic import op
|
||||||
|
|
||||||
|
# revision identifiers, used by Alembic.
|
||||||
|
revision: str = "9749b063b095"
|
||||||
|
down_revision: Union[str, None] = None
|
||||||
|
branch_labels: Union[str, Sequence[str], None] = None
|
||||||
|
depends_on: Union[str, Sequence[str], None] = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade() -> None:
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.create_table(
|
||||||
|
"joke",
|
||||||
|
sa.Column("type", sa.String(), nullable=False),
|
||||||
|
sa.Column("setup", sa.String(), nullable=False),
|
||||||
|
sa.Column("punchline", sa.String(), nullable=False),
|
||||||
|
sa.Column("id", sa.Uuid(), nullable=False),
|
||||||
|
sa.PrimaryKeyConstraint("id"),
|
||||||
|
)
|
||||||
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade() -> None:
|
||||||
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
|
op.drop_table("joke")
|
||||||
|
# ### end Alembic commands ###
|
|
@ -1,5 +1,4 @@
|
||||||
from .health import *
|
from .health import basic_router
|
||||||
|
from .joke import JokeHandler
|
||||||
|
|
||||||
__all__ = [
|
__all__ = ["JokeHandler", "basic_router"]
|
||||||
"basic_router",
|
|
||||||
]
|
|
||||||
|
|
25
src/fastapi_app/lib/api/v1/handlers/joke.py
Normal file
25
src/fastapi_app/lib/api/v1/handlers/joke.py
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
import fastapi
|
||||||
|
|
||||||
|
import lib.api.v1.schemas as api_shemas
|
||||||
|
import lib.joke.services as joke_services
|
||||||
|
|
||||||
|
|
||||||
|
class JokeHandler:
|
||||||
|
def __init__(self, joke_service: joke_services.JokeService):
|
||||||
|
self.joke_service = joke_service
|
||||||
|
self.router = fastapi.APIRouter()
|
||||||
|
self.router.add_api_route(
|
||||||
|
"/",
|
||||||
|
self.get_joke,
|
||||||
|
methods=["GET"],
|
||||||
|
summary="Статус работоспособности",
|
||||||
|
description="Проверяет доступность сервиса FastAPI.",
|
||||||
|
)
|
||||||
|
|
||||||
|
async def get_joke(self):
|
||||||
|
joke = await self.joke_service.get_joke()
|
||||||
|
if joke:
|
||||||
|
return api_shemas.JokeResponse(
|
||||||
|
joke=f"{joke.setup}\n{joke.punchline}", id=joke.id_field, category=joke.type_field
|
||||||
|
)
|
||||||
|
return api_shemas.JokeResponse(joke="No joke for you!", id=0, category="No category")
|
|
@ -1,5 +1,4 @@
|
||||||
from .base import HealthResponseModel
|
from .base import HealthResponseModel
|
||||||
|
from .joke import JokeResponse
|
||||||
|
|
||||||
__all__ = [
|
__all__ = ["HealthResponseModel", "JokeResponse"]
|
||||||
"HealthResponseModel",
|
|
||||||
]
|
|
||||||
|
|
7
src/fastapi_app/lib/api/v1/schemas/joke.py
Normal file
7
src/fastapi_app/lib/api/v1/schemas/joke.py
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import pydantic
|
||||||
|
|
||||||
|
|
||||||
|
class JokeResponse(pydantic.BaseModel):
|
||||||
|
id_field: int = pydantic.Field(alias="id")
|
||||||
|
joke: str
|
||||||
|
category: str
|
|
@ -11,6 +11,8 @@ import lib.app.errors as app_errors
|
||||||
import lib.app.settings as app_settings
|
import lib.app.settings as app_settings
|
||||||
import lib.app.split_settings as app_split_settings
|
import lib.app.split_settings as app_split_settings
|
||||||
import lib.clients as clients
|
import lib.clients as clients
|
||||||
|
import lib.joke.repository as joke_repository
|
||||||
|
import lib.joke.services as joke_services
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -45,7 +47,6 @@ class Application:
|
||||||
|
|
||||||
logger.info("Initializing global clients")
|
logger.info("Initializing global clients")
|
||||||
postgres_client = clients.AsyncPostgresClient(settings=settings)
|
postgres_client = clients.AsyncPostgresClient(settings=settings)
|
||||||
http_client = clients.get_async_http_session()
|
|
||||||
|
|
||||||
disposable_resources.append(
|
disposable_resources.append(
|
||||||
DisposableResource(
|
DisposableResource(
|
||||||
|
@ -61,6 +62,7 @@ class Application:
|
||||||
# Repositories
|
# Repositories
|
||||||
|
|
||||||
logger.info("Initializing repositories")
|
logger.info("Initializing repositories")
|
||||||
|
jk_repository = joke_repository.JokeRepository(async_session=postgres_client.get_async_session())
|
||||||
|
|
||||||
# Caches
|
# Caches
|
||||||
|
|
||||||
|
@ -69,12 +71,13 @@ class Application:
|
||||||
# Services
|
# Services
|
||||||
|
|
||||||
logger.info("Initializing services")
|
logger.info("Initializing services")
|
||||||
|
jk_serivces = joke_services.JokeService(jk_repository)
|
||||||
|
|
||||||
# Handlers
|
# Handlers
|
||||||
|
|
||||||
logger.info("Initializing handlers")
|
logger.info("Initializing handlers")
|
||||||
liveness_probe_handler = api_v1_handlers.basic_router
|
liveness_probe_handler = api_v1_handlers.basic_router
|
||||||
|
joke_handler = api_v1_handlers.JokeHandler(joke_service=jk_serivces).router
|
||||||
|
|
||||||
logger.info("Creating application")
|
logger.info("Creating application")
|
||||||
|
|
||||||
|
@ -88,6 +91,7 @@ class Application:
|
||||||
|
|
||||||
# Routes
|
# Routes
|
||||||
fastapi_app.include_router(liveness_probe_handler, prefix="/api/v1/health", tags=["health"])
|
fastapi_app.include_router(liveness_probe_handler, prefix="/api/v1/health", tags=["health"])
|
||||||
|
fastapi_app.include_router(joke_handler, prefix="/test", tags=["some"])
|
||||||
|
|
||||||
application = Application(
|
application = Application(
|
||||||
settings=settings,
|
settings=settings,
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
from .httpx import get_async_http_session
|
|
||||||
from .postgres import AsyncPostgresClient
|
from .postgres import AsyncPostgresClient
|
||||||
|
|
||||||
__all__ = ["AsyncPostgresClient", "get_async_http_session"]
|
__all__ = ["AsyncPostgresClient"]
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
import contextlib
|
|
||||||
import typing
|
|
||||||
|
|
||||||
import httpx
|
|
||||||
|
|
||||||
|
|
||||||
@contextlib.asynccontextmanager
|
|
||||||
async def get_async_http_session(
|
|
||||||
settings: dict[str, typing.Any] | None = None
|
|
||||||
) -> typing.AsyncGenerator[httpx.AsyncClient, None]:
|
|
||||||
"""Async http client."""
|
|
||||||
if settings is None:
|
|
||||||
settings = {}
|
|
||||||
client = httpx.AsyncClient(**settings) # Insert your own settings here
|
|
||||||
async with client as ac:
|
|
||||||
yield ac
|
|
4
src/fastapi_app/lib/joke/__init__.py
Normal file
4
src/fastapi_app/lib/joke/__init__.py
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
from .repository import JokeRepository
|
||||||
|
from .services import JokeService
|
||||||
|
|
||||||
|
__all__ = ["JokeRepository", "JokeService"]
|
30
src/fastapi_app/lib/joke/repository.py
Normal file
30
src/fastapi_app/lib/joke/repository.py
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
import logging
|
||||||
|
|
||||||
|
import sqlalchemy.exc
|
||||||
|
import sqlalchemy.ext.asyncio as sa_asyncio
|
||||||
|
|
||||||
|
import lib.models as models
|
||||||
|
|
||||||
|
|
||||||
|
class JokeRepository:
|
||||||
|
def __init__(self, async_session: sa_asyncio.async_sessionmaker[sa_asyncio.AsyncSession]):
|
||||||
|
self.async_session = async_session
|
||||||
|
self.logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
async def get_joke_by(self, id: int) -> models.JokeORM | None:
|
||||||
|
try:
|
||||||
|
async with self.async_session() as session:
|
||||||
|
joke = await session.get(models.JokeORM, id)
|
||||||
|
return joke
|
||||||
|
except sqlalchemy.exc.SQLAlchemyError as error:
|
||||||
|
self.logger.exception("Error: %s", error)
|
||||||
|
|
||||||
|
async def add_joke(self, joke: models.JokeORM) -> models.JokeORM | None:
|
||||||
|
try:
|
||||||
|
async with self.async_session() as session:
|
||||||
|
session.add(joke)
|
||||||
|
await session.commit()
|
||||||
|
await session.refresh(joke)
|
||||||
|
return joke
|
||||||
|
except sqlalchemy.exc.SQLAlchemyError as error:
|
||||||
|
self.logger.exception("Error: %s", error)
|
30
src/fastapi_app/lib/joke/services.py
Normal file
30
src/fastapi_app/lib/joke/services.py
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
import logging
|
||||||
|
|
||||||
|
import httpx
|
||||||
|
import pydantic
|
||||||
|
|
||||||
|
import lib.joke.repository as joke_repository
|
||||||
|
import lib.models as models
|
||||||
|
|
||||||
|
|
||||||
|
class JokeService:
|
||||||
|
def __init__(self, repository: joke_repository.JokeRepository):
|
||||||
|
self.repository = repository
|
||||||
|
self.logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
async def get_joke(self) -> models.Joke | None:
|
||||||
|
try:
|
||||||
|
async with httpx.AsyncClient() as client:
|
||||||
|
response = await client.get("https://official-joke-api.appspot.com/random_joke")
|
||||||
|
content = response.json()
|
||||||
|
self.logger.info("Joke retrieved from API")
|
||||||
|
formatted_joke = models.JokeORM(
|
||||||
|
type_field=content["type"], setup=content["setup"], punchline=content["punchline"]
|
||||||
|
)
|
||||||
|
await self.repository.add_joke(formatted_joke)
|
||||||
|
self.logger.info("Joke added to database")
|
||||||
|
return models.Joke(**content)
|
||||||
|
except pydantic.ValidationError as error:
|
||||||
|
self.logger.exception("Validation Error: %s", error)
|
||||||
|
except httpx.HTTPError as error:
|
||||||
|
self.logger.exception("HTTP Error: %s", error)
|
|
@ -1,4 +1,5 @@
|
||||||
from .base_sqlalchemy import Base, IdCreatedUpdatedBaseMixin
|
from .joke import Joke
|
||||||
|
from .orm import Base, IdCreatedUpdatedBaseMixin, JokeORM
|
||||||
from .token import Token
|
from .token import Token
|
||||||
|
|
||||||
__all__ = ["Base", "IdCreatedUpdatedBaseMixin", "Token"]
|
__all__ = ["Base", "IdCreatedUpdatedBaseMixin", "Joke", "JokeORM", "Token"]
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
import uuid
|
|
||||||
|
|
||||||
import sqlalchemy
|
|
||||||
import sqlalchemy.dialects.postgresql
|
|
||||||
import sqlalchemy.ext.declarative
|
|
||||||
import sqlalchemy.orm
|
|
||||||
|
|
||||||
|
|
||||||
class Base(sqlalchemy.orm.DeclarativeBase):
|
|
||||||
"""Base class for all models."""
|
|
||||||
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class IdCreatedUpdatedBaseMixin(Base):
|
|
||||||
@sqlalchemy.ext.declarative.declared_attr
|
|
||||||
def uuid(cls):
|
|
||||||
return sqlalchemy.Column(
|
|
||||||
sqlalchemy.dialects.postgresql.UUID(as_uuid=True),
|
|
||||||
primary_key=True,
|
|
||||||
default=uuid.uuid4,
|
|
||||||
unique=True,
|
|
||||||
nullable=False,
|
|
||||||
)
|
|
||||||
|
|
||||||
@sqlalchemy.ext.declarative.declared_attr
|
|
||||||
def created_at(cls):
|
|
||||||
return sqlalchemy.Column(sqlalchemy.DateTime, server_default=sqlalchemy.sql.func.now())
|
|
||||||
|
|
||||||
@sqlalchemy.ext.declarative.declared_attr
|
|
||||||
def updated_at(cls):
|
|
||||||
return sqlalchemy.Column(sqlalchemy.DateTime, server_default=sqlalchemy.sql.func.now())
|
|
||||||
|
|
||||||
@sqlalchemy.ext.declarative.declared_attr.directive
|
|
||||||
def __tablename__(cls) -> str:
|
|
||||||
return cls.__name__.lower()
|
|
10
src/fastapi_app/lib/models/joke.py
Normal file
10
src/fastapi_app/lib/models/joke.py
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
import pydantic
|
||||||
|
|
||||||
|
|
||||||
|
class Joke(pydantic.BaseModel):
|
||||||
|
"""Joke model."""
|
||||||
|
|
||||||
|
id_field: int = pydantic.Field(alias="id")
|
||||||
|
type_field: str = pydantic.Field(alias="type")
|
||||||
|
setup: str
|
||||||
|
punchline: str
|
4
src/fastapi_app/lib/models/orm/__init__.py
Normal file
4
src/fastapi_app/lib/models/orm/__init__.py
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
from .base import Base, IdCreatedUpdatedBaseMixin
|
||||||
|
from .joke import JokeORM
|
||||||
|
|
||||||
|
__all__ = ["Base", "IdCreatedUpdatedBaseMixin", "JokeORM"]
|
35
src/fastapi_app/lib/models/orm/base.py
Normal file
35
src/fastapi_app/lib/models/orm/base.py
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
import datetime
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
import sqlalchemy
|
||||||
|
import sqlalchemy.dialects.postgresql
|
||||||
|
import sqlalchemy.ext.declarative
|
||||||
|
import sqlalchemy.orm as sa_orm
|
||||||
|
import sqlalchemy.sql as sa_sql
|
||||||
|
|
||||||
|
|
||||||
|
class Base(sa_orm.DeclarativeBase):
|
||||||
|
"""Base class for all models."""
|
||||||
|
|
||||||
|
@sqlalchemy.ext.declarative.declared_attr.directive
|
||||||
|
def __tablename__(cls):
|
||||||
|
return cls.__name__.lower()
|
||||||
|
|
||||||
|
__mapper_args__ = {"eager_defaults": True}
|
||||||
|
|
||||||
|
id: sa_orm.Mapped[uuid.UUID] = sa_orm.mapped_column(primary_key=True, default=uuid.uuid4)
|
||||||
|
|
||||||
|
|
||||||
|
class IdCreatedUpdatedBaseMixin:
|
||||||
|
# id: sa_orm.Mapped[int] = sa_orm.mapped_column(primary_key=True)
|
||||||
|
# id_field: sa_orm.Mapped[uuid.UUID] = sa_orm.mapped_column(name="uuid", primary_key=True, unique=True, default=uuid.uuid4, nullable=False)
|
||||||
|
created: sa_orm.Mapped[datetime.datetime] = sa_orm.mapped_column(server_default=sa_sql.func.now())
|
||||||
|
updated: sa_orm.Mapped[datetime.datetime] = sa_orm.mapped_column(
|
||||||
|
server_default=sa_sql.func.now(), onupdate=sa_sql.func.now()
|
||||||
|
)
|
||||||
|
|
||||||
|
# __mapper_args__ = {"eager_defaults": True}
|
||||||
|
|
||||||
|
# @sqlalchemy.ext.declarative.declared_attr.directive
|
||||||
|
# def __tablename__(cls) -> str:
|
||||||
|
# return cls.__name__.lower()
|
13
src/fastapi_app/lib/models/orm/joke.py
Normal file
13
src/fastapi_app/lib/models/orm/joke.py
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
import sqlalchemy.orm as sa_orm
|
||||||
|
|
||||||
|
import lib.models.orm.base as base
|
||||||
|
|
||||||
|
Base = base.Base
|
||||||
|
|
||||||
|
|
||||||
|
class JokeORM(Base):
|
||||||
|
__tablename__ = "joke" # type: ignore
|
||||||
|
|
||||||
|
type_field: sa_orm.Mapped[str] = sa_orm.mapped_column(name="type", nullable=False)
|
||||||
|
setup: sa_orm.Mapped[str] = sa_orm.mapped_column()
|
||||||
|
punchline: sa_orm.Mapped[str] = sa_orm.mapped_column()
|
6
src/fastapi_app/poetry.lock
generated
6
src/fastapi_app/poetry.lock
generated
|
@ -988,13 +988,13 @@ pytest = ">=4.6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pyright"
|
name = "pyright"
|
||||||
version = "1.1.327"
|
version = "1.1.329"
|
||||||
description = "Command line wrapper for pyright"
|
description = "Command line wrapper for pyright"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
files = [
|
files = [
|
||||||
{file = "pyright-1.1.327-py3-none-any.whl", hash = "sha256:3462cda239e9140276238bbdbd0b59d77406f1c2e14d8cb8c20c8e25639c6b3c"},
|
{file = "pyright-1.1.329-py3-none-any.whl", hash = "sha256:c16f88a7ac14ddd0513e62fec56d69c37e3c6b412161ad16aa23a9c7e3dabaf4"},
|
||||||
{file = "pyright-1.1.327.tar.gz", hash = "sha256:ba74148ad64f22020dbbed6781c4bdb38ecb8a7ca90dc3c87a4f08d1c0e11592"},
|
{file = "pyright-1.1.329.tar.gz", hash = "sha256:5baf82ff5ecb8c8b3ac400e8536348efbde0b94a09d83d5b440c0d143fd151a8"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
|
|
|
@ -129,6 +129,8 @@ ignore = [
|
||||||
"D415",
|
"D415",
|
||||||
# Type-checkers interpret redundant `as` as exporting an item
|
# Type-checkers interpret redundant `as` as exporting an item
|
||||||
"PLC0414",
|
"PLC0414",
|
||||||
|
# Permit using alias for 'import'
|
||||||
|
"PLR0402",
|
||||||
# Causes churn and awful looking import blocks for little gain
|
# Causes churn and awful looking import blocks for little gain
|
||||||
"TCH"
|
"TCH"
|
||||||
]
|
]
|
||||||
|
|
Loading…
Reference in New Issue
Block a user