[project]
description = "Learnhouse Backend"
name = "learnhouse-api"
version = "1.3.5"
requires-python = ">=3.14.6,<3.14.7"
authors = [
    {name = "Badr B. (swve)"}
]
dependencies = [
    "boto3==1.43.80",
    "botocore==1.43.80",
    "faker==40.37.0",
    "fastapi==0.141.1",
    "httpx==0.28.1",
    "google-genai==2.20.0",
    "pydantic-ai-slim[openai,anthropic,google,mistral]==2.35.0",
    "pwdlib[argon2]==0.3.1",
    "psycopg2-binary==2.9.12",
    "asyncpg==0.31.0",
    "aiosqlite==0.22.1",
    "pydantic[email]==2.13.4",
    "pytest==9.1.1",
    "pytest-cov==7.1.0",
    "python-dotenv==1.2.3",
    "python-multipart==0.0.32",
    "pyyaml==6.0.3",
    "redis==8.1.0",
    "requests==2.34.2",
    "resend==2.41.0",
    "sqlmodel==0.0.39",
    "tiktoken==0.14.0",
    "uvicorn==0.52.4",
    "typer==0.27.1",
    "alembic==1.19.1",
    "alembic-postgresql-enum==1.10.0",
    "sqlalchemy-utils==0.42.1",
    "stripe==15.5.1",
    "cryptography==50.0.1",
    "pyjwt[crypto]==2.13.0",
    "pyotp==2.10.0",
    "beautifulsoup4==4.15.0",
    "pytest-asyncio==1.4.0",
    "sentry-sdk[fastapi]==2.68.1",
    "protobuf==7.36.0",
    "workos==10.2.0",
    "dnspython==2.8.0",
    "defusedxml==0.7.1",
    "llama-index-core==0.14.24",
    "pgvector==0.5.0",
    "pypdf==6.16.2",
    "regex==2026.7.19",
]

[tool.ruff]
lint.ignore = ["E501", "E712"]

[tool.pytest.ini_options]
asyncio_mode = "auto"
asyncio_default_fixture_loop_scope = "function"
markers = [
    "asyncio: mark test as async",
    "ollama: live test that requires a local Ollama server (opt-in; skipped if unreachable)",
]
filterwarnings = [
    "ignore::DeprecationWarning",
    "ignore::UserWarning",
    "ignore:.*crypt.*deprecated.*",
    "ignore:.*Instrumentation will have no effect.*",
    "ignore:.*handler names should be lower-case.*",
]

[tool.coverage.run]
source = ["src"]
omit = [
    "src/tests/*",
    "src/services/ai/*",
    "src/routers/ai/*",
    "src/routers/code_execution.py",
    "src/routers/stream.py",
]

[tool.coverage.report]
fail_under = 25
show_missing = true
exclude_lines = [
    "pragma: no cover",
    "if TYPE_CHECKING:",
    "if __name__",
]