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

pytestCheckHook: Switch from python -m pytest to simply pytest? #255262

Open
13 tasks
doronbehar opened this issue Sep 15, 2023 · 4 comments
Open
13 tasks

pytestCheckHook: Switch from python -m pytest to simply pytest? #255262

doronbehar opened this issue Sep 15, 2023 · 4 comments

Comments

@doronbehar
Copy link
Contributor

doronbehar commented Sep 15, 2023

Summary of issue

Many packages in Nixpkgs that use cython extension modules, demonstrate some issues with running tests via pytestCheckHook, credit to @natsukium for helping figuring that out.

Generally, the problem is that the extension modules are installed at the installCheckPhase at $out, and are not $PWD. This for instance may cause differences between running pytest and running python -m pytest - hence the issue title. What's rather peculiar, is the fact that all packages that manage to overcome that use different schemes. The most common of them all is:

preCheck = ''
  cd $out
'';

Below is a list of such packages, and PRs that improved the situation a bit:

Below is the original issue description, opened before further details were investigated. Hence the issues there may be a bit outdated.

Original issue description

Describe the bug

While trying to enable tests for pyerfa, I noticed that I got circular imports errors as explained upstream here. I then ran git grep circular import and learned that another Python package, pyrevolve is experiencing the same issue on NixOS:

nativeCheckInputs = [ pytest ];
# Using approach bellow bcs the tests fail with the pytestCheckHook, throwing the following error
# ImportError: cannot import name 'crevolve' from partially initialized module 'pyrevolve'
# (most likely due to a circular import)
checkPhase = ''
pytest
'';
pythonImportsCheck = [
"pyrevolve"
];

Steps To Reproduce

For each package that comes out in a git grep circular import search, I'll list what I learned, from most interesting, to less interesting:

python3.pkgs.pyrevolve

Try to build it with this patch:

diff --git i/pkgs/development/python-modules/pyrevolve/default.nix w/pkgs/development/python-modules/pyrevolve/default.nix
index 754baf91ad38..33df5d177f4d 100644
--- i/pkgs/development/python-modules/pyrevolve/default.nix
+++ w/pkgs/development/python-modules/pyrevolve/default.nix
@@ -38,7 +38,7 @@ buildPythonPackage rec {
   # ImportError: cannot import name 'crevolve' from partially initialized module 'pyrevolve'
   # (most likely due to a circular import)
   checkPhase = ''
-    pytest
+    python -m pytest
   '';
 
   pythonImportsCheck = [

Which does the same as replacing pytest with pytestCheckHook, and removing the overriding checkPhase. Note how the tests now fail.

python3.pkgs.orange3

Seems like a very similar case to what happens in python3.pkgs.pyrevolve, but replacing python -m pytest with pytest doesn't resolve the issue. I also haven't opened an issue upstream because I'm not sure whether this is our fault or theirs.

I tested this issue using this patch
diff --git i/pkgs/development/python-modules/orange3/default.nix w/pkgs/development/python-modules/orange3/default.nix
index cff4a603c846..4a9051548655 100644
--- i/pkgs/development/python-modules/orange3/default.nix
+++ w/pkgs/development/python-modules/orange3/default.nix
@@ -24,6 +24,7 @@
 , pyqtgraph
 , pyqtwebengine
 , python
+, pytest
 , python-louvain
 , pythonOlder
 , pyyaml
@@ -104,8 +105,13 @@ let
       baycomp
     ];
 
-    # FIXME: ImportError: cannot import name '_variable' from partially initialized module 'Orange.data' (most likely due to a circular import) (/build/source/Orange/data/__init__.py)
-    doCheck = false;
+    doCheck = true;
+    nativeCheckInputs = [
+      pytest
+    ];
+    checkPhase = ''
+      pytest
+    '';
 
     pythonImportsCheck = [ "Orange" "Orange.data._variable" ];
 

python3.pkgs.primer3

The circular import issue is mentioned there in a comment, but that comment seems maybe inaccurate to me, and the same testing failure is observed when adding pytest to nativeCheckInputs, and when running manually pytest in checkPhase. Comment improvement is in #255260

python3.pkgs.xdot

Don't know why was the purpose of the circular import comment, maybe it was outdated. Now a fix for tests and update is available in #255254 .

python3.pkgs.iniconfig

Not exactly this issue, but rather it is a form of #63168 . Improvement for the comment near it's doCheck = false; is in #255256 .

Expected behavior

No difference between pytest and python -m pytest.

Additional context

Problem was investigated also in https://discourse.nixos.org/t/python-package-testing-circular-import-in-a-version-py/33019/ .

Notify maintainers

@FRidh . Maybe python3.pkgs.orange3, and python3.pkgs.pyrevolve maintainers @lucasew and @AtilaSaraiva will be also interested.

@nixos-discourse
Copy link

This issue has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/python-package-testing-circular-import-in-a-version-py/33019/5

@natsukium
Copy link
Member

natsukium commented Sep 15, 2023

It is not a circular import, but this is a problem often encountered in extension modules generated by cython and others.

some examples

#240183 (review)

  • use pytest directly with a flag --import-mode append

#238058 (comment)

  • change the current directory

#102729 (comment)

  • remove source directory

python -m pytest adds the current directory to the head of the search path, so python imports packages in $src/ instead of packages installed in $out/{python.sitePackages}/.
https://docs.pytest.org/en/7.1.x/explanation/pythonpath.html#invoking-pytest-versus-python-m-pytest
I don't think this is the expected behavior of pytestCheckHook.

@lucasew
Copy link
Contributor

lucasew commented Sep 15, 2023

Just for reference:

pytestCheckHook is defined in pkgs/development/interpreters/python/hooks/pytest-check-hook.sh

And I think that -m behavior is to allow using a interpreter specific for testing. I don't know the usecases of this approach exactly as I am not the author of the hook.

Do you think that an option to disable this behaviour and use pytest directly would be better?

Like instead of that eval "@pythonCheckInterpreter@ $args" some kind of check that if a flag is enabled then pytest $args?

doronbehar added a commit to doronbehar/nixpkgs that referenced this issue Sep 16, 2023
Instead of manually specifying the disabled tests and test paths in
`checkPhase`, use the pytestCheckHook for that, and avoid the issue
described at NixOS#255262 by removing
the source directory.
@doronbehar
Copy link
Contributor Author

Like instead of that eval "@pythonCheckInterpreter@ $args" some kind of check that if a flag is enabled then pytest $args?

Definitely that would be nice, but I'm not sure that's the only thing that is required here. At astropy/astropy#15316 (comment) I summarized some my findings regarding pytest vs python -m pytest.

It is not a circular import, but this is a problem often encountered in extension modules generated by cython and others.

some examples

Thanks for the examples! Indeed for the packages I tried to update and enable tests (pyerfa and astropy) was using cd $out in preCheck. See also #255471 .

On the other hand over at #255260 a different solution was implemented eventually.

doronbehar added a commit to doronbehar/nixpkgs that referenced this issue Sep 16, 2023
Use NIX_CFLAGS_COMPILE = "-O2", due to upstream issue. cd "$out" to
avoid circular import issue (discuessed downstream at at
NixOS#255262).
doronbehar added a commit to doronbehar/nixpkgs that referenced this issue Sep 16, 2023
Add some informatory comments, add doronbehar as maintainers, use `rec`
instead of `let ... in`, add `pythonImportsCheck` and `pytestCheckHook`,
use `cd $out` to handle issue
NixOS#255262
lucasew added a commit to lucasew/playground that referenced this issue Sep 16, 2023
Signed-off-by: lucasew <lucas59356@gmail.com>
doronbehar added a commit to doronbehar/nixpkgs that referenced this issue Sep 17, 2023
Related to: NixOS#255262 . This allows
greater control over disabling tests and test paths in case needed in
the future. The NOSE_EXCLUDE environment variable was removed due to
being unneeded, as upstream uses pytest for a long time now, and that
disabled test was removed since.
doronbehar added a commit to doronbehar/nixpkgs that referenced this issue Sep 17, 2023
Related to: NixOS#255262 . This allows
Using the hook's builtin support for of `disabledTests` and
`disabledTestPaths`.
doronbehar added a commit to doronbehar/nixpkgs that referenced this issue Sep 20, 2023
Related to: NixOS#255262 and a
follow-up to NixOS#251923 :

- The NOSE_EXCLUDE environment variable was removed due to being
  unneeded, as upstream uses pytest for a long time now, and that
  disabled test was removed since.
- Support parallel testing with pytest-xdist
doronbehar added a commit to doronbehar/nixpkgs that referenced this issue Sep 20, 2023
Related to: NixOS#255262 . This allows
Using the hook's builtin support for of `disabledTests` and
`disabledTestPaths`.
doronbehar added a commit to doronbehar/nixpkgs that referenced this issue Sep 20, 2023
Related to: NixOS#255262 . This allows
Using the hook's builtin support for of `disabledTests` and
`disabledTestPaths`.
doronbehar added a commit to doronbehar/nixpkgs that referenced this issue Sep 21, 2023
Related to: NixOS#255262 . This allows
Using the hook's builtin support for of `disabledTests` and
`disabledTestPaths`.
digtail pushed a commit to digtail/nixpkgs that referenced this issue Sep 28, 2023
Use NIX_CFLAGS_COMPILE = "-O2", due to upstream issue. cd "$out" to
avoid circular import issue (discuessed downstream at at
NixOS#255262).
digtail pushed a commit to digtail/nixpkgs that referenced this issue Sep 28, 2023
Add some informatory comments, add doronbehar as maintainers, use `rec`
instead of `let ... in`, add `pythonImportsCheck` and `pytestCheckHook`,
use `cd $out` to handle issue
NixOS#255262
doronbehar added a commit to doronbehar/nixpkgs that referenced this issue Oct 1, 2023
Related to: NixOS#255262 and a
follow-up to NixOS#251923 :

- The NOSE_EXCLUDE environment variable was removed due to being
  unneeded, as upstream uses pytest for a long time now, and that
  disabled test was removed since.
- Support parallel testing with pytest-xdist
doronbehar added a commit to doronbehar/nixpkgs that referenced this issue Oct 1, 2023
Related to: NixOS#255262 . This allows
Using the hook's builtin support for of `disabledTests` and
`disabledTestPaths`.
doronbehar added a commit to doronbehar/nixpkgs that referenced this issue Oct 1, 2023
Related to: NixOS#255262 . This allows
Using the hook's builtin support for of `disabledTests` and
`disabledTestPaths`.
veprbl pushed a commit to doronbehar/nixpkgs that referenced this issue Jan 11, 2024
The link to the build docs is outdated, and it doesn't have an updated
direct alternative. While I tried to enable at least some of the tests,
I encountered NixOS#255262 which is
now linked in a comment.
sarahec added a commit to sarahec/nixpkgs that referenced this issue Mar 3, 2024
Cython is a Python compiler that emits native .so modules. By default, python derivations run tests in the wrong directory to see these modules and tests fail. 

Issue NixOS#255262 documents the root cause and solution for this problem. 

This PR adds a description of the problem and the most common solution to the test troubleshooting list.
sarahec added a commit to sarahec/nixpkgs that referenced this issue Mar 3, 2024
Cython is a Python compiler that emits native .so modules. By default, python derivations run tests in the wrong directory to see these modules and tests fail.

Issue NixOS#255262 documents the root cause and solution for this problem.

This PR adds a description of the problem and the most common solution to the test troubleshooting list.
sarahec added a commit to sarahec/nixpkgs that referenced this issue Mar 3, 2024
Cython is a Python compiler that emits native .so modules. By default, python derivations run tests in the wrong directory to see these modules and tests fail.

Issue NixOS#255262 documents the root cause and solution for this problem.

This PR adds a description of the problem and the most common solution to the test troubleshooting list.
FRidh pushed a commit that referenced this issue Mar 20, 2024
Cython is a Python compiler that emits native .so modules. By default, python derivations run tests in the wrong directory to see these modules and tests fail.

Issue #255262 documents the root cause and solution for this problem.

This PR adds a description of the problem and the most common solution to the test troubleshooting list.
abathur pushed a commit to abathur/nixpkgs that referenced this issue Mar 22, 2024
Cython is a Python compiler that emits native .so modules. By default, python derivations run tests in the wrong directory to see these modules and tests fail.

Issue NixOS#255262 documents the root cause and solution for this problem.

This PR adds a description of the problem and the most common solution to the test troubleshooting list.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants