jtojnar / nixpkgs-hammering

Beat your package expressions into a shape
MIT License
253 stars 15 forks source link

Add support for buildPythonPackage #15

Closed rmcgibbo closed 3 years ago

rmcgibbo commented 3 years ago

Hi @jtojnar:

I've started trying to add support for checking the arguments to buildPythonPackage as an addition to the current checking of the arguments to mkDerivation. So far, it appears to mostly work, although I can't yet seem to get it to report multiple failures at once -- the checks appear to short-circuit once a single failing check is identified.

Still WIP, but I wanted to post this now for any feedback.

SuperSandro2000 commented 3 years ago

I have a few ideas if you are interested:

rmcgibbo commented 3 years ago

I think I'm actually hitting this bug/issue, and I'm not sure how to solve it yet: https://github.com/NixOS/nixpkgs/issues/44426

jtojnar commented 3 years ago

Try https://github.com/NixOS/nixpkgs/pull/107044#discussion_r546236396?

rmcgibbo commented 3 years ago

Thanks for the hint. Let me bang my head against that for a bit.

rmcgibbo commented 3 years ago

This PR should be working now. I've force pushed and separated the commits into individual units.

I'm new to this codebase, and fairly new to nix in general, so any feedback would be appreciated. I'm sure I'm messing some things up.

Here's an example running with c64f442 and the new checks:

# hacked nixpkgs/pkgs/development/python-modules/aiostream/default.nix, with lots of bugs injected
{ lib
, buildPythonPackage
, numpy
}:

buildPythonPackage rec {
  pname = "aiostream";

  pythonImportCheck = [ "aiostream" ];  # typo
  propagatedBuildInputs = [ numpy ];
  checkInputs = [ numpy ];  # duplicate
  checkPhase = ''
    pytest
  '';  # unnecessary

  meta = with lib; {
    license = licenses.gpl3;  # deprecated
  };
}

Producing the output

$ ./tools/nixpkgs-hammer -f ~/projects/nixpkgs python38Packages.aiostream
When evaluating attribute ‘python38Packages.aiostream’:
warning: duplicate-check-inputs
Dependencies listed in propagatedBuildInputs shouldn't be repeated in checkInputs.

Near /home/mcgibbon/projects/nixpkgs/pkgs/development/python-modules/aiostream/default.nix:11:3:
   |
11 |   checkInputs = [ numpy ];  # duplicate
   |   ^
Near /home/mcgibbon/projects/nixpkgs/pkgs/development/python-modules/aiostream/default.nix:10:3:
   |
10 |   propagatedBuildInputs = [ numpy ];
   |   ^
See: https://github.com/jtojnar/nixpkgs-hammering/blob/master/explanations/duplicate-check-inputs.md
warning: python-explicit-check-phase
Consider using pytestCheckHook in checkInputs rather than checkPhase="pytest".

Near /home/mcgibbon/projects/nixpkgs/pkgs/development/python-modules/aiostream/default.nix:12:3:
   |
12 |   checkPhase = ''
   |   ^
See: https://github.com/jtojnar/nixpkgs-hammering/blob/master/explanations/python-explicit-check-phase.md
warning: python-imports-check-typo
A typo in pythonImportsCheck was detected.

Near /home/mcgibbon/projects/nixpkgs/pkgs/development/python-modules/aiostream/default.nix:9:3:
  |
9 |   pythonImportCheck = [ "aiostream" ];  # typo
  |   ^
See: https://github.com/jtojnar/nixpkgs-hammering/blob/master/explanations/python-imports-check-typo.md
warning: unclear-gpl
`gpl3` is a deprecated license, check if project uses `gpl3Plus` or `gpl3Only` and change `meta.license` accordingly.

Near /home/mcgibbon/projects/nixpkgs/pkgs/development/python-modules/aiostream/default.nix:17:5:
   |
17 |     license = licenses.gpl3;
   |     ^
See: https://github.com/jtojnar/nixpkgs-hammering/blob/master/explanations/unclear-gpl.md
rmcgibbo commented 3 years ago

@SuperSandro2000 wrote:

check for impure python imports which pull in another python version

I've implemented this in aa085cb, but the changes required are a little bigger to the code base, because it requires our checkDerivation functions knowing which interpreter version they're being called on. Making this consistent with the mkDerivation checks requires also changing those checks to get passed the relevant stdenv, I think.

So this commit will require some code review, I think. I'd be happy to move it to a separate PR, if you prefer.

jtojnar commented 3 years ago

Looks good at first glance, will give it a thorough review in the afternoon (CEST). Could you also add the test file to the tests directory, listing it in tests/default.nix and run-tests.py?

SuperSandro2000 commented 3 years ago

So this commit will require some code review, I think. I'd be happy to move it to a separate PR, if you prefer.

Can't decide that because it is jtojnar projects.

rmcgibbo commented 3 years ago

@jtojnar: I've added tests.

jtojnar commented 3 years ago

Do you feel like writing a short blurb for each check to add to explanations/ directory? Otherwise, I can do that in the next week.

rmcgibbo commented 3 years ago

I believe that I've fixed all of the more cosmetic changes in the last review, but I have not (yet) addressed the more substantive ones.

rmcgibbo commented 3 years ago

Rebase finished.

jtojnar commented 3 years ago

Turns out I made a mistake when writing the composeOverlays function. I corrected it and then I found out I have written the exact same code that is contained in lib.composeExtensions (up to alpha equivalence).

The following should work:

diff --git a/lib/default.nix b/lib/default.nix
index 28abae1..97d2255 100644
--- a/lib/default.nix
+++ b/lib/default.nix
@@ -25,6 +25,9 @@ rec {
       };
     };

+  # Identity element for overlays.
+  idOverlay = final: prev: {};
+
   # Creates a function based on the original one, that, when called on
   # one of the requested packages, runs a check on the arguments passed to it
   # and then returns the original result enriched with the reports.
@@ -101,16 +104,14 @@ rec {

     in
     lib.genAttrs pythonPackageSetNames (pythonName:
-      let
-        prvPython = builtins.getAttr pythonName prev;
-      in prvPython.override {
-        packageOverrides = python-self: python-super: {
-          buildPythonPackage = wrapFunctionWithChecks prvPython.pkgs.buildPythonPackage namePositions check;
-        };
-      });
+      prev.${pythonName}.override (oldOverrides: {
+        packageOverrides = lib.composeExtensions (oldOverrides.packageOverrides or idOverlay) (final: prev: {
+          buildPythonPackage = wrapFunctionWithChecks prev.buildPythonPackage namePositions check;
+        });
+      }));

     checkFor = check: let
       o1 = (checkMkDerivationFor check);
       o2 = (checkBuildPythonPackageFor check);
-    in attrs: final: prev: (o1 attrs final prev) // (o2 attrs final prev);
+    in attrs: lib.composeExtensions (o1 attrs) (o2 attrs);
 }
rmcgibbo commented 3 years ago

@jtojnar: Nice!. I've pulled that diff into the first commit in this PR (now d3d30b2).

rmcgibbo commented 3 years ago

Actually -- I need to bisect my changes a little bit. Something I've done has caused every error message do be repeated twice. I suspect that diff might be the problem...

rmcgibbo commented 3 years ago

(The duplication is has been fixed by slapping in a call to lib.unique, based on @jtojnar's suggestion.)

rmcgibbo commented 3 years ago

I think this is ready to go, pending writing explanations for each error message. Is there anything else that's a blocker for you, @jtojnar?

jtojnar commented 3 years ago

Looks good to me otherwise. Great job.

Unfortunately, I do not think I will be able to write the explanations this week after all. We can just add link = false; to the new checks for now.

rmcgibbo commented 3 years ago

I added some explanations in fa77e76. Maybe you could take a look at them, @SuperSandro2000?

jtojnar commented 3 years ago

I have fixed some minor style issues, squashed the explanations into the introducing commits, added some links. I have also changed the wording of python-imports-check-typo.md back since I am not sure it makes sense to require pythonImportsCheck when regular tests are present – they should already check imports work. I have also changed pytestFlagsArray example since pytestFlagsArray = [ "-o cache_dir=$(mktemp -d)" ]; is wrong on three counts.

jtojnar commented 3 years ago

Thank you for this great job.