GNU bug report logs - #70570
[PATCH 0/2] Python: Ignore unwanted development inputs.

Previous Next

Package: guix-patches;

Reported by: Nicolas Graves <ngraves <at> ngraves.fr>

Date: Thu, 25 Apr 2024 15:58:11 UTC

Severity: normal

Tags: patch

To reply to this bug, email your comments to 70570 AT debbugs.gnu.org.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to guix-patches <at> gnu.org:
bug#70570; Package guix-patches. (Thu, 25 Apr 2024 15:58:15 GMT) Full text and rfc822 format available.

Acknowledgement sent to Nicolas Graves <ngraves <at> ngraves.fr>:
New bug report received and forwarded. Copy sent to guix-patches <at> gnu.org. (Thu, 25 Apr 2024 15:58:16 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Nicolas Graves <ngraves <at> ngraves.fr>
To: guix-patches <at> gnu.org
Cc: ngraves <at> ngraves.fr
Subject: [PATCH 0/2] Python: Ignore unwanted development inputs.
Date: Thu, 25 Apr 2024 17:42:35 +0200
This patch series implements a way to robustly and with minimal burden on maintainers to remove some python packages that are often put in native inputs. This allows these packages to be removed almost seemlessly in most cases from native-inputs where they are of no use, enabling to cut down the dependent rebuilds upon update, and more easily update them and their real dependents.

It is for the python-team branch. It will be followed by a more consequential patch series upon the python-team branch to actually remove these unwanted developement inputs, but is send before for reviews.

The patch series handles :
- guix lint warnings against the inclusion of these packages
- guix import pypi will automatically not include them when read in the package result
- ignoring pytest arguments defined in pytest.ini or setup.cfg regarding those packages

The patch series doesn't handle:
- ignoring these packages when they are explicitely listed as required for installation (which means that sometimes a snippet or a patch are necessary, but this is not the general case).

Nicolas Graves (2):
  guix: import: pypi: Ignore pypi-ignored-inputs.
  guix: pyproject-build-system: Ignore unwanted pytest flags.

 guix/build/pyproject-build-system.scm | 88 ++++++++++++++++++++++++++-
 guix/import/pypi.scm                  | 20 +++++-
 guix/lint.scm                         | 11 ++--
 tests/pypi.scm                        |  3 +-
 4 files changed, 111 insertions(+), 11 deletions(-)

-- 
2.41.0





Information forwarded to guix-patches <at> gnu.org:
bug#70570; Package guix-patches. (Thu, 25 Apr 2024 16:01:05 GMT) Full text and rfc822 format available.

Message #8 received at 70570 <at> debbugs.gnu.org (full text, mbox):

From: Nicolas Graves <ngraves <at> ngraves.fr>
To: 70570 <at> debbugs.gnu.org
Cc: ngraves <at> ngraves.fr
Subject: [PATCH 1/2] guix: import: pypi: Ignore pypi-ignored-inputs.
Date: Thu, 25 Apr 2024 17:59:45 +0200
* guix/import/pypi.scm (pypi-ignored-inputs): New variable.
  (compute-inputs): Use it.

* tests/pypi.scm (parse-requires.txt): Add ignored input to test the
  feature.

* guix/lint.scm (check-inputs-should-be-native): Adapt list.
  (check-inputs-should-not-be-an-input-at-all): Use pypi-ignored-list.

Change-Id: I774e526c5a090026e778ee44049637174a1dca95
---
 guix/import/pypi.scm | 20 +++++++++++++++++---
 guix/lint.scm        | 11 ++++++-----
 tests/pypi.scm       |  3 ++-
 3 files changed, 25 insertions(+), 9 deletions(-)

diff --git a/guix/import/pypi.scm b/guix/import/pypi.scm
index 6719fde330..a43d4eca1d 100644
--- a/guix/import/pypi.scm
+++ b/guix/import/pypi.scm
@@ -14,6 +14,7 @@
 ;;; Copyright © 2022 Vivien Kraus <vivien <at> planete-kraus.eu>
 ;;; Copyright © 2021 Simon Tournier <zimon.toutoune <at> gmail.com>
 ;;; Copyright © 2022 Hartmut Goebel <h.goebel <at> crazy-compilers.com>
+;;; Copyright © 2024 Nicolas Graves <ngraves <at> ngraves.fr>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -61,6 +62,7 @@ (define-module (guix import pypi)
   #:use-module (guix upstream)
   #:use-module ((guix licenses) #:prefix license:)
   #:export (%pypi-base-url
+            pypi-ignored-inputs
             parse-requires.txt
             parse-wheel-metadata
             specification->requirement-name
@@ -77,6 +79,17 @@ (define %pypi-base-url
   ;; Base URL of the PyPI API.
   (make-parameter "https://pypi.org/pypi/"))
 
+(define pypi-ignored-inputs
+  ;; This list contains packages that are useful for development or quality
+  ;; testing, but that most of the time are not necessary to have as an input.
+  (list "argparse"  ; native
+        "codecov" "coverage"  ; coverage
+        "black" "isort" "pycodestyle" "pep8"  ; style
+        "pyflakes" "flake8" "pylint" "mypy"  ; style+lint
+        "coveralls" "twine"  ; upload integration tools
+        "pytest-isort" "pytest-flake8" "pytest-cov" "pytest-black"
+        "pytest-pep8" "pytest-mypy" "pytest-pep8" "pre-commit"))  ; variants
+
 (define non-empty-string-or-false
   (match-lambda
     ("" #f)
@@ -424,9 +437,10 @@ (define (compute-inputs source-url wheel-url archive)
   "Given the SOURCE-URL and WHEEL-URL of an already downloaded ARCHIVE, return
 the corresponding list of <upstream-input> records."
   (define (requirements->upstream-inputs deps type)
-    (filter-map (match-lambda
-                  ("argparse" #f)
-                  (name (upstream-input
+    (filter-map (lambda (name)
+                  (if (member name pypi-ignored-inputs)
+                      #f
+                      (upstream-input
                          (name name)
                          (downstream-name (python->package-name name))
                          (type type))))
diff --git a/guix/lint.scm b/guix/lint.scm
index 68d532968d..9867b71cfd 100644
--- a/guix/lint.scm
+++ b/guix/lint.scm
@@ -71,6 +71,7 @@ (define-module (guix lint)
                                     hg-reference-url)
   #:autoload   (guix bzr-download) (bzr-reference?
                                     bzr-reference-url)
+  #:use-module ((guix import pypi) #:select (pypi-ignored-inputs))
   #:use-module (guix import stackage)
   #:use-module (ice-9 match)
   #:use-module (ice-9 regex)
@@ -557,14 +558,12 @@ (define (check-inputs-should-be-native package)
             "m4"
             "qttools-5"
             "yasm" "nasm" "fasm"
-            "python-coverage"
             "python-cython"
             "python-docutils"
             "python-mock"
             "python-nose"
             "python-pbr"
             "python-pytest"
-            "python-pytest-cov"
             "python-setuptools-scm"
             "python-sphinx"
             "scdoc"
@@ -586,9 +585,11 @@ (define (check-inputs-should-be-native package)
 (define (check-inputs-should-not-be-an-input-at-all package)
   ;; Emit a warning if some inputs of PACKAGE are likely to should not be
   ;; an input at all.
-  (let ((input-names '("python-setuptools"
-                       "python-pip"
-                       "python-pre-commit")))
+  (let ((input-names (append
+                      '("python-setuptools"
+                        "python-pip"
+                        "python-pre-commit")
+                      pypi-ignored-inputs)))
     (map (lambda (input)
            (make-warning
             package
diff --git a/tests/pypi.scm b/tests/pypi.scm
index 42b39cde73..fe01ab3beb 100644
--- a/tests/pypi.scm
+++ b/tests/pypi.scm
@@ -97,6 +97,7 @@ (define test-requires.txt "\
 
 [test]
 pytest (>=2.5.0)
+pytest-cov  # read but ignored
 ")
 
 ;; Beaker contains only optional dependencies.
@@ -244,7 +245,7 @@ (define-syntax-rule (with-pypi responses body ...)
   (map specification->requirement-name test-specifications))
 
 (test-equal "parse-requires.txt"
-  (list '("foo" "bar") '("pytest"))
+  (list '("foo" "bar") '("pytest" "pytest-cov"))
   (mock ((ice-9 ports) call-with-input-file
          call-with-input-string)
         (parse-requires.txt test-requires.txt)))
-- 
2.41.0





Information forwarded to guix-patches <at> gnu.org:
bug#70570; Package guix-patches. (Thu, 25 Apr 2024 16:02:06 GMT) Full text and rfc822 format available.

Message #11 received at 70570 <at> debbugs.gnu.org (full text, mbox):

From: Nicolas Graves <ngraves <at> ngraves.fr>
To: 70570 <at> debbugs.gnu.org
Cc: ngraves <at> ngraves.fr
Subject: [PATCH 2/2] guix: pyproject-build-system: Ignore unwanted pytest
 flags.
Date: Thu, 25 Apr 2024 17:59:46 +0200
* guix/build/pyproject-build-system.scm : Ignore unwanted pytest flags.

Change-Id: Ib9f1602e5af11227e5b7ce124f0f9be4fa2b78e4
---
 guix/build/pyproject-build-system.scm | 88 ++++++++++++++++++++++++++-
 1 file changed, 86 insertions(+), 2 deletions(-)

diff --git a/guix/build/pyproject-build-system.scm b/guix/build/pyproject-build-system.scm
index 947d240114..3ca3c76c1c 100644
--- a/guix/build/pyproject-build-system.scm
+++ b/guix/build/pyproject-build-system.scm
@@ -1,6 +1,7 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2021 Lars-Dominik Braun <lars <at> 6xq.net>
 ;;; Copyright © 2022 Marius Bakke <marius <at> gnu.org>
+;;; Copyright © 2024 Nicolas Graves <ngraves <at> ngraves.fr>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -142,7 +143,86 @@ (define* (build #:key outputs build-backend backend-path configure-flags #:allow
      wheel-dir
      config-settings)))
 
-(define* (check #:key tests? test-backend test-flags #:allow-other-keys)
+;; Pytest plugin to filter out arguments to ignore.
+(define pytest-default-ignore-alist
+  '(("cov" . ("--cov" "--cov-reset" "--cov-report" "--cov-config"
+              "--no-cov-on-fail" "--no-cov" "--cov-fail-under"
+              "--cov-append" "--cov-branch" "--cov-context"))
+    ("mypy" . ("--mypy" "--mypy-config-file" "--mypy-ignore-missing-imports"))
+    ("isort" . ("--isort"))
+    ("flake8" . ("--flake8"))
+    ("black" . ("--black"))
+    ("flakes" . ("--flakes"))
+    ("pep8" . ("--pep8"))))
+
+;; Allow guix to ignore these options when underlying pytest package is not
+;; an input. These flags are not necessary to properly run tests.
+(define (pytest-ignore-options-plugin flags)
+  "This function converts an list of flags in a string that can
+  be instantiated as a python pytest plugin."
+  (format #f "\
+import pytest
+
+def pytest_addoption(parser):
+    group = parser.getgroup('guix','Guix ignored options')
+    options = [~{~s, ~}]
+    for option in options:
+        group.addoption(option, action='append', nargs='*')"
+          flags))
+
+(define (call-with-guix-pytest-plugin inputs thunk)
+  (let* ((former-path (getenv "PYTHONPATH"))
+         (input-names
+          (filter (match-lambda
+                    (((name . _) ...)
+                     (if (string-prefix? "python-pytest-" name)
+                         name
+                         #f))
+                    ( _ #f))
+                  inputs))
+         (filtered-flags
+          (filter identity
+                  (append-map
+                   (match-lambda
+                     ((group . flags)
+                      (if (member (string-append "python-pytest-" group)
+                                  input-names)
+                          (list #f)
+                          flags))
+                     (_ (list #f)))
+                   pytest-default-ignore-alist))))
+    (dynamic-wind
+      (lambda ()
+        (setenv "PYTHONPATH"
+                (string-append
+                 (if former-path
+                     (string-append former-path ":")
+                     "")
+                 ".guix-pytest"))
+        (setenv "PYTEST_PLUGINS"
+                (string-append
+                 (if (getenv "PYTEST_PLUGINS")
+                     (string-append former-path ",")
+                     "")
+                 "pytest_guix_plugin"))
+        (mkdir-p ".guix-pytest")
+        (with-output-to-file ".guix-pytest/__init__.py"
+          (lambda _ (display "")))
+        (with-output-to-file ".guix-pytest/pytest_guix_plugin.py"
+          (lambda _
+            (display (pytest-ignore-options-plugin filtered-flags)))))
+      thunk
+      (lambda ()
+        (setenv "PYTHONPATH" former-path)
+        (unsetenv "PYTEST_PLUGINS")
+        (when (file-exists? ".guix-pytest")
+          (delete-file-recursively ".guix-pytest"))))))
+
+(define-syntax-rule (with-guix-pytest-plugin inputs exp ...)
+  "Evaluate EXP in a context where the Guix pytest plugin is added."
+  (call-with-guix-pytest-plugin inputs (lambda () exp ...)))
+
+(define* (check #:key inputs tests? test-backend test-flags #:allow-other-keys)
   "Run the test suite of a given Python package."
   (if tests?
       ;; Unfortunately with PEP 517 there is no common method to specify test
@@ -165,7 +245,8 @@ (define* (check #:key tests? test-backend test-flags #:allow-other-keys)
         (format #t "Using ~a~%" use-test-backend)
         (match use-test-backend
           ('pytest
-           (apply invoke pytest "-vv" test-flags))
+           (with-guix-pytest-plugin inputs
+             (apply invoke pytest "-vv" test-flags)))
           ('nose
            (apply invoke nosetests "-v" test-flags))
           ('nose2
@@ -386,3 +467,6 @@ (define* (pyproject-build #:key inputs (phases %standard-phases)
   (apply python:python-build #:inputs inputs #:phases phases args))
 
 ;;; pyproject-build-system.scm ends here
+;;; Local Variables:
+;;; eval: (put 'with-guix-pytest-plugin 'scheme-indent-function 1)
+;;; End:
-- 
2.41.0





Information forwarded to guix-patches <at> gnu.org:
bug#70570; Package guix-patches. (Fri, 26 Apr 2024 08:27:04 GMT) Full text and rfc822 format available.

Message #14 received at 70570 <at> debbugs.gnu.org (full text, mbox):

From: Lars-Dominik Braun <lars <at> 6xq.net>
To: Nicolas Graves <ngraves <at> ngraves.fr>
Cc: 70570 <at> debbugs.gnu.org
Subject: Re: [PATCH 1/2] guix: import: pypi: Ignore pypi-ignored-inputs.
Date: Fri, 26 Apr 2024 10:26:28 +0200
Hi,

> +(define pypi-ignored-inputs
> +  ;; This list contains packages that are useful for development or quality
> +  ;; testing, but that most of the time are not necessary to have as an input.
> +  (list "argparse"  ; native
> +        "codecov" "coverage"  ; coverage
> +        "black" "isort" "pycodestyle" "pep8"  ; style
> +        "pyflakes" "flake8" "pylint" "mypy"  ; style+lint
> +        "coveralls" "twine"  ; upload integration tools
> +        "pytest-isort" "pytest-flake8" "pytest-cov" "pytest-black"
> +        "pytest-pep8" "pytest-mypy" "pytest-pep8" "pre-commit"))  ; variants

> +  (let ((input-names (append
> +                      '("python-setuptools"
> +                        "python-pip"
> +                        "python-pre-commit")
> +                      pypi-ignored-inputs)))

we should remove python-setuptools from this list now (since it actually
should be an input on the python-team branch), python-pre-commit is
also part of pypi-ignored-inputs and maybe we can just add pip to
pypi-ignored-inputs and use only that list?

Also note that check-inputs-should-not-be-an-input-at-all expects Guix
package names (with python- prefix), whereas pypi-ignored-inputs uses
Python package names, so you probably want to (map (cut (string-append
"python-" <>) …) (or similar) here.

Lars





Information forwarded to guix-patches <at> gnu.org:
bug#70570; Package guix-patches. (Fri, 26 Apr 2024 08:49:06 GMT) Full text and rfc822 format available.

Message #17 received at 70570 <at> debbugs.gnu.org (full text, mbox):

From: Lars-Dominik Braun <lars <at> 6xq.net>
To: Nicolas Graves <ngraves <at> ngraves.fr>
Cc: 70570 <at> debbugs.gnu.org
Subject: Re: [PATCH 2/2] guix: pyproject-build-system: Ignore unwanted pytest
 flags.
Date: Fri, 26 Apr 2024 10:47:47 +0200
Hi,

pretty smart idea to use a pytest plugin :)

> +;; Pytest plugin to filter out arguments to ignore.
> +(define pytest-default-ignore-alist

From the comment it’s not entirely clear to me what this list
does. It’s a map from pytest plugin name to it’s pytest command line
options, right?

> +;; Allow guix to ignore these options when underlying pytest package is not
> +;; an input. These flags are not necessary to properly run tests.
> +(define (pytest-ignore-options-plugin flags)
> +  "This function converts an list of flags in a string that can
> +  be instantiated as a python pytest plugin."
…
> +(define (call-with-guix-pytest-plugin inputs thunk)

Same here. As far as I understand you want to emulate command line
options provided by pytest plugins, so pytest won’t fail if the plugin
is not present. And we only do that if the plugin is not an input to
avoid clashing command line options, right?

+    for option in options:
+        group.addoption(option, action='append', nargs='*')"

Not sure nargs='*' is a good idea, since it might consume positional
arguments intended for pytest. '?' would be a more conservative option,
especially since we cannot override this easily per-package.

> +  (let* ((former-path (getenv "PYTHONPATH"))
…
> +    (dynamic-wind
> +      (lambda ()
> +        (setenv "PYTHONPATH"
…
> +      (lambda ()
> +        (setenv "PYTHONPATH" former-path)

Isn’t it GUIX_PYTHONPATH?

Lars





Information forwarded to guix-patches <at> gnu.org:
bug#70570; Package guix-patches. (Fri, 26 Apr 2024 10:16:03 GMT) Full text and rfc822 format available.

Message #20 received at 70570 <at> debbugs.gnu.org (full text, mbox):

From: Nicolas Graves <ngraves <at> ngraves.fr>
To: Lars-Dominik Braun <lars <at> 6xq.net>
Cc: 70570 <at> debbugs.gnu.org
Subject: Re: [PATCH 2/2] guix: pyproject-build-system: Ignore unwanted
 pytest flags.
Date: Fri, 26 Apr 2024 12:14:56 +0200
On 2024-04-26 10:47, Lars-Dominik Braun wrote:

> Hi,
>
> pretty smart idea to use a pytest plugin :)
>
>> +;; Pytest plugin to filter out arguments to ignore.
>> +(define pytest-default-ignore-alist
>
> From the comment it’s not entirely clear to me what this list
> does. It’s a map from pytest plugin name to it’s pytest command line
> options, right?

Right, I'll update the command.

>
>> +;; Allow guix to ignore these options when underlying pytest package is not
>> +;; an input. These flags are not necessary to properly run tests.
>> +(define (pytest-ignore-options-plugin flags)
>> +  "This function converts an list of flags in a string that can
>> +  be instantiated as a python pytest plugin."
> …
>> +(define (call-with-guix-pytest-plugin inputs thunk)
>
> Same here. As far as I understand you want to emulate command line
> options provided by pytest plugins, so pytest won’t fail if the plugin
> is not present. And we only do that if the plugin is not an input to
> avoid clashing command line options, right?

Will do.
>
> +    for option in options:
> +        group.addoption(option, action='append', nargs='*')"
>
> Not sure nargs='*' is a good idea, since it might consume positional
> arguments intended for pytest. '?' would be a more conservative option,
> especially since we cannot override this easily per-package.

It works. I'll try with '?' then!

>
>> +  (let* ((former-path (getenv "PYTHONPATH"))
> …
>> +    (dynamic-wind
>> +      (lambda ()
>> +        (setenv "PYTHONPATH"
> …
>> +      (lambda ()
>> +        (setenv "PYTHONPATH" former-path)
>
> Isn’t it GUIX_PYTHONPATH?
>
 
I know it works this way. Could be GUIX_PYTHONPATH too, I'm not sure I
properly get the difference. Can test with GUIX_PYTHONPATH too, but in
any case it's just for the tests, so it should be cleared out
too. Should I?

> Lars
>

-- 
Best regards,
Nicolas Graves




Information forwarded to guix-patches <at> gnu.org:
bug#70570; Package guix-patches. (Fri, 26 Apr 2024 10:24:04 GMT) Full text and rfc822 format available.

Message #23 received at 70570 <at> debbugs.gnu.org (full text, mbox):

From: Nicolas Graves <ngraves <at> ngraves.fr>
To: Lars-Dominik Braun <lars <at> 6xq.net>
Cc: 70570 <at> debbugs.gnu.org
Subject: Re: [PATCH 1/2] guix: import: pypi: Ignore pypi-ignored-inputs.
Date: Fri, 26 Apr 2024 12:23:30 +0200
On 2024-04-26 10:26, Lars-Dominik Braun wrote:

> Hi,
>
>> +(define pypi-ignored-inputs
>> +  ;; This list contains packages that are useful for development or quality
>> +  ;; testing, but that most of the time are not necessary to have as an input.
>> +  (list "argparse"  ; native
>> +        "codecov" "coverage"  ; coverage
>> +        "black" "isort" "pycodestyle" "pep8"  ; style
>> +        "pyflakes" "flake8" "pylint" "mypy"  ; style+lint
>> +        "coveralls" "twine"  ; upload integration tools
>> +        "pytest-isort" "pytest-flake8" "pytest-cov" "pytest-black"
>> +        "pytest-pep8" "pytest-mypy" "pytest-pep8" "pre-commit"))  ; variants
>
>> +  (let ((input-names (append
>> +                      '("python-setuptools"
>> +                        "python-pip"
>> +                        "python-pre-commit")
>> +                      pypi-ignored-inputs)))
>
> we should remove python-setuptools from this list now (since it actually
> should be an input on the python-team branch), python-pre-commit is
> also part of pypi-ignored-inputs and maybe we can just add pip to
> pypi-ignored-inputs and use only that list?

Yes, but then it should be done in an independent commit IMO to keep
this one focused on native-inputs and pytest, and then add one for your
other changes of the build system.

But yes, I think they ought to be in the same list.

>
> Also note that check-inputs-should-not-be-an-input-at-all expects Guix
> package names (with python- prefix), whereas pypi-ignored-inputs uses
> Python package names, so you probably want to (map (cut (string-append
> "python-" <>) …) (or similar) here.

Perfectly right, thanks for noticing.

About pre-commit : if we add the python- prefix, then we use the
outdated variable. Maybe we should remove if pypi-ignored-inputs here,
and add "pre-commit" idependently.


> Lars
>

Another quick note : The plugin could also be several plugins (one per
package) in the store added in the PYTHONPATH, which would enable us to
not regenerate the file everytime, but it doesn't compile with (guix
gexp) module. It might be more efficient / guixy this way, but I'm not
able to do it.

If you know how to, don't hesitate ;)

-- 
Best regards,
Nicolas Graves




Information forwarded to guix-patches <at> gnu.org:
bug#70570; Package guix-patches. (Sat, 27 Apr 2024 16:11:02 GMT) Full text and rfc822 format available.

Message #26 received at 70570 <at> debbugs.gnu.org (full text, mbox):

From: Nicolas Graves <ngraves <at> ngraves.fr>
To: Lars-Dominik Braun <lars <at> 6xq.net>
Cc: 70570 <at> debbugs.gnu.org
Subject: Re: [PATCH 2/2] guix: pyproject-build-system: Ignore unwanted
 pytest flags.
Date: Sat, 27 Apr 2024 18:09:39 +0200
On 2024-04-26 12:14, Nicolas Graves wrote:

> On 2024-04-26 10:47, Lars-Dominik Braun wrote:
>
>> Hi,
>>
>> pretty smart idea to use a pytest plugin :)
>>
>>> +;; Pytest plugin to filter out arguments to ignore.
>>> +(define pytest-default-ignore-alist
>>
>> From the comment it’s not entirely clear to me what this list
>> does. It’s a map from pytest plugin name to it’s pytest command line
>> options, right?
>
> Right, I'll update the command.
>
>>
>>> +;; Allow guix to ignore these options when underlying pytest package is not
>>> +;; an input. These flags are not necessary to properly run tests.
>>> +(define (pytest-ignore-options-plugin flags)
>>> +  "This function converts an list of flags in a string that can
>>> +  be instantiated as a python pytest plugin."
>> …
>>> +(define (call-with-guix-pytest-plugin inputs thunk)
>>
>> Same here. As far as I understand you want to emulate command line
>> options provided by pytest plugins, so pytest won’t fail if the plugin
>> is not present. And we only do that if the plugin is not an input to
>> avoid clashing command line options, right?
>
> Will do.
>>
>> +    for option in options:
>> +        group.addoption(option, action='append', nargs='*')"
>>
>> Not sure nargs='*' is a good idea, since it might consume positional
>> arguments intended for pytest. '?' would be a more conservative option,
>> especially since we cannot override this easily per-package.
>
> It works. I'll try with '?' then!
>
>>
>>> +  (let* ((former-path (getenv "PYTHONPATH"))
>> …
>>> +    (dynamic-wind
>>> +      (lambda ()
>>> +        (setenv "PYTHONPATH"
>> …
>>> +      (lambda ()
>>> +        (setenv "PYTHONPATH" former-path)
>>
>> Isn’t it GUIX_PYTHONPATH?
>>
>  
> I know it works this way. Could be GUIX_PYTHONPATH too, I'm not sure I
> properly get the difference. Can test with GUIX_PYTHONPATH too, but in
> any case it's just for the tests, so it should be cleared out
> too. Should I?

Actually, it doesn't seem to work with a replacement from PYTHONPATH to
GUIX_PYTHONPATH, so I would rather keep it this way.

>
>> Lars
>>

-- 
Best regards,
Nicolas Graves




Information forwarded to guix-patches <at> gnu.org:
bug#70570; Package guix-patches. (Sat, 27 Apr 2024 16:56:02 GMT) Full text and rfc822 format available.

Message #29 received at 70570 <at> debbugs.gnu.org (full text, mbox):

From: Nicolas Graves <ngraves <at> ngraves.fr>
To: 70570 <at> debbugs.gnu.org
Cc: ngraves <at> ngraves.fr
Subject: [PATCH v2 1/2] guix: import: pypi: Ignore pypi-ignored-inputs.
Date: Sat, 27 Apr 2024 18:54:52 +0200
* guix/import/pypi.scm (pypi-ignored-inputs): New variable.
  (compute-inputs): Use it.

* tests/pypi.scm (parse-requires.txt): Add ignored input to test the
  feature.

* guix/lint.scm (check-inputs-should-be-native): Adapt list.
  (check-inputs-should-not-be-an-input-at-all): Use pypi-ignored-list.

Change-Id: I774e526c5a090026e778ee44049637174a1dca95
---
 guix/import/pypi.scm | 20 +++++++++++++++++---
 guix/lint.scm        | 12 +++++++-----
 tests/pypi.scm       |  3 ++-
 3 files changed, 26 insertions(+), 9 deletions(-)

diff --git a/guix/import/pypi.scm b/guix/import/pypi.scm
index 6719fde330..a43d4eca1d 100644
--- a/guix/import/pypi.scm
+++ b/guix/import/pypi.scm
@@ -14,6 +14,7 @@
 ;;; Copyright © 2022 Vivien Kraus <vivien <at> planete-kraus.eu>
 ;;; Copyright © 2021 Simon Tournier <zimon.toutoune <at> gmail.com>
 ;;; Copyright © 2022 Hartmut Goebel <h.goebel <at> crazy-compilers.com>
+;;; Copyright © 2024 Nicolas Graves <ngraves <at> ngraves.fr>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -61,6 +62,7 @@ (define-module (guix import pypi)
   #:use-module (guix upstream)
   #:use-module ((guix licenses) #:prefix license:)
   #:export (%pypi-base-url
+            pypi-ignored-inputs
             parse-requires.txt
             parse-wheel-metadata
             specification->requirement-name
@@ -77,6 +79,17 @@ (define %pypi-base-url
   ;; Base URL of the PyPI API.
   (make-parameter "https://pypi.org/pypi/"))
 
+(define pypi-ignored-inputs
+  ;; This list contains packages that are useful for development or quality
+  ;; testing, but that most of the time are not necessary to have as an input.
+  (list "argparse"  ; native
+        "codecov" "coverage"  ; coverage
+        "black" "isort" "pycodestyle" "pep8"  ; style
+        "pyflakes" "flake8" "pylint" "mypy"  ; style+lint
+        "coveralls" "twine"  ; upload integration tools
+        "pytest-isort" "pytest-flake8" "pytest-cov" "pytest-black"
+        "pytest-pep8" "pytest-mypy" "pytest-pep8" "pre-commit"))  ; variants
+
 (define non-empty-string-or-false
   (match-lambda
     ("" #f)
@@ -424,9 +437,10 @@ (define (compute-inputs source-url wheel-url archive)
   "Given the SOURCE-URL and WHEEL-URL of an already downloaded ARCHIVE, return
 the corresponding list of <upstream-input> records."
   (define (requirements->upstream-inputs deps type)
-    (filter-map (match-lambda
-                  ("argparse" #f)
-                  (name (upstream-input
+    (filter-map (lambda (name)
+                  (if (member name pypi-ignored-inputs)
+                      #f
+                      (upstream-input
                          (name name)
                          (downstream-name (python->package-name name))
                          (type type))))
diff --git a/guix/lint.scm b/guix/lint.scm
index 68d532968d..dd9bf0fb46 100644
--- a/guix/lint.scm
+++ b/guix/lint.scm
@@ -71,6 +71,7 @@ (define-module (guix lint)
                                     hg-reference-url)
   #:autoload   (guix bzr-download) (bzr-reference?
                                     bzr-reference-url)
+  #:use-module ((guix import pypi) #:select (pypi-ignored-inputs))
   #:use-module (guix import stackage)
   #:use-module (ice-9 match)
   #:use-module (ice-9 regex)
@@ -557,14 +558,12 @@ (define (check-inputs-should-be-native package)
             "m4"
             "qttools-5"
             "yasm" "nasm" "fasm"
-            "python-coverage"
             "python-cython"
             "python-docutils"
             "python-mock"
             "python-nose"
             "python-pbr"
             "python-pytest"
-            "python-pytest-cov"
             "python-setuptools-scm"
             "python-sphinx"
             "scdoc"
@@ -586,9 +585,12 @@ (define (check-inputs-should-be-native package)
 (define (check-inputs-should-not-be-an-input-at-all package)
   ;; Emit a warning if some inputs of PACKAGE are likely to should not be
   ;; an input at all.
-  (let ((input-names '("python-setuptools"
-                       "python-pip"
-                       "python-pre-commit")))
+  (let ((input-names (append
+                      '("python-setuptools"
+                        "python-pip"
+                        "pre-commit")
+                      (map (cut (string-append "python-" <>))
+                           pypi-ignored-inputs))))
     (map (lambda (input)
            (make-warning
             package
diff --git a/tests/pypi.scm b/tests/pypi.scm
index 42b39cde73..fe01ab3beb 100644
--- a/tests/pypi.scm
+++ b/tests/pypi.scm
@@ -97,6 +97,7 @@ (define test-requires.txt "\
 
 [test]
 pytest (>=2.5.0)
+pytest-cov  # read but ignored
 ")
 
 ;; Beaker contains only optional dependencies.
@@ -244,7 +245,7 @@ (define-syntax-rule (with-pypi responses body ...)
   (map specification->requirement-name test-specifications))
 
 (test-equal "parse-requires.txt"
-  (list '("foo" "bar") '("pytest"))
+  (list '("foo" "bar") '("pytest" "pytest-cov"))
   (mock ((ice-9 ports) call-with-input-file
          call-with-input-string)
         (parse-requires.txt test-requires.txt)))
-- 
2.41.0





Information forwarded to guix-patches <at> gnu.org:
bug#70570; Package guix-patches. (Sat, 27 Apr 2024 16:56:02 GMT) Full text and rfc822 format available.

Message #32 received at 70570 <at> debbugs.gnu.org (full text, mbox):

From: Nicolas Graves <ngraves <at> ngraves.fr>
To: 70570 <at> debbugs.gnu.org
Cc: ngraves <at> ngraves.fr
Subject: [PATCH v2 2/2] guix: pyproject-build-system: Ignore unwanted pytest
 flags.
Date: Sat, 27 Apr 2024 18:54:53 +0200
* guix/build/pyproject-build-system.scm : Ignore unwanted pytest flags.

Change-Id: Ib9f1602e5af11227e5b7ce124f0f9be4fa2b78e4
---
 guix/build/pyproject-build-system.scm | 91 ++++++++++++++++++++++++++-
 1 file changed, 89 insertions(+), 2 deletions(-)

diff --git a/guix/build/pyproject-build-system.scm b/guix/build/pyproject-build-system.scm
index 947d240114..ebe4e1941d 100644
--- a/guix/build/pyproject-build-system.scm
+++ b/guix/build/pyproject-build-system.scm
@@ -1,6 +1,7 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2021 Lars-Dominik Braun <lars <at> 6xq.net>
 ;;; Copyright © 2022 Marius Bakke <marius <at> gnu.org>
+;;; Copyright © 2024 Nicolas Graves <ngraves <at> ngraves.fr>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -142,7 +143,89 @@ (define* (build #:key outputs build-backend backend-path configure-flags #:allow
      wheel-dir
      config-settings)))
 
-(define* (check #:key tests? test-backend test-flags #:allow-other-keys)
+(define pytest-default-ignore-alist
+  '(("cov" . ("--cov" "--cov-reset" "--cov-report" "--cov-config"
+              "--no-cov-on-fail" "--no-cov" "--cov-fail-under"
+              "--cov-append" "--cov-branch" "--cov-context"))
+    ("mypy" . ("--mypy" "--mypy-config-file" "--mypy-ignore-missing-imports"))
+    ("isort" . ("--isort"))
+    ("flake8" . ("--flake8"))
+    ("black" . ("--black"))
+    ("flakes" . ("--flakes"))
+    ("pep8" . ("--pep8"))))
+
+(define (pytest-ignore-flags-plugin flags)
+  "This function converts an list of flags into a string that can
+  be instantiated as a python pytest plugin."
+  (format #f "\
+import pytest
+
+def pytest_addoption(parser):
+    group = parser.getgroup('guix','Guix ignored options')
+    options = [~{~s, ~}]
+    for option in options:
+        group.addoption(option, action='append', nargs='?')"
+          flags))
+
+(define (call-with-guix-pytest-plugin inputs thunk)
+  "This function emulates command line options provided by pytest plugins in
+the absence of the plugins defining these options.
+
+This is done by selecting absent plugins, gettings their flags defined in
+PYTEST-DEFAULT-IGNORE-ALIST, and generating the plugin from there with
+PYTEST-IGNORE-FLAGS-PLUGIN."
+  (let* ((former-path (getenv "PYTHONPATH"))
+         (input-names
+          (filter (match-lambda
+                    (((name . _) ...)
+                     (if (string-prefix? "python-pytest-" name)
+                         name
+                         #f))
+                    ( _ #f))
+                  inputs))
+         (filtered-flags
+          (filter identity
+                  (append-map
+                   (match-lambda
+                     ((group . flags)
+                      (if (member (string-append "python-pytest-" group)
+                                  input-names)
+                          (list #f)
+                          flags))
+                     (_ (list #f)))
+                   pytest-default-ignore-alist))))
+    (dynamic-wind
+      (lambda ()
+        (setenv "PYTHONPATH"
+                (string-append
+                 (if former-path
+                     (string-append former-path ":")
+                     "")
+                 ".guix-pytest"))
+        (setenv "PYTEST_PLUGINS"
+                (string-append
+                 (if (getenv "PYTEST_PLUGINS")
+                     (string-append former-path ",")
+                     "")
+                 "pytest_guix_plugin"))
+        (mkdir-p ".guix-pytest")
+        (with-output-to-file ".guix-pytest/__init__.py"
+          (lambda _ (display "")))
+        (with-output-to-file ".guix-pytest/pytest_guix_plugin.py"
+          (lambda _
+            (display (pytest-ignore-flags-plugin filtered-flags)))))
+      thunk
+      (lambda ()
+        (setenv "PYTHONPATH" former-path)
+        (unsetenv "PYTEST_PLUGINS")
+        (when (file-exists? ".guix-pytest")
+          (delete-file-recursively ".guix-pytest"))))))
+
+(define-syntax-rule (with-guix-pytest-plugin inputs exp ...)
+  "Evaluate EXP in a context where the Guix pytest plugin is added."
+  (call-with-guix-pytest-plugin inputs (lambda () exp ...)))
+
+(define* (check #:key inputs tests? test-backend test-flags #:allow-other-keys)
   "Run the test suite of a given Python package."
   (if tests?
       ;; Unfortunately with PEP 517 there is no common method to specify test
@@ -165,7 +248,8 @@ (define* (check #:key tests? test-backend test-flags #:allow-other-keys)
         (format #t "Using ~a~%" use-test-backend)
         (match use-test-backend
           ('pytest
-           (apply invoke pytest "-vv" test-flags))
+           (with-guix-pytest-plugin inputs
+             (apply invoke pytest "-vv" test-flags)))
           ('nose
            (apply invoke nosetests "-v" test-flags))
           ('nose2
@@ -386,3 +470,6 @@ (define* (pyproject-build #:key inputs (phases %standard-phases)
   (apply python:python-build #:inputs inputs #:phases phases args))
 
 ;;; pyproject-build-system.scm ends here
+;;; Local Variables:
+;;; eval: (put 'with-guix-pytest-plugin 'scheme-indent-function 1)
+;;; End:
-- 
2.41.0





Information forwarded to guix-patches <at> gnu.org:
bug#70570; Package guix-patches. (Sun, 28 Apr 2024 10:16:02 GMT) Full text and rfc822 format available.

Message #35 received at 70570 <at> debbugs.gnu.org (full text, mbox):

From: Nicolas Graves <ngraves <at> ngraves.fr>
To: 70570 <at> debbugs.gnu.org
Subject: Re: [PATCH v2 2/2] guix: pyproject-build-system: Ignore unwanted
 pytest flags.
Date: Sun, 28 Apr 2024 12:14:42 +0200
On 2024-04-27 18:54, Nicolas Graves wrote:

> * guix/build/pyproject-build-system.scm : Ignore unwanted pytest flags.
>
> Change-Id: Ib9f1602e5af11227e5b7ce124f0f9be4fa2b78e4
> ---
>  guix/build/pyproject-build-system.scm | 91 ++++++++++++++++++++++++++-
>  1 file changed, 89 insertions(+), 2 deletions(-)
>
> diff --git a/guix/build/pyproject-build-system.scm b/guix/build/pyproject-build-system.scm
> index 947d240114..ebe4e1941d 100644
> --- a/guix/build/pyproject-build-system.scm
> +++ b/guix/build/pyproject-build-system.scm
> @@ -1,6 +1,7 @@
>  ;;; GNU Guix --- Functional package management for GNU
>  ;;; Copyright © 2021 Lars-Dominik Braun <lars <at> 6xq.net>
>  ;;; Copyright © 2022 Marius Bakke <marius <at> gnu.org>
> +;;; Copyright © 2024 Nicolas Graves <ngraves <at> ngraves.fr>
>  ;;;
>  ;;; This file is part of GNU Guix.
>  ;;;
> @@ -142,7 +143,89 @@ (define* (build #:key outputs build-backend backend-path configure-flags #:allow
>       wheel-dir
>       config-settings)))
>  
> -(define* (check #:key tests? test-backend test-flags #:allow-other-keys)
> +(define pytest-default-ignore-alist
> +  '(("cov" . ("--cov" "--cov-reset" "--cov-report" "--cov-config"
> +              "--no-cov-on-fail" "--no-cov" "--cov-fail-under"
> +              "--cov-append" "--cov-branch" "--cov-context"))
> +    ("mypy" . ("--mypy" "--mypy-config-file" "--mypy-ignore-missing-imports"))
> +    ("isort" . ("--isort"))
> +    ("flake8" . ("--flake8"))
> +    ("black" . ("--black"))
> +    ("flakes" . ("--flakes"))
> +    ("pep8" . ("--pep8"))))
> +
> +(define (pytest-ignore-flags-plugin flags)
> +  "This function converts an list of flags into a string that can
> +  be instantiated as a python pytest plugin."
> +  (format #f "\
> +import pytest
> +
> +def pytest_addoption(parser):
> +    group = parser.getgroup('guix','Guix ignored options')
> +    options = [~{~s, ~}]
> +    for option in options:
> +        group.addoption(option, action='append', nargs='?')"
> +          flags))
> +
> +(define (call-with-guix-pytest-plugin inputs thunk)
> +  "This function emulates command line options provided by pytest plugins in
> +the absence of the plugins defining these options.
> +
> +This is done by selecting absent plugins, gettings their flags defined in
> +PYTEST-DEFAULT-IGNORE-ALIST, and generating the plugin from there with
> +PYTEST-IGNORE-FLAGS-PLUGIN."
> +  (let* ((former-path (getenv "PYTHONPATH"))
> +         (input-names
> +          (filter (match-lambda
> +                    (((name . _) ...)
> +                     (if (string-prefix? "python-pytest-" name)
> +                         name
> +                         #f))
> +                    ( _ #f))
> +                  inputs))

This filter is not working properly as it doesn't output names but
pairs. Will be changed in the next revision with a map car.

> +         (filtered-flags
> +          (filter identity
> +                  (append-map
> +                   (match-lambda
> +                     ((group . flags)
> +                      (if (member (string-append "python-pytest-" group)
> +                                  input-names)
> +                          (list #f)
> +                          flags))
> +                     (_ (list #f)))
> +                   pytest-default-ignore-alist))))
> +    (dynamic-wind
> +      (lambda ()
> +        (setenv "PYTHONPATH"
> +                (string-append
> +                 (if former-path
> +                     (string-append former-path ":")
> +                     "")
> +                 ".guix-pytest"))

I found that in some edge cases, a hidden directory in the current dir
can cause tests to fail. It only happened for one package which was
failing on the __init__.py from .guix-pytest, meaning that tests could
consider this directory.

So it's better to put that out-of-source in ../.guix-pytest. Will be
done in the next revision.

> +        (setenv "PYTEST_PLUGINS"
> +                (string-append
> +                 (if (getenv "PYTEST_PLUGINS")
> +                     (string-append former-path ",")
> +                     "")
> +                 "pytest_guix_plugin"))
> +        (mkdir-p ".guix-pytest")
> +        (with-output-to-file ".guix-pytest/__init__.py"
> +          (lambda _ (display "")))
> +        (with-output-to-file ".guix-pytest/pytest_guix_plugin.py"
> +          (lambda _
> +            (display (pytest-ignore-flags-plugin filtered-flags)))))
> +      thunk
> +      (lambda ()
> +        (setenv "PYTHONPATH" former-path)
> +        (unsetenv "PYTEST_PLUGINS")
> +        (when (file-exists? ".guix-pytest")
> +          (delete-file-recursively ".guix-pytest"))))))
> +
> +(define-syntax-rule (with-guix-pytest-plugin inputs exp ...)
> +  "Evaluate EXP in a context where the Guix pytest plugin is added."
> +  (call-with-guix-pytest-plugin inputs (lambda () exp ...)))
> +
> +(define* (check #:key inputs tests? test-backend test-flags #:allow-other-keys)
>    "Run the test suite of a given Python package."
>    (if tests?
>        ;; Unfortunately with PEP 517 there is no common method to specify test
> @@ -165,7 +248,8 @@ (define* (check #:key tests? test-backend test-flags #:allow-other-keys)
>          (format #t "Using ~a~%" use-test-backend)
>          (match use-test-backend
>            ('pytest
> -           (apply invoke pytest "-vv" test-flags))
> +           (with-guix-pytest-plugin inputs
> +             (apply invoke pytest "-vv" test-flags)))
>            ('nose
>             (apply invoke nosetests "-v" test-flags))
>            ('nose2
> @@ -386,3 +470,6 @@ (define* (pyproject-build #:key inputs (phases %standard-phases)
>    (apply python:python-build #:inputs inputs #:phases phases args))
>  
>  ;;; pyproject-build-system.scm ends here
> +;;; Local Variables:
> +;;; eval: (put 'with-guix-pytest-plugin 'scheme-indent-function 1)
> +;;; End:

-- 
Best regards,
Nicolas Graves




This bug report was last modified 8 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.