Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FEAT: merge tox.ini into pyproject.toml #417

Merged
merged 12 commits into from
Oct 10, 2024
Merged
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.

Loading