Skip to content

MAINT: Move the development configuration into pyproject.toml - #1021

Merged
bashtage merged 7 commits into
mainfrom
a90-pyproject-modernize
Nov 11, 2026
Merged

bashtage merged 7 commits into
mainfrom
a90-pyproject-modernize

Conversation

@bashtage

Copy link
Copy Markdown
Owner

Moves the development configuration of arch into pyproject.toml, following the same change in randomgen 2.5.0. Each tool now has its settings in one place, and nothing says "keep synced with" another file any more. The minimum versions of arch and its dependencies are unchanged, and the wheel declares exactly the same Requires-Dist.

Commits

  1. MAINT: Replace flake8 with ruff. ruff already covers pyflakes, the pycodestyle errors and warnings it implements, and flake8-bugbear, while black handles the whitespace checks. The one extra check flake8 made, the 99-character limit on comments, docstrings and long strings, is now ruff's E501 with [tool.ruff.lint.pycodestyle] max-line-length = 99. black stays at 88. Removes .flake8 and the flake8 Lint step.

  2. MAINT: Move the development requirements into dependency groups. PEP 735 groups replace requirements.txt, requirements-dev.txt, doc/requirements.txt, the simulation scripts' requirements.txt, and the test/doc/dev extras. pip 25.1 or later installs them with --group:

    • build: what pip install -e . --no-build-isolation needs
    • test: pytest, pytest-xdist, pytest-cov and coverage
    • notebooks: what the example notebooks need
    • lint: black, isort, ruff, mypy and the type stubs
    • docstrings: numpydoc, which test and lint include
    • dev: build, test, lint and notebooks, plus matplotlib, seaborn and pytest-randomly
    • doc: what the documentation needs, on top of dev
    • simulation: what the critical value simulation scripts need

    CI installs the groups. The Lint workflow now uses the versions pinned in the lint group (black 26.10.1, isort 9.0, ruff 0.17.4 or later), which are the versions its unpinned install picks today.

  3. MAINT: Move the coverage settings into pyproject.toml. coverage reads .coveragerc before pyproject.toml, so the [tool.coverage] tables were never used. .coveragerc is removed, and CI no longer passes --cov-config.

  4. MAINT: Clean up the tool settings in pyproject.toml.

    • black and ruff take their target Python from requires-python.
    • The two mypy sections that used setup.cfg names, which mypy ignores, are now real overrides.
    • Fixes a typo in black's exclude list, and adds the "3 :: Only" classifier and an issues URL.
    • Removes .gitattributes, whose only line applied to arch/_version.py, a file git doesn't track.
  5. DOC: Add a release note under "Documentation and maintenance".

Left outside pyproject.toml

  • meson.build and meson.options: meson can't read pyproject.toml.
  • codecov.yml and .codacy.yml: those services read only their own files.
  • The CI files and docs build files.
  • Three build pins (Cython, meson-python, setuptools-scm) appear in both [build-system].requires and the build group, because a group can't include the build requirements. A comment says so.

CI changes to be aware of

  • Azure Windows installs only the build and test groups. It no longer installs pytest-randomly, so the fast tests run in a fixed order, as on Linux. The linters, Sphinx and jupyter are no longer installed there either.
  • Windows ARM installs the test group, which adds numpydoc, so test_docstrings.py now runs there.
  • Azure Linux installs the groups in the same pip command as the exact versions of numpy, scipy and the rest. In the conda job, pip installs the groups after the conda packages.
  • Coverage: [tool.coverage] has a few more exclusions than .coveragerc had and omits conftest.py, so the coverage figure may rise slightly.

Checks

  • Lint: ruff check arch, black --check arch, isort --check and numpydoc lint are all clean with the new settings.
  • ruff format: it would reformat 6 files, so black stays.
  • Builds: python -m build (an isolated sdist, then the wheel built from the sdist) and a no-binary wheel built from the sdist all pass twine check --strict. The sdist contains none of the removed files.
  • Fast suite: 31,582 passed (Windows, Python 3.14).
  • Installed wheel: run from outside the source tree, its tests pass.
  • Docs: built in a fresh environment set up only with pip install --group dev --group doc plus the wheel, with no Sphinx warnings.
  • Dependency groups: a dry-run install resolves for the setup of every Azure, Windows ARM, Lint and docs job.
  • arch-wheels: its build-wheels.yml doesn't depend on any moved or removed file.

🤖 Generated with Claude Code

ruff already runs pyflakes (F), the pycodestyle errors and warnings that it
implements (E, W) and the flake8-bugbear rules (B), and black handles the
whitespace checks of pycodestyle. The only check that flake8 added was the
99-character limit on comments, docstrings and long strings, which black
cannot shorten. ruff's E501 now enforces the same limit through
[tool.ruff.lint.pycodestyle] max-line-length = 99, while black and the rest of
ruff keep the 88-character line length. ruff E501 passes on arch at 99
characters.

- Remove .flake8 (max-line-length = 99, ignore = E203, W503, BLK100: ruff
  ignores E203 and does not implement W503, and flake8-black was never used).
- Remove the flake8 step from the Lint workflow, and flake8 and
  flake8-bugbear from the development requirements.
PEP 735 dependency groups in pyproject.toml replace requirements.txt,
requirements-dev.txt, doc/requirements.txt, the requirements.txt of the
critical value simulations and the test, doc and dev extras, which were not
features of arch. pip 25.1 or later installs them with "--group":

- build: what "pip install -e . --no-build-isolation" needs
- test: pytest >= 9, pytest-cov, pytest-xdist and coverage, with numpydoc
- notebooks: jupyter and nbconvert for the example notebooks
- lint: black, isort, ruff, mypy and the stubs, with numpydoc
- docstrings: numpydoc >= 1.10, included by test and lint
- dev: build, test, lint and notebooks, with matplotlib, seaborn and
  pytest-randomly
- doc: Sphinx, sphinx-immaterial and nbsphinx, in addition to dev
- simulation: colorama, joblib and psutil for the simulation scripts

The dependencies of arch are listed once, in [project]. The groups do not
repeat them; pip installs them with arch. The duplicated pins had drifted
apart (black 25.1 and 25.9, isort 5.12 and 6.0, ruff 0.8.6 while CI used the
newest of each). The Lint workflow now installs the lint group, with black
26.10.1, isort 9.0 and ruff 0.17.4 or later, the versions that it used.

Not carried over: setuptools and wheel (meson-python builds arch), patsy and
packaging (dependencies of statsmodels and of arch), jinja2 (a dependency of
Sphinx), sphinx-autodoc-typehints (not in the Sphinx extensions), the pins of
the unused doc extra, pyupgrade (ruff has the UP rules), the
jupyterlab-code-formatter editor plugin, property_cached (unused) and colorama
outside the simulation group. numba is optional and the CI jobs that test it
install it, so it is in no group; it has no wheels for some supported
platforms. The Snyk pins stay, in the groups that pull in those packages.

[build-system] requires meson-python >= 0.18.0, the first release that
supports the license and license-files fields, and uses the normalized name
setuptools-scm.

CI:
- Azure Linux installs the build, test and notebooks groups in the same pip
  command as the exact versions of numpy, scipy, ..., so pip resolves them
  together. In the conda job, pip installs the groups after the conda
  packages, so that it keeps numpy from conda-forge.
- Azure Windows installs the build and test groups with PACKAGES instead of
  requirements-dev.txt and requirements.txt. It no longer installs the
  linters, Sphinx, jupyter or pytest-randomly, which the fast tests do not
  use, so the tests run in the same order as on Linux.
- Windows ARM installs the test group instead of pinning pytest, which adds
  numpydoc (arch/tests/test_docstrings.py now runs there) and pytest-cov.
- The documentation workflow installs the dev and doc groups.

README.md and the contributing guide show how to install the groups.
coverage reads .coveragerc before pyproject.toml, so the [tool.coverage]
tables were never used, and CI passed --cov-config=.coveragerc. The two
copies had drifted apart. Remove .coveragerc and keep [tool.coverage], which
coverage and pytest-cov now read.

Compared with .coveragerc, [tool.coverage] also
- omits conftest.py from the measurement;
- adds to coverage's default exclusions instead of replacing them, and also
  excludes "def __repr__", "if self.debug", "raise AssertionError",
  "raise ImportError", "if 0:" and the __main__ guard;
- shows the missing lines in the terminal report.

The coverage numbers can therefore move up slightly. ignore_errors is now
true, as it was in .coveragerc, so that a file that coverage cannot read does
not fail the report in CI. Python 3.10 reads the TOML file through the
coverage[toml] extra in the test dependency group.
- black and ruff take their target versions from requires-python (black
  infers py310 to py315 and ruff 3.10, as before), so the target-version
  settings are removed and cannot fall behind requires-python.
- The [tool.mypy-arch.conftest] and [tool.mypy-arch._version] tables use the
  setup.cfg section names, which mypy ignores in pyproject.toml. arch.conftest
  already had an override, and arch._version joins it. [tool.pyrefly] moves
  after the mypy overrides.
- Fix the .pytest_cache pattern in black's exclude, which was misspelled.
- Add the "Python :: 3 :: Only" classifier and an issues URL.
- Remove .gitattributes, whose only line applied export-subst to
  arch/_version.py, which git does not track (setuptools-scm writes it at
  build time), so git archive never used it.
Add an entry to "Documentation and maintenance" in the 9.0 notes: the
development requirements are dependency groups in pyproject.toml, which
replace the requirements files and the test, doc and dev extras, the coverage
settings are in pyproject.toml, and ruff replaces flake8.
@bashtage
bashtage marked this pull request as ready for review November 11, 2026 17:34
ShellCheck (SC2086, reported by Codacy) warns about the unquoted expansion of
the group options in the conda job. Keep the options in an array and expand
it quoted, so that the words are split by the array rather than by the shell.
The commands that run are unchanged.
@codecov

codecov Bot commented Nov 11, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 99.51%. Comparing base (b7c5046) to head (4ec3bc5).
⚠️ Report is 7 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1021      +/-   ##
==========================================
+ Coverage   99.44%   99.51%   +0.06%     
==========================================
  Files         153      152       -1     
  Lines       34278    34209      -69     
  Branches     2595     2588       -7     
==========================================
- Hits        34088    34043      -45     
+ Misses        114       94      -20     
+ Partials       76       72       -4     
Flag Coverage Δ
adder 99.45% <ø> (+0.06%) ⬆️
subtractor 99.45% <ø> (+0.06%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@bashtage
bashtage merged commit 139c820 into main Nov 11, 2026
27 of 28 checks passed
@bashtage
bashtage deleted the a90-pyproject-modernize branch November 11, 2026 18:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant