From c1968ba4e34596e4b01b688ec51f6916dfe05032 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Sat, 18 Oct 2025 17:41:25 +0200 Subject: [PATCH] Add dependency groups to pyproject and drop pytest-cov dependency --- pyproject.toml | 78 +++++++++++++++++++++++++++++--------------------- run_tests.py | 29 ++++++++++++------- 2 files changed, 64 insertions(+), 43 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index f10c3529..1299f261 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,11 +4,9 @@ build-backend = "setuptools.build_meta" [project] name = "novelWriter" -authors = [ - {name = "Veronica Berglyd Olsen", email = "code@vkbo.net"}, -] +authors = [{ name = "Veronica Berglyd Olsen", email = "code@vkbo.net" }] description = "A plain text editor for planning and writing novels" -readme = {file = "setup/description_pypi.md", content-type = "text/markdown"} +readme = { file = "setup/description_pypi.md", content-type = "text/markdown" } license = "GPL-3.0-or-later AND Apache-2.0 AND CC-BY-4.0" license-files = ["LICENSE.md", "setup/LICENSE-Apache-2.0.txt"] classifiers = [ @@ -26,12 +24,28 @@ classifiers = [ "Topic :: Text Editors", ] requires-python = ">=3.10" -dependencies = [ - "pyqt6>=6.4", - "pyenchant>=3.0.0", -] +dependencies = ["pyqt6>=6.4", "pyenchant>=3.0.0"] dynamic = ["version"] +[dependency-groups] +dev = [ + { include-group = "docs" }, + { include-group = "test" }, + { include-group = "lint" }, +] +docs = [ + "docutils>=0.17.1", + "pygments>=2.7", + "sphinx-book-theme", + "sphinx-copybutton", + "sphinx-design", + "sphinx-favicon", + "sphinx-intl", + "sphinx>=5.0", +] +test = ["coverage>=7.2.0", "pytest-qt", "pytest-timeout", "pytest>=6.0.0"] +lint = ["isort", "pyright", "ruff"] + [project.urls] Homepage = "https://novelwriter.io" Documentation = "https://docs.novelwriter.io" @@ -42,13 +56,13 @@ Issues = "https://github.com/vkbo/novelWriter/issues" novelwriter = "novelwriter:main" [tool.setuptools.dynamic] -version = {attr = "novelwriter.__version__"} +version = { attr = "novelwriter.__version__" } [tool.setuptools.packages.find] include = ["novelwriter*"] [tool.isort] -py_version="310" +py_version = "310" line_length = 99 wrap_length = 79 multi_line_output = 5 @@ -64,26 +78,26 @@ preview = true # Rules: https://docs.astral.sh/ruff/rules select = [ - "A", # flake8-builtins (A) - "ANN", # flake8-annotations (ANN) - "B", # flake8-bugbear (B) - "D", # pydocstyle (D) - "E", # pycodestyle (E) - "F", # Pyflakes (F) - "FA", # flake8-future-annotations (FA) - "PERF", # Perflint (PERF) - "PLC", # Pylint Convention (PLC) - "PLE", # Pylint Error (PLE) - "PLR17", # Refactor (PLR) - Only PLR17xx - "PLW", # Pylint Warning (PLW) - "Q", # flake8-quotes (Q) - "RET", # flake8-return (RET) - "RUF", # Ruff-specific rules (RUF) - "SLF", # flake8-self (SLF) - "SLOT", # flake8-slots (SLOT) - "TC", # flake8-type-checking (TC) - "UP", # pyupgrade (UP) - "W", # pycodestyle (W) + "A", # flake8-builtins (A) + "ANN", # flake8-annotations (ANN) + "B", # flake8-bugbear (B) + "D", # pydocstyle (D) + "E", # pycodestyle (E) + "F", # Pyflakes (F) + "FA", # flake8-future-annotations (FA) + "PERF", # Perflint (PERF) + "PLC", # Pylint Convention (PLC) + "PLE", # Pylint Error (PLE) + "PLR17", # Refactor (PLR) - Only PLR17xx + "PLW", # Pylint Warning (PLW) + "Q", # flake8-quotes (Q) + "RET", # flake8-return (RET) + "RUF", # Ruff-specific rules (RUF) + "SLF", # flake8-self (SLF) + "SLOT", # flake8-slots (SLOT) + "TC", # flake8-type-checking (TC) + "UP", # pyupgrade (UP) + "W", # pycodestyle (W) ] ignore = [ "ANN401", # any-type @@ -149,6 +163,4 @@ branch = false [tool.coverage.report] precision = 2 -exclude_also = [ - "if TYPE_CHECKING:" -] +exclude_also = ["if TYPE_CHECKING:"] diff --git a/run_tests.py b/run_tests.py index b9687aa9..f2e91ec7 100755 --- a/run_tests.py +++ b/run_tests.py @@ -3,6 +3,7 @@ import argparse import os +import shlex import subprocess import sys @@ -12,27 +13,35 @@ if __name__ == "__main__": parser.add_argument("-o", action="store_true", help="Run off screen") parser.add_argument("-r", action="store_true", help="Generate reports") parser.add_argument("-t", action="store_true", help="Generate terminal report") - parser.add_argument("-m", help="Test modules") - parser.add_argument("-k", help="Test filters") + parser.add_argument("-u", action="store_true", help="Generate uncovered terminal report") + parser.add_argument("-m", help="Test modules", metavar="MARKEXPR") + parser.add_argument("-k", help="Test filters", metavar="EXPRESSION") args = parser.parse_args() env = os.environ.copy() env["QT_SCALE_FACTOR"] = "1.0" - cmd = [sys.executable, "-m", "pytest", "-vv"] + if args.r or args.t or args.u: + cmd = [sys.executable, "-m"] + else: + cmd = ["coverage", "-m"] + + cmd += ["pytest", "-vv"] if args.o: env["QT_QPA_PLATFORM"] = "offscreen" - if args.r or args.t: - cmd += ["--cov=novelwriter"] - if args.r: - cmd += ["--cov-report=xml", "--cov-report=html"] - if args.t: - cmd += ["--cov-report=term"] if args.m: cmd += ["-m", args.m] if args.k: cmd += ["-k", args.k] - print("Calling:", " ".join(cmd)) + print("Calling:", shlex.join(cmd)) subprocess.call(cmd, env=env) + + if args.r: + subprocess.call(["coverage", "xml"]) + subprocess.call(["coverage", "html"]) + if args.t and not args.u: + subprocess.call(["coverage", "report"]) + if args.u: + subprocess.call(["coverage", "report", "--skip-covered "])