[project] name = "imago" version = "2.0.0" description = "Backend FastAPI pour la gestion d'images et fonctionnalités AI — Imago" requires-python = ">=3.12" license = "MIT" license-files = ["LICENSE"] dependencies = [ # Web Framework "fastapi==0.115.0", "uvicorn[standard]==0.30.6", "python-multipart==0.0.9", # Database "sqlalchemy==2.0.35", "alembic==1.13.3", "aiosqlite==0.20.0", "asyncpg==0.29.0", # Validation "pydantic==2.9.2; python_version < '3.14'", "pydantic>=2.12.0; python_version >= '3.14'", "pydantic-settings==2.5.2", # Image Processing "Pillow==10.4.0; python_version < '3.14'", "Pillow>=11.0.0; python_version >= '3.14'", "piexif==1.1.3", # OCR "pytesseract==0.3.13", # AI "google-genai==1.0.0", "httpx==0.27.2", # Web scraping "beautifulsoup4==4.12.3", # Task scheduling "apscheduler==3.10.4", # Task queue "arq==0.25.0", "redis==5.0.8", # Storage abstraction "aioboto3==13.0.0", "itsdangerous==2.2.0", # Observability "structlog==24.4.0", "prometheus-fastapi-instrumentator==7.0.2", # Utilities "python-dotenv==1.0.1", "python-jose[cryptography]==3.3.0", "passlib[bcrypt]==1.7.4", "aiofiles==24.1.0", # Rate Limiting "slowapi==0.1.9", # WebSockets "websockets>=13.0", ] [project.optional-dependencies] dev = [ "pytest==8.3.3", "pytest-asyncio==0.24.0", "pytest-cov==5.0.0", "ruff==0.8.6", "mypy==1.13.0", "pre-commit==4.0.1", "types-aiofiles==24.1.0.20240626", ] [tool.ruff] target-version = "py312" line-length = 120 src = ["app", "tests"] [tool.ruff.lint] select = [ "E", # pycodestyle errors "W", # pycodestyle warnings "F", # pyflakes "I", # isort "N", # pep8-naming "UP", # pyupgrade "B", # bugbear "S", # bandit (security) "T20", # flake8-print "SIM", # flake8-simplify "RUF", # ruff-specific ] ignore = [ "S101", # allow assert in tests "S104", # allow 0.0.0.0 bindings "B008", # allow Depends() in function args (FastAPI pattern) "E501", # line length handled by formatter "UP007", # keep Optional[] syntax for readability ] [tool.ruff.lint.per-file-ignores] "tests/*" = ["S101", "S106", "T20"] [tool.ruff.format] quote-style = "double" indent-style = "space" docstring-code-format = true [tool.mypy] python_version = "3.12" warn_return_any = true warn_unused_configs = true ignore_missing_imports = true check_untyped_defs = true plugins = ["pydantic.mypy"] [tool.pytest.ini_options] asyncio_mode = "auto" testpaths = ["tests"] python_files = ["test_*.py"] python_functions = ["test_*"] filterwarnings = ["ignore::DeprecationWarning"] addopts = "--tb=short -q" [tool.coverage.run] source = ["app"] omit = ["app/workers/*", "tests/*"] [tool.coverage.report] show_missing = true fail_under = 60 exclude_lines = [ "pragma: no cover", "if __name__ ==", "if TYPE_CHECKING:", ]