-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtox.ini
More file actions
86 lines (76 loc) · 3.62 KB
/
Copy pathtox.ini
File metadata and controls
86 lines (76 loc) · 3.62 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
[tox]
# tox-uv swaps tox's env creation and package/dependency installs from
# virtualenv+pip to uv: dramatically faster (parallel downloads, a shared global
# wheel cache) and behavior-identical for our envs. Declaring it in `requires`
# means a plain `tox` auto-provisions it, so a local `tox` run uses uv with no
# extra step; CI installs it explicitly alongside tox. Force the old path with
# `tox --runner virtualenv` if ever needed.
requires =
tox-uv>=1
envlist = py310, py311, py312, py313, py314, lint, mypy, bandit, openapi
[testenv:lint]
description = lint source code
# ruff only reads the source tree, so don't build/install the package (which
# would impose the project's requires-python on the lint interpreter).
skip_install = true
deps =
ruff
commands =
ruff check cronstable
ruff format --check cronstable
[testenv:mypy]
description = static type-check the source with mypy
# Unlike lint/bandit this env DOES install the package: mypy resolves the
# runtime deps (aiohttp, jinja2, sentry-sdk, ...) for real instead of running
# under a global --ignore-missing-imports, which silently typed every
# third-party surface as Any and defeated the curated per-module override
# table in pyproject.toml. The deps that legitimately cannot resolve
# (optional extras, untyped libraries) are enumerated there.
deps =
mypy
mypy-extensions
commands =
mypy -p cronstable
[testenv:bandit]
description = security-lint the source with bandit
# bandit reads the source tree; like lint, skip installing the package so
# its interpreter isn't constrained by the project's requires-python. The
# severity floor and config (tests excluded) match the removed pre-commit hook.
skip_install = true
deps =
bandit[toml]
commands =
bandit -c pyproject.toml -r cronstable --severity-level=medium
[testenv:openapi]
description = validate the OpenAPI spec (docs/openapi.yaml)
# validates only the spec file; no need to build/install the package.
skip_install = true
deps =
openapi-spec-validator
commands =
python .github/scripts/check_openapi.py
[testenv]
deps = -rrequirements_dev.txt
setenv =
PYTHONPATH = {toxinidir}
# pytest-cov collects in coverage's parallel mode (so cronstable's spawned
# subprocesses are measured), writing `.coverage.<host>.<pid>.*` files and
# then combine()-ing every `.coverage.*` it finds in the data dir. That dir
# defaults to {toxinidir}, shared by all envs -- so under `tox -p` one env's
# combine races another's: it tries to os.remove() a data file the other
# env's live process still holds open. On Windows that's a hard WinError 32,
# and pytest dies with an INTERNALERROR (exit 3) in whichever env loses the
# race. Pin each env's coverage data under its own {envdir} so parallel runs
# never share (or delete) each other's files. Serial runs and CI (one env
# per runner) are unaffected.
COVERAGE_FILE = {envdir}/.coverage
# --cov-fail-under gates the build on coverage: a change that drops a tested
# path to zero coverage fails CI instead of merging green. The floor is set
# conservatively below the measured branch coverage (~98% on both the Windows
# and POSIX cells; Windows stays the marginally lower one because the
# POSIX-only privilege-drop/user-group paths skip there). Ratchet it up as
# coverage rises; never down without a recorded reason.
# --cov-report=xml writes coverage.xml for the CI Codecov upload; Codecov merges
# every matrix cell's report, so the published number reflects POSIX + Windows
# combined rather than any single (lower) row.
commands = pytest --color=yes -vv --cov=cronstable --cov-report=term-missing --cov-report=xml --cov-fail-under=92