Skip to content

Commit

Permalink
python3Packages.mkPythonMetaPackage: init
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
adisbladis committed Aug 29, 2024
1 parent ee2a36d commit 8cd58c7
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 0 deletions.
13 changes: 13 additions & 0 deletions doc/languages-frameworks/python.section.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
58 changes: 58 additions & 0 deletions pkgs/development/interpreters/python/meta-package.nix
Original file line number Diff line number Diff line change
@@ -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 ];
}
3 changes: 3 additions & 0 deletions pkgs/development/interpreters/python/python-packages-base.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand Down Expand Up @@ -97,6 +99,7 @@ in {
inherit buildPythonPackage buildPythonApplication;
inherit hasPythonModule requiredPythonModules makePythonPath disabled disabledIf;
inherit toPythonModule toPythonApplication;
inherit mkPythonMetaPackage;

python = toPythonModule python;

Expand Down

0 comments on commit 8cd58c7

Please sign in to comment.