lol

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

authored by

Robert Hensing and committed by
GitHub
0abfc619 ef0bb1fc

+75
+53
lib/modules.nix
··· 1366 1366 ]); 1367 1367 }; 1368 1368 1369 + /** 1370 + `importApply file arg :: Path -> a -> Module`, where `import file :: a -> Module` 1371 + 1372 + `importApply` imports a Nix expression file much like the module system would, 1373 + after passing an extra positional argument to the function in the file. 1374 + 1375 + This function should be used when declaring a module in a file that refers to 1376 + values from a different scope, such as that in a flake. 1377 + 1378 + It solves the problems of alternative solutions: 1379 + 1380 + - While `importApply file arg` is _mostly_ equivalent to 1381 + `import file arg`, the latter returns a module without a location, 1382 + as `import` only returns the contained expression. This leads to worse 1383 + error messages. 1384 + 1385 + - Using `specialArgs` to provide arguments to all modules. This effectively 1386 + creates an incomplete module, and requires the user of the module to 1387 + manually pass the `specialArgs` to the configuration, which is error-prone, 1388 + verbose, and unnecessary. 1389 + 1390 + The nix file must contain a function that returns a module. 1391 + A module may itself be a function, so the file is often a function with two 1392 + positional arguments instead of one. See the example below. 1393 + 1394 + This function does not add support for deduplication and `disabledModules`, 1395 + although that could be achieved by wrapping the returned module and setting 1396 + the `_key` module attribute. 1397 + The reason for this omission is that the file path is not guaranteed to be 1398 + a unique identifier for the module, as two instances of the module may 1399 + reference different `arg`s in their closures. 1400 + 1401 + Example 1402 + 1403 + # lib.nix 1404 + imports = [ 1405 + (lib.modules.importApply ./module.nix { bar = bar; }) 1406 + ]; 1407 + 1408 + # module.nix 1409 + { bar }: 1410 + { lib, config, ... }: 1411 + { 1412 + options = ...; 1413 + config = ... bar ...; 1414 + } 1415 + 1416 + */ 1417 + importApply = 1418 + modulePath: staticArg: 1419 + lib.setDefaultModuleLocation modulePath (import modulePath staticArg); 1420 + 1369 1421 /* Use this function to import a JSON file as NixOS configuration. 1370 1422 1371 1423 modules.importJSON :: path -> attrs ··· 1415 1467 filterOverrides' 1416 1468 fixMergeModules 1417 1469 fixupOptionType # should be private? 1470 + importApply 1418 1471 importJSON 1419 1472 importTOML 1420 1473 mergeDefinitions
+8
lib/tests/modules.sh
··· 247 247 checkConfigOutput '^true$' "$@" ./define-enable.nix ./define-attrsOfSub-foo-if-enable.nix 248 248 checkConfigOutput '^true$' "$@" ./define-enable.nix ./define-attrsOfSub-foo-enable-if.nix 249 249 250 + # Check importApply 251 + checkConfigOutput '"abc"' config.value ./importApply.nix 252 + # importApply does not set a key. 253 + # Disabling the function file is not sufficient, because importApply can't reasonably assume that the key is unique. 254 + # e.g. user may call it multiple times with different arguments and expect each of the module to apply. 255 + # While this is excusable for the disabledModules aspect, it is not for the deduplication of modules. 256 + checkConfigOutput '"abc"' config.value ./importApply-disabling.nix 257 + 250 258 # Check disabledModules with config definitions and option declarations. 251 259 set -- config.enable ./define-enable.nix ./declare-enable.nix 252 260 checkConfigOutput '^true$' "$@"
+4
lib/tests/modules/importApply-disabling.nix
··· 1 + { 2 + imports = [ ./importApply.nix ]; 3 + disabledModules = [ ./importApply-function.nix ]; 4 + }
+5
lib/tests/modules/importApply-function.nix
··· 1 + { foo }: 2 + { lib, config, ... }: 3 + { 4 + value = foo; 5 + }
+5
lib/tests/modules/importApply.nix
··· 1 + { lib, ... }: 2 + { 3 + options.value = lib.mkOption { default = 1; }; 4 + imports = [ (lib.modules.importApply ./importApply-function.nix { foo = "abc"; }) ]; 5 + }