Skip to content

Commit

Permalink
FEAT: merge tox.ini into pyproject.toml (#417)
Browse files Browse the repository at this point in the history
* DX: disable Sphinx warnings in `linkcheck` job
* DX: remove `pydeps` support
* DX: run `cov` instead of `py` in `tox` CI
* DX: run `linkcheck` in `tox` CI job
  Avoids raising a `RemovedInSphinx80Warning` warnings
* ENH: read Tox config from `tox.ini` or `pyproject.toml`
* FIX: start `sphinx-autobuild` on random available port
* MAINT: move `description` on one line
* MAINT: remove `FORCE_COLOR` from `tox`
* MAINT: share `passenv` through base environment
* MAINT: use `--ignore` instead of `--re-ignore` where possible
* MAINT: write CLI flags with `=` sign
  • Loading branch information
redeboer authored Oct 10, 2024
1 parent 7bc6895 commit a4b371c
Show file tree
Hide file tree
Showing 6 changed files with 142 additions and 119 deletions.
1 change: 0 additions & 1 deletion .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
"labels/*.toml",
"pyproject.toml",
"pyrightconfig.json",
"tox.ini",
"typings"
],
"language": "en-US",
Expand Down
85 changes: 81 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ dev = [
"compwa-policy[sty]",
"compwa-policy[test]",
"labels",
"pydeps",
"sphinx-autobuild",
"tox >=1.9", # for skip_install, use_develop
'sphinx-autobuild!=2024.4.*; python_version <"3.10.0"',
Expand Down Expand Up @@ -184,9 +183,6 @@ cmd = "tox -e doclive"
[tool.pixi.feature.dev.tasks.linkcheck]
cmd = "tox -e linkcheck"

[tool.pixi.feature.dev.tasks.pydeps]
cmd = "tox -e pydeps"

[tool.pixi.feature.dev.tasks.sty]
cmd = "pre-commit run --all-files"

Expand Down Expand Up @@ -344,3 +340,84 @@ sort_first = [
]
spaces_indent_inline_array = 4
trailing_comma_inline_array = true

[tool.tox]
legacy_tox_ini = """
[tox]
envlist =
cov
doc
linkcheck
sty
skip_install = True
skip_missing_interpreters = True
skipsdist = True
[testenv]
allowlist_externals =
pytest
commands =
pytest {posargs}
description = Run all unit tests
passenv = *
[testenv:cov]
allowlist_externals =
pytest
commands =
pytest {posargs} \
--cov-fail-under=35 \
--cov-report=html \
--cov-report=xml \
--cov=compwa_policy
description = Compute test coverage
[testenv:doc]
allowlist_externals =
sphinx-build
commands =
sphinx-build \
--builder=html \
--fail-on-warning \
--keep-going \
--show-traceback \
docs/ docs/_build/html
description = Build documentation and API through Sphinx
[testenv:doclive]
allowlist_externals =
sphinx-autobuild
commands =
sphinx-autobuild \
--ignore=docs/_build \
--ignore=docs/api \
--open-browser \
--port=0 \
--re-ignore='.*\\.egg-info' \
--re-ignore='.*/__pycache__/.*' \
--watch=docs \
--watch=src \
docs/ docs/_build/html
description = Set up a server to directly preview changes to the HTML pages
[testenv:linkcheck]
allowlist_externals =
sphinx-build
commands =
sphinx-build \
--builder=linkcheck \
--show-traceback \
docs/ docs/_build/linkcheck
description = Check external links in the documentation (requires internet connection)
setenv =
PYTHONWARNINGS =
[testenv:sty]
allowlist_externals =
pre-commit
commands =
pre-commit run {posargs} --all-files
description = Perform all linting, formatting, and spelling checks
setenv =
SKIP = pyright
"""
10 changes: 5 additions & 5 deletions src/compwa_policy/check_dev_files/pixi.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
import yaml
from tomlkit import inline_table, string

from compwa_policy.check_dev_files.tox import read_tox_config
from compwa_policy.errors import PrecommitError
from compwa_policy.utilities import CONFIG_PATH, append_safe, vscode
from compwa_policy.utilities.cfg import open_config
from compwa_policy.utilities.executor import Executor
from compwa_policy.utilities.match import filter_files
from compwa_policy.utilities.pyproject import (
Expand Down Expand Up @@ -190,9 +190,9 @@ def __import_conda_environment(pyproject: ModifiablePyproject) -> None:


def __import_tox_tasks(pyproject: ModifiablePyproject) -> None:
if not CONFIG_PATH.tox.exists():
tox = read_tox_config()
if tox is None:
return
tox = open_config(CONFIG_PATH.tox)
tox_jobs = ___get_tox_job_names(tox)
imported_tasks = []
blacklisted_jobs = {"jcache"} # cspell:ignore jcache
Expand Down Expand Up @@ -308,9 +308,9 @@ def __install_package_editable(pyproject: ModifiablePyproject) -> None:


def __outsource_pixi_tasks_to_tox(pyproject: ModifiablePyproject) -> None:
if not CONFIG_PATH.tox.exists():
tox = read_tox_config()
if tox is None:
return
tox = open_config(CONFIG_PATH.tox)
blacklisted_jobs = {"sty"}
updated_tasks = []
for tox_job, pixi_task in ___get_tox_job_names(tox).items():
Expand Down
58 changes: 51 additions & 7 deletions src/compwa_policy/check_dev_files/tox.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,47 @@

from __future__ import annotations

import re
from configparser import ConfigParser
from pathlib import Path
from typing import TYPE_CHECKING

from compwa_policy.errors import PrecommitError
from compwa_policy.utilities import CONFIG_PATH
from compwa_policy.utilities.pyproject import ModifiablePyproject, Pyproject
from compwa_policy.utilities.toml import to_multiline_string

if TYPE_CHECKING:
from tomlkit.items import String


def main(has_notebooks: bool) -> None:
if not CONFIG_PATH.tox.exists():
_merge_tox_ini_into_pyproject()
tox = read_tox_config()
if tox is None:
return
tox = _read_tox_config(CONFIG_PATH.tox)
_check_expected_sections(tox, has_notebooks)


def _read_tox_config(path: Path) -> ConfigParser:
config = ConfigParser()
config.read(path)
return config
def _merge_tox_ini_into_pyproject() -> None:
if not CONFIG_PATH.tox.is_file():
return
with open(CONFIG_PATH.tox) as file:
tox_ini = file.read()
with ModifiablePyproject.load() as pyproject:
tox_table = pyproject.get_table("tool.tox", create=True)
tox_table["legacy_tox_ini"] = __ini_to_toml(tox_ini)
CONFIG_PATH.tox.unlink()
msg = f"Merged {CONFIG_PATH.tox} into {CONFIG_PATH.pyproject}"
pyproject.changelog.append(msg)


def __ini_to_toml(ini: str) -> String:
ini = re.sub(r"(?<!\\)(\\)(?!\n)", r"\\\\", ini)
if not re.match(r"^ [^ ]", ini):
ini = ini.replace(" ", " ")
ini = f"\n{ini.strip()}\n"
return to_multiline_string(ini)


def _check_expected_sections(tox: ConfigParser, has_notebooks: bool) -> None:
Expand All @@ -40,7 +63,28 @@ def _check_expected_sections(tox: ConfigParser, has_notebooks: bool) -> None:
missing_sections = expected_sections - sections
if missing_sections:
msg = (
f"{CONFIG_PATH.tox} is missing job definitions:"
f"Tox configuration is missing job definitions:"
f" {', '.join(sorted(missing_sections))}"
)
raise PrecommitError(msg)


def read_tox_config() -> ConfigParser | None:
if CONFIG_PATH.tox.is_file():
return _load_tox_ini()
if CONFIG_PATH.pyproject.is_file():
pyproject = Pyproject.load()
if not pyproject.has_table("tool.tox"):
return None
tox_table = pyproject.get_table("tool.tox")
tox_config_str = tox_table.get("legacy_tox_ini")
if tox_config_str is not None:
config = ConfigParser()
config.read_string(tox_config_str)
return None


def _load_tox_ini() -> ConfigParser:
config = ConfigParser()
config.read(CONFIG_PATH.tox)
return config
5 changes: 5 additions & 0 deletions src/compwa_policy/utilities/toml.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from typing import TYPE_CHECKING, Any, Iterable

import tomlkit
from tomlkit.items import String, StringType, Trivia

if TYPE_CHECKING:
from tomlkit.items import Array
Expand All @@ -18,3 +19,7 @@ def to_toml_array(items: Iterable[Any], multiline: bool | None = None) -> Array:
else:
array.multiline(multiline)
return array


def to_multiline_string(value: str) -> String:
return String(StringType.MLB, value, value, Trivia())
102 changes: 0 additions & 102 deletions tox.ini

This file was deleted.

0 comments on commit a4b371c

Please sign in to comment.