From 1ced979707eaa26b248399862267b043b175eec0 Mon Sep 17 00:00:00 2001 From: Doron Behar Date: Sun, 20 Aug 2023 15:20:21 +0300 Subject: [PATCH] Add nix files & relax rpyc dep versions --- .envrc | 1 + .gitignore | 2 + aiopath/default.nix | 33 +++ app-paths/default.nix | 36 +++ flake.lock | 167 +++++++++++++ flake.nix | 277 +++++++++++++++++++++ linien-client/pkg.nix | 33 +++ linien-common/pkg.nix | 41 +++ linien-gui/pkg.nix | 70 ++++++ linien-server/linien_server/linien.service | 2 +- linien-server/pkg.nix | 51 ++++ mdio-tool.nix | 22 ++ pyrp3/default.nix | 49 ++++ unpackable/default.nix | 26 ++ 14 files changed, 809 insertions(+), 1 deletion(-) create mode 100644 .envrc create mode 100644 aiopath/default.nix create mode 100644 app-paths/default.nix create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 linien-client/pkg.nix create mode 100644 linien-common/pkg.nix create mode 100644 linien-gui/pkg.nix create mode 100644 linien-server/pkg.nix create mode 100644 mdio-tool.nix create mode 100644 pyrp3/default.nix create mode 100644 unpackable/default.nix diff --git a/.envrc b/.envrc new file mode 100644 index 00000000..3550a30f --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use flake diff --git a/.gitignore b/.gitignore index c29f0273..97efc395 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,5 @@ share/python-wheels/ .installed.cfg *.egg MANIFEST +# Nix build symlinks +result* diff --git a/aiopath/default.nix b/aiopath/default.nix new file mode 100644 index 00000000..b75038e6 --- /dev/null +++ b/aiopath/default.nix @@ -0,0 +1,33 @@ +{ lib +, src +, version +, buildPythonPackage +, anyio +, aiofile +}: + +buildPythonPackage { + pname = "aiopath"; + inherit version; + + inherit src; + + propagatedBuildInputs = [ + anyio + aiofile + ]; + # Tests require a module that is deprecated, and is not packaged in Nixpkgs, + # named: asynctempfile. URL: https://github.com/alemigo/asynctempfile . + # Ideally upstream would adopt less obscure dependencies. + doCheck = false; + + pythonImportsCheck = [ + "aiopath" + ]; + + meta = with lib; { + description = "A complete implementation of Python's pathlib that's compatible with asyncio, trio, and the async/await syntax"; + homepage = "https://github.com/alexdelorenzo/aiopath"; + license = licenses.lgpl3Plus; + }; +} diff --git a/app-paths/default.nix b/app-paths/default.nix new file mode 100644 index 00000000..4869874e --- /dev/null +++ b/app-paths/default.nix @@ -0,0 +1,36 @@ +{ lib +, src +, version +, buildPythonPackage +, setuptools +, unpackable +, asyncstdlib +, appdirs +, aiopath +, strenum +}: + +buildPythonPackage { + pname = "app-paths"; + inherit version; + + inherit src; + + pythonImportsCheck = [ + "app_paths" + ]; + + propagatedBuildInputs = [ + unpackable + asyncstdlib + appdirs + aiopath + strenum + ]; + + meta = with lib; { + description = "Like appdirs, but with pathlib, path creation and async support"; + homepage = "https://github.com/alexdelorenzo/app_paths"; + license = licenses.lgpl3Plus; + }; +} diff --git a/flake.lock b/flake.lock new file mode 100644 index 00000000..6fdfb5bc --- /dev/null +++ b/flake.lock @@ -0,0 +1,167 @@ +{ + "nodes": { + "aiopath": { + "flake": false, + "locked": { + "lastModified": 1666918137, + "narHash": "sha256-29b4YQkDQNtIKQWYQckhdnMfjJ8Tr0H6OupI1TiLLT8=", + "owner": "alexdelorenzo", + "repo": "aiopath", + "rev": "f381224d6262c2523c0e38de4feb18657015efcb", + "type": "github" + }, + "original": { + "owner": "alexdelorenzo", + "repo": "aiopath", + "type": "github" + } + }, + "app-paths": { + "flake": false, + "locked": { + "lastModified": 1631410001, + "narHash": "sha256-RSSn0UUl9haAqVGtCcuuM3AQM9FvD96uC+0pL/9No7o=", + "owner": "alexdelorenzo", + "repo": "app_paths", + "rev": "02fe3c1019ee0bb708620867a220491267ebd4b9", + "type": "github" + }, + "original": { + "owner": "alexdelorenzo", + "repo": "app_paths", + "type": "github" + } + }, + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1689068808, + "narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "gitignore": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1660459072, + "narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=", + "owner": "hercules-ci", + "repo": "gitignore.nix", + "rev": "a20de23b925fd8264fd7fad6454652e142fd7f73", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "gitignore.nix", + "type": "github" + } + }, + "mdio-tool": { + "flake": false, + "locked": { + "lastModified": 1549466461, + "narHash": "sha256-NNLFmYzd1trh/9b90r+OdE/FloNQpMzsTgur49Ep4A0=", + "owner": "linien-org", + "repo": "mdio-tool", + "rev": "72bd5a915ff046a59ce4303c8de672e77622a86c", + "type": "github" + }, + "original": { + "owner": "linien-org", + "repo": "mdio-tool", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1692447944, + "narHash": "sha256-fkJGNjEmTPvqBs215EQU4r9ivecV5Qge5cF/QDLVn3U=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "d680ded26da5cf104dd2735a51e88d2d8f487b4d", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "pyrp3": { + "flake": false, + "locked": { + "lastModified": 1688557073, + "narHash": "sha256-43TTlpJ5SMAjQM71bNVvrWQyciRXM3zpuA/Dw41AEgU=", + "owner": "linien-org", + "repo": "pyrp3", + "rev": "4744ec814acf0478ec0f3198bd97e077d9825350", + "type": "github" + }, + "original": { + "owner": "linien-org", + "repo": "pyrp3", + "type": "github" + } + }, + "root": { + "inputs": { + "aiopath": "aiopath", + "app-paths": "app-paths", + "flake-utils": "flake-utils", + "gitignore": "gitignore", + "mdio-tool": "mdio-tool", + "nixpkgs": "nixpkgs", + "pyrp3": "pyrp3", + "unpackable": "unpackable" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "unpackable": { + "flake": false, + "locked": { + "lastModified": 1643253876, + "narHash": "sha256-7wTMpcPhWosxKxllPk3a6mz0lJp5VhS1nJg+aDH1U2s=", + "owner": "alexdelorenzo", + "repo": "unpackable", + "rev": "d685ae9be0040d6020cdda6de9225e6d3c210ef6", + "type": "github" + }, + "original": { + "owner": "alexdelorenzo", + "repo": "unpackable", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 00000000..72259592 --- /dev/null +++ b/flake.nix @@ -0,0 +1,277 @@ +{ + description = "Spectroscopy lock application using RedPitaya"; + + # Updating this triggers a lot of rebuilds, since scipy has many dependents, + # prepare yourself before updating. + inputs.nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; + inputs.flake-utils.url = "github:numtide/flake-utils"; + inputs.gitignore = { + url = "github:hercules-ci/gitignore.nix"; + # Use the same nixpkgs + inputs.nixpkgs.follows = "nixpkgs"; + }; + inputs.pyrp3 = { + url = "github:linien-org/pyrp3"; + flake = false; + }; + inputs.mdio-tool = { + url = "github:linien-org/mdio-tool"; + flake = false; + }; + # Ideally the rest of these python deps should be part of nixpkgs. See also: + # https://github.com/alexdelorenzo/app_paths/issues/1 + inputs.app-paths = { + url = "github:alexdelorenzo/app_paths"; + flake = false; + }; + inputs.unpackable = { + url = "github:alexdelorenzo/unpackable"; + flake = false; + }; + inputs.aiopath = { + url = "github:alexdelorenzo/aiopath"; + flake = false; + }; + + outputs = { self + , nixpkgs + , flake-utils + , gitignore + , pyrp3 + , app-paths + , unpackable + , aiopath + , mdio-tool + }: + flake-utils.lib.eachDefaultSystem (system: + let + # Credit @kranzes <3: https://github.com/NixOS/nix/issues/8163#issuecomment-1517774089 + flakeDate2human = flakeInput: builtins.concatStringsSep "-" (builtins.match "(.{4})(.{2})(.{2}).*" flakeInput.lastModifiedDate); + # Generate a `python` interpreter, with some python packages overriden + # and added - we merge the pythonOverrides of scipy-fork as well. We use + # lib.composeExtensions as instructed here: + # https://github.com/NixOS/nixpkgs/issues/44426 + lockFile = builtins.fromJSON (builtins.readFile ./flake.lock); + pkgs = import nixpkgs { + inherit system; + overlays = [ + (self: super: { + mdio-tool = self.callPackage ./mdio-tool.nix { + src = self.fetchFromGitHub { + inherit (lockFile.nodes.mdio-tool.original) + owner + repo + ; + sha256 = lockFile.nodes.mdio-tool.locked.narHash; + rev = lockFile.nodes.mdio-tool.locked.rev; + }; + version = flakeDate2human mdio-tool; + }; + }) + ]; + }; + inherit (pkgs) lib; + pythonDevEnv = (python.withPackages(ps: builtins.attrValues { + inherit (ps) + app-paths + click + cma + matplotlib + migen + misoc + myhdl + numpy + paramiko + plumbum + pylpsd + pyqt5 + pyqtgraph + pyrp3 + pytestCheckHook + pytest-plt + rpyc + superqt + scipy # From our fork + # For text editor + jedi-language-server + debugpy + # For testing installations + setuptools + setuptools-scm + ; + })).overrideAttrs (old: { + meta = old.meta // { + description = "Linien Python development environment"; + }; + }); + inherit (gitignore.lib) gitignoreFilterWith; + get-src = subdirectory: lib.cleanSourceWith { + filter = gitignoreFilterWith { + basePath = ./.; + extraRules = '' + flake* + ''; + }; + src = "${self}/${subdirectory}"; + }; + get-github-src = pname: pkgs.fetchFromGitHub { + inherit (lockFile.nodes.${pname}.original) + owner + repo + ; + sha256 = lockFile.nodes.${pname}.locked.narHash; + rev = lockFile.nodes.${pname}.locked.rev; + }; + linienBuildArgs = { + version = (builtins.fromJSON (builtins.readFile ./version-info.json)).latest; + }; + pythonOverrides = lib.composeExtensions + # Empty override, may be useful in the future + (selfPython: superPython: {}) + (selfPython: superPython: { + linien-gui = superPython.python.pkgs.callPackage ./linien-gui/pkg.nix (linienBuildArgs // { + src = get-src "linien-gui"; + inherit (selfPython) + linien-client + pyqtgraph + app-paths + ; + }); + linien-client = superPython.python.pkgs.callPackage ./linien-client/pkg.nix (linienBuildArgs // { + src = get-src "linien-client"; + inherit (selfPython) + linien-common + ; + }); + linien-common = superPython.python.pkgs.callPackage ./linien-common/pkg.nix (linienBuildArgs // { + src = get-src "linien-common"; + }); + linien-server = superPython.python.pkgs.callPackage ./linien-server/pkg.nix (linienBuildArgs // { + src = get-src "linien-server"; + inherit (selfPython) + linien-common + pylpsd + pyrp3 + ; + inherit (selfPython.python.pkgs.pkgs) mdio-tool; + }); + pyrp3 = superPython.python.pkgs.callPackage ./pyrp3 { + src = get-github-src "pyrp3"; + version = flakeDate2human pyrp3; + }; + app-paths = superPython.python.pkgs.callPackage ./app-paths { + src = get-github-src "app-paths"; + version = flakeDate2human app-paths; + inherit (selfPython) + unpackable + aiopath + ; + }; + unpackable = superPython.python.pkgs.callPackage ./unpackable { + src = get-github-src "unpackable"; + version = flakeDate2human unpackable; + }; + aiopath = superPython.python.pkgs.callPackage ./aiopath { + src = get-github-src "aiopath"; + version = flakeDate2human aiopath; + }; + }) + ; + python = (pkgs.python3.override { + packageOverrides = pythonOverrides; + }).overrideAttrs(old: { + meta = old.meta // { + description = "Python interpreter with .pkgs set including linien"; + }; + }); + python-armv7l-hf-multiplatform = (pkgs.pkgsCross.armv7l-hf-multiplatform.python3.override { + packageOverrides = pythonOverrides; + }).overrideAttrs(old: { + meta = old.meta // { + description = "Python interpreter (cross compiled) with .pkgs set including linien"; + }; + }); + buildDeb = {pkg, targetArch, pkgName ? pkg.name}: pkgs.stdenv.mkDerivation { + name = "${pkg.name}.deb"; + buildInputs = [ + pkgs.dpkg + ]; + unpackPhase = "true"; + buildPhase = '' + export HOME=$PWD + mkdir -p pkgtree/nix/store/ + for item in "$(cat ${pkgs.referencesByPopularity pkg})"; do + cp -r $item pkgtree/nix/store/ + done + + mkdir -p pkgtree/bin + cp -r ${pkg}/bin/* pkgtree/bin/ + mkdir -p pkgtree/lib + cp -r ${pkg}/lib/systemd pkgtree/lib/ + + chmod -R a+rwx pkgtree/nix + chmod -R a+rwx pkgtree/bin + mkdir pkgtree/DEBIAN + cat << EOF > pkgtree/DEBIAN/control + Package: ${pkgName} + Version: ${pkg.version} + Maintainer: "github.com/bleykauf" + '' + # TODO: Ideally we would parse `pkgs.stdenv.gcc.arch` or a similar + # attribute and use this argument such that dpkg-deb will be + # satisfied with our name of the platform. + + '' + Architecture: ${targetArch} + Description: ${pkg.meta.description} + EOF + ''; + installPhase = '' + dpkg-deb -b pkgtree + mv pkgtree.deb $out + ''; + meta = { + description = "Debian package of ${pkg.name} compiled for architecture ${targetArch}"; + }; + }; + in { + devShells = { + default = pkgs.mkShell { + nativeBuildInputs = [ + pythonDevEnv + # To inspect deb packages we build, using: + # + # dpkg --contents $(nix build --print-out-paths -L .\#linien-server-deb-armv7l-hf-multiplatform)` + pkgs.dpkg + # To manage linien.bin + pkgs.git-lfs + ]; + }; + }; + packages = { + # Put it here so it'll be easy to run commands such as: + # + # nix why-depends --all --derivation .\#python.pkgs.linien-gui .\#nixpkgs-python.pkgs.scipy + # + nixpkgs-python = pkgs.python3; + inherit pythonDevEnv; + inherit (pkgs) mdio-tool; + mdio-tool-static = pkgs.pkgsCross.armv7l-hf-multiplatform.pkgsStatic.mdio-tool; + # The server is built for debian only, so we don't inherit it here + inherit (python.pkgs) + linien-common + linien-client + linien-gui + ; + inherit + python + python-armv7l-hf-multiplatform + ; + linien-server-deb-armv7l-hf-multiplatform = buildDeb { + pkg = python-armv7l-hf-multiplatform.pkgs.linien-server; + targetArch = "armhf"; + pkgName = "linien-server"; + }; + }; + } + ); +} diff --git a/linien-client/pkg.nix b/linien-client/pkg.nix new file mode 100644 index 00000000..b6b3cfc4 --- /dev/null +++ b/linien-client/pkg.nix @@ -0,0 +1,33 @@ +{ lib +, buildPythonPackage +, version +, src +, fabric +, numpy +, typing-extensions +, linien-common +}: + +buildPythonPackage { + pname = "linien-client"; + inherit version; + + inherit src; + + propagatedBuildInputs = [ + fabric + numpy + typing-extensions + linien-common + ]; + + pythonImportsCheck = [ + "linien_client" + ]; + + meta = with lib; { + description = "Client components of the Linien spectroscopy lock application"; + homepage = "https://github.com/linien-org/linien"; + license = licenses.gpl3; + }; +} diff --git a/linien-common/pkg.nix b/linien-common/pkg.nix new file mode 100644 index 00000000..d790f4ab --- /dev/null +++ b/linien-common/pkg.nix @@ -0,0 +1,41 @@ +{ lib +, buildPythonPackage +, version +, src +, numpy +, scipy +, importlib-metadata +, rpyc +, appdirs +}: + +buildPythonPackage { + pname = "linien-common"; + inherit version; + + inherit src; + + propagatedBuildInputs = [ + numpy + scipy + importlib-metadata + rpyc + appdirs + ]; + # https://github.com/linien-org/pyrp3/pull/10#pullrequestreview-1585887668 + # From some reason pythonRelaxDepsHook doesn't work here + preConfigure = '' + substituteInPlace setup.py \ + --replace "rpyc>=4.0,<5.0" rpyc + ''; + + pythonImportsCheck = [ + "linien_common" + ]; + + meta = with lib; { + description = "Shared components of the Linien spectroscopy lock application"; + homepage = "https://github.com/linien-org/linien"; + license = licenses.gpl3; + }; +} diff --git a/linien-gui/pkg.nix b/linien-gui/pkg.nix new file mode 100644 index 00000000..a096b290 --- /dev/null +++ b/linien-gui/pkg.nix @@ -0,0 +1,70 @@ +{ lib +, buildPythonPackage +, version +, src +, pyqtgraph +, pyqt5 +, superqt +, click +, linien-client +, qt5 +, makeDesktopItem +, copyDesktopItems +, graphicsmagick +, app-paths +}: + +buildPythonPackage rec { + pname = "linien-gui"; + inherit version; + + inherit src; + + buildInputs = [ + qt5.qtbase + qt5.qtwayland + ]; + + propagatedBuildInputs = [ + app-paths + pyqtgraph + pyqt5 + superqt + click + linien-client + ]; + + nativeBuildInputs = [ + qt5.wrapQtAppsHook + copyDesktopItems + graphicsmagick + ]; + preFixup = '' + makeWrapperArgs+=("''${qtWrapperArgs[@]}") + ''; + desktopItems = makeDesktopItem { + name = meta.mainProgram; + exec = meta.mainProgram; + icon = meta.mainProgram; + desktopName = meta.mainProgram; + comment = meta.description; + type = "Application"; + categories = [ "Science" ]; + }; + + postInstall = '' + mkdir -p $out/share/icons/hicolor/256x256/apps/ + gm convert linien_gui/icon.ico $out/share/icons/hicolor/256x256/apps/${meta.mainProgram}.png + ''; + + pythonImportsCheck = [ + "linien_gui" + ]; + + meta = with lib; { + description = "Graphical user interface of the Linien spectroscopy lock application"; + homepage = "https://github.com/linien-org/linien"; + license = licenses.gpl3; + mainProgram = "linien"; + }; +} diff --git a/linien-server/linien_server/linien.service b/linien-server/linien_server/linien.service index b62955a4..d1d1174f 100644 --- a/linien-server/linien_server/linien.service +++ b/linien-server/linien_server/linien.service @@ -5,7 +5,7 @@ Wants=network-online.target After=network-online.target [Service] -ExecStart=/usr/bin/env python3 /usr/lib/python3.10/site-packages/linien/server/server.py +ExecStart=/usr/bin/linien-server # stop / start ethernet blinking using: mdio-tool[1], see: # https://github.com/RedPitaya/RedPitaya/issues/205 # diff --git a/linien-server/pkg.nix b/linien-server/pkg.nix new file mode 100644 index 00000000..72afc1d5 --- /dev/null +++ b/linien-server/pkg.nix @@ -0,0 +1,51 @@ +{ lib +, buildPythonPackage +, version +, src +, click +, cma +, pylpsd +, pyrp3 +, rpyc +, linien-common +, requests +, mdio-tool +, python +}: + +buildPythonPackage { + pname = "linien-server"; + inherit version; + + inherit src; + + propagatedBuildInputs = [ + click + cma + pylpsd + pyrp3 + rpyc + linien-common + requests + ]; + postInstall = '' + # Not needed in declarative Nix installations + rm $out/bin/linien_install_requirements.sh + rm $out/${python.sitePackages}/linien_server/linien_install_requirements.sh + mkdir -p $out/lib/systemd/system + mv $out/${python.sitePackages}/linien_server/linien.service $out/lib/systemd/system/linien.service + substituteInPlace $out/lib/systemd/system/linien.service \ + --replace /usr/bin/mdio-tool ${mdio-tool}/bin/mdio-tool \ + --replace /usr/bin/linien-server $out/bin/linien-server + ''; + + pythonImportsCheck = [ + "linien_server" + ]; + + meta = with lib; { + description = "Server components of the Linien spectroscopy lock application"; + homepage = "https://github.com/linien-org/linien"; + license = licenses.gpl3; + }; +} diff --git a/mdio-tool.nix b/mdio-tool.nix new file mode 100644 index 00000000..77f0e937 --- /dev/null +++ b/mdio-tool.nix @@ -0,0 +1,22 @@ +{ lib +, stdenv +, src +, version +, cmake +}: + +stdenv.mkDerivation { + pname = "mdio-tool"; + inherit version src; + + nativeBuildInputs = [ + cmake + ]; + + meta = with lib; { + description = "A tool to read and write MII registers from ethernet physicals under linux"; + homepage = "https://github.com/linien-org/mdio-tool"; + license = licenses.gpl2Plus; + platforms = platforms.linux; + }; +} diff --git a/pyrp3/default.nix b/pyrp3/default.nix new file mode 100644 index 00000000..a5f5c1e6 --- /dev/null +++ b/pyrp3/default.nix @@ -0,0 +1,49 @@ +{ lib +, src +, version +, buildPythonPackage +, setuptools +, importlib-metadata +, myhdl +, rpyc +, cached-property +, numpy +}: + +buildPythonPackage { + pname = "pyrp3"; + inherit version; + format = "pyproject"; + + inherit src; + + pythonImportsCheck = [ + "pyrp3" + "pyrp3.board" + ]; + # https://github.com/linien-org/pyrp3/pull/10#pullrequestreview-1585887668 + # From some reason pythonRelaxDepsHook doesn't work here + preConfigure = '' + substituteInPlace setup.py \ + --replace "rpyc>=4.0,<5.0" rpyc + ''; + + nativeBuildInputs = [ + setuptools + ]; + + propagatedBuildInputs = [ + importlib-metadata + myhdl + rpyc + cached-property + numpy + ]; + + meta = with lib; { + description = "Python 3 port of PyRedPitaya library providing access to Red Pitaya registers"; + homepage = "https://github.com/linien-org/pyrp3"; + license = licenses.bsd3; + platforms = platforms.linux; + }; +} diff --git a/unpackable/default.nix b/unpackable/default.nix new file mode 100644 index 00000000..0f1d79ac --- /dev/null +++ b/unpackable/default.nix @@ -0,0 +1,26 @@ +{ lib +, src +, version +, buildPythonPackage +}: + +buildPythonPackage { + pname = "unpackable"; + inherit version; + + inherit src; + + pythonImportsCheck = [ + "unpackable" + ]; + # See also https://github.com/alexdelorenzo/unpackable/commit/d685ae9be0040d6020cdda6de9225e6d3c210ef6 + preConfigure = '' + sed -i /varname/d requirements.txt + ''; + + meta = with lib; { + description = "A module that lets you use Python's destructuring assignment to unpack an object's attributes."; + homepage = "https://github.com/alexdelorenzo/unpackable"; + license = licenses.lgpl3Plus; + }; +}