mirror of
https://github.com/nix-community/dream2nix.git
synced 2024-11-25 03:35:55 +03:00
python/pdm: several improvements
- infer build-systems from pyproject.toml - add more generic getClosure lib function to get the closure of any given dependency + extra - resolve extras correctly for each computed closure - overhaul some of the existing tests
This commit is contained in:
parent
916bca75a1
commit
3f6c7cbd80
@ -32,6 +32,10 @@
|
||||
parsed_lock_data = libpdm.parseLockData {
|
||||
inherit environ lock_data;
|
||||
};
|
||||
buildSystemNames =
|
||||
map
|
||||
(name: (libpyproject.pep508.parseString name).name)
|
||||
(pyproject.pyproject.build-system.requires or []);
|
||||
in {
|
||||
imports = [
|
||||
dream2nix.modules.dream2nix.WIP-groups
|
||||
@ -66,6 +70,7 @@ in {
|
||||
format = lib.mkDefault "pyproject";
|
||||
};
|
||||
mkDerivation = {
|
||||
buildInputs = map (name: config.deps.python3.pkgs.${name}) buildSystemNames;
|
||||
propagatedBuildInputs =
|
||||
map
|
||||
(x: (lib.head (lib.attrValues x)).public)
|
||||
@ -73,13 +78,16 @@ in {
|
||||
(lib.attrValues config.groups.default.packages);
|
||||
};
|
||||
groups = let
|
||||
populateGroup = groupname: deps: let
|
||||
deps' = libpdm.selectForGroups {
|
||||
groupNames = lib.attrNames groups_with_deps;
|
||||
populateGroup = groupname: let
|
||||
# Get transitive closure for specific group.
|
||||
# The 'default' group is always included no matter the selection.
|
||||
transitiveGroupDeps = libpdm.closureForGroups {
|
||||
inherit parsed_lock_data groups_with_deps;
|
||||
groupNames = lib.unique ["default" groupname];
|
||||
};
|
||||
|
||||
packages = lib.flip lib.mapAttrs deps' (name: pkg: {
|
||||
packages = lib.flip lib.mapAttrs transitiveGroupDeps (name: pkg: {
|
||||
${pkg.version}.module = {...} @ depConfig: let
|
||||
selector =
|
||||
if lib.isFunction depConfig.config.sourceSelector
|
||||
@ -108,20 +116,20 @@ in {
|
||||
};
|
||||
mkDerivation = {
|
||||
# required: { pname, file, version, hash, kind, curlOpts ? "" }:
|
||||
src = libpyproject-fetchers.fetchFromPypi {
|
||||
src = lib.mkDefault (libpyproject-fetchers.fetchFromPypi {
|
||||
pname = name;
|
||||
file = source.file;
|
||||
version = pkg.version;
|
||||
hash = source.hash;
|
||||
};
|
||||
});
|
||||
propagatedBuildInputs =
|
||||
lib.forEach
|
||||
parsed_lock_data.${name}.dependencies
|
||||
(depName: (lib.head (lib.attrValues (config.groups.${groupname}.packages.${depName}))).public);
|
||||
lib.mapAttrsToList
|
||||
(name: dep: (lib.head (lib.attrValues (config.groups.${groupname}.packages.${name}))).public)
|
||||
(libpdm.getClosure parsed_lock_data name pkg.extras);
|
||||
};
|
||||
};
|
||||
});
|
||||
in {inherit packages;};
|
||||
in
|
||||
lib.mapAttrs populateGroup groups_with_deps;
|
||||
lib.genAttrs groupNames populateGroup;
|
||||
}
|
||||
|
@ -156,23 +156,16 @@
|
||||
then wheel
|
||||
else null;
|
||||
|
||||
# Get the dependency names out from a list of parsed deps
|
||||
# Get the dependency names out from a list of parsed deps which are
|
||||
# required due to the current environment.
|
||||
# requiredDeps :: Attrset -> [Attrset] -> [String]
|
||||
requiredDeps = environ: parsed_deps: let
|
||||
requiredDeps' = lib.filter (isDependencyRequired environ) parsed_deps;
|
||||
in
|
||||
map (dep: dep.name) requiredDeps';
|
||||
requiredDeps';
|
||||
|
||||
# Parse lockfile data.
|
||||
# Returns a set with package name as key
|
||||
# and as value the version, sources and dependencies
|
||||
# The packages are not yet divided into groups.
|
||||
parseLockData = {
|
||||
lock_data,
|
||||
environ, # Output from `libpyproject.pep508.mkEnviron`
|
||||
}: let
|
||||
# TODO: validate against lock file version.
|
||||
parsePackage = item: let
|
||||
parsePackage = environ: item: let
|
||||
sources = sourcesToAttrs item.files;
|
||||
compatibleSources =
|
||||
lib.filterAttrs
|
||||
@ -181,25 +174,56 @@
|
||||
isUsableFilename {inherit environ filename;}
|
||||
)
|
||||
sources;
|
||||
parsedDeps = with lib.trivial; (
|
||||
map
|
||||
((flip pipe) [
|
||||
libpyproject.pep508.parseString
|
||||
])
|
||||
item.dependencies or []
|
||||
);
|
||||
value = {
|
||||
parsedDeps = map libpyproject.pep508.parseString item.dependencies or [];
|
||||
in {
|
||||
inherit (item) name version;
|
||||
extras = item.extras or [];
|
||||
dependencies = requiredDeps environ parsedDeps;
|
||||
inherit (item) version;
|
||||
sources = compatibleSources;
|
||||
# In the future we could add additional meta data fields
|
||||
# such as summary
|
||||
};
|
||||
in
|
||||
lib.nameValuePair item.name value;
|
||||
in
|
||||
# TODO: packages need to be filtered on environment.
|
||||
lib.listToAttrs (map parsePackage lock_data.package);
|
||||
|
||||
# Create a string identified for a set of extras.
|
||||
mkExtrasKey = dep @ {extras ? [], ...}:
|
||||
if extras == []
|
||||
then "default"
|
||||
else lib.concatStringsSep "," extras;
|
||||
|
||||
# Constructs dependency entry for internal use.
|
||||
# We could use the pyproject.nix representation directly instead, but it seems
|
||||
# easier to test this code if we only keep the data we need.
|
||||
mkDepEntry = parsed_lock_data: dep @ {
|
||||
name,
|
||||
extras,
|
||||
...
|
||||
}: {
|
||||
extras = extras;
|
||||
sources = parsed_lock_data.${name}.${mkExtrasKey {inherit extras;}}.sources;
|
||||
version = parsed_lock_data.${name}.${mkExtrasKey {inherit extras;}}.version;
|
||||
};
|
||||
|
||||
# Parse lockfile data.
|
||||
# Returns a set with package name as key
|
||||
# and as value the version, sources and dependencies
|
||||
# The packages are not yet divided into groups.
|
||||
parseLockData = {
|
||||
lock_data,
|
||||
environ, # Output from `libpyproject.pep508.mkEnviron`
|
||||
}:
|
||||
lib.foldl
|
||||
(acc: dep:
|
||||
acc
|
||||
// {
|
||||
"${dep.name}" =
|
||||
acc.${dep.name}
|
||||
or {}
|
||||
// {
|
||||
"${mkExtrasKey dep}" = dep;
|
||||
};
|
||||
})
|
||||
{}
|
||||
(map (parsePackage environ) lock_data.package);
|
||||
|
||||
# Create an overview of all groups and dependencies
|
||||
# Keys are group names, and values lists with strings.
|
||||
@ -224,31 +248,76 @@
|
||||
all_groups;
|
||||
|
||||
# Get a set with all transitive dependencies flattened.
|
||||
# For every dependency we have the version, source
|
||||
# and dependencies as names.
|
||||
# getDepsRecursively :: Attrset -> String -> Attrset
|
||||
getDepsRecursively = parsedLockData: name: let
|
||||
getDeps = name: let
|
||||
dep = parsedLockData.${name};
|
||||
in
|
||||
[{"${name}" = dep;}] ++ lib.flatten (map getDeps dep.dependencies);
|
||||
in
|
||||
lib.attrsets.mergeAttrsList (lib.unique (getDeps name));
|
||||
# For every dependency we have the version, sources and extras.
|
||||
# getClosure :: Attrset -> String -> [String] -> Attrset
|
||||
getClosure = parsed_lock_data: name: extras: let
|
||||
closure = builtins.genericClosure {
|
||||
startSet = [
|
||||
{
|
||||
key = "${name}#${mkExtrasKey {inherit extras;}}";
|
||||
value = parsed_lock_data.${name}.${mkExtrasKey {inherit extras;}};
|
||||
}
|
||||
];
|
||||
operator = item:
|
||||
lib.forEach item.value.dependencies or [] (dep: {
|
||||
key = "${dep.name}#${mkExtrasKey dep}";
|
||||
value = parsed_lock_data.${dep.name}.${mkExtrasKey dep};
|
||||
});
|
||||
};
|
||||
|
||||
# Select the dependencies we need in our group.
|
||||
# Here we recurse so we get a set with all dependencies.
|
||||
# selectForGroups :: {Attrset, Attrset, String}
|
||||
selectForGroups = {
|
||||
# mapping of all dependencies by name with merged extras.
|
||||
depsByNames =
|
||||
lib.foldl'
|
||||
(
|
||||
acc: x: let
|
||||
dep = x.value;
|
||||
in
|
||||
acc
|
||||
// {
|
||||
"${dep.name}" =
|
||||
acc.${dep.name}
|
||||
or {}
|
||||
// {
|
||||
extras =
|
||||
lib.sort (x: y: x > y)
|
||||
(lib.unique (acc.${dep.name}.extras or [] ++ dep.extras));
|
||||
version = dep.version;
|
||||
sources = dep.sources;
|
||||
};
|
||||
}
|
||||
)
|
||||
{}
|
||||
closure;
|
||||
in
|
||||
# remove self references from the closure to prevent cycles
|
||||
builtins.removeAttrs depsByNames [name];
|
||||
|
||||
# Compute the dependency closure for the given groups.
|
||||
# closureForGroups :: {Attrset, Attrset, String}
|
||||
closureForGroups = {
|
||||
parsed_lock_data,
|
||||
groups_with_deps,
|
||||
groupNames,
|
||||
}: let
|
||||
# List of top-level package names we need.
|
||||
# List of all top-level dependencies for the given groups.
|
||||
deps_top_level =
|
||||
lib.concatMap
|
||||
(groupName: groups_with_deps.${groupName})
|
||||
groupNames;
|
||||
getDeps = getDepsRecursively parsed_lock_data;
|
||||
# Top-level dependencies in expected format.
|
||||
# Children are already returned in correct format by 'getClosure'.
|
||||
topLevelEntries =
|
||||
map
|
||||
(dep: {
|
||||
name = dep.name;
|
||||
value = mkDepEntry parsed_lock_data dep;
|
||||
})
|
||||
deps_top_level;
|
||||
# helper to get the closure for a single dependency.
|
||||
getClosureForDep = dep: getClosure parsed_lock_data dep.name dep.extras;
|
||||
in
|
||||
lib.attrsets.mergeAttrsList (map getDeps deps_top_level);
|
||||
# top-level dependencies
|
||||
(lib.listToAttrs topLevelEntries)
|
||||
# transitive dependencies
|
||||
// (lib.attrsets.mergeAttrsList (map getClosureForDep deps_top_level));
|
||||
}
|
||||
|
@ -82,11 +82,11 @@ in {
|
||||
"certifi-2023.7.22.zip"
|
||||
];
|
||||
in {
|
||||
test_selectSdist__tar_gz = {
|
||||
test_tar_gz = {
|
||||
expr = libpdm.selectSdist names;
|
||||
expected = "certifi-2023.7.22.tar.gz";
|
||||
};
|
||||
test_selectSdist__no_sdist = let
|
||||
test_no_sdist = let
|
||||
names = [
|
||||
"certifi-2023.7.22-py3-abi3-any.whl"
|
||||
];
|
||||
@ -94,7 +94,7 @@ in {
|
||||
expr = libpdm.selectSdist names;
|
||||
expected = null;
|
||||
};
|
||||
test_selectSdist__order = let
|
||||
test_order = let
|
||||
names = [
|
||||
"certifi-2023.7.22.zip"
|
||||
"certifi-2023.7.22.tar.gz"
|
||||
@ -117,7 +117,7 @@ in {
|
||||
};
|
||||
|
||||
preferWheelSelector = {
|
||||
test_preferWheelSelector__has_wheel = let
|
||||
test_has_wheel = let
|
||||
names = [
|
||||
"certifi-2023.7.22-py3-abi3-any.whl"
|
||||
"certifi-2023.7.22.tar.gz"
|
||||
@ -127,7 +127,7 @@ in {
|
||||
expr = libpdm.preferWheelSelector names;
|
||||
expected = "certifi-2023.7.22-py3-abi3-any.whl";
|
||||
};
|
||||
test_preferWheelSelector__only_sdist = let
|
||||
test_only_sdist = let
|
||||
names = [
|
||||
"certifi-2023.7.22.zip"
|
||||
"certifi-2023.7.22.tar.gz"
|
||||
@ -139,7 +139,7 @@ in {
|
||||
};
|
||||
|
||||
preferSdistSelector = {
|
||||
test_preferSdistSelector__has_sdist = let
|
||||
test_has_sdist = let
|
||||
names = [
|
||||
"certifi-2023.7.22-py3-abi3-any.whl"
|
||||
"certifi-2023.7.22.tar.gz"
|
||||
@ -149,7 +149,7 @@ in {
|
||||
expr = libpdm.preferSdistSelector names;
|
||||
expected = "certifi-2023.7.22.tar.gz";
|
||||
};
|
||||
test_preferSdistSelectorr__only_sdist = let
|
||||
test_only_sdist = let
|
||||
names = [
|
||||
"certifi-2023.7.22.zip"
|
||||
"certifi-2023.7.22.tar.gz"
|
||||
@ -159,29 +159,90 @@ in {
|
||||
expected = "certifi-2023.7.22.tar.gz";
|
||||
};
|
||||
};
|
||||
|
||||
parsePackage = {
|
||||
test_simple = {
|
||||
expr = libpdm.parsePackage linux_environ {
|
||||
name = "foo";
|
||||
version = "1.0.0";
|
||||
extras = ["extra1" "extra2"];
|
||||
requires_python = ">=3.9";
|
||||
files = [
|
||||
{
|
||||
file = "foo-1.0.0-py3-none-any.whl";
|
||||
hash = "sha256:foo";
|
||||
}
|
||||
{
|
||||
file = "foo-1.0.0.tar.gz";
|
||||
hash = "sha256:bar";
|
||||
}
|
||||
];
|
||||
dependencies = [
|
||||
"bar[security,performance]==1.0.0"
|
||||
];
|
||||
};
|
||||
expected = {
|
||||
name = "foo";
|
||||
version = "1.0.0";
|
||||
extras = ["extra1" "extra2"];
|
||||
dependencies = [
|
||||
{
|
||||
conditions = [
|
||||
{
|
||||
op = "==";
|
||||
version = {
|
||||
dev = null;
|
||||
epoch = 0;
|
||||
local = null;
|
||||
post = null;
|
||||
pre = null;
|
||||
release = [1 0 0];
|
||||
};
|
||||
}
|
||||
];
|
||||
extras = ["security" "performance"];
|
||||
markers = null;
|
||||
name = "bar";
|
||||
url = null;
|
||||
}
|
||||
];
|
||||
sources = {
|
||||
"foo-1.0.0-py3-none-any.whl" = {
|
||||
file = "foo-1.0.0-py3-none-any.whl";
|
||||
hash = "sha256:foo";
|
||||
};
|
||||
"foo-1.0.0.tar.gz" = {
|
||||
file = "foo-1.0.0.tar.gz";
|
||||
hash = "sha256:bar";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
parseLockData = let
|
||||
lock_data = lib.importTOML ./../../../examples/packages/single-language/python-pdm/pdm.lock;
|
||||
lock_data = lib.importTOML ./fixtures/pdm-example1.lock;
|
||||
version = "2.31.0";
|
||||
parsed = libpdm.parseLockData {
|
||||
inherit lock_data;
|
||||
environ = linux_environ;
|
||||
};
|
||||
in {
|
||||
test_parseLockData = {
|
||||
test_simple = {
|
||||
expr =
|
||||
(parsed ? "requests")
|
||||
&& (parsed.requests.version == version)
|
||||
&& (parsed.requests ? sources);
|
||||
&& (parsed.requests.default.version == version)
|
||||
&& (parsed.requests.default ? sources);
|
||||
expected = true;
|
||||
};
|
||||
|
||||
test_parseLockData_file = {
|
||||
expr = libpdm.preferWheelSelector (lib.attrNames parsed.requests.sources);
|
||||
test_file = {
|
||||
expr = libpdm.preferWheelSelector (lib.attrNames parsed.requests.default.sources);
|
||||
expected = "requests-2.31.0-py3-none-any.whl";
|
||||
};
|
||||
|
||||
test_parseLockData_dependencies = {
|
||||
expr = parsed.requests.dependencies;
|
||||
test_dependencies = {
|
||||
expr = map (dep: dep.name) parsed.requests.default.dependencies;
|
||||
expected = [
|
||||
"certifi"
|
||||
"charset-normalizer"
|
||||
@ -189,68 +250,150 @@ in {
|
||||
"urllib3"
|
||||
];
|
||||
};
|
||||
test_candidates_with_different_extras = rec {
|
||||
expr = libpdm.parseLockData {
|
||||
environ = linux_environ;
|
||||
lock_data = {
|
||||
package = [
|
||||
{
|
||||
name = "foo";
|
||||
version = "1.0.0";
|
||||
extras = [];
|
||||
dependencies = [
|
||||
"dep1==1.0.0"
|
||||
];
|
||||
files = [
|
||||
{
|
||||
file = "foo-1.0.0.tar.gz";
|
||||
hash = "sha256:bar";
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
name = "foo";
|
||||
version = "1.0.0";
|
||||
extras = ["extra1" "extra2"];
|
||||
dependencies = [
|
||||
"extradep1==1.0.0"
|
||||
];
|
||||
files = [
|
||||
{
|
||||
file = "foo-1.0.0.tar.gz";
|
||||
hash = "sha256:bar";
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
expected = {
|
||||
foo = {
|
||||
default = {
|
||||
name = "foo";
|
||||
version = "1.0.0";
|
||||
extras = [];
|
||||
dependencies = expr.foo.default.dependencies;
|
||||
sources = expr.foo.default.sources;
|
||||
};
|
||||
"extra1,extra2" = {
|
||||
name = "foo";
|
||||
version = "1.0.0";
|
||||
extras = ["extra1" "extra2"];
|
||||
dependencies = expr.foo."extra1,extra2".dependencies;
|
||||
sources = expr.foo."extra1,extra2".sources;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
groupsWithDeps = let
|
||||
environ = linux_environ;
|
||||
pyproject = libpdm.loadPdmPyProject (lib.importTOML ./../../../examples/packages/single-language/python-pdm/pyproject.toml);
|
||||
pyproject = libpdm.loadPdmPyProject (lib.importTOML ./fixtures/pyproject.toml);
|
||||
groups_with_deps = libpdm.groupsWithDeps {
|
||||
inherit environ pyproject;
|
||||
};
|
||||
in {
|
||||
test_groupsWithDeps__has_main_group = {
|
||||
test_has_main_group = {
|
||||
expr = groups_with_deps ? "default";
|
||||
expected = true;
|
||||
};
|
||||
test_groupsWithDeps__main_group_has_deps = {
|
||||
expr = groups_with_deps.default;
|
||||
test_main_group_has_deps = {
|
||||
expr = map (dep: dep.name) groups_with_deps.default;
|
||||
expected = ["requests"];
|
||||
};
|
||||
test_groupsWithDeps__optionals_dev_has_deps = {
|
||||
expr = groups_with_deps.dev;
|
||||
test_optionals_dev_has_deps = {
|
||||
expr = map (dep: dep.name) groups_with_deps.dev;
|
||||
expected = ["pi"];
|
||||
};
|
||||
};
|
||||
|
||||
getDepsRecursively = let
|
||||
getClosure = let
|
||||
environ = linux_environ;
|
||||
lock_data = lib.importTOML ./../../../examples/packages/single-language/python-pdm/pdm.lock;
|
||||
parsed_lock_data = libpdm.parseLockData {
|
||||
inherit environ lock_data;
|
||||
lock_data_2 = lib.importTOML ./fixtures/pdm-example1.lock;
|
||||
parsed_lock_data_2 = libpdm.parseLockData {
|
||||
inherit environ;
|
||||
lock_data = lock_data_2;
|
||||
};
|
||||
deps = libpdm.getDepsRecursively parsed_lock_data "requests";
|
||||
in {
|
||||
test_getDepsRecursively_names = {
|
||||
expr = lib.attrNames deps;
|
||||
expected = ["certifi" "charset-normalizer" "idna" "requests" "urllib3"];
|
||||
};
|
||||
test_getDepsRecursively_versions = {
|
||||
expr = lib.mapAttrs (key: value: value.version) deps;
|
||||
in rec {
|
||||
deps = libpdm.getClosure parsed_lock_data_2 "requests" [];
|
||||
|
||||
test_versions = {
|
||||
expr = lib.mapAttrs (name: dep: dep.version) deps;
|
||||
expected = {
|
||||
certifi = "2023.7.22";
|
||||
charset-normalizer = "3.2.0";
|
||||
idna = "3.4";
|
||||
requests = "2.31.0";
|
||||
urllib3 = "2.0.5";
|
||||
};
|
||||
};
|
||||
test_getDepsRecursively_sources = let
|
||||
|
||||
test_sources = let
|
||||
selectFilename = sources: libpdm.preferWheelSelector (lib.attrNames sources);
|
||||
in {
|
||||
expr = lib.mapAttrs (key: value: selectFilename value.sources) deps;
|
||||
expr = lib.mapAttrs (name: dep: selectFilename dep.sources) deps;
|
||||
expected = {
|
||||
certifi = "certifi-2023.7.22-py3-none-any.whl";
|
||||
charset-normalizer = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl";
|
||||
idna = "idna-3.4-py3-none-any.whl";
|
||||
requests = "requests-2.31.0-py3-none-any.whl";
|
||||
urllib3 = "urllib3-2.0.5-py3-none-any.whl";
|
||||
};
|
||||
};
|
||||
|
||||
test_no_cycles = let
|
||||
lock_data = lib.importTOML ./fixtures/pdm-with-cycles.lock;
|
||||
parsed_lock_data = libpdm.parseLockData {
|
||||
inherit environ lock_data;
|
||||
};
|
||||
deps = libpdm.getClosure parsed_lock_data "pyjwt" ["crypto"];
|
||||
in {
|
||||
expr = lib.mapAttrs (name: dep: dep.version) deps;
|
||||
expected = {
|
||||
cffi = "1.16.0";
|
||||
cryptography = "41.0.7";
|
||||
pycparser = "2.21";
|
||||
};
|
||||
};
|
||||
|
||||
test_closure_collects_all_extras = let
|
||||
lock_data = lib.importTOML ./fixtures/pdm-extras.lock;
|
||||
parsed_lock_data = libpdm.parseLockData {
|
||||
inherit environ lock_data;
|
||||
};
|
||||
deps = libpdm.getClosure parsed_lock_data "root" [];
|
||||
in {
|
||||
expr.foo = deps.foo.extras;
|
||||
expr.bar = deps.bar.extras;
|
||||
expected = {
|
||||
foo = ["extra1"];
|
||||
bar = ["extra2"];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
selectForGroups = let
|
||||
closureForGroups = let
|
||||
environ = linux_environ;
|
||||
pyproject = libpdm.loadPdmPyProject (lib.importTOML ./../../../examples/packages/single-language/python-pdm/pyproject.toml);
|
||||
lock_data = lib.importTOML ./../../../examples/packages/single-language/python-pdm/pdm.lock;
|
||||
pyproject = libpdm.loadPdmPyProject (lib.importTOML ./fixtures/pyproject.toml);
|
||||
lock_data = lib.importTOML ./fixtures/pdm-example1.lock;
|
||||
groups_with_deps = libpdm.groupsWithDeps {
|
||||
inherit environ pyproject;
|
||||
};
|
||||
@ -258,20 +401,20 @@ in {
|
||||
inherit lock_data;
|
||||
environ = linux_environ;
|
||||
};
|
||||
deps_default = libpdm.selectForGroups {
|
||||
deps_default = libpdm.closureForGroups {
|
||||
inherit parsed_lock_data groups_with_deps;
|
||||
groupNames = ["default"];
|
||||
};
|
||||
deps_dev = libpdm.selectForGroups {
|
||||
deps_dev = libpdm.closureForGroups {
|
||||
inherit parsed_lock_data groups_with_deps;
|
||||
groupNames = ["default" "dev"];
|
||||
};
|
||||
in {
|
||||
test_selectForGroups_names = {
|
||||
test_names = {
|
||||
expr = lib.attrNames deps_default;
|
||||
expected = ["certifi" "charset-normalizer" "idna" "requests" "urllib3"];
|
||||
};
|
||||
test_selectForGroups_versions = {
|
||||
test_versions = {
|
||||
expr = lib.mapAttrs (key: value: value.version) deps_default;
|
||||
expected = {
|
||||
certifi = "2023.7.22";
|
||||
@ -281,7 +424,7 @@ in {
|
||||
urllib3 = "2.0.5";
|
||||
};
|
||||
};
|
||||
test_selectForGroups_sources = let
|
||||
test_closureForGroups_sources = let
|
||||
selectFilename = sources: libpdm.preferWheelSelector (lib.attrNames sources);
|
||||
in {
|
||||
expr = lib.mapAttrs (key: value: selectFilename value.sources) deps_default;
|
||||
@ -293,7 +436,7 @@ in {
|
||||
urllib3 = "urllib3-2.0.5-py3-none-any.whl";
|
||||
};
|
||||
};
|
||||
test_selectForGroups_dev_versions = {
|
||||
test_dev_versions = {
|
||||
expr = lib.mapAttrs (key: value: value.version) deps_dev;
|
||||
expected = {
|
||||
certifi = "2023.7.22";
|
||||
|
103
tests/nix-unit/test_python-pdm-lib/fixtures/pdm-example1.lock
Normal file
103
tests/nix-unit/test_python-pdm-lib/fixtures/pdm-example1.lock
Normal file
@ -0,0 +1,103 @@
|
||||
# This file is @generated by PDM.
|
||||
# It is not intended for manual editing.
|
||||
|
||||
[metadata]
|
||||
groups = ["default", "dev"]
|
||||
cross_platform = true
|
||||
static_urls = false
|
||||
lock_version = "4.3"
|
||||
content_hash = "sha256:6b124fd8499d7ddefb13cb60a64760b0601a8db060263247076bc4f4309cd6cd"
|
||||
|
||||
[[package]]
|
||||
name = "certifi"
|
||||
version = "2023.7.22"
|
||||
requires_python = ">=3.6"
|
||||
summary = "Python package for providing Mozilla's CA Bundle."
|
||||
files = [
|
||||
{file = "certifi-2023.7.22-py3-none-any.whl", hash = "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"},
|
||||
{file = "certifi-2023.7.22.tar.gz", hash = "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "charset-normalizer"
|
||||
version = "3.2.0"
|
||||
requires_python = ">=3.7.0"
|
||||
summary = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
|
||||
files = [
|
||||
{file = "charset-normalizer-3.2.0.tar.gz", hash = "sha256:3bb3d25a8e6c0aedd251753a79ae98a093c7e7b471faa3aa9a93a81431987ace"},
|
||||
{file = "charset_normalizer-3.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b87549028f680ca955556e3bd57013ab47474c3124dc069faa0b6545b6c9710"},
|
||||
{file = "charset_normalizer-3.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7c70087bfee18a42b4040bb9ec1ca15a08242cf5867c58726530bdf3945672ed"},
|
||||
{file = "charset_normalizer-3.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a103b3a7069b62f5d4890ae1b8f0597618f628b286b03d4bc9195230b154bfa9"},
|
||||
{file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94aea8eff76ee6d1cdacb07dd2123a68283cb5569e0250feab1240058f53b623"},
|
||||
{file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:db901e2ac34c931d73054d9797383d0f8009991e723dab15109740a63e7f902a"},
|
||||
{file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b0dac0ff919ba34d4df1b6131f59ce95b08b9065233446be7e459f95554c0dc8"},
|
||||
{file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:193cbc708ea3aca45e7221ae58f0fd63f933753a9bfb498a3b474878f12caaad"},
|
||||
{file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09393e1b2a9461950b1c9a45d5fd251dc7c6f228acab64da1c9c0165d9c7765c"},
|
||||
{file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:baacc6aee0b2ef6f3d308e197b5d7a81c0e70b06beae1f1fcacffdbd124fe0e3"},
|
||||
{file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:bf420121d4c8dce6b889f0e8e4ec0ca34b7f40186203f06a946fa0276ba54029"},
|
||||
{file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:c04a46716adde8d927adb9457bbe39cf473e1e2c2f5d0a16ceb837e5d841ad4f"},
|
||||
{file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:aaf63899c94de41fe3cf934601b0f7ccb6b428c6e4eeb80da72c58eab077b19a"},
|
||||
{file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d62e51710986674142526ab9f78663ca2b0726066ae26b78b22e0f5e571238dd"},
|
||||
{file = "charset_normalizer-3.2.0-cp310-cp310-win32.whl", hash = "sha256:04e57ab9fbf9607b77f7d057974694b4f6b142da9ed4a199859d9d4d5c63fe96"},
|
||||
{file = "charset_normalizer-3.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:48021783bdf96e3d6de03a6e39a1171ed5bd7e8bb93fc84cc649d11490f87cea"},
|
||||
{file = "charset_normalizer-3.2.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4957669ef390f0e6719db3613ab3a7631e68424604a7b448f079bee145da6e09"},
|
||||
{file = "charset_normalizer-3.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:46fb8c61d794b78ec7134a715a3e564aafc8f6b5e338417cb19fe9f57a5a9bf2"},
|
||||
{file = "charset_normalizer-3.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f779d3ad205f108d14e99bb3859aa7dd8e9c68874617c72354d7ecaec2a054ac"},
|
||||
{file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f25c229a6ba38a35ae6e25ca1264621cc25d4d38dca2942a7fce0b67a4efe918"},
|
||||
{file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2efb1bd13885392adfda4614c33d3b68dee4921fd0ac1d3988f8cbb7d589e72a"},
|
||||
{file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f30b48dd7fa1474554b0b0f3fdfdd4c13b5c737a3c6284d3cdc424ec0ffff3a"},
|
||||
{file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:246de67b99b6851627d945db38147d1b209a899311b1305dd84916f2b88526c6"},
|
||||
{file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bd9b3b31adcb054116447ea22caa61a285d92e94d710aa5ec97992ff5eb7cf3"},
|
||||
{file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:8c2f5e83493748286002f9369f3e6607c565a6a90425a3a1fef5ae32a36d749d"},
|
||||
{file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:3170c9399da12c9dc66366e9d14da8bf7147e1e9d9ea566067bbce7bb74bd9c2"},
|
||||
{file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7a4826ad2bd6b07ca615c74ab91f32f6c96d08f6fcc3902ceeedaec8cdc3bcd6"},
|
||||
{file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:3b1613dd5aee995ec6d4c69f00378bbd07614702a315a2cf6c1d21461fe17c23"},
|
||||
{file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9e608aafdb55eb9f255034709e20d5a83b6d60c054df0802fa9c9883d0a937aa"},
|
||||
{file = "charset_normalizer-3.2.0-cp311-cp311-win32.whl", hash = "sha256:f2a1d0fd4242bd8643ce6f98927cf9c04540af6efa92323e9d3124f57727bfc1"},
|
||||
{file = "charset_normalizer-3.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:681eb3d7e02e3c3655d1b16059fbfb605ac464c834a0c629048a30fad2b27489"},
|
||||
{file = "charset_normalizer-3.2.0-py3-none-any.whl", hash = "sha256:8e098148dd37b4ce3baca71fb394c81dc5d9c7728c95df695d2dca218edf40e6"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "3.4"
|
||||
requires_python = ">=3.5"
|
||||
summary = "Internationalized Domain Names in Applications (IDNA)"
|
||||
files = [
|
||||
{file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"},
|
||||
{file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pi"
|
||||
version = "0.1.2"
|
||||
summary = "Simpler python package installation"
|
||||
files = [
|
||||
{file = "pi-0.1.2.tar.gz", hash = "sha256:8d503a790317f7fbce7469c4160e44b1c76492571b2b0c0596636a1794800f75"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "requests"
|
||||
version = "2.31.0"
|
||||
requires_python = ">=3.7"
|
||||
summary = "Python HTTP for Humans."
|
||||
dependencies = [
|
||||
"certifi>=2017.4.17",
|
||||
"charset-normalizer<4,>=2",
|
||||
"idna<4,>=2.5",
|
||||
"urllib3<3,>=1.21.1",
|
||||
]
|
||||
files = [
|
||||
{file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"},
|
||||
{file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "urllib3"
|
||||
version = "2.0.5"
|
||||
requires_python = ">=3.7"
|
||||
summary = "HTTP library with thread-safe connection pooling, file post, and more."
|
||||
files = [
|
||||
{file = "urllib3-2.0.5-py3-none-any.whl", hash = "sha256:ef16afa8ba34a1f989db38e1dbbe0c302e4289a47856990d0682e374563ce35e"},
|
||||
{file = "urllib3-2.0.5.tar.gz", hash = "sha256:13abf37382ea2ce6fb744d4dad67838eec857c9f4f57009891805e0b5e123594"},
|
||||
]
|
39
tests/nix-unit/test_python-pdm-lib/fixtures/pdm-extras.lock
Normal file
39
tests/nix-unit/test_python-pdm-lib/fixtures/pdm-extras.lock
Normal file
@ -0,0 +1,39 @@
|
||||
# Tests: When 'root' is resolved,
|
||||
|
||||
[metadata]
|
||||
groups = ["default"]
|
||||
strategy = ["cross_platform"]
|
||||
lock_version = "4.4"
|
||||
|
||||
[[package]]
|
||||
name = "foo"
|
||||
version = "1.0.0"
|
||||
files = []
|
||||
|
||||
[[package]]
|
||||
name = "foo"
|
||||
extras = ["extra1"]
|
||||
version = "1.0.0"
|
||||
files = []
|
||||
|
||||
[[package]]
|
||||
name = "bar"
|
||||
version = "1.0.0"
|
||||
files = []
|
||||
|
||||
[[package]]
|
||||
name = "bar"
|
||||
extras = ["extra2"]
|
||||
version = "1.0.0"
|
||||
files = []
|
||||
|
||||
[[package]]
|
||||
name = "root"
|
||||
version = "1.0.0"
|
||||
dependencies = [
|
||||
"foo[extra1]==1.0.0",
|
||||
"foo==1.0.0",
|
||||
"bar==1.0.0",
|
||||
"bar[extra2]==1.0.0"
|
||||
]
|
||||
files = []
|
@ -0,0 +1,64 @@
|
||||
# This file is @generated by PDM.
|
||||
# It is not intended for manual editing.
|
||||
|
||||
[metadata]
|
||||
groups = ["default", "default", "dev"]
|
||||
strategy = ["cross_platform"]
|
||||
lock_version = "4.4"
|
||||
content_hash = "sha256:ac27f396f238ef001a11c5abacfd9412eafa638da66cfe9d079176e5c2b30c31"
|
||||
|
||||
[[package]]
|
||||
name = "pyjwt"
|
||||
version = "2.8.0"
|
||||
requires_python = ">=3.7"
|
||||
summary = "JSON Web Token implementation in Python"
|
||||
files = [
|
||||
{file = "PyJWT-2.8.0.tar.gz", hash = "sha256:57e28d156e3d5c10088e0c68abb90bfac3df82b40a71bd0daa20c65ccd5c23de"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyjwt"
|
||||
version = "2.8.0"
|
||||
extras = ["crypto"]
|
||||
requires_python = ">=3.7"
|
||||
summary = "JSON Web Token implementation in Python"
|
||||
dependencies = [
|
||||
"cryptography>=3.4.0",
|
||||
"pyjwt==2.8.0",
|
||||
]
|
||||
files = [
|
||||
{file = "PyJWT-2.8.0.tar.gz", hash = "sha256:57e28d156e3d5c10088e0c68abb90bfac3df82b40a71bd0daa20c65ccd5c23de"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cffi"
|
||||
version = "1.16.0"
|
||||
requires_python = ">=3.8"
|
||||
summary = "Foreign Function Interface for Python calling C code."
|
||||
dependencies = [
|
||||
"pycparser",
|
||||
]
|
||||
files = [
|
||||
{file = "cffi-1.16.0.tar.gz", hash = "sha256:bcb3ef43e58665bbda2fb198698fcae6776483e0c4a631aa5647806c25e02cc0"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cryptography"
|
||||
version = "41.0.7"
|
||||
requires_python = ">=3.7"
|
||||
summary = "cryptography is a package which provides cryptographic recipes and primitives to Python developers."
|
||||
dependencies = [
|
||||
"cffi>=1.12",
|
||||
]
|
||||
files = [
|
||||
{file = "cryptography-41.0.7.tar.gz", hash = "sha256:13f93ce9bea8016c253b34afc6bd6a75993e5c40672ed5405a9c832f0d4a00bc"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pycparser"
|
||||
version = "2.21"
|
||||
requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
|
||||
summary = "C parser in Python"
|
||||
files = [
|
||||
{file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"},
|
||||
]
|
23
tests/nix-unit/test_python-pdm-lib/fixtures/pyproject.toml
Normal file
23
tests/nix-unit/test_python-pdm-lib/fixtures/pyproject.toml
Normal file
@ -0,0 +1,23 @@
|
||||
|
||||
[project]
|
||||
name = "my-project"
|
||||
version = "0.1.0"
|
||||
description = ""
|
||||
dependencies = [
|
||||
"requests>=2.31.0",
|
||||
]
|
||||
requires-python = ">=3.10"
|
||||
readme = "README.md"
|
||||
license = {text = "MIT"}
|
||||
|
||||
[project.scripts]
|
||||
my-script = "my_project:main"
|
||||
|
||||
[project.optional-dependencies]
|
||||
dev = [
|
||||
"pi>=0.1.2",
|
||||
]
|
||||
|
||||
[build-system]
|
||||
requires = ["pdm-backend"]
|
||||
build-backend = "pdm.backend"
|
@ -1,8 +1,8 @@
|
||||
{
|
||||
pkgs ? import <nixpkgs> {},
|
||||
lib ? import <nixpkgs/lib>,
|
||||
inputs ? {},
|
||||
dream2nix ? import ../../.. inputs,
|
||||
dream2nix ? import ../../../. inputs,
|
||||
inputs ? (import ../../../.).inputs,
|
||||
}: let
|
||||
eval = module:
|
||||
(lib.evalModules {
|
||||
@ -19,9 +19,8 @@
|
||||
in {
|
||||
test_pdm = let
|
||||
config = eval {
|
||||
# TODO: create fixtures
|
||||
pdm.lockfile = ./../../../examples/packages/single-language/python-pdm/pdm.lock;
|
||||
pdm.pyproject = ./../../../examples/packages/single-language/python-pdm/pyproject.toml;
|
||||
pdm.lockfile = ./../test_python-pdm-lib/fixtures/pdm-example1.lock;
|
||||
pdm.pyproject = ./../test_python-pdm-lib/fixtures/pyproject.toml;
|
||||
};
|
||||
in {
|
||||
expr = (lib.head (lib.attrValues config.groups.default.packages.certifi)).public ? drvPath;
|
||||
|
Loading…
Reference in New Issue
Block a user