types.attrListWith: add valueMeta.definitions

This commit is contained in:
Robert Hensing
2026-05-04 17:08:18 +02:00
committed by Johannes Kirschbauer
parent e29bf2412b
commit 8aa6e3dbb9
4 changed files with 92 additions and 1 deletions
+3
View File
@@ -906,6 +906,9 @@ checkConfigError 'A definition for option .attrList.badListElem. is not of type
checkConfigError 'A definition for option .attrList.badString. is not of type .attribute list of string.. TypeError: Definition values:' config.attrListStrict.badString ./declare-attrList.nix
checkConfigError 'A definition for option .attrList.badListString. is not of type .attribute list of string.. Each list element must be a single-key attribute set.' config.attrListStrict.badListString ./declare-attrList.nix
# attrListWith valueMeta.definitions: file propagation
checkConfigError 'the-defs-file\.nix' config.argv ./attrList-valueMeta-definitions-file-diagnostic-forwarding.nix
cat <<EOF
====== module tests ======
$pass Pass
@@ -0,0 +1,25 @@
{ lib, options, ... }:
let
inherit (lib) mkOption mkMerge types;
in
{
imports = [
{
_file = "the-defs-file.nix";
config.flags.my-flag = 3.14;
}
];
options.flags = mkOption {
type = types.attrListWith {
elemType = types.anything;
asAttrs = true;
mergeAttrValues = _name: vs: lib.head vs;
};
};
options.argv = mkOption { type = types.listOf types.str; };
# Feed definitions into argv; the float from the-defs-file.nix should cause
# a type error mentioning that file
config.argv = mkMerge options.flags.valueMeta.definitions;
}
+54
View File
@@ -864,6 +864,60 @@ in
{ x = 30; }
];
# valueMeta.definitions: mkDefinition records with mkOrder-wrapped single-key attrsets
# Use duplicateKeys which has mixed priorities and repeated keys
assert
let
defs = c.options.asAttrs.valueMeta.attrs.duplicateKeys.definitions;
extract = d: {
prio = d.value.priority;
value = d.value.content;
};
in
map extract defs == [
{
prio = 500;
value = {
x = "first";
};
}
{
prio = 1000;
value = {
y = "only";
};
}
{
prio = 1500;
value = {
x = "last";
};
}
];
# Round-trip: feed definitions through mapDefinitionValue + mkMerge into a listOf option
assert
let
rendered = lib.modules.mapDefinitionValue (attr: lib.cli.toCommandLineGNU { } attr) (
mkMerge c.options.asAttrs.valueMeta.attrs.duplicateKeys.definitions
);
result =
(lib.evalModules {
modules = [
{ options.out = mkOption { type = types.listOf types.str; }; }
{ config.out = rendered; }
# Interleave: mkOrder 800 lands between x(500) and y(1000)
{ config.out = mkOrder 800 [ "--interleaved" ]; }
];
}).config.out;
in
result == [
"-xfirst"
"--interleaved"
"-yonly"
"-xlast"
];
# Error cases are tested via checkConfigError in modules.sh
"ok";
+10 -1
View File
@@ -74,6 +74,8 @@ let
mergeOptionDecls
defaultOrderPriority
defaultOverridePriority
mkDefinition
mkOrder
mkOverride
;
inherit (lib.fileset)
@@ -928,7 +930,7 @@ rec {
evals = filter (e: e.eval.optionalValue ? value) (
map (item: {
inherit (item) key;
inherit (item) key file prio;
eval = mergeDefinitions (loc ++ [ item.key ]) elemType [
{
inherit (item) file value;
@@ -947,6 +949,13 @@ rec {
The ordered list representation, especially useful when asAttrs is set.
*/
valueMeta.attrListValue = attrListValue;
valueMeta.definitions = map (
e:
mkDefinition {
inherit (e) file;
value = mkOrder e.prio { ${e.key} = e.eval.optionalValue.value or e.eval.mergedValue; };
}
) evals;
};
};
emptyValue = {