Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sage
Path: blob/develop/src/tox.ini
4013 views
1
## Configuration for tox.
2
## Needs tox installed in the system python.
3
##
4
## doctest: Run the sage doctests. From the SAGE_ROOT/src directory:
5
##
6
## $ tox
7
##
8
## Arguments are passed on to "sage -t":
9
##
10
## $ tox sage/geometry
11
##
12
## To pass on options to "sage -t", use -- to separate it from tox options:
13
##
14
## $ tox -- --verbose --optional=sage,pynormaliz --long sage/geometry
15
##
16
## pycodestyle:
17
##
18
## $ tox -e pycodestyle
19
##
20
## Note that on the first run, tox automatically installs pycodestyle
21
## in a virtual environment.
22
##
23
[tox]
24
envlist = doctest, coverage, startuptime, pycodestyle-minimal, relint, codespell, rst, ruff-minimal
25
# When adding environments above, also update the delegations in SAGE_ROOT/tox.ini
26
skipsdist = true
27
28
requires =
29
# For the renamed "allowlist_externals" keyword, need >= 3.18
30
# Because of https://github.com/tox-dev/tox/issues/3238, need <4.14.1
31
tox>=3.18
32
tox<4.14.1
33
34
[sagedirect]
35
# Base for tox environments that bypass the virtual environment set up by tox,
36
# calling sage directly.
37
passenv =
38
HOME
39
setenv =
40
SAGE={toxinidir}/../sage
41
envdir={toxworkdir}/sagedirect
42
allowlist_externals =
43
{env:SAGE}
44
45
[testenv:doctest]
46
description =
47
run the Sage doctester (same as "sage -t")
48
## This toxenv bypasses the virtual environment set up by tox.
49
passenv = {[sagedirect]passenv}
50
setenv = {[sagedirect]setenv}
51
envdir = {[sagedirect]envdir}
52
allowlist_externals = {[sagedirect]allowlist_externals}
53
commands =
54
{env:SAGE} -t -p 0 {posargs:--all}
55
56
[testenv:coverage.py]
57
# https://coverage.readthedocs.io/en/latest/index.html
58
description =
59
run the Sage doctester with Coverage.py
60
## This toxenv bypasses the virtual environment set up by tox.
61
passenv = {[sagedirect]passenv}
62
setenv = {[sagedirect]setenv}
63
envdir = {[sagedirect]envdir}
64
allowlist_externals = {[sagedirect]allowlist_externals}
65
commands_pre =
66
{env:SAGE} -pip install -U coverage
67
commands =
68
{env:SAGE} --python -m coverage run "{toxinidir}/../venv/bin/sage-runtests" -p 0 {posargs:--all}
69
commands_post =
70
{env:SAGE} --python -m coverage combine
71
{env:SAGE} --python -m coverage report
72
73
[testenv:coverage.py-html]
74
# https://coverage.readthedocs.io/en/latest/index.html
75
description =
76
run the Sage doctester with Coverage.py, generate HTML report
77
## This toxenv bypasses the virtual environment set up by tox.
78
passenv = {[sagedirect]passenv}
79
setenv = {[sagedirect]setenv}
80
envdir = {[sagedirect]envdir}
81
allowlist_externals = {[sagedirect]allowlist_externals}
82
commands_pre =
83
{env:SAGE} -pip install -U coverage
84
commands =
85
{env:SAGE} --python -m coverage run "{toxinidir}/../venv/bin/sage-runtests" -p 0 {posargs:--all}
86
commands_post =
87
{env:SAGE} --python -m coverage combine
88
{env:SAGE} --python -m coverage report
89
{env:SAGE} --python -m coverage html -d "{envdir}"
90
91
[testenv:coverage.py-xml]
92
# https://coverage.readthedocs.io/en/latest/index.html
93
description =
94
run the Sage doctester with Coverage.py, generate XML report
95
## This toxenv bypasses the virtual environment set up by tox.
96
passenv = {[sagedirect]passenv}
97
setenv = {[sagedirect]setenv}
98
envdir = {[sagedirect]envdir}
99
allowlist_externals = {[sagedirect]allowlist_externals}
100
commands_pre =
101
{env:SAGE} -pip install -U coverage
102
commands =
103
{env:SAGE} --python -m coverage run "{toxinidir}/../venv/bin/sage-runtests" -p 0 {posargs:--all}
104
commands_post =
105
{env:SAGE} --python -m coverage combine
106
{env:SAGE} --python -m coverage report
107
{env:SAGE} --python -m coverage xml -o "{envdir}/coverage.xml"
108
109
[testenv:coverage]
110
description =
111
give information about doctest coverage of files
112
(same as "sage --coverage[all]")
113
## This toxenv bypasses the virtual environment set up by tox.
114
passenv = {[sagedirect]passenv}
115
setenv = {[sagedirect]setenv}
116
envdir = {[sagedirect]envdir}
117
allowlist_externals = {[sagedirect]allowlist_externals}
118
commands =
119
{env:SAGE} --coverage {posargs:--all}
120
121
[testenv:startuptime]
122
description =
123
display how long each component of Sage takes to start up
124
(same as "sage --startuptime")
125
## This toxenv bypasses the virtual environment set up by tox.
126
passenv = {[sagedirect]passenv}
127
setenv = {[sagedirect]setenv}
128
envdir = {[sagedirect]envdir}
129
allowlist_externals = {[sagedirect]allowlist_externals}
130
commands =
131
{env:SAGE} --startuptime {posargs}
132
133
[testenv:pyright]
134
description =
135
run the static typing checker pyright
136
deps = pyright
137
setenv =
138
{[sagedirect]setenv}
139
HOME={envdir}
140
# Fix version, see .github/workflows/build.yml
141
PYRIGHT_PYTHON_FORCE_VERSION=1.1.232
142
allowlist_externals = {[sagedirect]allowlist_externals}
143
## We run pyright from within the sage-env so that SAGE_LOCAL is available.
144
## pyright is already configured via SAGE_ROOT/pyrightconfig.json to use our venv.
145
##
146
## Running pyright on the whole Sage source tree takes very long
147
## and may run out of memory. When no files/directories are given, just run it
148
## on the packages that already have typing annotations.
149
commands =
150
{env:SAGE} -sh -c 'pyright {posargs:{toxinidir}/sage/combinat {toxinidir}/sage/manifolds}'
151
152
[testenv:pycodestyle]
153
description =
154
check against the Python style conventions of PEP8
155
deps = pycodestyle
156
commands = pycodestyle {posargs:{toxinidir}/sage/}
157
158
[testenv:pycodestyle-minimal]
159
description =
160
check against Sage minimal style conventions
161
# Check for the following issues:
162
# E111: indentation is not a multiple of four
163
# E211: whitespace before '('
164
# E271: multiple spaces after keyword
165
# E305: expected 2 blank lines after class or function definition, found 1
166
# E306: expected 1 blank line before a nested definition, found 0
167
# E401: multiple imports on one line
168
# E502 the backslash is redundant between brackets
169
# E701: multiple statements on one line (colon)
170
# E702: multiple statements on one line (semicolon)
171
# E703: statement ends with a semicolon
172
# E711: comparison to None should be ‘if cond is None:’
173
# E712: comparison to True should be ‘if cond is True:’ or ‘if cond:’
174
# E713 test for membership should be ’not in’
175
# E721: do not compare types, use isinstance()
176
# E722: do not use bare except, specify exception instead
177
# W291: trailing whitespace
178
# W293: blank line contains whitespace
179
# W391: blank line at end of file
180
# W605: invalid escape sequence ‘x’
181
# See https://pycodestyle.pycqa.org/en/latest/intro.html#error-codes
182
deps = pycodestyle
183
commands =
184
pycodestyle --select E111,E115,E21,E221,E222,E225,E227,E228,E25,E271,E272,E275,E302,E303,E305,E306,E401,E502,E701,E702,E703,E71,E72,W291,W293,W391,W605 {posargs:{toxinidir}/sage/}
185
pycodestyle --select E111,E222,E271,E301,E302,E303,E305,E306,E401,E502,E703,E712,E713,E714,E72,W29,W391,W605, --filename *.pyx {posargs:{toxinidir}/sage/}
186
187
[pycodestyle]
188
max-line-length = 160
189
statistics = True
190
191
[testenv:relint]
192
description =
193
check whether some forbidden patterns appear
194
# https://github.com/codingjoe/relint
195
# The patterns are in .relint.yml
196
deps = relint
197
allowlist_externals = find
198
commands = find {posargs:{toxinidir}/sage/} \
199
-name "*\#*" -prune -o \
200
-name "*.a" -prune -o \
201
-name "*.bak" -prune -o \
202
-name "*.bz2" -prune -o \
203
-name "*.dia" -prune -o \
204
-name "*.gz" -prune -o \
205
-name "*.ico" -prune -o \
206
-name "*.inv" -prune -o \
207
-name "*.JPEG" -prune -o \
208
-name "*.jpeg" -prune -o \
209
-name "*.JPG" -prune -o \
210
-name "*.jpg" -prune -o \
211
-name "*.log" -prune -o \
212
-name "*.o" -prune -o \
213
-name "*.orig" -prune -o \
214
-name "*.PDF" -prune -o \
215
-name "*.pdf" -prune -o \
216
-name "*.PNG" -prune -o \
217
-name "*.png" -prune -o \
218
-name "*.pyc" -prune -o \
219
-name "*.so" -prune -o \
220
-name "*.sobj" -prune -o \
221
-name "*.sws" -prune -o \
222
-name "*.tar" -prune -o \
223
-name "*.tgz" -prune -o \
224
-name "*.xz" -prune -o \
225
-name "*.zip" -prune -o \
226
-name "*~*" -prune -o \
227
-name ".DS_Store" -prune -o \
228
-exec relint -c {toxinidir}/.relint.yml \{\} +
229
230
[testenv:codespell]
231
description =
232
check for misspelled words in source code
233
# https://pypi.org/project/codespell/
234
deps = codespell
235
commands = codespell \
236
--skip="*\#*,*.a,*.bak,*.bz2,*.dia,*.gz,*.ico,*.inv,*.JPEG,*.jpeg" \
237
--skip="*.JPG,*.jpg,*.log,*.o,*.orig,*.PDF,*.pdf,*.PNG,*.png,*.pyc" \
238
--skip="*.so,*.sobj,*.sws,*.tar,*.tgz,*.xz,*.zip,*~*,.DS_Store" \
239
--skip="doc/ca,doc/de,doc/es,doc/fr,doc/hu,doc/it,doc/ja,doc/pt,doc/ru,doc/tr" \
240
--skip="src/doc/ca,src/doc/de,src/doc/es,src/doc/fr,src/doc/hu" \
241
--skip="src/doc/it,src/doc/ja,src/doc/pt,src/doc/ru,src/doc/tr" \
242
--skip=".git,.tox,autom4te.cache,cythonized,dist,lib.*,local" \
243
--skip="logs,scripts-3,tmp,upstream,worktree*,*.egg-info" \
244
--dictionary=- \
245
--dictionary={toxinidir}/.codespell-dictionary.txt \
246
--ignore-words={toxinidir}/.codespell-ignore.txt \
247
{posargs:{toxinidir}/sage/}
248
249
[testenv:rst]
250
description =
251
validate Python docstrings markup as reStructuredText
252
deps = flake8-rst-docstrings
253
commands = flake8 --select=RST {posargs:{toxinidir}/sage/}
254
255
[testenv:cython-lint]
256
description =
257
check Cython files for code style
258
deps = cython-lint
259
commands = cython-lint --no-pycodestyle {posargs:{toxinidir}/sage/}
260
261
[testenv:ruff]
262
description =
263
check against Python style conventions
264
deps = ruff
265
passenv = RUFF_OUTPUT_FORMAT
266
commands = ruff check {posargs:{toxinidir}/sage/}
267
268
[testenv:ruff-minimal]
269
description =
270
check against Sage minimal style conventions
271
deps = ruff
272
# https://github.com/ChartBoost/ruff-action/issues/7#issuecomment-1887780308
273
passenv = RUFF_OUTPUT_FORMAT
274
# Output of currently failing, from "./sage -tox -e ruff -- --statistics":
275
#
276
# 3579 PLR2004 [ ] Magic value used in comparison, consider replacing `- 0.5` with a constant variable
277
# 3498 I001 [*] Import block is un-sorted or un-formatted
278
# 2146 F401 [*] `.PyPolyBoRi.Monomial` imported but unused
279
# 1964 E741 [ ] Ambiguous variable name: `I`
280
# 1676 F821 [ ] Undefined name `AA`
281
# 1513 PLR0912 [ ] Too many branches (102 > 12)
282
# 1159 PLR0913 [ ] Too many arguments in function definition (10 > 5)
283
# 815 E402 [ ] Module level import not at top of file
284
# 671 PLR0915 [ ] Too many statements (100 > 50)
285
# 483 PLW2901 [ ] Outer `for` loop variable `ext` overwritten by inner `for` loop target
286
# 433 PLR5501 [*] Use `elif` instead of `else` then `if`, to reduce indentation
287
# 428 PLR0911 [ ] Too many return statements (10 > 6)
288
# 404 E731 [*] Do not assign a `lambda` expression, use a `def`
289
# 351 F405 [ ] `ComplexField` may be undefined, or defined from star imports
290
# 306 PLR1714 [*] Consider merging multiple comparisons. Use a `set` if the elements are hashable.
291
# 236 F403 [ ] `from .abelian_gps.all import *` used; unable to detect undefined names
292
# 116 PLR0402 [*] Use `from matplotlib import cm` in lieu of alias
293
# 111 PLW0603 [ ] Using the global statement to update `AA_0` is discouraged
294
# 78 F841 [*] Local variable `B` is assigned to but never used
295
# 48 PLW0602 [ ] Using global for `D` but no assignment is done
296
# 33 PLR1711 [*] Useless `return` statement at end of function
297
# 24 E714 [*] Test for object identity should be `is not`
298
# 20 PLR1701 [*] Merge `isinstance` calls
299
# 17 PLW3301 [ ] Nested `max` calls can be flattened
300
# 16 PLW1510 [*] `subprocess.run` without explicit `check` argument
301
# 14 E721 [ ] Do not compare types, use `isinstance()`
302
# 14 PLW0120 [*] `else` clause on loop without a `break` statement; remove the `else` and dedent its contents
303
# 12 F811 [*] Redefinition of unused `CompleteDiscreteValuationRings` from line 49
304
# 8 PLC0414 [*] Import alias does not rename original package
305
# 7 E743 [ ] Ambiguous function name: `I`
306
# 7 PLR0124 [ ] Name compared with itself, consider replacing `a == a`
307
# 5 PLW0127 [ ] Self-assignment of variable `a`
308
# 4 PLW1508 [ ] Invalid type for environment variable default; expected `str` or `None`
309
# 3 PLC3002 [ ] Lambda expression called directly. Execute the expression inline instead.
310
# 2 E742 [ ] Ambiguous class name: `I`
311
# 2 PLE0302 [ ] The special method `__len__` expects 1 parameter, 3 were given
312
# 1 F402 [ ] Import `factor` from line 259 shadowed by loop variable
313
# 1 PLC0208 [*] Use a sequence type instead of a `set` when iterating over values
314
#
315
commands =
316
ruff check --ignore E402,E721,E731,E741,E742,E743,F401,F402,F403,F405,F821,F841,I001,PLC0206,PLC0208,PLC2401,PLC3002,PLE0302,PLR0124,PLR0402,PLR0911,PLR0912,PLR0913,PLR0915,PLR1704,PLR1711,PLR1714,PLR1716,PLR1736,PLR2004,PLR5501,PLW0120,PLW0211,PLW0602,PLW0603,PLW0642,PLW1508,PLW1510,PLW2901,PLW3301 {posargs:{toxinidir}/sage/}
317
ruff check --preview --select E111,E115,E21,E221,E222,E225,E227,E228,E25,E271,E272,E275,E302,E303,E305,E306,E401,E502,E701,E702,E703,E71,W291,W293,W391,W605 {posargs:{toxinidir}/sage/}
318
319
[flake8]
320
rst-roles =
321
# Sphinx
322
doc,
323
file,
324
ref,
325
# Sphinx - https://www.sphinx-doc.org/en/master/usage/restructuredtext/domains.html#the-standard-domain (selection)
326
envvar,
327
# Sphinx - https://www.sphinx-doc.org/en/master/usage/restructuredtext/domains.html#cross-referencing-python-objects
328
attr,
329
class,
330
const,
331
data,
332
exc,
333
func,
334
kbd,
335
meth,
336
mod,
337
obj,
338
# from src/sage/misc/sagedoc.py
339
arxiv,
340
doi,
341
mathscinet,
342
oeis,
343
pari,
344
python,
345
issue,
346
wikipedia,
347
common_lisp,
348
ecl,
349
gap,
350
gap_package,
351
giac_cascmd,
352
giac_us,
353
maxima,
354
meson,
355
polymake,
356
ppl,
357
qepcad,
358
scip,
359
singular,
360
soplex
361
rst-directives =
362
attribute,
363
automethod,
364
autofunction,
365
toctree,
366
MODULEAUTHOR,
367
ONLY,
368
PLOT,
369
SEEALSO,
370
TODO
371
extend-ignore =
372
# Ignore RST306 Unknown target name -- because of references to the global bibliography
373
RST306
374
exclude =
375
# Avoid errors by exclude files with generated docstring portions such as {PLOT_OPTIONS_TABLE}
376
sage/combinat/designs/database.py
377
sage/graphs/graph_plot.py
378
sage/misc/sagedoc.py
379
380
[coverage:run]
381
source = sage
382
concurrency = multiprocessing,thread
383
data_file = .coverage/.coverage
384
disable_warnings =
385
no-data-collected
386
module-not-measured
387
388
[coverage:report]
389
ignore_errors = True
390
skip_empty = True
391
392