build: add ruff and format code
This commit is contained in:
parent
afadffbaac
commit
9d24f79436
20 changed files with 122 additions and 60 deletions
|
@ -1,10 +1,8 @@
|
||||||
from logging.config import fileConfig
|
from logging.config import fileConfig
|
||||||
|
|
||||||
from sqlalchemy import engine_from_config
|
from sqlalchemy import engine_from_config, pool
|
||||||
from sqlalchemy import pool
|
|
||||||
|
|
||||||
from alembic import context
|
from alembic import context
|
||||||
|
|
||||||
from foxnouns.db import Base
|
from foxnouns.db import Base
|
||||||
from foxnouns.db.sync import SYNC_DATABASE_URL
|
from foxnouns.db.sync import SYNC_DATABASE_URL
|
||||||
|
|
||||||
|
@ -70,9 +68,7 @@ def run_migrations_online() -> None:
|
||||||
)
|
)
|
||||||
|
|
||||||
with connectable.connect() as connection:
|
with connectable.connect() as connection:
|
||||||
context.configure(
|
context.configure(connection=connection, target_metadata=target_metadata)
|
||||||
connection=connection, target_metadata=target_metadata
|
|
||||||
)
|
|
||||||
|
|
||||||
with context.begin_transaction():
|
with context.begin_transaction():
|
||||||
context.run_migrations()
|
context.run_migrations()
|
||||||
|
|
|
@ -5,11 +5,12 @@ Revises:
|
||||||
Create Date: 2024-03-09 16:32:28.590145
|
Create Date: 2024-03-09 16:32:28.590145
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from typing import Sequence, Union
|
from typing import Sequence, Union
|
||||||
|
|
||||||
from alembic import op
|
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
from alembic import op
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
# revision identifiers, used by Alembic.
|
||||||
revision: str = "b39613fd7327"
|
revision: str = "b39613fd7327"
|
||||||
|
|
|
@ -5,12 +5,14 @@ Revises: b39613fd7327
|
||||||
Create Date: 2024-03-13 17:01:50.434602
|
Create Date: 2024-03-13 17:01:50.434602
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from typing import Sequence, Union
|
from typing import Sequence, Union
|
||||||
|
|
||||||
from alembic import op
|
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
from sqlalchemy.dialects import postgresql
|
from sqlalchemy.dialects import postgresql
|
||||||
|
|
||||||
|
from alembic import op
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
# revision identifiers, used by Alembic.
|
||||||
revision: str = "0b63f7c8ab96"
|
revision: str = "0b63f7c8ab96"
|
||||||
down_revision: Union[str, None] = "b39613fd7327"
|
down_revision: Union[str, None] = "b39613fd7327"
|
||||||
|
|
|
@ -5,12 +5,14 @@ Revises: 0b63f7c8ab96
|
||||||
Create Date: 2024-03-20 15:36:08.756635
|
Create Date: 2024-03-20 15:36:08.756635
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from typing import Sequence, Union
|
from typing import Sequence, Union
|
||||||
|
|
||||||
from alembic import op
|
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
from sqlalchemy.dialects import postgresql
|
from sqlalchemy.dialects import postgresql
|
||||||
|
|
||||||
|
from alembic import op
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
# revision identifiers, used by Alembic.
|
||||||
revision: str = "1d8f8443a7f5"
|
revision: str = "1d8f8443a7f5"
|
||||||
down_revision: Union[str, None] = "0b63f7c8ab96"
|
down_revision: Union[str, None] = "0b63f7c8ab96"
|
||||||
|
|
|
@ -5,37 +5,43 @@ Revises: 1d8f8443a7f5
|
||||||
Create Date: 2024-03-20 16:00:59.251354
|
Create Date: 2024-03-20 16:00:59.251354
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from typing import Sequence, Union
|
from typing import Sequence, Union
|
||||||
|
|
||||||
from alembic import op
|
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
from sqlalchemy.dialects import postgresql
|
from sqlalchemy.dialects import postgresql
|
||||||
|
|
||||||
|
from alembic import op
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
# revision identifiers, used by Alembic.
|
||||||
revision: str = '17cc8cb77be5'
|
revision: str = "17cc8cb77be5"
|
||||||
down_revision: Union[str, None] = '1d8f8443a7f5'
|
down_revision: Union[str, None] = "1d8f8443a7f5"
|
||||||
branch_labels: Union[str, Sequence[str], None] = None
|
branch_labels: Union[str, Sequence[str], None] = None
|
||||||
depends_on: Union[str, Sequence[str], None] = None
|
depends_on: Union[str, Sequence[str], None] = None
|
||||||
|
|
||||||
|
|
||||||
def upgrade() -> None:
|
def upgrade() -> None:
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
op.create_table('members',
|
op.create_table(
|
||||||
sa.Column('id', sa.BigInteger(), nullable=False),
|
"members",
|
||||||
sa.Column('name', sa.Text(), nullable=False),
|
sa.Column("id", sa.BigInteger(), nullable=False),
|
||||||
sa.Column('display_name', sa.Text(), nullable=True),
|
sa.Column("name", sa.Text(), nullable=False),
|
||||||
sa.Column('bio', sa.Text(), nullable=True),
|
sa.Column("display_name", sa.Text(), nullable=True),
|
||||||
sa.Column('names', postgresql.JSONB(astext_type=sa.Text()), nullable=False),
|
sa.Column("bio", sa.Text(), nullable=True),
|
||||||
sa.Column('pronouns', postgresql.JSONB(astext_type=sa.Text()), nullable=False),
|
sa.Column("names", postgresql.JSONB(astext_type=sa.Text()), nullable=False),
|
||||||
sa.Column('fields', postgresql.JSONB(astext_type=sa.Text()), nullable=False),
|
sa.Column("pronouns", postgresql.JSONB(astext_type=sa.Text()), nullable=False),
|
||||||
sa.Column('user_id', sa.BigInteger(), nullable=False),
|
sa.Column("fields", postgresql.JSONB(astext_type=sa.Text()), nullable=False),
|
||||||
sa.ForeignKeyConstraint(['user_id'], ['users.id'], ),
|
sa.Column("user_id", sa.BigInteger(), nullable=False),
|
||||||
sa.PrimaryKeyConstraint('id')
|
sa.ForeignKeyConstraint(
|
||||||
|
["user_id"],
|
||||||
|
["users.id"],
|
||||||
|
),
|
||||||
|
sa.PrimaryKeyConstraint("id"),
|
||||||
)
|
)
|
||||||
# ### end Alembic commands ###
|
# ### end Alembic commands ###
|
||||||
|
|
||||||
|
|
||||||
def downgrade() -> None:
|
def downgrade() -> None:
|
||||||
# ### commands auto generated by Alembic - please adjust! ###
|
# ### commands auto generated by Alembic - please adjust! ###
|
||||||
op.drop_table('members')
|
op.drop_table("members")
|
||||||
# ### end Alembic commands ###
|
# ### end Alembic commands ###
|
||||||
|
|
|
@ -5,11 +5,12 @@ Revises: 17cc8cb77be5
|
||||||
Create Date: 2024-03-21 15:52:09.403257
|
Create Date: 2024-03-21 15:52:09.403257
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from typing import Sequence, Union
|
from typing import Sequence, Union
|
||||||
|
|
||||||
from alembic import op
|
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
from alembic import op
|
||||||
|
|
||||||
# revision identifiers, used by Alembic.
|
# revision identifiers, used by Alembic.
|
||||||
revision: str = "a000d800f45f"
|
revision: str = "a000d800f45f"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from quart import Quart, request, g
|
from quart import Quart, g, request
|
||||||
from quart_schema import QuartSchema, RequestSchemaValidationError
|
from quart_schema import QuartSchema, RequestSchemaValidationError
|
||||||
|
|
||||||
from .blueprints import users_blueprint, members_blueprint
|
from .blueprints import members_blueprint, users_blueprint
|
||||||
from .db.aio import async_session
|
from .db.aio import async_session
|
||||||
from .db.util import validate_token
|
from .db.util import validate_token
|
||||||
from .exceptions import ExpectedError
|
from .exceptions import ExpectedError
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
|
|
||||||
from quart import g
|
from quart import g
|
||||||
|
|
||||||
from foxnouns.exceptions import ForbiddenError, ErrorCode
|
from foxnouns.exceptions import ErrorCode, ForbiddenError
|
||||||
|
|
||||||
|
|
||||||
def require_auth(*, scope: str | None = None):
|
def require_auth(*, scope: str | None = None):
|
||||||
def decorator(func):
|
def decorator(func):
|
||||||
@wraps(func)
|
@wraps(func)
|
||||||
async def wrapper(*args, **kwargs):
|
async def wrapper(*args, **kwargs):
|
||||||
if not ("user" in g) or not ("token" in g):
|
if "user" not in g or "token" not in g:
|
||||||
raise ForbiddenError("Not authenticated", type=ErrorCode.Forbidden)
|
raise ForbiddenError("Not authenticated", type=ErrorCode.Forbidden)
|
||||||
|
|
||||||
if scope and not g.token.has_scope(scope):
|
if scope and not g.token.has_scope(scope):
|
||||||
|
|
|
@ -1,2 +1,4 @@
|
||||||
from .v2.users import bp as users_blueprint
|
|
||||||
from .v2.members import bp as members_blueprint
|
from .v2.members import bp as members_blueprint
|
||||||
|
from .v2.users import bp as users_blueprint
|
||||||
|
|
||||||
|
__all__ = [users_blueprint, members_blueprint]
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
from pydantic import Field
|
from pydantic import Field
|
||||||
from quart import Blueprint, g
|
from quart import Blueprint, g
|
||||||
from quart_schema import validate_response, validate_request
|
from quart_schema import validate_request, validate_response
|
||||||
from sqlalchemy import select
|
|
||||||
|
|
||||||
from foxnouns.auth import require_auth
|
from foxnouns.auth import require_auth
|
||||||
from foxnouns.db import Member
|
from foxnouns.db import Member
|
||||||
from foxnouns.db.aio import async_session
|
from foxnouns.db.aio import async_session
|
||||||
from foxnouns.db.util import user_from_ref, is_self
|
from foxnouns.db.util import user_from_ref
|
||||||
from foxnouns.exceptions import NotFoundError, ErrorCode
|
from foxnouns.exceptions import ErrorCode, NotFoundError
|
||||||
from foxnouns.models.member import FullMemberModel, MemberPatchModel
|
from foxnouns.models.member import FullMemberModel, MemberPatchModel
|
||||||
from foxnouns.settings import BASE_DOMAIN
|
from foxnouns.settings import BASE_DOMAIN
|
||||||
|
|
||||||
|
@ -50,6 +49,9 @@ async def create_member(data: MemberCreateModel):
|
||||||
|
|
||||||
session.add(member)
|
session.add(member)
|
||||||
await session.commit()
|
await session.commit()
|
||||||
|
# This has to be fetched before we can pass the model to Pydantic.
|
||||||
|
# In a normal SELECT this is automatically fetched, but because we just created the object,
|
||||||
|
# we have to do it manually.
|
||||||
await member.awaitable_attrs.user
|
await member.awaitable_attrs.user
|
||||||
|
|
||||||
return FullMemberModel.model_validate(member)
|
return FullMemberModel.model_validate(member)
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
from pydantic import Field, field_validator
|
from pydantic import Field, field_validator
|
||||||
from quart import Blueprint, g
|
from quart import Blueprint, g
|
||||||
from quart_schema import validate_response, validate_request
|
from quart_schema import validate_request, validate_response
|
||||||
from sqlalchemy import select
|
from sqlalchemy import select
|
||||||
|
|
||||||
from foxnouns.auth import require_auth
|
from foxnouns.auth import require_auth
|
||||||
from foxnouns.db import User
|
from foxnouns.db import User
|
||||||
from foxnouns.db.aio import async_session
|
from foxnouns.db.aio import async_session
|
||||||
from foxnouns.db.snowflake import Snowflake
|
from foxnouns.db.snowflake import Snowflake
|
||||||
from foxnouns.db.util import user_from_ref, is_self, create_token, generate_token
|
from foxnouns.db.util import create_token, generate_token, is_self, user_from_ref
|
||||||
from foxnouns.exceptions import NotFoundError, ErrorCode
|
from foxnouns.exceptions import ErrorCode, NotFoundError
|
||||||
from foxnouns.models import BasePatchModel
|
from foxnouns.models import BasePatchModel
|
||||||
from foxnouns.models.user import UserModel, SelfUserModel, check_username
|
from foxnouns.models.user import SelfUserModel, UserModel, check_username
|
||||||
from foxnouns.settings import BASE_DOMAIN
|
from foxnouns.settings import BASE_DOMAIN
|
||||||
|
|
||||||
bp = Blueprint("users_v2", __name__)
|
bp = Blueprint("users_v2", __name__)
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
from .base import Base
|
from .base import Base
|
||||||
from .user import User, Token, AuthMethod, FediverseApp
|
|
||||||
from .member import Member
|
from .member import Member
|
||||||
|
from .user import AuthMethod, FediverseApp, Token, User
|
||||||
|
|
||||||
|
__all__ = [Base, User, Token, AuthMethod, FediverseApp, Member]
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
from sqlalchemy import URL
|
from sqlalchemy import URL
|
||||||
from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker
|
from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine
|
||||||
|
|
||||||
from foxnouns.settings import DATABASE, ECHO_SQL
|
from foxnouns.settings import DATABASE, ECHO_SQL
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from sqlalchemy import Text, BigInteger, ForeignKey, Index, func, text
|
from sqlalchemy import BigInteger, ForeignKey, Index, Text, func, text
|
||||||
from sqlalchemy.dialects.postgresql import JSONB
|
from sqlalchemy.dialects.postgresql import JSONB
|
||||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
from datetime import datetime
|
|
||||||
import enum
|
import enum
|
||||||
|
from datetime import datetime
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from sqlalchemy import Text, Integer, BigInteger, ForeignKey, DateTime
|
from sqlalchemy import BigInteger, DateTime, ForeignKey, Integer, Text
|
||||||
from sqlalchemy.dialects.postgresql import ARRAY, JSONB
|
from sqlalchemy.dialects.postgresql import ARRAY, JSONB
|
||||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||||
|
|
||||||
|
@ -38,7 +38,9 @@ class User(Base):
|
||||||
return f"User(id={self.id!r}, username={self.username!r})"
|
return f"User(id={self.id!r}, username={self.username!r})"
|
||||||
|
|
||||||
|
|
||||||
from .member import Member
|
# Import Member here--it's needed for the back reference in User, but Member references User, so we can only import it
|
||||||
|
# after User is initialized.
|
||||||
|
from .member import Member # noqa: E402
|
||||||
|
|
||||||
|
|
||||||
class Token(Base):
|
class Token(Base):
|
||||||
|
|
|
@ -2,16 +2,17 @@ import datetime
|
||||||
|
|
||||||
from itsdangerous import BadSignature
|
from itsdangerous import BadSignature
|
||||||
from itsdangerous.url_safe import URLSafeTimedSerializer
|
from itsdangerous.url_safe import URLSafeTimedSerializer
|
||||||
from sqlalchemy.ext.asyncio import AsyncSession
|
|
||||||
from sqlalchemy import select, insert
|
|
||||||
from sqlalchemy.orm import selectinload
|
|
||||||
from quart import g
|
from quart import g
|
||||||
|
from sqlalchemy import insert, select
|
||||||
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||||||
|
from sqlalchemy.orm import selectinload
|
||||||
|
|
||||||
from .user import User, Token
|
from foxnouns.exceptions import ErrorCode, ForbiddenError
|
||||||
from .member import Member
|
|
||||||
from foxnouns.exceptions import ForbiddenError, ErrorCode
|
|
||||||
from foxnouns.settings import SECRET_KEY
|
from foxnouns.settings import SECRET_KEY
|
||||||
|
|
||||||
|
from .member import Member
|
||||||
|
from .user import Token, User
|
||||||
|
|
||||||
|
|
||||||
async def user_from_ref(session: AsyncSession, user_ref: str):
|
async def user_from_ref(session: AsyncSession, user_ref: str):
|
||||||
"""Returns a user from a `user_ref` value. If `user_ref` is `@me`, returns the current user.
|
"""Returns a user from a `user_ref` value. If `user_ref` is `@me`, returns the current user.
|
||||||
|
@ -25,7 +26,7 @@ async def user_from_ref(session: AsyncSession, user_ref: str):
|
||||||
query = query.where(User.id == g.user.id)
|
query = query.where(User.id == g.user.id)
|
||||||
else:
|
else:
|
||||||
raise ForbiddenError(
|
raise ForbiddenError(
|
||||||
f"Missing scope 'user.read'", type=ErrorCode.MissingScope
|
"Missing scope 'user.read'", type=ErrorCode.MissingScope
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
raise ForbiddenError("Not authenticated")
|
raise ForbiddenError("Not authenticated")
|
||||||
|
@ -63,7 +64,7 @@ async def create_token(session: AsyncSession, user: User, scopes: list[str] = ["
|
||||||
return await session.scalar(query)
|
return await session.scalar(query)
|
||||||
|
|
||||||
|
|
||||||
async def validate_token(session: AsyncSession, header: str) -> (Token, User):
|
async def validate_token(session: AsyncSession, header: str) -> tuple[Token, User]:
|
||||||
try:
|
try:
|
||||||
token_id = serializer.loads(header)
|
token_id = serializer.loads(header)
|
||||||
except BadSignature:
|
except BadSignature:
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from pydantic import Field
|
from pydantic import Field
|
||||||
|
|
||||||
from . import BaseSnowflakeModel
|
from . import BaseSnowflakeModel
|
||||||
from .fields import ProfileField, FieldEntry, PronounEntry
|
from .fields import FieldEntry, ProfileField, PronounEntry
|
||||||
|
|
||||||
|
|
||||||
class BaseUserModel(BaseSnowflakeModel):
|
class BaseUserModel(BaseSnowflakeModel):
|
||||||
|
|
29
poetry.lock
generated
29
poetry.lock
generated
|
@ -1010,6 +1010,33 @@ async-timeout = {version = ">=4.0.3", markers = "python_full_version < \"3.11.3\
|
||||||
hiredis = ["hiredis (>=1.0.0)"]
|
hiredis = ["hiredis (>=1.0.0)"]
|
||||||
ocsp = ["cryptography (>=36.0.1)", "pyopenssl (==20.0.1)", "requests (>=2.26.0)"]
|
ocsp = ["cryptography (>=36.0.1)", "pyopenssl (==20.0.1)", "requests (>=2.26.0)"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ruff"
|
||||||
|
version = "0.3.4"
|
||||||
|
description = "An extremely fast Python linter and code formatter, written in Rust."
|
||||||
|
category = "dev"
|
||||||
|
optional = false
|
||||||
|
python-versions = ">=3.7"
|
||||||
|
files = [
|
||||||
|
{file = "ruff-0.3.4-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:60c870a7d46efcbc8385d27ec07fe534ac32f3b251e4fc44b3cbfd9e09609ef4"},
|
||||||
|
{file = "ruff-0.3.4-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:6fc14fa742e1d8f24910e1fff0bd5e26d395b0e0e04cc1b15c7c5e5fe5b4af91"},
|
||||||
|
{file = "ruff-0.3.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3ee7880f653cc03749a3bfea720cf2a192e4f884925b0cf7eecce82f0ce5854"},
|
||||||
|
{file = "ruff-0.3.4-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:cf133dd744f2470b347f602452a88e70dadfbe0fcfb5fd46e093d55da65f82f7"},
|
||||||
|
{file = "ruff-0.3.4-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3f3860057590e810c7ffea75669bdc6927bfd91e29b4baa9258fd48b540a4365"},
|
||||||
|
{file = "ruff-0.3.4-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:986f2377f7cf12efac1f515fc1a5b753c000ed1e0a6de96747cdf2da20a1b369"},
|
||||||
|
{file = "ruff-0.3.4-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c4fd98e85869603e65f554fdc5cddf0712e352fe6e61d29d5a6fe087ec82b76c"},
|
||||||
|
{file = "ruff-0.3.4-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:64abeed785dad51801b423fa51840b1764b35d6c461ea8caef9cf9e5e5ab34d9"},
|
||||||
|
{file = "ruff-0.3.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:df52972138318bc7546d92348a1ee58449bc3f9eaf0db278906eb511889c4b50"},
|
||||||
|
{file = "ruff-0.3.4-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:98e98300056445ba2cc27d0b325fd044dc17fcc38e4e4d2c7711585bd0a958ed"},
|
||||||
|
{file = "ruff-0.3.4-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:519cf6a0ebed244dce1dc8aecd3dc99add7a2ee15bb68cf19588bb5bf58e0488"},
|
||||||
|
{file = "ruff-0.3.4-py3-none-musllinux_1_2_i686.whl", hash = "sha256:bb0acfb921030d00070539c038cd24bb1df73a2981e9f55942514af8b17be94e"},
|
||||||
|
{file = "ruff-0.3.4-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:cf187a7e7098233d0d0c71175375c5162f880126c4c716fa28a8ac418dcf3378"},
|
||||||
|
{file = "ruff-0.3.4-py3-none-win32.whl", hash = "sha256:af27ac187c0a331e8ef91d84bf1c3c6a5dea97e912a7560ac0cef25c526a4102"},
|
||||||
|
{file = "ruff-0.3.4-py3-none-win_amd64.whl", hash = "sha256:de0d5069b165e5a32b3c6ffbb81c350b1e3d3483347196ffdf86dc0ef9e37dd6"},
|
||||||
|
{file = "ruff-0.3.4-py3-none-win_arm64.whl", hash = "sha256:6810563cc08ad0096b57c717bd78aeac888a1bfd38654d9113cb3dc4d3f74232"},
|
||||||
|
{file = "ruff-0.3.4.tar.gz", hash = "sha256:f0f4484c6541a99862b693e13a151435a279b271cff20e37101116a21e2a1ad1"},
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "six"
|
name = "six"
|
||||||
version = "1.16.0"
|
version = "1.16.0"
|
||||||
|
@ -1213,4 +1240,4 @@ h11 = ">=0.9.0,<1"
|
||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "2.0"
|
lock-version = "2.0"
|
||||||
python-versions = "^3.11"
|
python-versions = "^3.11"
|
||||||
content-hash = "c4719965b47a0a85c480b6a26e0c7fd84d61e281a4bb012049fac9c61cd813df"
|
content-hash = "a04cf866b1b5efd1f9484114b0e5924947a4044c7b7e70127f042778246c0ce6"
|
||||||
|
|
|
@ -23,6 +23,12 @@ asyncpg = "^0.29.0"
|
||||||
environs = "^11.0.0"
|
environs = "^11.0.0"
|
||||||
alembic = "^1.13.1"
|
alembic = "^1.13.1"
|
||||||
|
|
||||||
|
[tool.poetry.group.dev]
|
||||||
|
optional = true
|
||||||
|
|
||||||
|
[tool.poetry.group.dev.dependencies]
|
||||||
|
ruff = "^0.3.4"
|
||||||
|
|
||||||
[tool.poetry.group.test]
|
[tool.poetry.group.test]
|
||||||
optional = true
|
optional = true
|
||||||
|
|
||||||
|
@ -30,11 +36,23 @@ optional = true
|
||||||
pytest = "^8.0.2"
|
pytest = "^8.0.2"
|
||||||
pytest-asyncio = "^0.23.5.post1"
|
pytest-asyncio = "^0.23.5.post1"
|
||||||
|
|
||||||
|
[tool.poe.tasks.dev]
|
||||||
|
help = "Run a development server with auto-reload"
|
||||||
|
cmd = "env QUART_APP=foxnouns.app:app quart --debug run --reload"
|
||||||
|
|
||||||
|
[tool.poe.tasks.server]
|
||||||
|
help = "Run a production server"
|
||||||
|
cmd = "uvicorn 'foxnouns.app:app'"
|
||||||
|
|
||||||
|
[tool.poe.tasks.migrate]
|
||||||
|
help = "Migrate the database to the latest revision"
|
||||||
|
cmd = "alembic upgrade head"
|
||||||
|
|
||||||
[tool.poe.tasks]
|
[tool.poe.tasks]
|
||||||
dev = "env QUART_APP=foxnouns.app:app quart --debug run --reload"
|
|
||||||
server = "uvicorn 'foxnouns.app:app'"
|
|
||||||
migrate = "alembic upgrade head"
|
|
||||||
test = "pytest"
|
test = "pytest"
|
||||||
|
lint = "ruff check"
|
||||||
|
format = "ruff format"
|
||||||
|
"sort-imports" = "ruff check --select I --fix "
|
||||||
|
|
||||||
[tool.pytest.ini_options]
|
[tool.pytest.ini_options]
|
||||||
addopts = ["--import-mode=importlib"]
|
addopts = ["--import-mode=importlib"]
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
import pytest
|
import pytest
|
||||||
import pytest_asyncio
|
import pytest_asyncio
|
||||||
from sqlalchemy import text, delete
|
from sqlalchemy import delete, text
|
||||||
|
|
||||||
from foxnouns.db import Base
|
from foxnouns.db import Base
|
||||||
from foxnouns.settings import DATABASE
|
from foxnouns.settings import DATABASE
|
||||||
|
|
||||||
|
|
||||||
# Override the database name to the testing database
|
# Override the database name to the testing database
|
||||||
DATABASE["NAME"] = f"{DATABASE['NAME']}_test"
|
DATABASE["NAME"] = f"{DATABASE['NAME']}_test"
|
||||||
|
|
||||||
|
@ -25,8 +24,8 @@ def pytest_collection_modifyitems(items):
|
||||||
def setup():
|
def setup():
|
||||||
"""Migrate the testing database to the latest migration, and once the tests complete, clear the database again."""
|
"""Migrate the testing database to the latest migration, and once the tests complete, clear the database again."""
|
||||||
|
|
||||||
from foxnouns.db.sync import engine
|
|
||||||
from alembic import command, config
|
from alembic import command, config
|
||||||
|
from foxnouns.db.sync import engine
|
||||||
|
|
||||||
cfg = config.Config("alembic.ini")
|
cfg = config.Config("alembic.ini")
|
||||||
cfg.attributes["connection"] = engine.connect()
|
cfg.attributes["connection"] = engine.connect()
|
||||||
|
|
Loading…
Reference in a new issue