mirror of
https://github.com/NixOS/nixpkgs.git
synced 2026-10-04 22:10:14 +00:00
lib.modules.mapAttrsOfSubmodule: init
This commit is contained in:
@@ -1601,6 +1601,78 @@ let
|
||||
else
|
||||
f def;
|
||||
|
||||
/**
|
||||
Consume the `options` metadata of the submodules in `attrsOf submodule`.
|
||||
|
||||
It also works with `lazyAttrsOf` and `attrsWith`.
|
||||
|
||||
# Inputs
|
||||
|
||||
1. A function that takes `name: { cfg, opt }:` and returns anything.
|
||||
`name` is the attribute name at the level of `attrsOf`.
|
||||
`cfg` is the corresponding option *value*, as typically found in `config`.
|
||||
`opt` is the corresponding evaluated option, as typically found in `options`.
|
||||
|
||||
2. An `options` attribute value, e.g. `options.users.groups`.
|
||||
|
||||
# Output
|
||||
|
||||
An attribute set whose attribute names correspond to the definitions of the
|
||||
option, and whose values are the return value of the passed function.
|
||||
|
||||
# Type
|
||||
|
||||
```
|
||||
mapAttrsOfSubmodule :: (String -> { cfg :: AttrSet, opt :: AttrSet } -> a) -> Option -> AttrSetOf a
|
||||
```
|
||||
|
||||
`Option` refers to an evaluated option,
|
||||
retrievable from the `options` module argument
|
||||
or the `options` configuration attribute returned by `evalModules`.
|
||||
It carries attribute `_type = "option";`.
|
||||
|
||||
# Example
|
||||
|
||||
:::{.example}
|
||||
## Use `mapAttrsOfSubmodule` to distinguish which NixOS system services are explicitly enabled or disabled
|
||||
```nix
|
||||
lib.modules.mapAttrsOfSubmodule
|
||||
(name: { cfg, opt }:
|
||||
{
|
||||
isExplicit = opt.enable.highestPrio < (lib.mkOptionDefault null).priority;
|
||||
value = cfg.enable;
|
||||
})
|
||||
(pkgs.nixos { }).options.systemd.services
|
||||
=>
|
||||
{
|
||||
console-getty = {
|
||||
isExplicit = true;
|
||||
value = false;
|
||||
};
|
||||
"container-getty@" = {
|
||||
isExplicit = false;
|
||||
value = true;
|
||||
};
|
||||
# ...
|
||||
}
|
||||
```
|
||||
|
||||
:::
|
||||
*/
|
||||
mapAttrsOfSubmodule =
|
||||
f: opt:
|
||||
assert opt._type or null == "option";
|
||||
assert opt.type.name == "attrsOf" || opt.type.name == "lazyAttrsOf";
|
||||
assert opt.type.nestedTypes.elemType.name == "submodule";
|
||||
|
||||
mapAttrs (
|
||||
name: attrMeta:
|
||||
f name {
|
||||
cfg = attrMeta.configuration.config;
|
||||
opt = attrMeta.configuration.options;
|
||||
}
|
||||
) opt.valueMeta.attrs;
|
||||
|
||||
mkBefore = mkOrder 500;
|
||||
defaultOrderPriority = 1000;
|
||||
mkAfter = mkOrder 1500;
|
||||
@@ -2305,6 +2377,7 @@ private
|
||||
importApply
|
||||
importJSON
|
||||
importTOML
|
||||
mapAttrsOfSubmodule
|
||||
mapDefinitionValue
|
||||
mergeDefinitions
|
||||
mergeAttrDefinitionsWithPrio
|
||||
|
||||
@@ -859,6 +859,8 @@ checkConfigError 'the-defs-file\.nix' config.argv ./attrList-valueMeta-definitio
|
||||
# attrListOf does not support type merging
|
||||
checkConfigError 'The option .merged. in .*/declare-attrList-type-merge.nix. is already declared in .*/declare-attrList-type-merge.nix' config.merged ./declare-attrList-type-merge.nix
|
||||
|
||||
checkConfigOutput '"ok"' config.result ./mapAttrsOfSubmodule.nix
|
||||
|
||||
cat <<EOF
|
||||
====== module tests ======
|
||||
$pass Pass
|
||||
|
||||
77
lib/tests/modules/mapAttrsOfSubmodule.nix
Normal file
77
lib/tests/modules/mapAttrsOfSubmodule.nix
Normal file
@@ -0,0 +1,77 @@
|
||||
{
|
||||
lib,
|
||||
options,
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (lib) types mkOption;
|
||||
inherit (types)
|
||||
submodule
|
||||
attrsOf
|
||||
lazyAttrsOf
|
||||
attrsWith
|
||||
;
|
||||
def = (lib.mkDefault null).priority;
|
||||
optdef = (lib.mkOptionDefault null).priority;
|
||||
|
||||
enabledModule = {
|
||||
options.enable = mkOption { default = true; };
|
||||
};
|
||||
in
|
||||
{
|
||||
options.services = mkOption {
|
||||
type = attrsOf (submodule enabledModule);
|
||||
};
|
||||
options.files = mkOption {
|
||||
type = lazyAttrsOf (submodule enabledModule);
|
||||
};
|
||||
options.noDefs = mkOption {
|
||||
type = attrsWith { elemType = submodule enabledModule; };
|
||||
};
|
||||
options.result = mkOption { };
|
||||
config.services.empty = { };
|
||||
config.services.default.enable = lib.mkDefault false;
|
||||
config.files.empty = { };
|
||||
config.files.default.enable = lib.mkDefault false;
|
||||
config.files.quirk = lib.mkIf false { };
|
||||
config.result =
|
||||
assert
|
||||
lib.modules.mapAttrsOfSubmodule (name: { cfg, opt }: {
|
||||
inherit name cfg;
|
||||
prio = opt.enable.highestPrio;
|
||||
}) options.services == {
|
||||
empty = {
|
||||
name = "empty";
|
||||
cfg.enable = true;
|
||||
prio = optdef;
|
||||
};
|
||||
default = {
|
||||
name = "default";
|
||||
cfg.enable = false;
|
||||
prio = def;
|
||||
};
|
||||
};
|
||||
assert
|
||||
lib.modules.mapAttrsOfSubmodule (name: { cfg, opt }: {
|
||||
inherit name cfg;
|
||||
prio = opt.enable.highestPrio;
|
||||
}) options.files == {
|
||||
empty = {
|
||||
name = "empty";
|
||||
cfg.enable = true;
|
||||
prio = optdef;
|
||||
};
|
||||
default = {
|
||||
name = "default";
|
||||
cfg.enable = false;
|
||||
prio = def;
|
||||
};
|
||||
quirk = {
|
||||
name = "quirk";
|
||||
cfg.enable = true; # unmitigated flaw; could add emptyValue to attrsWith
|
||||
prio = optdef;
|
||||
};
|
||||
};
|
||||
assert lib.modules.mapAttrsOfSubmodule (abort "unused") options.noDefs == { };
|
||||
"ok";
|
||||
}
|
||||
Reference in New Issue
Block a user