[[source]] name = "pypi" url = "https://pypi.org/simple" verify_ssl = true [dev-packages] pytest-playwright = "*" pytest-django = "*" # settings.py loads .env through it when present and runs without it (production # gets its variables from Render). The old 3.9 venv had it installed by hand and # nobody noticed; without it every test that reads an AI key from .env fails. python-dotenv = "*" tblib = "*" [packages] # ~=5.2: the LTS (April 2028). `*` is how 4.2 stayed pinned for a year — the resolver # re-picks the newest Django the interpreter allows, and would jump to 6.0 next. django = "~=5.2" django-debug-toolbar = "*" psycopg2-binary = "*" django-leaflet = "*" geojson = "*" django-registration = "*" # The three pins below hold major versions the Python 3.12 resolver would otherwise # jump (pandas 3, gunicorn 26, Pillow 12): each is its own change with its own checks # (pandas: export value tests; gunicorn: scripts/gunicorn_recycle_check.py against the # DrainingThreadWorker, which subclasses gthread internals). pandas = "~=2.3" gunicorn = "~=23.0" whitenoise = "*" django-storages = "*" boto3 = "*" pillow = "~=11.3" celery = {extras = ["redis"], version = "*"} django-ratelimit = "*" # Token store and, from #313, the OAuth 2.1 authorization server (change auth-core, #379). # ~=3.4: the RFC 9700 gates and hashed token storage arrived in 3.x; 4.0 flips their # defaults, which our explicit settings block already pins. django-oauth-toolkit = "~=3.4" django-redis = "*" requests = "*" google-api-python-client = "*" google-auth = "*" nh3 = "*" # <1: the 1.x SDK changed its API; the provider code is Gemini-first and the Anthropic # path is exercised only by its tests — bump in its own change. anthropic = "~=0.122" # 6.7.5-6.7.13 shipped with broken Django exception capture (posthog-python #286/#329); # PostHogErrorTrackingTest are the canaries — run them before moving this in either # direction. Read openspec/changes/posthog-error-tracking/design.md first. posthog = "~=6.9" # Excel export (survey/export.py), write-only mode. openpyxl = "*" # The REST API v1 (change rest-api-v1, #380): pydantic schemas are the validation AND the # OpenAPI document, so there is no serializer layer to keep in sync. django-ninja = "~=1.7" # QR codes for the share API and MCP (change api-v2-distribution, #410): pure Python, # writes SVG and PNG itself -- no Pillow, no system library. segno = "~=1.6" # Printable paper forms (change printable-form, #489): pure Python over Pillow, no system # library in the image. survey/print/ registers the bundled DejaVu fonts with it. reportlab = "~=4.4" # Photos of filled paper forms (change paper-photo-entry, #495). All three ship their # native library inside the wheel (pdfium, libheif, the zxing decoder), so the image # needs no apt line; the worker, never the web process, imports them. pypdfium2 = "~=4.30" # Numbered copies: the form is laid out once and each copy's codes are merged onto # it page by page (survey/print/pdf.py::print_copies). Pure Python. Tests also read # the printed PDFs back with it (it was a dev package until this change). pypdf = "*" pillow-heif = "*" zxing-cpp = "*" # Photographed maps are matched against the printed frame (survey/paper/texture.py: # FFT cross-correlation, the registration's inverse on a grid). Was transitive before. numpy = "~=2.5" [requires] python_version = "3.12"