From 39a8dbbd6c686f9a64cf4e82148e1767ea53491a Mon Sep 17 00:00:00 2001 From: Nicolas Graves Date: Tue, 17 Mar 2026 12:07:55 +0100 Subject: [PATCH] build-system: pyproject: Add arguments to pytest_guix plugin. * guix/build/pyproject-build-system.scm (keywords->alist, guile->python-keywords): Add procedures. (check): Convert keyword alist before writing it. * guix/build-system/pyproject.scm (%default-pytest-guix-options): Add some python kwargs in a guile format. * gnu/packages/aux-files/python/pytest_guix.py (pytest_addoption): Handle python kwargs when some are provided. Change-Id: Ie35e9b300acda830f35b6b754e8ccc07ad730faa Signed-off-by: Sharlatan Hellseher --- gnu/packages/aux-files/python/pytest_guix.py | 13 +++++- guix/build-system/pyproject.scm | 48 +++++++++++++------- guix/build/pyproject-build-system.scm | 26 ++++++++++- 3 files changed, 67 insertions(+), 20 deletions(-) diff --git a/gnu/packages/aux-files/python/pytest_guix.py b/gnu/packages/aux-files/python/pytest_guix.py index dbe8dfe136..2ec0a3bc53 100644 --- a/gnu/packages/aux-files/python/pytest_guix.py +++ b/gnu/packages/aux-files/python/pytest_guix.py @@ -31,6 +31,12 @@ def pytest_addoption(parser): otherwise, --cov is ignored (read by this parser, but nothing is done with it). + Flags can be given with additional keyword arguments in a json object. + If the json object is not given, fallback to the default + {"action": "append", "nargs": "?"}. In practice, these arguments are only + mandatory for the store_true and store_const actions to avoid eating other + arguments. + This allows to remove development packages, which are not required at build time while at the same time avoiding the need to adjust test options in pyproject.toml or other configuration files. @@ -45,5 +51,8 @@ def pytest_addoption(parser): for key, options in plugin_options.items(): if importlib.util.find_spec(f"pytest_{key}") is None: # Plugin not found, add stub options - for option in options: - group.addoption(option, action="append", nargs="?") + for option, kwargs in options.items(): + if kwargs: + group.addoption(option, **kwargs) + else: + group.addoption(option, action="append", nargs="?") diff --git a/guix/build-system/pyproject.scm b/guix/build-system/pyproject.scm index a46bd7751b..739ba451db 100644 --- a/guix/build-system/pyproject.scm +++ b/guix/build-system/pyproject.scm @@ -98,26 +98,40 @@ build-system level.") (license license:gpl3+)))) (define %default-pytest-guix-options + ;; Guile keyword arguments are translated to Python keyword arguments + ;; and passed to `group.addoption'. pytest_guix assumes default options + ;; '(#:action "append" #:nargs "?") + ;; It is required to store at least the store_const and store_true actions + ;; to ensure boolean args are not eating the next argument, but it is not + ;; necessary to do more than that so keep it minimal for maintainability. #~'(("cov" - "--cov" - "--cov-reset" - "--cov-report" - "--cov-config" - "--no-cov-on-fail" - "--no-cov" - "--cov-fail-under" - "--cov-append" - "--cov-branch" - "--cov-context") + ("--cov") + ("--cov-reset" #:action "store_const") + ("--cov-report") + ("--cov-config") + ("--no-cov-on-fail" #:action "store_true") + ("--no-cov" #:action "store_true") + ("--cov-fail-under") + ("--cov-append" #:action "store_true") + ("--cov-branch" #:action "store_true") + ("--cov-precision") + ("--cov-context")) ("html" - "--html" "--self-contained-html" "--css") + ("--html") + ("--self-contained-html" #:action "store_true") + ("--css")) ("mypy" - "--mypy" "--mypy-config-file" "--mypy-ignore-missing-imports") - ("isort" "isort") - ("flake8" "flake8") - ("black" "black") - ("flakes" "flakes") - ("pep8" "pep8"))) + ("--mypy" #:action "store_true") + ("--mypy-ignore-missing-imports" #:action "store_true") + ("--mypy-config-file") + ("--mypy-report-style") + ("--mypy-no-status-check" #:action "store_true") + ("--mypy-xfail" #:action "store_true")) + ("isort" ("--isort" #:action "store_true")) + ("flake8" ("--flake8" #:action "store_true")) + ("black" ("--black" #:action "store_true")) + ("flakes" ("--flakes" #:action "store_true")) + ("pep8" ("--pep8" #:action "store_true")))) ;; TODO: On the next iteration of python-team, migrate the sanity-check to ;; importlib_metadata instead of setuptools. diff --git a/guix/build/pyproject-build-system.scm b/guix/build/pyproject-build-system.scm index 8cf2d2c599..90995af49f 100644 --- a/guix/build/pyproject-build-system.scm +++ b/guix/build/pyproject-build-system.scm @@ -314,6 +314,27 @@ without errors." (with-directory-excursion "/tmp" (invoke "python" sanity-check.py (site-packages inputs outputs))))) +(define (keywords->alist lst) + (let loop ((lst lst) + (result '())) + (match lst + (() + (reverse result)) + ((kw value rest ...) + (cons (symbol->string (keyword->symbol kw)) value))))) + +(define (guile->python-keywords args) + (map (match-lambda + ((head . tail) + (cons head + (map (match-lambda + ((arg . ()) + (cons arg '())) + ((arg . keyword-args) + (cons arg (list (keywords->alist keyword-args))))) + tail)))) + args)) + (define* (check #:key inputs tests? test-backend test-flags pytest-guix-options #:allow-other-keys) "Run the test suite of a given Python package." @@ -349,7 +370,10 @@ without errors." (match use-test-backend ('pytest-with-guix-plugin (call-with-output-file ".pytest_guix_options.json" - (cut scm->json pytest-guix-options <>)) + (lambda (port) + (scm->json + (guile->python-keywords pytest-guix-options) + port))) (apply invoke pytest "-vv" "-p" "pytest_guix" test-flags)) ('pytest (apply invoke pytest "-vv" test-flags))