Repository navigation
Expand file tree
/
Copy path.pre-commit-config.yaml
More file actions
116 lines (108 loc) · 5.56 KB
/
Copy path.pre-commit-config.yaml
File metadata and controls
116 lines (108 loc) · 5.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# Pre-commit hooks for ML4T Technical Review
# Install: pre-commit install
# Run manually: pre-commit run --all-files
repos:
# Keep in lockstep with the `ruff==` pin in pyproject.toml's dev extra;
# tests/test_toolchain_pins.py fails when the two drift.
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.15.14
hooks:
- id: ruff
args: [--fix]
types: [python]
exclude: \.ipynb$
- id: ruff-format
types: [python]
exclude: \.ipynb$
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
- id: trailing-whitespace
exclude: \.md$
- id: end-of-file-fixer
exclude: \.md$
- id: check-yaml
- id: check-toml
- repo: local
hooks:
# Compile-time syntax check. ast.parse misses errors raised only at
# compile time (duplicate kwargs, await outside async, return at module
# level, etc.) — `python -m py_compile` invokes the full compile()
# path and catches them. Cheap; runs on every staged Python file.
- id: py-compile
name: python -m py_compile (catches duplicate kwargs etc.)
language: system
entry: python3 -m py_compile
types: [python]
exclude: \.ipynb$
# Load gate: a paired .ipynb must agree with its .py, or JupyterLab's
# jupytext contents manager refuses to open it and the reader gets a
# "File Load Error" instead of a notebook (public issue #372 — papermill
# leaves an empty `tags: []` on every cell that the .py does not carry).
# Only checks the staged pairs. See .github/scripts/check_notebook_pair_sync.py.
- id: notebook-pair-sync
name: notebook/py pair opens in JupyterLab
language: system
entry: python3 .github/scripts/check_notebook_pair_sync.py
files: \.(ipynb|py)$
# A committed notebook must not carry the Plotly figure JSON beside the static
# image of the same figure. Plotly serializes every data point of every trace,
# which made 25.3 MB out of 0.03 MB of source in 01_academic_characteristics and
# left a reader on github.com staring at an empty pane for twenty seconds. The
# PNG is what every static reader shows; a reader who runs the cell gets the
# interactive figure back. Only outputs that carry no static image are left
# alone, because there the payload is the only copy of the chart.
# Fix: strip_plotly_json.py, then notebook_provenance.py sync-plotly <nb>.
- id: strip-plotly-json
name: no embedded Plotly JSON beside a static image
language: system
entry: python3 .github/scripts/strip_plotly_json.py --check
files: \.ipynb$
# Sync gate: a stamped notebook must be its CURRENT .py executed in a
# production run. Fails if any provenance-stamped .ipynb is stale (its
# paired .py changed since execution) or was committed from a TEST-mode
# run. Unstamped notebooks are advisory only (gradual adoption). See
# .github/scripts/notebook_provenance.py.
# Scoped to the staged files since 2026-08-22. It used to scan the whole tree
# on every commit, so one notebook another session had left dirty blocked every
# unrelated commit in that worktree - three worktrees were stuck that way in a
# single day, and the cme_futures one could not commit anything for six days.
# Nothing unstaged can reach main, so the narrower scan gives up no protection.
# This hook gates the commit; the merge is gated separately, by the `guards` job
# in .github/workflows/test.yml running
# notebook_provenance.py check --since <base>
# over the notebooks the pull request touches, and against the previous tip on a
# push to main. A stale render only reaches a reader through a merge, and until
# that job existed no merge was covered at all.
- id: notebook-sync
name: notebook provenance sync gate
language: system
entry: python3 .github/scripts/notebook_provenance.py check
files: \.(py|ipynb)$
pass_filenames: true
# Verification gate: a notebook whose verifier signed off on one exact
# version may not be silently changed. `.verified-notebooks.tsv` records
# the .py blob at sign-off; this fails a commit that changes a listed .py
# while leaving its row intact. Four batch rewrites in the week to
# 2026-08-06 erased ~30 verifications this way, PR #478 doing 34 notebooks
# in one commit. See .github/scripts/check_verified_notebooks.py.
- id: verified-notebooks
name: verified notebook not silently changed
language: system
entry: python3 .github/scripts/check_verified_notebooks.py
pass_filenames: false
always_run: true
# OpenMP gate: scikit-learn, LightGBM, XGBoost, CatBoost and torch each
# ship an OpenMP runtime and the first one loaded wins for the process.
# A reader on macOS ARM64 who gets scikit-learn's first loses the kernel
# to a segfault on the next multithreaded LightGBM fit — no traceback
# (R2P issues #7 and #10). No Linux runner reproduces it, so CI never saw
# it, and "organize imports" silently reintroduces it. Runs repo-wide
# because the order can also be broken from a module the commit does not
# touch. See .github/scripts/check_openmp_import_order.py.
- id: openmp-import-order
name: GBM imported before scikit-learn
language: system
entry: python3 .github/scripts/check_openmp_import_order.py
pass_filenames: false
always_run: true