Commit 074964bb58
074964bb58c52719130815f70d75b3dbea0930e1
parent: c1c3100941
Verified · cmc
cmc <hello@cleberg.net> · 2026-08-23 01:48 UTC
Pin the notebook dependencies
The workflow executes every notebook on each push, which is the right check —
but it installed from a requirements.txt of >= floors, so what actually ran was
whatever those resolved to that day. A notebook that broke against a new pandas
would fail on an unrelated PR, and one that quietly changed behaviour would not
fail at all.
requirements.in is now the source and requirements.txt the compiled pin: 112
packages resolved against Python 3.10, the version the workflow uses.
environment.yml carries the same list loosely and can drift; it now says which
of the two CI believes.
Layout: unified · split
environment.yml
+3
| @@ -1,3 +1,6 @@ |
| |
1 | # Conda convenience file. requirements.txt is what CI installs and is pinned; |
| |
2 | # this list is loose and can drift from it. Prefer requirements.txt when the two |
| |
3 | # disagree. |
| 1 | name: audit-tutorials |
4 | name: audit-tutorials |
| 2 | channels: |
5 | channels: |
| 3 | - conda-forge |
6 | - conda-forge |
requirements.in
added
+10
| @@ -0,0 +1,10 @@ |
| |
1 | pandas>=2.3.3 |
| |
2 | numpy>=1.26 |
| |
3 | matplotlib>=3.10 |
| |
4 | seaborn>=0.13 |
| |
5 | openpyxl |
| |
6 | jupyterlab |
| |
7 | ipykernel |
| |
8 | nbconvert |
| |
9 | nbclient |
| |
10 | papermill\ No newline at end of file |
requirements.txt
+352 −10
| @@ -1,10 +1,352 @@ |
| 1 | pandas>=2.3.3 |
1 | # This file was autogenerated by uv via the following command: |
| 2 | numpy>=1.26 |
2 | # uv pip compile requirements.in -o requirements.txt --python-version 3.10 |
| 3 | matplotlib>=3.10 |
3 | anyio==4.14.2 |
| 4 | seaborn>=0.13 |
4 | # via |
| 5 | openpyxl |
5 | # httpx |
| 6 | jupyterlab |
6 | # jupyter-server |
| 7 | ipykernel |
7 | appnope==1.0.0 |
| 8 | nbconvert |
8 | # via ipykernel |
| 9 | nbclient |
9 | argon2-cffi==25.1.0 |
| 10 | papermill\ No newline at end of file |
10 | # via jupyter-server |
| |
11 | argon2-cffi-bindings==26.1.0 |
| |
12 | # via argon2-cffi |
| |
13 | arrow==1.4.0 |
| |
14 | # via isoduration |
| |
15 | asttokens==3.0.2 |
| |
16 | # via stack-data |
| |
17 | async-lru==2.3.0 |
| |
18 | # via jupyterlab |
| |
19 | attrs==26.1.0 |
| |
20 | # via |
| |
21 | # jsonschema |
| |
22 | # referencing |
| |
23 | babel==2.18.0 |
| |
24 | # via jupyterlab-server |
| |
25 | beautifulsoup4==4.15.0 |
| |
26 | # via nbconvert |
| |
27 | bleach==6.4.0 |
| |
28 | # via nbconvert |
| |
29 | certifi==2026.7.22 |
| |
30 | # via |
| |
31 | # httpcore |
| |
32 | # httpx |
| |
33 | # requests |
| |
34 | cffi==2.1.1 |
| |
35 | # via argon2-cffi-bindings |
| |
36 | charset-normalizer==3.5.1 |
| |
37 | # via requests |
| |
38 | click==8.4.2 |
| |
39 | # via papermill |
| |
40 | comm==0.2.3 |
| |
41 | # via ipykernel |
| |
42 | contourpy==1.3.2 |
| |
43 | # via matplotlib |
| |
44 | cycler==0.12.1 |
| |
45 | # via matplotlib |
| |
46 | debugpy==1.8.21 |
| |
47 | # via ipykernel |
| |
48 | decorator==5.3.1 |
| |
49 | # via ipython |
| |
50 | defusedxml==0.7.1 |
| |
51 | # via nbconvert |
| |
52 | entrypoints==0.4 |
| |
53 | # via papermill |
| |
54 | et-xmlfile==2.0.0 |
| |
55 | # via openpyxl |
| |
56 | exceptiongroup==1.3.1 |
| |
57 | # via |
| |
58 | # anyio |
| |
59 | # ipython |
| |
60 | executing==2.2.1 |
| |
61 | # via stack-data |
| |
62 | fastjsonschema==2.22.2 |
| |
63 | # via nbformat |
| |
64 | fonttools==4.63.0 |
| |
65 | # via matplotlib |
| |
66 | fqdn==1.5.1 |
| |
67 | # via jsonschema |
| |
68 | h11==0.16.0 |
| |
69 | # via httpcore |
| |
70 | httpcore==1.0.9 |
| |
71 | # via httpx |
| |
72 | httpx==0.28.1 |
| |
73 | # via jupyterlab |
| |
74 | idna==3.19 |
| |
75 | # via |
| |
76 | # anyio |
| |
77 | # httpx |
| |
78 | # jsonschema |
| |
79 | # requests |
| |
80 | ipykernel==7.3.0 |
| |
81 | # via |
| |
82 | # -r requirements.in |
| |
83 | # jupyterlab |
| |
84 | ipython==8.39.0 |
| |
85 | # via ipykernel |
| |
86 | isoduration==20.11.0 |
| |
87 | # via jsonschema |
| |
88 | jedi==0.20.0 |
| |
89 | # via ipython |
| |
90 | jinja2==3.1.6 |
| |
91 | # via |
| |
92 | # jupyter-server |
| |
93 | # jupyterlab |
| |
94 | # jupyterlab-server |
| |
95 | # nbconvert |
| |
96 | json5==0.15.0 |
| |
97 | # via jupyterlab-server |
| |
98 | jsonpointer==3.1.1 |
| |
99 | # via jsonschema |
| |
100 | jsonschema==4.26.0 |
| |
101 | # via |
| |
102 | # jupyter-events |
| |
103 | # jupyterlab-server |
| |
104 | # nbformat |
| |
105 | jsonschema-specifications==2025.9.1 |
| |
106 | # via jsonschema |
| |
107 | jupyter-builder==1.2.2 |
| |
108 | # via jupyterlab |
| |
109 | jupyter-client==8.9.1 |
| |
110 | # via |
| |
111 | # ipykernel |
| |
112 | # jupyter-server |
| |
113 | # nbclient |
| |
114 | jupyter-core==5.9.1 |
| |
115 | # via |
| |
116 | # ipykernel |
| |
117 | # jupyter-builder |
| |
118 | # jupyter-client |
| |
119 | # jupyter-server |
| |
120 | # jupyterlab |
| |
121 | # nbclient |
| |
122 | # nbconvert |
| |
123 | # nbformat |
| |
124 | jupyter-events==0.12.1 |
| |
125 | # via jupyter-server |
| |
126 | jupyter-lsp==2.3.1 |
| |
127 | # via jupyterlab |
| |
128 | jupyter-server==2.20.0 |
| |
129 | # via |
| |
130 | # jupyter-lsp |
| |
131 | # jupyterlab |
| |
132 | # jupyterlab-server |
| |
133 | # notebook-shim |
| |
134 | jupyter-server-terminals==0.5.4 |
| |
135 | # via jupyter-server |
| |
136 | jupyterlab==4.6.3 |
| |
137 | # via -r requirements.in |
| |
138 | jupyterlab-pygments==0.3.0 |
| |
139 | # via nbconvert |
| |
140 | jupyterlab-server==2.28.0 |
| |
141 | # via jupyterlab |
| |
142 | kiwisolver==1.5.0 |
| |
143 | # via matplotlib |
| |
144 | lark==1.3.1 |
| |
145 | # via rfc3987-syntax |
| |
146 | markupsafe==3.0.3 |
| |
147 | # via |
| |
148 | # jinja2 |
| |
149 | # nbconvert |
| |
150 | matplotlib==3.10.9 |
| |
151 | # via |
| |
152 | # -r requirements.in |
| |
153 | # seaborn |
| |
154 | matplotlib-inline==0.2.2 |
| |
155 | # via |
| |
156 | # ipykernel |
| |
157 | # ipython |
| |
158 | mistune==3.3.4 |
| |
159 | # via nbconvert |
| |
160 | nbclient==0.11.0 |
| |
161 | # via |
| |
162 | # -r requirements.in |
| |
163 | # nbconvert |
| |
164 | # papermill |
| |
165 | nbconvert==7.17.1 |
| |
166 | # via |
| |
167 | # -r requirements.in |
| |
168 | # jupyter-server |
| |
169 | nbformat==5.11.1 |
| |
170 | # via |
| |
171 | # jupyter-server |
| |
172 | # nbclient |
| |
173 | # nbconvert |
| |
174 | # papermill |
| |
175 | nest-asyncio2==1.7.2 |
| |
176 | # via ipykernel |
| |
177 | notebook-shim==0.2.4 |
| |
178 | # via jupyterlab |
| |
179 | numpy==2.2.6 |
| |
180 | # via |
| |
181 | # -r requirements.in |
| |
182 | # contourpy |
| |
183 | # matplotlib |
| |
184 | # pandas |
| |
185 | # seaborn |
| |
186 | openpyxl==3.1.5 |
| |
187 | # via -r requirements.in |
| |
188 | overrides==7.7.0 |
| |
189 | # via jupyter-server |
| |
190 | packaging==26.3 |
| |
191 | # via |
| |
192 | # ipykernel |
| |
193 | # jupyter-events |
| |
194 | # jupyter-server |
| |
195 | # jupyterlab |
| |
196 | # jupyterlab-server |
| |
197 | # matplotlib |
| |
198 | # nbconvert |
| |
199 | pandas==2.3.3 |
| |
200 | # via |
| |
201 | # -r requirements.in |
| |
202 | # seaborn |
| |
203 | pandocfilters==1.5.1 |
| |
204 | # via nbconvert |
| |
205 | papermill==2.7.0 |
| |
206 | # via -r requirements.in |
| |
207 | parso==0.8.7 |
| |
208 | # via jedi |
| |
209 | pexpect==4.9.0 |
| |
210 | # via ipython |
| |
211 | pillow==12.3.0 |
| |
212 | # via matplotlib |
| |
213 | platformdirs==4.11.3 |
| |
214 | # via jupyter-core |
| |
215 | prometheus-client==0.26.0 |
| |
216 | # via jupyter-server |
| |
217 | prompt-toolkit==3.0.53 |
| |
218 | # via ipython |
| |
219 | psutil==7.2.2 |
| |
220 | # via ipykernel |
| |
221 | ptyprocess==0.7.0 |
| |
222 | # via |
| |
223 | # pexpect |
| |
224 | # terminado |
| |
225 | pure-eval==0.2.3 |
| |
226 | # via stack-data |
| |
227 | pycparser==3.0 |
| |
228 | # via cffi |
| |
229 | pygments==2.21.0 |
| |
230 | # via |
| |
231 | # ipython |
| |
232 | # nbconvert |
| |
233 | pyparsing==3.3.2 |
| |
234 | # via matplotlib |
| |
235 | python-dateutil==2.9.0.post0 |
| |
236 | # via |
| |
237 | # arrow |
| |
238 | # jupyter-client |
| |
239 | # matplotlib |
| |
240 | # pandas |
| |
241 | python-json-logger==4.2.0 |
| |
242 | # via jupyter-events |
| |
243 | pytz==2026.3.post1 |
| |
244 | # via pandas |
| |
245 | pyyaml==6.0.3 |
| |
246 | # via |
| |
247 | # jupyter-events |
| |
248 | # papermill |
| |
249 | pyzmq==27.2.0 |
| |
250 | # via |
| |
251 | # ipykernel |
| |
252 | # jupyter-client |
| |
253 | # jupyter-server |
| |
254 | referencing==0.37.0 |
| |
255 | # via |
| |
256 | # jsonschema |
| |
257 | # jsonschema-specifications |
| |
258 | # jupyter-events |
| |
259 | requests==2.34.2 |
| |
260 | # via |
| |
261 | # jupyterlab-server |
| |
262 | # papermill |
| |
263 | rfc3339-validator==0.1.4 |
| |
264 | # via |
| |
265 | # jsonschema |
| |
266 | # jupyter-events |
| |
267 | rfc3986-validator==0.1.1 |
| |
268 | # via |
| |
269 | # jsonschema |
| |
270 | # jupyter-events |
| |
271 | rfc3987-syntax==1.1.0 |
| |
272 | # via jsonschema |
| |
273 | rpds-py==0.30.0 |
| |
274 | # via |
| |
275 | # jsonschema |
| |
276 | # referencing |
| |
277 | seaborn==0.13.2 |
| |
278 | # via -r requirements.in |
| |
279 | send2trash==2.1.0 |
| |
280 | # via jupyter-server |
| |
281 | six==1.17.0 |
| |
282 | # via |
| |
283 | # python-dateutil |
| |
284 | # rfc3339-validator |
| |
285 | soupsieve==2.9.2 |
| |
286 | # via beautifulsoup4 |
| |
287 | stack-data==0.6.3 |
| |
288 | # via ipython |
| |
289 | tenacity==9.1.4 |
| |
290 | # via papermill |
| |
291 | terminado==0.18.1 |
| |
292 | # via |
| |
293 | # jupyter-server |
| |
294 | # jupyter-server-terminals |
| |
295 | tinycss2==1.5.1 |
| |
296 | # via bleach |
| |
297 | tomli==2.4.1 |
| |
298 | # via |
| |
299 | # jupyter-builder |
| |
300 | # jupyterlab |
| |
301 | tornado==6.5.8 |
| |
302 | # via |
| |
303 | # ipykernel |
| |
304 | # jupyter-client |
| |
305 | # jupyter-server |
| |
306 | # jupyterlab |
| |
307 | # terminado |
| |
308 | tqdm==4.70.0 |
| |
309 | # via papermill |
| |
310 | traitlets==5.16.1 |
| |
311 | # via |
| |
312 | # ipykernel |
| |
313 | # ipython |
| |
314 | # jupyter-builder |
| |
315 | # jupyter-client |
| |
316 | # jupyter-core |
| |
317 | # jupyter-events |
| |
318 | # jupyter-server |
| |
319 | # jupyterlab |
| |
320 | # matplotlib-inline |
| |
321 | # nbclient |
| |
322 | # nbconvert |
| |
323 | # nbformat |
| |
324 | typing-extensions==4.16.0 |
| |
325 | # via |
| |
326 | # anyio |
| |
327 | # async-lru |
| |
328 | # beautifulsoup4 |
| |
329 | # exceptiongroup |
| |
330 | # ipython |
| |
331 | # jupyter-client |
| |
332 | # jupyterlab |
| |
333 | # mistune |
| |
334 | # referencing |
| |
335 | tzdata==2026.3 |
| |
336 | # via |
| |
337 | # arrow |
| |
338 | # pandas |
| |
339 | uri-template==1.3.0 |
| |
340 | # via jsonschema |
| |
341 | urllib3==2.7.0 |
| |
342 | # via requests |
| |
343 | wcwidth==0.8.2 |
| |
344 | # via prompt-toolkit |
| |
345 | webcolors==25.10.0 |
| |
346 | # via jsonschema |
| |
347 | webencodings==0.6.1 |
| |
348 | # via |
| |
349 | # bleach |
| |
350 | # tinycss2 |
| |
351 | websocket-client==1.9.0 |
| |
352 | # via jupyter-server |