summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorShea Levy <shea@shealevy.com>2018-01-31 14:02:19 -0500
committerShea Levy <shea@shealevy.com>2018-01-31 14:02:19 -0500
commit943592f69850fd07dd2422da062b1c1ebc45974d (patch)
tree3376a06cd3ab25a1622c8f320573ab09b55a9470 /lib
parent0d7a0d7572d35526ddf34b6d011b7b88a8904b36 (diff)
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.
Diffstat (limited to 'lib')
-rw-r--r--lib/customisation.nix14
-rw-r--r--lib/debug.nix4
-rw-r--r--lib/default.nix4
-rw-r--r--lib/deprecated.nix8
-rw-r--r--lib/generators.nix4
-rw-r--r--lib/modules.nix2
-rw-r--r--lib/trivial.nix27
7 files changed, 45 insertions, 18 deletions
diff --git a/lib/customisation.nix b/lib/customisation.nix
index 3988f4e9b690..823395f04d4a 100644
--- a/lib/customisation.nix
+++ b/lib/customisation.nix
@@ -1,7 +1,7 @@
{ lib }:
let
- inherit (builtins) attrNames isFunction;
+ inherit (builtins) attrNames;
in
@@ -72,7 +72,7 @@ rec {
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);
@@ -81,7 +81,7 @@ rec {
${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";
@@ -112,8 +112,8 @@ rec {
*/
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);
@@ -122,8 +122,8 @@ rec {
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;
diff --git a/lib/debug.nix b/lib/debug.nix
index 646ef220ad0a..d163e60b6957 100644
--- a/lib/debug.nix
+++ b/lib/debug.nix
@@ -2,10 +2,10 @@
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
diff --git a/lib/default.nix b/lib/default.nix
index 6d2a95e559c8..97d7c10192a7 100644
--- a/lib/default.nix
+++ b/lib/default.nix
@@ -51,12 +51,12 @@ let
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;
diff --git a/lib/deprecated.nix b/lib/deprecated.nix
index 2a0f5a55bf14..34cf336d1f42 100644
--- a/lib/deprecated.nix
+++ b/lib/deprecated.nix
@@ -1,6 +1,6 @@
{ lib }:
let
- inherit (builtins) isFunction head tail isList isAttrs isInt attrNames;
+ inherit (builtins) head tail isList isAttrs isInt attrNames;
in
@@ -53,7 +53,7 @@ rec {
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);
@@ -63,7 +63,7 @@ rec {
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
@@ -374,7 +374,7 @@ rec {
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"
diff --git a/lib/generators.nix b/lib/generators.nix
index f207033c9554..73017f2c6796 100644
--- a/lib/generators.nix
+++ b/lib/generators.nix
@@ -14,6 +14,8 @@ let
libAttr = lib.attrsets;
flipMapAttrs = flip libAttr.mapAttrs;
+
+ inherit (lib) isFunction;
in
rec {
@@ -110,7 +112,7 @@ 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);
diff --git a/lib/modules.nix b/lib/modules.nix
index 8c3584bbbf4c..654c4c588de6 100644
--- a/lib/modules.nix
+++ b/lib/modules.nix
@@ -155,7 +155,7 @@ rec {
# 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;
diff --git a/lib/trivial.nix b/lib/trivial.nix
index c452c7b65bc1..d8d51298143e 100644
--- a/lib/trivial.nix
+++ b/lib/trivial.nix
@@ -52,7 +52,7 @@ rec {
# Pull in some builtins not included elsewhere.
inherit (builtins)
- pathExists readFile isBool isFunction
+ pathExists readFile isBool
isInt add sub lessThan
seq deepSeq genericClosure;
@@ -99,4 +99,29 @@ rec {
*/
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));
}