Spaces:
Runtime error
Runtime error
Soutrik
commited on
Commit
·
36ed17a
1
Parent(s):
8753097
added: fastapi framework
Browse files- .gitignore +16 -0
- Dockerfile +8 -8
- app/api/chat.py +32 -0
- app/core/__pycache__/config.cpython-310.pyc +0 -0
- app/core/celery_app.py +8 -0
- app/core/config.py +1 -1
- app/crud/chat_crud.py +14 -0
- app/db/database.py +17 -0
- app/db/models.py +12 -0
- app/schemas/chat.py +12 -0
- app/tasks/chat_task.py +6 -0
- docker-compose.yaml +11 -1
- main.py +16 -0
- poetry.lock +280 -4
- pyproject.toml +4 -0
- src/__pycache__/test_infra.cpython-310.pyc +0 -0
- src/number_manipulation.py +7 -0
- src/test_infra.py +1 -1
- tests/__init__.py +0 -0
- tests/test_db_connection.py +17 -0
.gitignore
CHANGED
|
@@ -3,3 +3,19 @@ aws/
|
|
| 3 |
*.tar.gz
|
| 4 |
*.tar.bz2
|
| 5 |
.env
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3 |
*.tar.gz
|
| 4 |
*.tar.bz2
|
| 5 |
.env
|
| 6 |
+
*.pyc
|
| 7 |
+
*.cpython-*.*
|
| 8 |
+
src/__pycache__/
|
| 9 |
+
src/*.egg-info/
|
| 10 |
+
src/dist/
|
| 11 |
+
src/build/
|
| 12 |
+
src/.eggs/
|
| 13 |
+
src/.pytest_cache/
|
| 14 |
+
src/.mypy_cache/
|
| 15 |
+
src/.tox/
|
| 16 |
+
src/.coverage
|
| 17 |
+
src/.vscode/
|
| 18 |
+
src/.vscode-test/
|
| 19 |
+
app/core/__pycache__/
|
| 20 |
+
src/__pycache__/test_infra.cpython-310.pyc
|
| 21 |
+
app/core/__pycache__/config.cpython-310.pyc
|
Dockerfile
CHANGED
|
@@ -1,7 +1,7 @@
|
|
| 1 |
# Use an official Python base image
|
| 2 |
FROM python:3.10.15-slim
|
| 3 |
|
| 4 |
-
# Set environment variables
|
| 5 |
ENV POETRY_VERSION=1.6.1 \
|
| 6 |
POETRY_HOME="/opt/poetry" \
|
| 7 |
POETRY_VIRTUALENVS_IN_PROJECT=true \
|
|
@@ -20,16 +20,16 @@ WORKDIR /app
|
|
| 20 |
# Copy Poetry files for dependency installation
|
| 21 |
COPY pyproject.toml poetry.lock ./
|
| 22 |
|
| 23 |
-
# Install dependencies with Poetry
|
| 24 |
RUN poetry install --no-root --only main
|
| 25 |
|
| 26 |
-
# Copy the source code
|
| 27 |
COPY src/ src/
|
| 28 |
-
# copy app
|
| 29 |
COPY app/ app/
|
|
|
|
| 30 |
|
| 31 |
-
#
|
| 32 |
-
|
| 33 |
|
| 34 |
-
#
|
| 35 |
-
CMD ["
|
|
|
|
| 1 |
# Use an official Python base image
|
| 2 |
FROM python:3.10.15-slim
|
| 3 |
|
| 4 |
+
# Set environment variables for Poetry
|
| 5 |
ENV POETRY_VERSION=1.6.1 \
|
| 6 |
POETRY_HOME="/opt/poetry" \
|
| 7 |
POETRY_VIRTUALENVS_IN_PROJECT=true \
|
|
|
|
| 20 |
# Copy Poetry files for dependency installation
|
| 21 |
COPY pyproject.toml poetry.lock ./
|
| 22 |
|
| 23 |
+
# Install dependencies with Poetry (without development dependencies)
|
| 24 |
RUN poetry install --no-root --only main
|
| 25 |
|
| 26 |
+
# Copy the application source code
|
| 27 |
COPY src/ src/
|
|
|
|
| 28 |
COPY app/ app/
|
| 29 |
+
COPY main.py .
|
| 30 |
|
| 31 |
+
# Expose the port for FastAPI
|
| 32 |
+
EXPOSE 8000
|
| 33 |
|
| 34 |
+
# Command to run the FastAPI application with uvicorn
|
| 35 |
+
CMD ["poetry", "run", "uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
|
app/api/chat.py
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from fastapi import APIRouter, Depends
|
| 2 |
+
from sqlalchemy.ext.asyncio import AsyncSession
|
| 3 |
+
from app.schemas.chat import ChatMessage, ChatResponse
|
| 4 |
+
from app.crud.chat_crud import create_chat_message
|
| 5 |
+
from app.tasks.chat_task import process_chat_message
|
| 6 |
+
from src.number_manipulation import add_random_number
|
| 7 |
+
from app.db.database import get_db
|
| 8 |
+
|
| 9 |
+
router = APIRouter()
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
@router.post("/chat", response_model=ChatResponse)
|
| 13 |
+
async def chat(message: ChatMessage, db: AsyncSession = Depends(get_db)):
|
| 14 |
+
# Process user input using add_random_number
|
| 15 |
+
processed_value = add_random_number(message.user_input)
|
| 16 |
+
|
| 17 |
+
# Save message to database along with the user input and processed value
|
| 18 |
+
message_id = await create_chat_message(
|
| 19 |
+
db=db,
|
| 20 |
+
content=message.content,
|
| 21 |
+
user_input=message.user_input,
|
| 22 |
+
processed_value=processed_value,
|
| 23 |
+
)
|
| 24 |
+
|
| 25 |
+
# Trigger async processing of the chat message content in the background
|
| 26 |
+
process_chat_message.delay(message.content)
|
| 27 |
+
|
| 28 |
+
return ChatResponse(
|
| 29 |
+
message_id=message_id,
|
| 30 |
+
status="Message received",
|
| 31 |
+
processed_value=processed_value,
|
| 32 |
+
)
|
app/core/__pycache__/config.cpython-310.pyc
CHANGED
|
Binary files a/app/core/__pycache__/config.cpython-310.pyc and b/app/core/__pycache__/config.cpython-310.pyc differ
|
|
|
app/core/celery_app.py
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from celery import Celery
|
| 2 |
+
from app.core.config import settings
|
| 3 |
+
|
| 4 |
+
celery_app = Celery("chat_tasks", broker=settings.redis_url, backend=settings.redis_url)
|
| 5 |
+
|
| 6 |
+
celery_app.conf.update(
|
| 7 |
+
task_serializer="json", result_serializer="json", accept_content=["json"]
|
| 8 |
+
)
|
app/core/config.py
CHANGED
|
@@ -24,7 +24,7 @@ class Settings(BaseSettings):
|
|
| 24 |
instance = cls()
|
| 25 |
# Set the correct database URL without the +asyncpg
|
| 26 |
instance.database_url = (
|
| 27 |
-
f"
|
| 28 |
f"{'localhost' if not instance.is_docker else 'postgres'}:5432/{instance.POSTGRES_DB}"
|
| 29 |
)
|
| 30 |
instance.redis_url = (
|
|
|
|
| 24 |
instance = cls()
|
| 25 |
# Set the correct database URL without the +asyncpg
|
| 26 |
instance.database_url = (
|
| 27 |
+
f"postgresql+asyncpg://{instance.POSTGRES_USER}:{instance.POSTGRES_PASSWORD}@"
|
| 28 |
f"{'localhost' if not instance.is_docker else 'postgres'}:5432/{instance.POSTGRES_DB}"
|
| 29 |
)
|
| 30 |
instance.redis_url = (
|
app/crud/chat_crud.py
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from sqlalchemy.ext.asyncio import AsyncSession
|
| 2 |
+
from app.db.models import ChatMessageModel
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
async def create_chat_message(
|
| 6 |
+
db: AsyncSession, content: str, user_input: int, processed_value: int
|
| 7 |
+
):
|
| 8 |
+
new_message = ChatMessageModel(
|
| 9 |
+
content=content, user_input=user_input, processed_value=processed_value
|
| 10 |
+
)
|
| 11 |
+
db.add(new_message)
|
| 12 |
+
await db.commit()
|
| 13 |
+
await db.refresh(new_message) # Fetches the latest state after commit
|
| 14 |
+
return new_message.id
|
app/db/database.py
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
|
| 2 |
+
from sqlalchemy.orm import sessionmaker, declarative_base
|
| 3 |
+
from app.core.config import settings
|
| 4 |
+
|
| 5 |
+
# Create an async engine
|
| 6 |
+
engine = create_async_engine(settings.database_url, echo=True)
|
| 7 |
+
|
| 8 |
+
# Async session factory
|
| 9 |
+
SessionLocal = sessionmaker(bind=engine, class_=AsyncSession, expire_on_commit=False)
|
| 10 |
+
|
| 11 |
+
Base = declarative_base()
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
# Dependency for asynchronous database session
|
| 15 |
+
async def get_db():
|
| 16 |
+
async with SessionLocal() as session:
|
| 17 |
+
yield session
|
app/db/models.py
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from sqlalchemy import Column, Integer, String, DateTime, func
|
| 2 |
+
from app.db.database import Base
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
class ChatMessageModel(Base):
|
| 6 |
+
__tablename__ = "chat_messages"
|
| 7 |
+
|
| 8 |
+
id = Column(Integer, primary_key=True, index=True)
|
| 9 |
+
content = Column(String, nullable=False)
|
| 10 |
+
user_input = Column(Integer, nullable=False)
|
| 11 |
+
processed_value = Column(Integer, nullable=False)
|
| 12 |
+
timestamp = Column(DateTime, server_default=func.now())
|
app/schemas/chat.py
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from pydantic import BaseModel
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
class ChatMessage(BaseModel):
|
| 5 |
+
content: str
|
| 6 |
+
user_input: int
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
class ChatResponse(BaseModel):
|
| 10 |
+
message_id: int
|
| 11 |
+
status: str
|
| 12 |
+
processed_value: int
|
app/tasks/chat_task.py
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from app.core.celery_app import celery_app
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
@celery_app.task
|
| 5 |
+
def process_chat_message(content: str):
|
| 6 |
+
print(f"Processing message: {content}")
|
docker-compose.yaml
CHANGED
|
@@ -12,6 +12,8 @@ services:
|
|
| 12 |
- "5432:5432"
|
| 13 |
volumes:
|
| 14 |
- postgres_data:/var/lib/postgresql/data
|
|
|
|
|
|
|
| 15 |
healthcheck:
|
| 16 |
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
|
| 17 |
interval: 30s
|
|
@@ -25,6 +27,8 @@ services:
|
|
| 25 |
- "8001:8001"
|
| 26 |
environment:
|
| 27 |
DOCKER_ENV: 1
|
|
|
|
|
|
|
| 28 |
healthcheck:
|
| 29 |
test: ["CMD", "redis-cli", "ping"]
|
| 30 |
interval: 30s
|
|
@@ -40,6 +44,8 @@ services:
|
|
| 40 |
- 5557:5555
|
| 41 |
depends_on:
|
| 42 |
- redis
|
|
|
|
|
|
|
| 43 |
|
| 44 |
app:
|
| 45 |
build:
|
|
@@ -59,7 +65,11 @@ services:
|
|
| 59 |
condition: service_healthy
|
| 60 |
redis:
|
| 61 |
condition: service_healthy
|
| 62 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 63 |
|
| 64 |
volumes:
|
| 65 |
postgres_data:
|
|
|
|
| 12 |
- "5432:5432"
|
| 13 |
volumes:
|
| 14 |
- postgres_data:/var/lib/postgresql/data
|
| 15 |
+
networks:
|
| 16 |
+
- my_network
|
| 17 |
healthcheck:
|
| 18 |
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
|
| 19 |
interval: 30s
|
|
|
|
| 27 |
- "8001:8001"
|
| 28 |
environment:
|
| 29 |
DOCKER_ENV: 1
|
| 30 |
+
networks:
|
| 31 |
+
- my_network
|
| 32 |
healthcheck:
|
| 33 |
test: ["CMD", "redis-cli", "ping"]
|
| 34 |
interval: 30s
|
|
|
|
| 44 |
- 5557:5555
|
| 45 |
depends_on:
|
| 46 |
- redis
|
| 47 |
+
networks:
|
| 48 |
+
- my_network
|
| 49 |
|
| 50 |
app:
|
| 51 |
build:
|
|
|
|
| 65 |
condition: service_healthy
|
| 66 |
redis:
|
| 67 |
condition: service_healthy
|
| 68 |
+
networks:
|
| 69 |
+
- my_network
|
| 70 |
+
ports:
|
| 71 |
+
- "8000:8000"
|
| 72 |
+
command: ["poetry", "run", "uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
|
| 73 |
|
| 74 |
volumes:
|
| 75 |
postgres_data:
|
main.py
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from fastapi import FastAPI
|
| 2 |
+
from app.api import chat
|
| 3 |
+
from app.db.database import Base, engine # Import Base and engine for table creation
|
| 4 |
+
|
| 5 |
+
app = FastAPI()
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
# Create tables on startup
|
| 9 |
+
@app.on_event("startup")
|
| 10 |
+
async def startup():
|
| 11 |
+
async with engine.begin() as conn:
|
| 12 |
+
await conn.run_sync(Base.metadata.create_all)
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
# Include the chat route
|
| 16 |
+
app.include_router(chat.router)
|
poetry.lock
CHANGED
|
@@ -233,13 +233,13 @@ frozenlist = ">=1.1.0"
|
|
| 233 |
|
| 234 |
[[package]]
|
| 235 |
name = "alembic"
|
| 236 |
-
version = "1.
|
| 237 |
description = "A database migration tool for SQLAlchemy."
|
| 238 |
optional = false
|
| 239 |
python-versions = ">=3.8"
|
| 240 |
files = [
|
| 241 |
-
{file = "alembic-1.
|
| 242 |
-
{file = "alembic-1.
|
| 243 |
]
|
| 244 |
|
| 245 |
[package.dependencies]
|
|
@@ -250,6 +250,20 @@ typing-extensions = ">=4"
|
|
| 250 |
[package.extras]
|
| 251 |
tz = ["backports.zoneinfo"]
|
| 252 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 253 |
[[package]]
|
| 254 |
name = "annotated-types"
|
| 255 |
version = "0.7.0"
|
|
@@ -414,6 +428,73 @@ azure-core = ">=1.28.0"
|
|
| 414 |
isodate = ">=0.6.0"
|
| 415 |
typing-extensions = ">=4.6.0"
|
| 416 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 417 |
[[package]]
|
| 418 |
name = "certifi"
|
| 419 |
version = "2024.8.30"
|
|
@@ -553,6 +634,55 @@ files = [
|
|
| 553 |
[package.dependencies]
|
| 554 |
colorama = {version = "*", markers = "platform_system == \"Windows\""}
|
| 555 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 556 |
[[package]]
|
| 557 |
name = "colorama"
|
| 558 |
version = "0.4.6"
|
|
@@ -1094,6 +1224,17 @@ files = [
|
|
| 1094 |
[package.extras]
|
| 1095 |
all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"]
|
| 1096 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1097 |
[[package]]
|
| 1098 |
name = "isodate"
|
| 1099 |
version = "0.7.2"
|
|
@@ -1105,6 +1246,39 @@ files = [
|
|
| 1105 |
{file = "isodate-0.7.2.tar.gz", hash = "sha256:4cd1aa0f43ca76f4a6c6c0292a85f40b35ec2e43e315b59f06e6d32171a953e6"},
|
| 1106 |
]
|
| 1107 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1108 |
[[package]]
|
| 1109 |
name = "loguru"
|
| 1110 |
version = "0.7.2"
|
|
@@ -1484,6 +1658,35 @@ sql-other = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-d
|
|
| 1484 |
test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)"]
|
| 1485 |
xml = ["lxml (>=4.9.2)"]
|
| 1486 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1487 |
[[package]]
|
| 1488 |
name = "propcache"
|
| 1489 |
version = "0.2.0"
|
|
@@ -1836,6 +2039,46 @@ azure-key-vault = ["azure-identity (>=1.16.0)", "azure-keyvault-secrets (>=4.8.0
|
|
| 1836 |
toml = ["tomli (>=2.0.1)"]
|
| 1837 |
yaml = ["pyyaml (>=6.0.1)"]
|
| 1838 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1839 |
[[package]]
|
| 1840 |
name = "python-dateutil"
|
| 1841 |
version = "2.9.0.post0"
|
|
@@ -2193,6 +2436,17 @@ files = [
|
|
| 2193 |
doc = ["reno", "sphinx"]
|
| 2194 |
test = ["pytest", "tornado (>=4.5)", "typeguard"]
|
| 2195 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2196 |
[[package]]
|
| 2197 |
name = "typing-extensions"
|
| 2198 |
version = "4.12.2"
|
|
@@ -2266,6 +2520,28 @@ typing-extensions = {version = ">=4.0", markers = "python_version < \"3.11\""}
|
|
| 2266 |
[package.extras]
|
| 2267 |
standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.4)"]
|
| 2268 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2269 |
[[package]]
|
| 2270 |
name = "win32-setctime"
|
| 2271 |
version = "1.1.0"
|
|
@@ -2379,4 +2655,4 @@ propcache = ">=0.2.0"
|
|
| 2379 |
[metadata]
|
| 2380 |
lock-version = "2.0"
|
| 2381 |
python-versions = "3.10.15"
|
| 2382 |
-
content-hash = "
|
|
|
|
| 233 |
|
| 234 |
[[package]]
|
| 235 |
name = "alembic"
|
| 236 |
+
version = "1.14.0"
|
| 237 |
description = "A database migration tool for SQLAlchemy."
|
| 238 |
optional = false
|
| 239 |
python-versions = ">=3.8"
|
| 240 |
files = [
|
| 241 |
+
{file = "alembic-1.14.0-py3-none-any.whl", hash = "sha256:99bd884ca390466db5e27ffccff1d179ec5c05c965cfefc0607e69f9e411cb25"},
|
| 242 |
+
{file = "alembic-1.14.0.tar.gz", hash = "sha256:b00892b53b3642d0b8dbedba234dbf1924b69be83a9a769d5a624b01094e304b"},
|
| 243 |
]
|
| 244 |
|
| 245 |
[package.dependencies]
|
|
|
|
| 250 |
[package.extras]
|
| 251 |
tz = ["backports.zoneinfo"]
|
| 252 |
|
| 253 |
+
[[package]]
|
| 254 |
+
name = "amqp"
|
| 255 |
+
version = "5.2.0"
|
| 256 |
+
description = "Low-level AMQP client for Python (fork of amqplib)."
|
| 257 |
+
optional = false
|
| 258 |
+
python-versions = ">=3.6"
|
| 259 |
+
files = [
|
| 260 |
+
{file = "amqp-5.2.0-py3-none-any.whl", hash = "sha256:827cb12fb0baa892aad844fd95258143bce4027fdac4fccddbc43330fd281637"},
|
| 261 |
+
{file = "amqp-5.2.0.tar.gz", hash = "sha256:a1ecff425ad063ad42a486c902807d1482311481c8ad95a72694b2975e75f7fd"},
|
| 262 |
+
]
|
| 263 |
+
|
| 264 |
+
[package.dependencies]
|
| 265 |
+
vine = ">=5.0.0,<6.0.0"
|
| 266 |
+
|
| 267 |
[[package]]
|
| 268 |
name = "annotated-types"
|
| 269 |
version = "0.7.0"
|
|
|
|
| 428 |
isodate = ">=0.6.0"
|
| 429 |
typing-extensions = ">=4.6.0"
|
| 430 |
|
| 431 |
+
[[package]]
|
| 432 |
+
name = "billiard"
|
| 433 |
+
version = "4.2.1"
|
| 434 |
+
description = "Python multiprocessing fork with improvements and bugfixes"
|
| 435 |
+
optional = false
|
| 436 |
+
python-versions = ">=3.7"
|
| 437 |
+
files = [
|
| 438 |
+
{file = "billiard-4.2.1-py3-none-any.whl", hash = "sha256:40b59a4ac8806ba2c2369ea98d876bc6108b051c227baffd928c644d15d8f3cb"},
|
| 439 |
+
{file = "billiard-4.2.1.tar.gz", hash = "sha256:12b641b0c539073fc8d3f5b8b7be998956665c4233c7c1fcd66a7e677c4fb36f"},
|
| 440 |
+
]
|
| 441 |
+
|
| 442 |
+
[[package]]
|
| 443 |
+
name = "celery"
|
| 444 |
+
version = "5.4.0"
|
| 445 |
+
description = "Distributed Task Queue."
|
| 446 |
+
optional = false
|
| 447 |
+
python-versions = ">=3.8"
|
| 448 |
+
files = [
|
| 449 |
+
{file = "celery-5.4.0-py3-none-any.whl", hash = "sha256:369631eb580cf8c51a82721ec538684994f8277637edde2dfc0dacd73ed97f64"},
|
| 450 |
+
{file = "celery-5.4.0.tar.gz", hash = "sha256:504a19140e8d3029d5acad88330c541d4c3f64c789d85f94756762d8bca7e706"},
|
| 451 |
+
]
|
| 452 |
+
|
| 453 |
+
[package.dependencies]
|
| 454 |
+
billiard = ">=4.2.0,<5.0"
|
| 455 |
+
click = ">=8.1.2,<9.0"
|
| 456 |
+
click-didyoumean = ">=0.3.0"
|
| 457 |
+
click-plugins = ">=1.1.1"
|
| 458 |
+
click-repl = ">=0.2.0"
|
| 459 |
+
kombu = ">=5.3.4,<6.0"
|
| 460 |
+
python-dateutil = ">=2.8.2"
|
| 461 |
+
tzdata = ">=2022.7"
|
| 462 |
+
vine = ">=5.1.0,<6.0"
|
| 463 |
+
|
| 464 |
+
[package.extras]
|
| 465 |
+
arangodb = ["pyArango (>=2.0.2)"]
|
| 466 |
+
auth = ["cryptography (==42.0.5)"]
|
| 467 |
+
azureblockblob = ["azure-storage-blob (>=12.15.0)"]
|
| 468 |
+
brotli = ["brotli (>=1.0.0)", "brotlipy (>=0.7.0)"]
|
| 469 |
+
cassandra = ["cassandra-driver (>=3.25.0,<4)"]
|
| 470 |
+
consul = ["python-consul2 (==0.1.5)"]
|
| 471 |
+
cosmosdbsql = ["pydocumentdb (==2.3.5)"]
|
| 472 |
+
couchbase = ["couchbase (>=3.0.0)"]
|
| 473 |
+
couchdb = ["pycouchdb (==1.14.2)"]
|
| 474 |
+
django = ["Django (>=2.2.28)"]
|
| 475 |
+
dynamodb = ["boto3 (>=1.26.143)"]
|
| 476 |
+
elasticsearch = ["elastic-transport (<=8.13.0)", "elasticsearch (<=8.13.0)"]
|
| 477 |
+
eventlet = ["eventlet (>=0.32.0)"]
|
| 478 |
+
gcs = ["google-cloud-storage (>=2.10.0)"]
|
| 479 |
+
gevent = ["gevent (>=1.5.0)"]
|
| 480 |
+
librabbitmq = ["librabbitmq (>=2.0.0)"]
|
| 481 |
+
memcache = ["pylibmc (==1.6.3)"]
|
| 482 |
+
mongodb = ["pymongo[srv] (>=4.0.2)"]
|
| 483 |
+
msgpack = ["msgpack (==1.0.8)"]
|
| 484 |
+
pymemcache = ["python-memcached (>=1.61)"]
|
| 485 |
+
pyro = ["pyro4 (==4.82)"]
|
| 486 |
+
pytest = ["pytest-celery[all] (>=1.0.0)"]
|
| 487 |
+
redis = ["redis (>=4.5.2,!=4.5.5,<6.0.0)"]
|
| 488 |
+
s3 = ["boto3 (>=1.26.143)"]
|
| 489 |
+
slmq = ["softlayer-messaging (>=1.0.3)"]
|
| 490 |
+
solar = ["ephem (==4.1.5)"]
|
| 491 |
+
sqlalchemy = ["sqlalchemy (>=1.4.48,<2.1)"]
|
| 492 |
+
sqs = ["boto3 (>=1.26.143)", "kombu[sqs] (>=5.3.4)", "pycurl (>=7.43.0.5)", "urllib3 (>=1.26.16)"]
|
| 493 |
+
tblib = ["tblib (>=1.3.0)", "tblib (>=1.5.0)"]
|
| 494 |
+
yaml = ["PyYAML (>=3.10)"]
|
| 495 |
+
zookeeper = ["kazoo (>=1.3.1)"]
|
| 496 |
+
zstd = ["zstandard (==0.22.0)"]
|
| 497 |
+
|
| 498 |
[[package]]
|
| 499 |
name = "certifi"
|
| 500 |
version = "2024.8.30"
|
|
|
|
| 634 |
[package.dependencies]
|
| 635 |
colorama = {version = "*", markers = "platform_system == \"Windows\""}
|
| 636 |
|
| 637 |
+
[[package]]
|
| 638 |
+
name = "click-didyoumean"
|
| 639 |
+
version = "0.3.1"
|
| 640 |
+
description = "Enables git-like *did-you-mean* feature in click"
|
| 641 |
+
optional = false
|
| 642 |
+
python-versions = ">=3.6.2"
|
| 643 |
+
files = [
|
| 644 |
+
{file = "click_didyoumean-0.3.1-py3-none-any.whl", hash = "sha256:5c4bb6007cfea5f2fd6583a2fb6701a22a41eb98957e63d0fac41c10e7c3117c"},
|
| 645 |
+
{file = "click_didyoumean-0.3.1.tar.gz", hash = "sha256:4f82fdff0dbe64ef8ab2279bd6aa3f6a99c3b28c05aa09cbfc07c9d7fbb5a463"},
|
| 646 |
+
]
|
| 647 |
+
|
| 648 |
+
[package.dependencies]
|
| 649 |
+
click = ">=7"
|
| 650 |
+
|
| 651 |
+
[[package]]
|
| 652 |
+
name = "click-plugins"
|
| 653 |
+
version = "1.1.1"
|
| 654 |
+
description = "An extension module for click to enable registering CLI commands via setuptools entry-points."
|
| 655 |
+
optional = false
|
| 656 |
+
python-versions = "*"
|
| 657 |
+
files = [
|
| 658 |
+
{file = "click-plugins-1.1.1.tar.gz", hash = "sha256:46ab999744a9d831159c3411bb0c79346d94a444df9a3a3742e9ed63645f264b"},
|
| 659 |
+
{file = "click_plugins-1.1.1-py2.py3-none-any.whl", hash = "sha256:5d262006d3222f5057fd81e1623d4443e41dcda5dc815c06b442aa3c02889fc8"},
|
| 660 |
+
]
|
| 661 |
+
|
| 662 |
+
[package.dependencies]
|
| 663 |
+
click = ">=4.0"
|
| 664 |
+
|
| 665 |
+
[package.extras]
|
| 666 |
+
dev = ["coveralls", "pytest (>=3.6)", "pytest-cov", "wheel"]
|
| 667 |
+
|
| 668 |
+
[[package]]
|
| 669 |
+
name = "click-repl"
|
| 670 |
+
version = "0.3.0"
|
| 671 |
+
description = "REPL plugin for Click"
|
| 672 |
+
optional = false
|
| 673 |
+
python-versions = ">=3.6"
|
| 674 |
+
files = [
|
| 675 |
+
{file = "click-repl-0.3.0.tar.gz", hash = "sha256:17849c23dba3d667247dc4defe1757fff98694e90fe37474f3feebb69ced26a9"},
|
| 676 |
+
{file = "click_repl-0.3.0-py3-none-any.whl", hash = "sha256:fb7e06deb8da8de86180a33a9da97ac316751c094c6899382da7feeeeb51b812"},
|
| 677 |
+
]
|
| 678 |
+
|
| 679 |
+
[package.dependencies]
|
| 680 |
+
click = ">=7.0"
|
| 681 |
+
prompt-toolkit = ">=3.0.36"
|
| 682 |
+
|
| 683 |
+
[package.extras]
|
| 684 |
+
testing = ["pytest (>=7.2.1)", "pytest-cov (>=4.0.0)", "tox (>=4.4.3)"]
|
| 685 |
+
|
| 686 |
[[package]]
|
| 687 |
name = "colorama"
|
| 688 |
version = "0.4.6"
|
|
|
|
| 1224 |
[package.extras]
|
| 1225 |
all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"]
|
| 1226 |
|
| 1227 |
+
[[package]]
|
| 1228 |
+
name = "iniconfig"
|
| 1229 |
+
version = "2.0.0"
|
| 1230 |
+
description = "brain-dead simple config-ini parsing"
|
| 1231 |
+
optional = false
|
| 1232 |
+
python-versions = ">=3.7"
|
| 1233 |
+
files = [
|
| 1234 |
+
{file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"},
|
| 1235 |
+
{file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
|
| 1236 |
+
]
|
| 1237 |
+
|
| 1238 |
[[package]]
|
| 1239 |
name = "isodate"
|
| 1240 |
version = "0.7.2"
|
|
|
|
| 1246 |
{file = "isodate-0.7.2.tar.gz", hash = "sha256:4cd1aa0f43ca76f4a6c6c0292a85f40b35ec2e43e315b59f06e6d32171a953e6"},
|
| 1247 |
]
|
| 1248 |
|
| 1249 |
+
[[package]]
|
| 1250 |
+
name = "kombu"
|
| 1251 |
+
version = "5.4.2"
|
| 1252 |
+
description = "Messaging library for Python."
|
| 1253 |
+
optional = false
|
| 1254 |
+
python-versions = ">=3.8"
|
| 1255 |
+
files = [
|
| 1256 |
+
{file = "kombu-5.4.2-py3-none-any.whl", hash = "sha256:14212f5ccf022fc0a70453bb025a1dcc32782a588c49ea866884047d66e14763"},
|
| 1257 |
+
{file = "kombu-5.4.2.tar.gz", hash = "sha256:eef572dd2fd9fc614b37580e3caeafdd5af46c1eff31e7fba89138cdb406f2cf"},
|
| 1258 |
+
]
|
| 1259 |
+
|
| 1260 |
+
[package.dependencies]
|
| 1261 |
+
amqp = ">=5.1.1,<6.0.0"
|
| 1262 |
+
tzdata = {version = "*", markers = "python_version >= \"3.9\""}
|
| 1263 |
+
vine = "5.1.0"
|
| 1264 |
+
|
| 1265 |
+
[package.extras]
|
| 1266 |
+
azureservicebus = ["azure-servicebus (>=7.10.0)"]
|
| 1267 |
+
azurestoragequeues = ["azure-identity (>=1.12.0)", "azure-storage-queue (>=12.6.0)"]
|
| 1268 |
+
confluentkafka = ["confluent-kafka (>=2.2.0)"]
|
| 1269 |
+
consul = ["python-consul2 (==0.1.5)"]
|
| 1270 |
+
librabbitmq = ["librabbitmq (>=2.0.0)"]
|
| 1271 |
+
mongodb = ["pymongo (>=4.1.1)"]
|
| 1272 |
+
msgpack = ["msgpack (==1.1.0)"]
|
| 1273 |
+
pyro = ["pyro4 (==4.82)"]
|
| 1274 |
+
qpid = ["qpid-python (>=0.26)", "qpid-tools (>=0.26)"]
|
| 1275 |
+
redis = ["redis (>=4.5.2,!=4.5.5,!=5.0.2)"]
|
| 1276 |
+
slmq = ["softlayer-messaging (>=1.0.3)"]
|
| 1277 |
+
sqlalchemy = ["sqlalchemy (>=1.4.48,<2.1)"]
|
| 1278 |
+
sqs = ["boto3 (>=1.26.143)", "pycurl (>=7.43.0.5)", "urllib3 (>=1.26.16)"]
|
| 1279 |
+
yaml = ["PyYAML (>=3.10)"]
|
| 1280 |
+
zookeeper = ["kazoo (>=2.8.0)"]
|
| 1281 |
+
|
| 1282 |
[[package]]
|
| 1283 |
name = "loguru"
|
| 1284 |
version = "0.7.2"
|
|
|
|
| 1658 |
test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)"]
|
| 1659 |
xml = ["lxml (>=4.9.2)"]
|
| 1660 |
|
| 1661 |
+
[[package]]
|
| 1662 |
+
name = "pluggy"
|
| 1663 |
+
version = "1.5.0"
|
| 1664 |
+
description = "plugin and hook calling mechanisms for python"
|
| 1665 |
+
optional = false
|
| 1666 |
+
python-versions = ">=3.8"
|
| 1667 |
+
files = [
|
| 1668 |
+
{file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"},
|
| 1669 |
+
{file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"},
|
| 1670 |
+
]
|
| 1671 |
+
|
| 1672 |
+
[package.extras]
|
| 1673 |
+
dev = ["pre-commit", "tox"]
|
| 1674 |
+
testing = ["pytest", "pytest-benchmark"]
|
| 1675 |
+
|
| 1676 |
+
[[package]]
|
| 1677 |
+
name = "prompt-toolkit"
|
| 1678 |
+
version = "3.0.48"
|
| 1679 |
+
description = "Library for building powerful interactive command lines in Python"
|
| 1680 |
+
optional = false
|
| 1681 |
+
python-versions = ">=3.7.0"
|
| 1682 |
+
files = [
|
| 1683 |
+
{file = "prompt_toolkit-3.0.48-py3-none-any.whl", hash = "sha256:f49a827f90062e411f1ce1f854f2aedb3c23353244f8108b89283587397ac10e"},
|
| 1684 |
+
{file = "prompt_toolkit-3.0.48.tar.gz", hash = "sha256:d6623ab0477a80df74e646bdbc93621143f5caf104206aa29294d53de1a03d90"},
|
| 1685 |
+
]
|
| 1686 |
+
|
| 1687 |
+
[package.dependencies]
|
| 1688 |
+
wcwidth = "*"
|
| 1689 |
+
|
| 1690 |
[[package]]
|
| 1691 |
name = "propcache"
|
| 1692 |
version = "0.2.0"
|
|
|
|
| 2039 |
toml = ["tomli (>=2.0.1)"]
|
| 2040 |
yaml = ["pyyaml (>=6.0.1)"]
|
| 2041 |
|
| 2042 |
+
[[package]]
|
| 2043 |
+
name = "pytest"
|
| 2044 |
+
version = "7.4.4"
|
| 2045 |
+
description = "pytest: simple powerful testing with Python"
|
| 2046 |
+
optional = false
|
| 2047 |
+
python-versions = ">=3.7"
|
| 2048 |
+
files = [
|
| 2049 |
+
{file = "pytest-7.4.4-py3-none-any.whl", hash = "sha256:b090cdf5ed60bf4c45261be03239c2c1c22df034fbffe691abe93cd80cea01d8"},
|
| 2050 |
+
{file = "pytest-7.4.4.tar.gz", hash = "sha256:2cf0005922c6ace4a3e2ec8b4080eb0d9753fdc93107415332f50ce9e7994280"},
|
| 2051 |
+
]
|
| 2052 |
+
|
| 2053 |
+
[package.dependencies]
|
| 2054 |
+
colorama = {version = "*", markers = "sys_platform == \"win32\""}
|
| 2055 |
+
exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""}
|
| 2056 |
+
iniconfig = "*"
|
| 2057 |
+
packaging = "*"
|
| 2058 |
+
pluggy = ">=0.12,<2.0"
|
| 2059 |
+
tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""}
|
| 2060 |
+
|
| 2061 |
+
[package.extras]
|
| 2062 |
+
testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"]
|
| 2063 |
+
|
| 2064 |
+
[[package]]
|
| 2065 |
+
name = "pytest-asyncio"
|
| 2066 |
+
version = "0.20.3"
|
| 2067 |
+
description = "Pytest support for asyncio"
|
| 2068 |
+
optional = false
|
| 2069 |
+
python-versions = ">=3.7"
|
| 2070 |
+
files = [
|
| 2071 |
+
{file = "pytest-asyncio-0.20.3.tar.gz", hash = "sha256:83cbf01169ce3e8eb71c6c278ccb0574d1a7a3bb8eaaf5e50e0ad342afb33b36"},
|
| 2072 |
+
{file = "pytest_asyncio-0.20.3-py3-none-any.whl", hash = "sha256:f129998b209d04fcc65c96fc85c11e5316738358909a8399e93be553d7656442"},
|
| 2073 |
+
]
|
| 2074 |
+
|
| 2075 |
+
[package.dependencies]
|
| 2076 |
+
pytest = ">=6.1.0"
|
| 2077 |
+
|
| 2078 |
+
[package.extras]
|
| 2079 |
+
docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1.0)"]
|
| 2080 |
+
testing = ["coverage (>=6.2)", "flaky (>=3.5.0)", "hypothesis (>=5.7.1)", "mypy (>=0.931)", "pytest-trio (>=0.7.0)"]
|
| 2081 |
+
|
| 2082 |
[[package]]
|
| 2083 |
name = "python-dateutil"
|
| 2084 |
version = "2.9.0.post0"
|
|
|
|
| 2436 |
doc = ["reno", "sphinx"]
|
| 2437 |
test = ["pytest", "tornado (>=4.5)", "typeguard"]
|
| 2438 |
|
| 2439 |
+
[[package]]
|
| 2440 |
+
name = "tomli"
|
| 2441 |
+
version = "2.0.2"
|
| 2442 |
+
description = "A lil' TOML parser"
|
| 2443 |
+
optional = false
|
| 2444 |
+
python-versions = ">=3.8"
|
| 2445 |
+
files = [
|
| 2446 |
+
{file = "tomli-2.0.2-py3-none-any.whl", hash = "sha256:2ebe24485c53d303f690b0ec092806a085f07af5a5aa1464f3931eec36caaa38"},
|
| 2447 |
+
{file = "tomli-2.0.2.tar.gz", hash = "sha256:d46d457a85337051c36524bc5349dd91b1877838e2979ac5ced3e710ed8a60ed"},
|
| 2448 |
+
]
|
| 2449 |
+
|
| 2450 |
[[package]]
|
| 2451 |
name = "typing-extensions"
|
| 2452 |
version = "4.12.2"
|
|
|
|
| 2520 |
[package.extras]
|
| 2521 |
standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.4)"]
|
| 2522 |
|
| 2523 |
+
[[package]]
|
| 2524 |
+
name = "vine"
|
| 2525 |
+
version = "5.1.0"
|
| 2526 |
+
description = "Python promises."
|
| 2527 |
+
optional = false
|
| 2528 |
+
python-versions = ">=3.6"
|
| 2529 |
+
files = [
|
| 2530 |
+
{file = "vine-5.1.0-py3-none-any.whl", hash = "sha256:40fdf3c48b2cfe1c38a49e9ae2da6fda88e4794c810050a728bd7413811fb1dc"},
|
| 2531 |
+
{file = "vine-5.1.0.tar.gz", hash = "sha256:8b62e981d35c41049211cf62a0a1242d8c1ee9bd15bb196ce38aefd6799e61e0"},
|
| 2532 |
+
]
|
| 2533 |
+
|
| 2534 |
+
[[package]]
|
| 2535 |
+
name = "wcwidth"
|
| 2536 |
+
version = "0.2.13"
|
| 2537 |
+
description = "Measures the displayed width of unicode strings in a terminal"
|
| 2538 |
+
optional = false
|
| 2539 |
+
python-versions = "*"
|
| 2540 |
+
files = [
|
| 2541 |
+
{file = "wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859"},
|
| 2542 |
+
{file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"},
|
| 2543 |
+
]
|
| 2544 |
+
|
| 2545 |
[[package]]
|
| 2546 |
name = "win32-setctime"
|
| 2547 |
version = "1.1.0"
|
|
|
|
| 2655 |
[metadata]
|
| 2656 |
lock-version = "2.0"
|
| 2657 |
python-versions = "3.10.15"
|
| 2658 |
+
content-hash = "db72df885a8c6d58dfb9ab3d27f3823b4546e1cd0c08b50b2d1bf50ffcd3798c"
|
pyproject.toml
CHANGED
|
@@ -39,7 +39,11 @@ redisearch = "2.0.0"
|
|
| 39 |
pandas = "^2.2.3"
|
| 40 |
python-multipart = "^0.0.17"
|
| 41 |
python-dotenv = "^1.0.1"
|
|
|
|
| 42 |
|
|
|
|
|
|
|
|
|
|
| 43 |
|
| 44 |
[build-system]
|
| 45 |
requires = ["poetry-core"]
|
|
|
|
| 39 |
pandas = "^2.2.3"
|
| 40 |
python-multipart = "^0.0.17"
|
| 41 |
python-dotenv = "^1.0.1"
|
| 42 |
+
celery = "^5.4.0"
|
| 43 |
|
| 44 |
+
[tool.poetry.dev-dependencies]
|
| 45 |
+
pytest = "^7.2.0"
|
| 46 |
+
pytest-asyncio = "^0.20.3"
|
| 47 |
|
| 48 |
[build-system]
|
| 49 |
requires = ["poetry-core"]
|
src/__pycache__/test_infra.cpython-310.pyc
CHANGED
|
Binary files a/src/__pycache__/test_infra.cpython-310.pyc and b/src/__pycache__/test_infra.cpython-310.pyc differ
|
|
|
src/number_manipulation.py
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import random
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
def add_random_number(user_input: int) -> int:
|
| 5 |
+
random_addition = random.randint(1, 100) # Add a random number between 1 and 100
|
| 6 |
+
result = user_input + random_addition
|
| 7 |
+
return result
|
src/test_infra.py
CHANGED
|
@@ -26,7 +26,7 @@ async def test_redis_connection(redis_url: str):
|
|
| 26 |
async def main():
|
| 27 |
logger.info(f"Settings: {settings.dict()}")
|
| 28 |
|
| 29 |
-
await test_postgres_connection(settings.database_url)
|
| 30 |
await test_redis_connection(settings.redis_url)
|
| 31 |
|
| 32 |
|
|
|
|
| 26 |
async def main():
|
| 27 |
logger.info(f"Settings: {settings.dict()}")
|
| 28 |
|
| 29 |
+
await test_postgres_connection(settings.database_url.replace("+asyncpg", ""))
|
| 30 |
await test_redis_connection(settings.redis_url)
|
| 31 |
|
| 32 |
|
tests/__init__.py
ADDED
|
File without changes
|
tests/test_db_connection.py
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import pytest
|
| 2 |
+
from sqlalchemy.ext.asyncio import AsyncSession
|
| 3 |
+
from sqlalchemy import text
|
| 4 |
+
from app.db.database import get_db
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
@pytest.mark.asyncio
|
| 8 |
+
async def test_database_connection():
|
| 9 |
+
# Use the get_db dependency directly for testing
|
| 10 |
+
async for session in get_db():
|
| 11 |
+
assert isinstance(
|
| 12 |
+
session, AsyncSession
|
| 13 |
+
), "Session is not an instance of AsyncSession"
|
| 14 |
+
|
| 15 |
+
# Check if the session can execute a simple query
|
| 16 |
+
result = await session.execute(text("SELECT 1"))
|
| 17 |
+
assert result.scalar() == 1, "Database did not return expected result"
|