From 8cd58c7e149bc85af98d1697426a2ac5019ece29 Mon Sep 17 00:00:00 2001 From: adisbladis Date: Thu, 29 Aug 2024 20:38:30 +1200 Subject: [PATCH] python3Packages.mkPythonMetaPackage: init This function exists create a meta package containing [metadata files](https://packaging.python.org/en/latest/specifications/recording-installed-packages/) to satisfy a dependency on a package, without it actually having been installed into the environment. --- doc/languages-frameworks/python.section.md | 13 +++++ .../interpreters/python/meta-package.nix | 58 +++++++++++++++++++ .../python/python-packages-base.nix | 3 + 3 files changed, 74 insertions(+) create mode 100644 pkgs/development/interpreters/python/meta-package.nix diff --git a/doc/languages-frameworks/python.section.md b/doc/languages-frameworks/python.section.md index 8992d36fb25b..ce83102acd84 100644 --- a/doc/languages-frameworks/python.section.md +++ b/doc/languages-frameworks/python.section.md @@ -361,6 +361,19 @@ modifications. Do pay attention to passing in the right Python version! +#### `mkPythonMetaPackage` function {#mkpythonmetapackage-function} + +This will create a meta package containing [metadata files](https://packaging.python.org/en/latest/specifications/recording-installed-packages/) to satisfy a dependency on a package, without it actually having been installed into the environment. +In nixpkgs this is used to package Python packages with split binary/source distributions such as [psycopg2](https://pypi.org/project/psycopg2/)/[psycopg2-binary](https://pypi.org/project/psycopg2-binary/). + +```nix +mkPythonMetaPackage { + pname = "pscycopg2-binary"; + inherit (psycopg2) optional-dependencies version meta; + dependencies = [ psycopg2 ]; +} +``` + #### `python.buildEnv` function {#python.buildenv-function} Python environments can be created using the low-level `pkgs.buildEnv` function. diff --git a/pkgs/development/interpreters/python/meta-package.nix b/pkgs/development/interpreters/python/meta-package.nix new file mode 100644 index 000000000000..2e25dff85fe0 --- /dev/null +++ b/pkgs/development/interpreters/python/meta-package.nix @@ -0,0 +1,58 @@ +{ + buildPythonPackage, + lib, + hatchling, +}: +{ + pname, + version, + dependencies ? [ ], + optional-dependencies ? { }, + passthru ? { }, + meta ? { }, +}: + +# Create a "fake" meta package to satisfy a dependency on a package, but don't actually build it. +# This is useful for packages that have a split binary/source dichotomy like psycopg2/psycopg2-binary, +# where we want to use the former, but some projects declare a dependency on the latter. + +buildPythonPackage { + inherit + pname + version + dependencies + optional-dependencies + meta + passthru + ; + + pyproject = true; + + # Make a minimal pyproject.toml that can be built + unpackPhase = '' + cat > pyproject.toml << EOF + [project] + name = "${pname}" + version = "${version}" + dependencies = ${builtins.toJSON (map lib.getName dependencies)} + + [project.optional-dependencies] + ${lib.optionalString (optional-dependencies != { }) ( + (lib.concatStringsSep "\n" ( + lib.mapAttrsToList ( + group: deps: group + " = " + builtins.toJSON (map lib.getName deps) + ) optional-dependencies + )) + )} + + [tool.hatch.build.targets.wheel] + bypass-selection = true + + [build-system] + requires = ["hatchling"] + build-backend = "hatchling.build" + EOF + ''; + + build-system = [ hatchling ]; +} diff --git a/pkgs/development/interpreters/python/python-packages-base.nix b/pkgs/development/interpreters/python/python-packages-base.nix index a807b6e6e33c..edd0937098b6 100644 --- a/pkgs/development/interpreters/python/python-packages-base.nix +++ b/pkgs/development/interpreters/python/python-packages-base.nix @@ -61,6 +61,8 @@ let removePythonPrefix = lib.removePrefix namePrefix; + mkPythonMetaPackage = callPackage ./meta-package.nix { }; + # Convert derivation to a Python module. toPythonModule = drv: drv.overrideAttrs( oldAttrs: { @@ -97,6 +99,7 @@ in { inherit buildPythonPackage buildPythonApplication; inherit hasPythonModule requiredPythonModules makePythonPath disabled disabledIf; inherit toPythonModule toPythonApplication; + inherit mkPythonMetaPackage; python = toPythonModule python;