Skip to content

Commit c594786

Browse files
authored
Merge pull request #1343 from Open-Source-Legal/claude/fix-mypy-issue-1331-Hs6Vk
Wire mypy into pre-commit and CI with ignore-errors baseline
2 parents c4b049b + 705614e commit c594786

134 files changed

Lines changed: 8698 additions & 15 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/backend.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ jobs:
5858
- 'Dockerfile*'
5959
- '.pre-commit-config.yaml'
6060
- 'setup.cfg'
61+
- 'mypy.ini'
6162
- 'pyproject.toml'
6263
- '.github/workflows/backend.yml'
6364
@@ -92,6 +93,15 @@ jobs:
9293
- name: Run pre-commit
9394
run: pre-commit run --all-files
9495

96+
- name: Run mypy
97+
# Runs from requirements/local.txt (not via pre-commit) so CI is
98+
# authoritative even when contributors skip the hook. Keep the
99+
# mypy pin in requirements/local.txt in sync with the `rev:` of
100+
# the mirrors-mypy hook in .pre-commit-config.yaml — a drift
101+
# means the hook and CI can disagree silently. See
102+
# docs/typing/README.md.
103+
run: python -m mypy --config-file mypy.ini opencontractserver config
104+
95105
pytest:
96106
needs: [changes, linter]
97107
# Same fail-open semantics as the linter gate above.

.pre-commit-config.yaml

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,91 @@ repos:
3333
args: ["--config=setup.cfg"]
3434
additional_dependencies: [flake8-isort]
3535

36+
- repo: https://github.com/pre-commit/mirrors-mypy
37+
rev: v1.20.1
38+
hooks:
39+
- id: mypy
40+
# Always check the full project surface, not just staged files —
41+
# the Django plugin is a per-project load so partial runs miss
42+
# cross-module errors. See docs/typing/README.md.
43+
pass_filenames: false
44+
args: ["--config-file=mypy.ini", "opencontractserver", "config"]
45+
# mypy-django-plugin imports config.settings.mypy at startup, which
46+
# pulls in most of INSTALLED_APPS. Pinning the Django + stub runtime
47+
# here keeps the hook self-contained (contributors don't need the
48+
# full dev env installed locally).
49+
# pre-commit autoupdate only bumps `rev`; additional_dependencies
50+
# are resolved fresh every time the hook env is (re)built, so
51+
# anything less than `==` can drift. Direct dependencies whose
52+
# API surface mypy actually checks against are `==`-pinned and
53+
# MUST match requirements/base.txt + requirements/local.txt. The
54+
# admin autodiscover that django-stubs triggers transitively
55+
# imports most of the project, which is why the list is long.
56+
# A handful of transitive deps (pandas, python-docx, openpyxl,
57+
# python-pptx, spacy) are left unpinned or range-pinned — they
58+
# are import-only (mypy never follows into their types with
59+
# ignore_missing_imports=True), so a compatible bump cannot
60+
# introduce new type errors. Range pins upper-bound known
61+
# major breakages (e.g. pypdf 7, openai 3) for the same reason.
62+
additional_dependencies:
63+
# --- Type stubs -----------------------------------------------
64+
- django-stubs==6.0.2
65+
- djangorestframework-stubs==3.16.9
66+
- types-requests==2.33.0.20260408
67+
- types-PyYAML==6.0.12.20260408
68+
# --- Django runtime (must match requirements/base.txt) --------
69+
- django==5.2.13
70+
- django-environ==0.13.0
71+
- django-model-utils==5.0.0
72+
- django-redis==6.0.0
73+
- django-filter==25.1
74+
- django-storages[boto3,google]==1.14.6
75+
- django-tree-queries[admin]==0.24.0
76+
- django-cte==3.0.0
77+
- django-guardian==3.3.1
78+
- django-celery-beat==2.9.0
79+
- django-cors-headers==4.9.0
80+
- djangorestframework==3.17.1
81+
- drf-extra-fields==3.7.0
82+
- whitenoise==6.12.0
83+
- channels==4.3.2
84+
- channels-redis==4.3.0
85+
- daphne==4.2.1
86+
- celery==5.6.3
87+
- pgvector==0.4.2
88+
- graphene-django==3.2.3
89+
- django-graphql-jwt==0.4.0
90+
- pydantic==2.13.3
91+
- psycopg2-binary==2.9.11
92+
# --- Pulled in transitively by app admin autodiscover ---------
93+
- Pillow>=10.4.0
94+
- pypdf>=4.0.0,<7
95+
- plasmapdf==0.1.3
96+
- pdfplumber>=0.10.0
97+
- pdf2image>=1.16.0
98+
- shapely>=2.0.0
99+
- opencv-python-headless==4.13.0.92
100+
- filetype==1.2.0
101+
- python-docx
102+
- openpyxl
103+
- python-pptx
104+
- pandas
105+
- tiktoken==0.12.0
106+
- openai>=2.11.0,<3
107+
- pydantic-ai>=1.56.0,<2
108+
- spacy
109+
- tokenizers>=0.21,<0.23
110+
- posthog==7.12.0
111+
- jsonschema==4.26.0
112+
- mcp>=1.0.0
113+
- python-slugify==8.0.4
114+
- argon2-cffi==25.1.0
115+
- cryptography==46.0.7
116+
- pyjwt==2.12.1
117+
- requests>=2.32.2
118+
- httpx>=0.27.0,<1
119+
- redis==7.4.0
120+
36121
# sets up .pre-commit-ci.yaml to ensure pre-commit dependencies stay up to date
37122
ci:
38123
autoupdate_schedule: weekly

CHANGELOG.md

Lines changed: 9 additions & 0 deletions

config/settings/mypy.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
"""
2+
Settings module used exclusively by `mypy_django_plugin` during type checking.
3+
4+
The plugin imports this module at startup to introspect `INSTALLED_APPS` and
5+
model metadata. It does **not** run the ORM, so the database URL below is a
6+
dummy value that only needs to parse cleanly through `django-environ`.
7+
8+
Keeping a dedicated module here (instead of pointing the plugin at
9+
`config.settings.test`) means contributors do not need to set `DATABASE_URL`
10+
to run mypy locally or via pre-commit.
11+
"""
12+
13+
import os
14+
15+
# `env.db(...)` in `config.settings.base` raises unless DATABASE_URL is set.
16+
# Set it *and* keep a local copy so we can reassert it after the test
17+
# import below, in case `config.settings.test` (or any of its transitive
18+
# imports) ever grows a DATABASE_URL override that runs before we re-read
19+
# the env.
20+
_MYPY_DUMMY_DATABASE_URL = "postgres://mypy:mypy@localhost:5432/mypy_dummy_db"
21+
os.environ.setdefault("DATABASE_URL", _MYPY_DUMMY_DATABASE_URL)
22+
23+
# As of 2026-04, `config.settings.test` only requires DATABASE_URL from
24+
# the environment. If a future change adds another required env var to
25+
# the test chain, add a matching os.environ.setdefault() above.
26+
from .test import * # noqa: E402, F401, F403
27+
28+
# Defensive: if the test-settings import chain ever pops DATABASE_URL from
29+
# the environment (unlikely but cheap to guard), put it back so the rest of
30+
# the plugin start-up doesn't explode on a later env.db() call.
31+
os.environ.setdefault("DATABASE_URL", _MYPY_DUMMY_DATABASE_URL)
8.44 KB
-6 Bytes
1.91 KB
1.74 KB
-468 Bytes
-1.32 KB

0 commit comments

Comments
 (0)