poetry2nix/vendor/pyproject.nix/lib/renderers.nix
2023-10-26 17:02:10 +13:00

147 lines
4.8 KiB
Nix

{ lib
, pep508
, pep621
, ...
}:
let
inherit (builtins) attrValues length attrNames head foldl';
inherit (lib) optionalAttrs flatten mapAttrs' filterAttrs;
# Group licenses by their SPDX IDs for easy lookup
licensesBySpdxId = mapAttrs'
(_: license: {
name = license.spdxId;
value = license;
})
(filterAttrs (_: license: license ? spdxId) lib.licenses);
in
{
/*
Renders a project as an argument that can be passed to withPackages
Evaluates PEP-508 environment markers to select correct dependencies for the platform but does not validate version constraints.
For validation see `lib.validators`.
Type: withPackages :: AttrSet -> lambda
Example:
# withPackages (lib.project.loadPyproject { ... })
«lambda @ «string»:1:1»
*/
withPackages =
{
# Project metadata as returned by `lib.project.loadPyproject`
project
, # Python derivation
python
, # Python extras (optionals) to enable
extras ? [ ]
,
}:
let
filteredDeps = pep621.filterDependencies {
inherit (project) dependencies;
environ = pep508.mkEnviron python;
inherit extras;
};
namedDeps = pep621.getDependenciesNames filteredDeps;
flatDeps = namedDeps.dependencies ++ flatten (attrValues namedDeps.extras) ++ namedDeps.build-systems;
in
ps: map (dep: ps.${dep}) flatDeps;
/*
Renders a project as an argument that can be passed to buildPythonPackage/buildPythonApplication.
Evaluates PEP-508 environment markers to select correct dependencies for the platform but does not validate version constraints.
For validation see `lib.validators`.
Type: buildPythonPackage :: AttrSet -> AttrSet
Example:
# buildPythonPackage { project = lib.project.loadPyproject ...; python = pkgs.python3; }
{ pname = "blinker"; version = "1.3.3.7"; propagatedBuildInputs = [ ]; }
*/
buildPythonPackage =
{
# Project metadata as returned by `lib.project.loadPyproject`
project
, # Python derivation
python
, # Python extras (optionals) to enable
extras ? [ ]
, # Map a Python extras group name to a Nix attribute set.
# This is intended to be used with optionals such as test dependencies that you might
# want to add to checkInputs instead of propagatedBuildInputs
extrasAttrMappings ? { }
, # Which package format to pass to buildPythonPackage
# If the format is "wheel" PEP-518 build-systems are excluded from the build.
format ? "pyproject"
}:
let
filteredDeps = pep621.filterDependencies {
inherit (project) dependencies;
environ = pep508.mkEnviron python;
inherit extras;
};
namedDeps = pep621.getDependenciesNames filteredDeps;
inherit (project) pyproject;
meta =
let
project' = project.pyproject.project;
urls = project'.urls or { };
in
# Optional changelog
optionalAttrs (urls ? changelog)
{
inherit (urls) changelog;
} //
# Optional description
optionalAttrs (project' ? description) {
inherit (project') description;
} //
# Optional license
optionalAttrs (project'.license ? text) (
assert !(project'.license ? file); {
# From PEP-621:
# "The text key has a string value which is the license of the project whose meaning is that of the License field from the core metadata.
# These keys are mutually exclusive, so a tool MUST raise an error if the metadata specifies both keys."
# Hence the assert above.
license = licensesBySpdxId.${project'.license.text};
}
) //
# Only set mainProgram if we only have one script, otherwise it's ambigious which one is main
(
let
scriptNames = attrNames project'.scripts;
in
optionalAttrs (project' ? scripts && length scriptNames == 1) {
mainProgram = head scriptNames;
}
);
in
foldl'
(attrs: group:
let
attr = extrasAttrMappings.${group} or "propagatedBuildInputs";
in
attrs // {
${attr} = attrs.${attr} or [ ] ++ map (dep: python.pkgs.${dep}) namedDeps.extras.${group};
})
({
propagatedBuildInputs = map (dep: python.pkgs.${dep}) namedDeps.dependencies;
inherit format meta;
} // optionalAttrs (format != "wheel") {
nativeBuildInputs = map (dep: python.pkgs.${dep}) namedDeps.build-systems;
} // optionalAttrs (pyproject.project ? name) {
pname = pyproject.project.name;
}
// optionalAttrs (pyproject.project ? version) {
inherit (pyproject.project) version;
})
(attrNames namedDeps.extras);
}