Add setFunctionArgs lib function.

Among other things, this will allow *2nix tools to output plain data
while still being composable with the traditional
callPackage/.override interfaces.

Changed files
+60 -33
lib
nixos
doc
manual
lib
modules
tests
pkgs
build-support
emacs
development
beam-modules
haskell-modules
os-specific
darwin
apple-source-releases
top-level
+7 -7
lib/customisation.nix
···
{ lib }:
let
-
inherit (builtins) attrNames isFunction;
+
inherit (builtins) attrNames;
in
···
makeOverridable = f: origArgs:
let
ff = f origArgs;
-
overrideWith = newArgs: origArgs // (if builtins.isFunction newArgs then newArgs origArgs else newArgs);
+
overrideWith = newArgs: origArgs // (if lib.isFunction newArgs then newArgs origArgs else newArgs);
in
if builtins.isAttrs ff then (ff // {
override = newArgs: makeOverridable f (overrideWith newArgs);
···
${if ff ? overrideAttrs then "overrideAttrs" else null} = fdrv:
makeOverridable (args: (f args).overrideAttrs fdrv) origArgs;
})
-
else if builtins.isFunction ff then {
+
else if lib.isFunction ff then {
override = newArgs: makeOverridable f (overrideWith newArgs);
__functor = self: ff;
overrideDerivation = throw "overrideDerivation not yet supported for functors";
···
*/
callPackageWith = autoArgs: fn: args:
let
-
f = if builtins.isFunction fn then fn else import fn;
-
auto = builtins.intersectAttrs (builtins.functionArgs f) autoArgs;
+
f = if lib.isFunction fn then fn else import fn;
+
auto = builtins.intersectAttrs (lib.functionArgs f) autoArgs;
in makeOverridable f (auto // args);
···
individual attributes. */
callPackagesWith = autoArgs: fn: args:
let
-
f = if builtins.isFunction fn then fn else import fn;
-
auto = builtins.intersectAttrs (builtins.functionArgs f) autoArgs;
+
f = if lib.isFunction fn then fn else import fn;
+
auto = builtins.intersectAttrs (lib.functionArgs f) autoArgs;
origArgs = auto // args;
pkgs = f origArgs;
mkAttrOverridable = name: pkg: makeOverridable (newArgs: (f newArgs).${name}) origArgs;
+2 -2
lib/debug.nix
···
let
-
inherit (builtins) trace attrNamesToStr isAttrs isFunction isList isInt
+
inherit (builtins) trace attrNamesToStr isAttrs isList isInt
isString isBool head substring attrNames;
-
inherit (lib) all id mapAttrsFlatten elem;
+
inherit (lib) all id mapAttrsFlatten elem isFunction;
in
+2 -2
lib/default.nix
···
inherit (builtins) add addErrorContext attrNames
concatLists deepSeq elem elemAt filter genericClosure genList
-
getAttr hasAttr head isAttrs isBool isFunction isInt isList
+
getAttr hasAttr head isAttrs isBool isInt isList
isString length lessThan listToAttrs pathExists readFile
replaceStrings seq stringLength sub substring tail;
inherit (trivial) id const concat or and boolToString mergeAttrs
flip mapNullable inNixShell min max importJSON warn info
-
nixpkgsVersion mod;
+
nixpkgsVersion mod functionArgs setFunctionArgs isFunction;
inherit (fixedPoints) fix fix' extends composeExtensions
makeExtensible makeExtensibleWithCustomName;
+4 -4
lib/deprecated.nix
···
{ lib }:
let
-
inherit (builtins) isFunction head tail isList isAttrs isInt attrNames;
+
inherit (builtins) head tail isList isAttrs isInt attrNames;
in
···
f: # the function applied to the arguments
initial: # you pass attrs, the functions below are passing a function taking the fix argument
let
-
takeFixed = if isFunction initial then initial else (fixed : initial); # transform initial to an expression always taking the fixed argument
+
takeFixed = if lib.isFunction initial then initial else (fixed : initial); # transform initial to an expression always taking the fixed argument
tidy = args:
let # apply all functions given in "applyPreTidy" in sequence
applyPreTidyFun = fold ( n: a: x: n ( a x ) ) lib.id (maybeAttr "applyPreTidy" [] args);
···
let args = takeFixed fixed;
mergeFun = args.${n};
in if isAttrs x then (mergeFun args x)
-
else assert isFunction x;
+
else assert lib.isFunction x;
mergeFun args (x ( args // { inherit fixed; }));
in overridableDelayableArgs f newArgs;
in
···
if isAttrs x then
if x ? outPath then "derivation"
else "attrs"
-
else if isFunction x then "function"
+
else if lib.isFunction x then "function"
else if isList x then "list"
else if x == true then "bool"
else if x == false then "bool"
+3 -1
lib/generators.nix
···
libAttr = lib.attrsets;
flipMapAttrs = flip libAttr.mapAttrs;
+
+
inherit (lib) isFunction;
in
rec {
···
else if isString v then "\"" + v + "\""
else if null == v then "null"
else if isFunction v then
-
let fna = functionArgs v;
+
let fna = lib.functionArgs v;
showFnas = concatStringsSep "," (libAttr.mapAttrsToList
(name: hasDefVal: if hasDefVal then "(${name})" else name)
fna);
+1 -1
lib/modules.nix
···
# a module will resolve strictly the attributes used as argument but
# not their values. The values are forwarding the result of the
# evaluation of the option.
-
requiredArgs = builtins.attrNames (builtins.functionArgs f);
+
requiredArgs = builtins.attrNames (lib.functionArgs f);
context = name: ''while evaluating the module argument `${name}' in "${key}":'';
extraArgs = builtins.listToAttrs (map (name: {
inherit name;
+26 -1
lib/trivial.nix
···
# Pull in some builtins not included elsewhere.
inherit (builtins)
-
pathExists readFile isBool isFunction
+
pathExists readFile isBool
isInt add sub lessThan
seq deepSeq genericClosure;
···
*/
warn = msg: builtins.trace "WARNING: ${msg}";
info = msg: builtins.trace "INFO: ${msg}";
+
+
# | Add metadata about expected function arguments to a function.
+
# The metadata should match the format given by
+
# builtins.functionArgs, i.e. a set from expected argument to a bool
+
# representing whether that argument has a default or not.
+
# setFunctionArgs : (a → b) → Map String Bool → (a → b)
+
#
+
# This function is necessary because you can't dynamically create a
+
# function of the { a, b ? foo, ... }: format, but some facilities
+
# like callPackage expect to be able to query expected arguments.
+
setFunctionArgs = f: args:
+
{ # TODO: Should we add call-time "type" checking like built in?
+
__functor = self: f;
+
__functionArgs = args;
+
};
+
+
# | Extract the expected function arguments from a function.
+
# This works both with nix-native { a, b ? foo, ... }: style
+
# functions and functions with args set with 'setFunctionArgs'. It
+
# has the same return type and semantics as builtins.functionArgs.
+
# setFunctionArgs : (a → b) → Map String Bool.
+
functionArgs = f: f.__functionArgs or (builtins.functionArgs f);
+
+
isFunction = f: builtins.isFunction f ||
+
(f ? __functor && isFunction (f.__functor f));
}
+1 -1
nixos/doc/manual/default.nix
···
substFunction = x:
if builtins.isAttrs x then lib.mapAttrs (name: substFunction) x
else if builtins.isList x then map substFunction x
-
else if builtins.isFunction x then "<function>"
+
else if lib.isFunction x then "<function>"
else x;
# Clean up declaration sites to not refer to the NixOS source tree.
+1 -1
nixos/lib/testing.nix
···
testScript' =
# Call the test script with the computed nodes.
-
if builtins.isFunction testScript
+
if lib.isFunction testScript
then testScript { inherit nodes; }
else testScript;
+3 -3
nixos/modules/misc/nixpkgs.nix
···
let
isConfig = x:
-
builtins.isAttrs x || builtins.isFunction x;
+
builtins.isAttrs x || lib.isFunction x;
optCall = f: x:
-
if builtins.isFunction f
+
if lib.isFunction f
then f x
else f;
···
overlayType = mkOptionType {
name = "nixpkgs-overlay";
description = "nixpkgs overlay";
-
check = builtins.isFunction;
+
check = lib.isFunction;
merge = lib.mergeOneOption;
};
+1 -1
nixos/modules/profiles/clone-config.nix
···
# you should use files).
moduleFiles =
# FIXME: use typeOf (Nix 1.6.1).
-
filter (x: !isAttrs x && !builtins.isFunction x) modules;
+
filter (x: !isAttrs x && !lib.isFunction x) modules;
# Partition module files because between NixOS and non-NixOS files. NixOS
# files may change if the repository is updated.
+1 -1
nixos/tests/make-test.nix
···
with import ../lib/testing.nix { inherit system; };
-
makeTest (if builtins.isFunction f then f (args // { inherit pkgs; inherit (pkgs) lib; }) else f)
+
makeTest (if lib.isFunction f then f (args // { inherit pkgs; inherit (pkgs) lib; }) else f)
+1 -1
pkgs/build-support/emacs/wrapper.nix
···
let
explicitRequires =
-
if builtins.isFunction packagesFun
+
if lib.isFunction packagesFun
then packagesFun self
else packagesFun;
in
+2 -2
pkgs/development/beam-modules/lib.nix
···
*/
callPackageWith = autoArgs: fn: args:
let
-
f = if builtins.isFunction fn then fn else import fn;
-
auto = builtins.intersectAttrs (builtins.functionArgs f) autoArgs;
+
f = if pkgs.lib.isFunction fn then fn else import fn;
+
auto = builtins.intersectAttrs (stdenv.lib.functionArgs f) autoArgs;
in f (auto // args);
callPackage = callPackageWith pkgs;
+2 -2
pkgs/development/haskell-modules/make-package-set.nix
···
# lost on `.override`) but determine the auto-args based on `drv` (the problem here
# is that nix has no way to "passthrough" args while preserving the reflection
# info that callPackage uses to determine the arguments).
-
drv = if builtins.isFunction fn then fn else import fn;
-
auto = builtins.intersectAttrs (builtins.functionArgs drv) scope;
+
drv = if stdenv.lib.isFunction fn then fn else import fn;
+
auto = builtins.intersectAttrs (stdenv.lib.functionArgs drv) scope;
# this wraps the `drv` function to add a `overrideScope` function to the result.
drvScope = allArgs: drv allArgs // {
+1 -1
pkgs/os-specific/darwin/apple-source-releases/default.nix
···
# There should be an IOVideo here, but they haven't released it :(
};
-
IOKitSrcs = stdenv.lib.mapAttrs (name: value: if builtins.isFunction value then value name else value) IOKitSpecs;
+
IOKitSrcs = stdenv.lib.mapAttrs (name: value: if stdenv.lib.isFunction value then value name else value) IOKitSpecs;
adv_cmds = applePackage "adv_cmds" "osx-10.5.8" "102ssayxbg9wb35mdmhswbnw0bg7js3pfd8fcbic83c5q3bqa6c6" {};
+1 -1
pkgs/top-level/default.nix
···
# { /* the config */ } and
# { pkgs, ... } : { /* the config */ }
config =
-
if builtins.isFunction configExpr
+
if lib.isFunction configExpr
then configExpr { inherit pkgs; }
else configExpr;
+1 -1
pkgs/top-level/python-packages.nix
···
makeOverridablePythonPackage = f: origArgs:
let
ff = f origArgs;
-
overrideWith = newArgs: origArgs // (if builtins.isFunction newArgs then newArgs origArgs else newArgs);
+
overrideWith = newArgs: origArgs // (if pkgs.lib.isFunction newArgs then newArgs origArgs else newArgs);
in
if builtins.isAttrs ff then (ff // {
overridePythonAttrs = newArgs: makeOverridablePythonPackage f (overrideWith newArgs);