lib.importApply: init (#230588)
* lib.modules.importApply: init Brings variables from rich scopes to modules defined in separate files. A helper for functions in files that return a module. * lib.modules.importApply: Edit doc Generally improve the quality. Notes: - Not rendered to the manual yet, so probably the syntax could be improved, but I have no way to test this now. - The docs use `arg` vs `staticArg` in the code. This is intentional, because the doc is pretty clear about the role of `arg` whereas the code exists in a context where ambiguities are more harmful. * Format
This commit is contained in:
parent
ef0bb1fc69
commit
0abfc619bc
@ -1366,6 +1366,58 @@ let
|
||||
]);
|
||||
};
|
||||
|
||||
/**
|
||||
`importApply file arg :: Path -> a -> Module`, where `import file :: a -> Module`
|
||||
|
||||
`importApply` imports a Nix expression file much like the module system would,
|
||||
after passing an extra positional argument to the function in the file.
|
||||
|
||||
This function should be used when declaring a module in a file that refers to
|
||||
values from a different scope, such as that in a flake.
|
||||
|
||||
It solves the problems of alternative solutions:
|
||||
|
||||
- While `importApply file arg` is _mostly_ equivalent to
|
||||
`import file arg`, the latter returns a module without a location,
|
||||
as `import` only returns the contained expression. This leads to worse
|
||||
error messages.
|
||||
|
||||
- Using `specialArgs` to provide arguments to all modules. This effectively
|
||||
creates an incomplete module, and requires the user of the module to
|
||||
manually pass the `specialArgs` to the configuration, which is error-prone,
|
||||
verbose, and unnecessary.
|
||||
|
||||
The nix file must contain a function that returns a module.
|
||||
A module may itself be a function, so the file is often a function with two
|
||||
positional arguments instead of one. See the example below.
|
||||
|
||||
This function does not add support for deduplication and `disabledModules`,
|
||||
although that could be achieved by wrapping the returned module and setting
|
||||
the `_key` module attribute.
|
||||
The reason for this omission is that the file path is not guaranteed to be
|
||||
a unique identifier for the module, as two instances of the module may
|
||||
reference different `arg`s in their closures.
|
||||
|
||||
Example
|
||||
|
||||
# lib.nix
|
||||
imports = [
|
||||
(lib.modules.importApply ./module.nix { bar = bar; })
|
||||
];
|
||||
|
||||
# module.nix
|
||||
{ bar }:
|
||||
{ lib, config, ... }:
|
||||
{
|
||||
options = ...;
|
||||
config = ... bar ...;
|
||||
}
|
||||
|
||||
*/
|
||||
importApply =
|
||||
modulePath: staticArg:
|
||||
lib.setDefaultModuleLocation modulePath (import modulePath staticArg);
|
||||
|
||||
/* Use this function to import a JSON file as NixOS configuration.
|
||||
|
||||
modules.importJSON :: path -> attrs
|
||||
@ -1415,6 +1467,7 @@ private //
|
||||
filterOverrides'
|
||||
fixMergeModules
|
||||
fixupOptionType # should be private?
|
||||
importApply
|
||||
importJSON
|
||||
importTOML
|
||||
mergeDefinitions
|
||||
|
@ -247,6 +247,14 @@ checkConfigOutput '^true$' "$@" ./define-enable.nix ./define-attrsOfSub-if-foo-e
|
||||
checkConfigOutput '^true$' "$@" ./define-enable.nix ./define-attrsOfSub-foo-if-enable.nix
|
||||
checkConfigOutput '^true$' "$@" ./define-enable.nix ./define-attrsOfSub-foo-enable-if.nix
|
||||
|
||||
# Check importApply
|
||||
checkConfigOutput '"abc"' config.value ./importApply.nix
|
||||
# importApply does not set a key.
|
||||
# Disabling the function file is not sufficient, because importApply can't reasonably assume that the key is unique.
|
||||
# e.g. user may call it multiple times with different arguments and expect each of the module to apply.
|
||||
# While this is excusable for the disabledModules aspect, it is not for the deduplication of modules.
|
||||
checkConfigOutput '"abc"' config.value ./importApply-disabling.nix
|
||||
|
||||
# Check disabledModules with config definitions and option declarations.
|
||||
set -- config.enable ./define-enable.nix ./declare-enable.nix
|
||||
checkConfigOutput '^true$' "$@"
|
||||
|
4
lib/tests/modules/importApply-disabling.nix
Normal file
4
lib/tests/modules/importApply-disabling.nix
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
imports = [ ./importApply.nix ];
|
||||
disabledModules = [ ./importApply-function.nix ];
|
||||
}
|
5
lib/tests/modules/importApply-function.nix
Normal file
5
lib/tests/modules/importApply-function.nix
Normal file
@ -0,0 +1,5 @@
|
||||
{ foo }:
|
||||
{ lib, config, ... }:
|
||||
{
|
||||
value = foo;
|
||||
}
|
5
lib/tests/modules/importApply.nix
Normal file
5
lib/tests/modules/importApply.nix
Normal file
@ -0,0 +1,5 @@
|
||||
{ lib, ... }:
|
||||
{
|
||||
options.value = lib.mkOption { default = 1; };
|
||||
imports = [ (lib.modules.importApply ./importApply-function.nix { foo = "abc"; }) ];
|
||||
}
|
Loading…
Reference in New Issue
Block a user