[project] name = "tradein-mvp-backend" version = "0.1.0" description = "Trade-In Estimator MVP — standalone fork of gendesign trade-in feature" requires-python = ">=3.12" dependencies = [ "fastapi>=0.115.0", "uvicorn[standard]>=0.30.0", "sqlalchemy>=2.0.30", "geoalchemy2>=0.15.0", # PostGIS support для SQLAlchemy "pydantic>=2.7.0", "pydantic-settings>=2.3.0", "psycopg[binary]>=3.2.0", "Pillow>=10.3.0", # photo sanitization re-encode (#6 audit fix) "weasyprint>=62.0", "jinja2>=3.1.0", "httpx[socks]>=0.27.0", # для geocoder + scrapers; [socks] тянет socksio для socks5:// "tenacity>=9.0.0", # retry с exp backoff "selectolax>=0.3.0", # быстрый HTML парсинг для scrapers "lxml>=5.0.0", # стриминговый iterparse для многогигабайтных ГАР XML (#143) "segno>=1.6.0", # QR-код для PDF shareable URL "matplotlib>=3.9.0", # price-range chart (SVG) для PDF отчёта Trade-In "curl-cffi>=0.7.0", # impersonate=chrome120 для Cian/Avito (TLS fingerprint) "python-multipart>=0.0.9", # FastAPI UploadFile — загрузка фото квартиры (#394) "sentry-sdk>=2.0.0", # мониторинг ошибок → GlitchTip (#396) "redis>=5.0.0", # async hot cache для /api/v1/search (Phase 3.2) "pyyaml>=6.0.0", # RBAC roles.yaml loader (app/core/auth.py) "playwright>=1.45", # Playwright client для connect к tradein-browser (#905) "scraper-kit", # internal workspace-package (#2137) — общие утилиты скрапперов; # резолвится из workspace (см. [tool.uv.sources]), не с PyPI. # Docker-context = tradein-mvp root, uv sync ставит editable. ] [tool.uv.sources] scraper-kit = { workspace = true } [dependency-groups] dev = [ "pytest>=8.0.0", "pytest-asyncio>=0.24.0", "pytest-timeout>=2.3.0", "ruff>=0.5.0", ] [tool.pytest.ini_options] asyncio_mode = "auto" # Страховка от зависших тестов в CI (per-test wall-clock limit, секунды). # Покрывает и pre-merge гейт (ci-tradein.yml), и post-merge test-job (deploy). timeout = 120 [tool.setuptools.packages.find] include = ["app*"] [tool.ruff] target-version = "py312" line-length = 100 [tool.ruff.lint] select = ["E", "F", "I", "B", "UP", "N", "RUF"] ignore = ["RUF001", "RUF002", "RUF003"]