Create a nix file to install python lib from git

I want to create nix file witch create env for python with uniswap-python
library:

let
    uni-py = pkgs.python3Packages.buildPythonPackage rec {
      name = "uniswap-python";
      version = "v0.7.1";

      src = pkgs.fetchFromGitHub {
      	 owner = "uniswap-python";
	 repo = "${name}";
	 rev = "${version}";
	 sha256 = "Uw77XsKDlvKECQIIE0P577mktb/FOSweOccDHFDZVaY=";
      };

      propagatedBuildInputs = with pkgs.python3Packages; [ web3 ];

      meta = {
        homepage = "https://github.com/uniswap-python/uniswap-python";
        description = "uniswap-python";
        license = lib.licenses.mit;
        maintainers = with maintainers; [ uniswap-python ];
      };
    };

in mkShell {
   name = "uni-py";
   buildInputs = with pkgs.python3Packages; [ web3 uni-py ];
   shellHook = ''
     echo "Whatever makes this happen."
   '';
}

run with nix-shell ue.nix

get this error:

Executing setuptoolsBuildPhase
Traceback (most recent call last):
  File "/build/source/nix_run_setup", line 8, in <module>
    exec(compile(getattr(tokenize, 'open', open)(__file__).read().replace('\\r\\n', '\\n'), __file__, 'exec'))
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/nix/store/yvhwsfbh4bc99vfvwpaa70m4yng4pvpz-python3-3.11.8/lib/python3.11/tokenize.py", line 396, in open
    buffer = _builtin_open(filename, 'rb')
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
FileNotFoundError: [Errno 2] No such file or directory: 'setup.py'
/nix/store/10i1kjjq5szjn1gp6418x8bc1hswqc90-stdenv-linux/setup: line 1553: pop_var_context: head of shell_variables not a function context
error: builder for '/nix/store/mfnkr2ygb3kazkw91h3xhzrfwlya3sc9-python3.11-uniswap-python.drv' failed with exit code 1;
       last 10 log lines:
       > Executing setuptoolsBuildPhase
       > Traceback (most recent call last):
       >   File "/build/source/nix_run_setup", line 8, in <module>
       >     exec(compile(getattr(tokenize, 'open', open)(__file__).read().replace('\\r\\n', '\\n'), __file__, 'exec'))
       >                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
       >   File "/nix/store/yvhwsfbh4bc99vfvwpaa70m4yng4pvpz-python3-3.11.8/lib/python3.11/tokenize.py", line 396, in open
       >     buffer = _builtin_open(filename, 'rb')
       >              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
       > FileNotFoundError: [Errno 2] No such file or directory: 'setup.py'
       > /nix/store/10i1kjjq5szjn1gp6418x8bc1hswqc90-stdenv-linux/setup: line 1553: pop_var_context: head of shell_variables not a function context
       For full logs, run 'nix-store -l /nix/store/mfnkr2ygb3kazkw91h3xhzrfwlya3sc9-python3.11-uniswap-python.drv'.

Please help to fix

as the error sais, there is no setup.py in the source dir.

FileNotFoundError: [Errno 2] No such file or directory: 'setup.py'

the nix wiki sais that in this case you should use

buildPythonPackage {
  format = "pyproject";
}

I hope that will work

with import <nixpkgs> {};

let
    uni-py = pkgs.python3Packages.buildPythonPackage rec {
      name = "uniswap-python";
      version = "v0.7.1";

      src = pkgs.fetchFromGitHub {
      	 owner = "uniswap-python";
	 repo = "${name}";
	 rev = "${version}";
	 sha256 = "Uw77XsKDlvKECQIIE0P577mktb/FOSweOccDHFDZVaY=";	 
      };

      propagatedBuildInputs = with pkgs.python3Packages; [ web3 ];

      meta = {
        homepage = "https://github.com/uniswap-python/uniswap-python";
        description = "uniswap-python";
        license = lib.licenses.mit;
        maintainers = with maintainers; [ uniswap-python ];
      };
    };

in mkShell {
   name = "uni-py";
   buildInputs = with pkgs.python3Packages; [ web3 uni-py ];
   format = "pyproject";
   shellHook = ''
     echo "Whatever makes this happen."
   '';
}

Gives same error

i think it should be declared in the buildPythonPackage

1 Like

Thx it fix, but now I have this problem:

let
uni-py = pkgs.python3Packages.buildPythonPackage rec {
name = “uniswap-python”;
version = “v0.7.1”;

  src = pkgs.fetchFromGitHub {
  	 owner = "uniswap-python";

repo = “${name}”;
rev = “${version}”;
sha256 = “Uw77XsKDlvKECQIIE0P577mktb/FOSweOccDHFDZVaY=”;
};
format = “pyproject”;
#propagatedBuildInputs = with pkgs.python3Packages; ;
propagatedBuildInputs = with pkgs; [ poetry python3 ];

  meta = {
    homepage = "https://github.com/uniswap-python/uniswap-python";
    description = "uniswap-python";
    license = lib.licenses.mit;
    maintainers = with maintainers; [ uniswap-python ];
  };
};

in mkShell {
name = “uni-py”;
#buildInputs = with pkgs.python3Packages; [ uni-py ];
buildInputs = with pkgs; [ poetry python3 uni-py ];
shellHook = ‘’
echo “Whatever makes this happen.”
‘’;
}

Error:

Executing pypaBuildPhase
Creating a wheel…

  • Getting build dependencies for wheel…

Traceback (most recent call last):
File “/nix/store/z42spfv8zgigkvd3m68j7hbzcj7dpahz-python3.11-pyproject-hooks-1.0.0/lib/python3.11/site-packages/pyproject_hooks/_impl.py”, line 321, in _call_hook
raise BackendUnavailable(data.get(‘traceback’, ‘’))
pyproject_hooks._impl.BackendUnavailable: Traceback (most recent call last):
File “/nix/store/z42spfv8zgigkvd3m68j7hbzcj7dpahz-python3.11-pyproject-hooks-1.0.0/lib/python3.11/site-packages/pyproject_hooks/_in_process/_in_process.py”, line 77, in _build_backend
obj = import_module(mod_path)
^^^^^^^^^^^^^^^^^^^^^^^
File “/nix/store/yvhwsfbh4bc99vfvwpaa70m4yng4pvpz-python3-3.11.8/lib/python3.11/importlib/init.py”, line 126, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “”, line 1204, in _gcd_import
File “”, line 1176, in _find_and_load
File “”, line 1147, in _find_and_load_unlocked
File “”, line 690, in _load_unlocked
File “”, line 940, in exec_module
File “”, line 241, in _call_with_frames_removed
File “/nix/store/lfjsaawdq1g6vk98fjffa6hs1ix7i04m-python3.11-poetry-1.7.1/lib/python3.11/site-packages/poetry/masonry/api.py”, line 3, in
from poetry.core.masonry.api import build_sdist
ModuleNotFoundError: No module named ‘poetry.core’

ERROR Backend ‘poetry.masonry.api’ is not available.
error: builder for ‘/nix/store/lr12yd1mvy53mganr9jqdrbjcfba4ywk-python3.11-uniswap-python.drv’ failed with exit code 1;
last 10 log lines:
> File “”, line 1176, in _find_and_load
> File “”, line 1147, in _find_and_load_unlocked
> File “”, line 690, in _load_unlocked
> File “”, line 940, in exec_module
> File “”, line 241, in _call_with_frames_removed
> File “/nix/store/lfjsaawdq1g6vk98fjffa6hs1ix7i04m-python3.11-poetry-1.7.1/lib/python3.11/site-packages/poetry/masonry/api.py”, line 3, in
> from poetry.core.masonry.api import build_sdist
> ModuleNotFoundError: No module named ‘poetry.core’
>
> ERROR Backend ‘poetry.masonry.api’ is not available.
For full logs, run ‘nix-store -l /nix/store/lr12yd1mvy53mganr9jqdrbjcfba4ywk-python3.11-uniswap-python.drv’.

I really have no idea of anything regarding python but

ModuleNotFoundError: No module named ‘poetry.core’

suggests, that there is a dependency missing that you need to add to your build

Indeed, poetry-core is required inside propagatedBuildInputs and poetry should be in nativeBuildInputs.

I cleaned up things a little bit and I added the package dependencies. Now everything compiles correctly.

with import <nixpkgs> { };

let
  uni-py = pkgs.python3Packages.buildPythonPackage rec {
    name = "uniswap-python";
    version = "v0.7.1";

    src = pkgs.fetchFromGitHub {
      owner = "uniswap-python";
      repo = name;
      rev = version;
      sha256 = "Uw77XsKDlvKECQIIE0P577mktb/FOSweOccDHFDZVaY=";
    };

    pyproject = true;

    nativeBuildInputs = [ poetry ];

    propagatedBuildInputs =
      (with pkgs.python3Packages; [
        web3
        poetry-core
        tomlkit
        cleo
        shellingham
        fastjsonschema
        trove-classifiers
        crashtest
        virtualenv
        requests-toolbelt
        pkginfo
        pexpect
        keyring
        dulwich
        cachecontrol
        click
        python-dotenv
      ])
      ++
      (with poetryPlugins; [
        poetry-plugin-export
      ]);

    meta = {
      homepage = "https://github.com/uniswap-python/uniswap-python";
      description = "uniswap-python";
      license = lib.licenses.mit;
      maintainers = with maintainers; [ uniswap-python ];
    };
  };

in
mkShell {
  name = "uni-py";
  buildInputs = with pkgs.python3Packages; [ web3 uni-py ];
  shellHook = ''
    echo "Whatever makes this happen."
  '';
}
1 Like

Many thanks!
Can you please explain there from you extract this list of deps ?

Of course! I just ran the shell with just web3 poetry-core and I got the following error message:

* Getting build dependencies for wheel...

ERROR Missing dependencies:
        poetry>=0.12
        tomlkit<1.0.0,>=0.11.4
        poetry>=0.12
        cleo<3.0.0,>=2.1.0
        poetry>=0.12
        shellingham<2.0,>=1.5
        poetry>=0.12
        fastjsonschema<3.0.0,>=2.18.0
        poetry>=0.12
        trove-classifiers>=2022.5.19
        poetry>=0.12
        crashtest<0.5.0,>=0.4.1
        poetry>=0.12
        virtualenv<21.0.0,>=20.23.0
        poetry>=0.12
        requests-toolbelt<2.0.0,>=1.0.0
        poetry>=0.12
        pkginfo<2.0.0,>=1.9.4
        poetry>=0.12
        pexpect<5.0.0,>=4.7.0
        poetry>=0.12
        keyring<25.0.0,>=24.0.0
        poetry>=0.12
        dulwich<0.22.0,>=0.21.2
        poetry>=0.12
        cachecontrol[filecache]<0.15.0,>=0.14.0
        poetry>=0.12
        platformdirs<5,>=3.0.

So I just added the packages from that list until everything worked. I don’t know how well of an approach this is as I didn’t test or run the app, so there might be other dependencies. Perhaps it would be better to use something like poetry2nix in this case.

1 Like

For me it gets error :slightly_frowning_face::

  • Getting build dependencies for wheel…

ERROR Missing dependencies:
poetry>=0.12
poetry-core==1.8.1
poetry>=0.12
fastjsonschema<3.0.0,>=2.18.0
error: builder for ‘/nix/store/vlbsnbir370gaa0jh47dm0rg9cv1nj71-python3.11-uniswap-python.drv’ failed with exit code 1;
last 10 log lines:
> Running phase: buildPhase
> Executing pypaBuildPhase
> Creating a wheel…
> * Getting build dependencies for wheel…
>
> ERROR Missing dependencies:
> poetry>=0.12
> poetry-core==1.8.1
> poetry>=0.12
> fastjsonschema<3.0.0,>=2.18.0
For full logs, run ‘nix-store -l /nix/store/vlbsnbir370gaa0jh47dm0rg9cv1nj71-python3.11-uniswap-python.drv’.

This is because you’re running an older version of NixOS, so the shell is trying to use your system packages, which are out of date.

You have a few options to solve this:

Use unstable channel

Perhaps the most straightforward way is to change the nixpkgs channel to the unstable branch. This way the build script will use the latest packages available.

let
  nixpkgs = fetchTarball "https://github.com/NixOS/nixpkgs/tarball/nixos-unstable";
  pkgs = import nixpkgs { };
in

with pkgs;
let
  uni-py = pkgs.python3Packages.buildPythonPackage rec {
    name = "uniswap-python";
    version = "v0.7.1";

    src = pkgs.fetchFromGitHub {
    ...

If you want more reproducibility, you can pin a specific nixpkgs version by specifying the channel commit. For example

-  nixpkgs = fetchTarball "https://github.com/NixOS/nixpkgs/tarball/nixos-unstable";
+  nixpkgs = fetchTarball "https://github.com/NixOS/nixpkgs/tarball/4cba8b53da471aea2ab2b0c1f30a81e7c451f4b6";

Where 4cba8b53da471aea2ab2b0c1f30a81e7c451f4b6 is the latest nixos-unstable commit at the time of writing this post.

Use flakes with direnv

The disadvantage with the method above is that once you run garbage collection on your system, the cache for this project will get removed and you will need to download the channel and packages again.

To prevent this we’re gonna use flakes with nix-direnv. First, install nix-direnv to your system, then run the following command in the project directory:

$ nix flake new -t github:nix-community/nix-direnv .

It will ask if you want to install some extra stuff but you can just keep hitting enter to skip them.

Next, edit the newly created flake.nix and set the channel and the shell we want it to run by default:

{
  description = "Building uniswap-python";
  inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; # <---
  inputs.flake-utils.url = "github:numtide/flake-utils";

  outputs = { nixpkgs, flake-utils, ... }:
    flake-utils.lib.eachDefaultSystem (system:
      let
        pkgs = nixpkgs.legacyPackages.${system};
      in
      {
        devShells.default = import ./shell.nix { inherit pkgs; }; # <---
      });
}

Now, we need to tell the shell where the packages are gonna come from, so edit shell.nix and add:

{ pkgs ? (
    let
      inherit (builtins) fetchTree fromJSON readFile;
      inherit ((fromJSON (readFile ./flake.lock)).nodes) nixpkgs flake-utils;
    in
    import (fetchTree nixpkgs.locked)
  )
}:

with pkgs;
let
  uni-py = pkgs.python3Packages.buildPythonPackage rec {
    name = "uniswap-python";
    version = "v0.7.1";
    ...

Finally, run the following command to activate the environment:

$ direnv allow

The shell should execute automatically (because it’s the default) and you should see the following message each time you enter the project directory:

direnv: loading <project-path>/.envrc
direnv: using flake
direnv: nix-direnv: using cached dev shell
Whatever makes this happen.

Also, if you check flake.lock you’ll see that each input, including the NixOS channel, is pinned to a specific version, which makes the project more reproducible.

In order to update the versions, all we have to do is run the following command:

$ nix flake update

Whether you use shells directly or flakes, I recommend to always version control your project. In case anything breaks in the future, you can always roll back to a version you’re sure that works.

Now, we can make other shells depending on what we want to do. For example, I made another shell where I replaced the message with “Hello, world”:

        devShells.default = import ./shell.nix { inherit pkgs; };
        devShells.hello = import ./hello.nix { inherit pkgs; };

Since it’s not the default, we need to run it manually with:

$ nix develop .#hello
Hello, World!

PS: If you’ve noticed, there is a new directory called .direnv. This ensures that the channels and packages you use in your project don’t get cleaned up when you run the garbage collector.

If you do want that to happen (for example you no longer work on the project), just delete that directory and run the garbage collector.

Extra: You can add the following scripts to your shell to quickly use direnv.

Everything should work correctly now. If it doesn’t, don’t hesitate to ask again :grin:

1 Like