Merge pull request #65728 from Infinisil/types-eithers

lib/types: Add oneOf, extension of either to a list of types
This commit is contained in:
Aaron Andersen 2019-08-13 11:48:42 -04:00 committed by GitHub
commit 6f6468bef3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 55 additions and 13 deletions

View file

@ -71,6 +71,15 @@ checkConfigError 'The option value .* in .* is not of type.*positive integer.*'
checkConfigOutput "42" config.value ./declare-int-between-value.nix ./define-value-int-positive.nix
checkConfigError 'The option value .* in .* is not of type.*between.*-21 and 43.*inclusive.*' config.value ./declare-int-between-value.nix ./define-value-int-negative.nix
# Check either types
# types.either
checkConfigOutput "42" config.value ./declare-either.nix ./define-value-int-positive.nix
checkConfigOutput "\"24\"" config.value ./declare-either.nix ./define-value-string.nix
# types.oneOf
checkConfigOutput "42" config.value ./declare-oneOf.nix ./define-value-int-positive.nix
checkConfigOutput "[ ]" config.value ./declare-oneOf.nix ./define-value-list.nix
checkConfigOutput "\"24\"" config.value ./declare-oneOf.nix ./define-value-string.nix
# Check mkForce without submodules.
set -- config.enable ./declare-enable.nix ./define-enable.nix
checkConfigOutput "true" "$@"

View file

@ -0,0 +1,5 @@
{ lib, ... }: {
options.value = lib.mkOption {
type = lib.types.either lib.types.int lib.types.str;
};
}

View file

@ -0,0 +1,9 @@
{ lib, ... }: {
options.value = lib.mkOption {
type = lib.types.oneOf [
lib.types.int
(lib.types.listOf lib.types.int)
lib.types.str
];
};
}

View file

@ -443,6 +443,13 @@ rec {
functor = (defaultFunctor name) // { wrapped = [ t1 t2 ]; };
};
# Any of the types in the given list
oneOf = ts:
let
head' = if ts == [] then throw "types.oneOf needs to get at least one type in its argument" else head ts;
tail' = tail ts;
in foldl' either head' tail';
# Either value of type `finalType` or `coercedType`, the latter is
# converted to `finalType` using `coerceFunc`.
coercedTo = coercedType: coerceFunc: finalType:

View file

@ -346,6 +346,18 @@
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<varname>types.oneOf</varname> [ <replaceable>t1</replaceable> <replaceable>t2</replaceable> ... ]
</term>
<listitem>
<para>
Type <replaceable>t1</replaceable> or type <replaceable>t2</replaceable> and so forth,
e.g. <literal>with types; oneOf [ int str bool ]</literal>. Multiple definitions
cannot be merged.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>
<varname>types.coercedTo</varname> <replaceable>from</replaceable> <replaceable>f</replaceable> <replaceable>to</replaceable>

View file

@ -41,7 +41,7 @@ in
};
config = mkOption {
type = with types; attrsOf (either (either str (either int bool)) (listOf str));
type = with types; attrsOf (oneOf [ str int bool (listOf str) ]);
default = {};
description = ''
automysqlbackup configuration. Refer to

View file

@ -118,7 +118,7 @@ in {
};
serverProperties = mkOption {
type = with types; attrsOf (either bool (either int str));
type = with types; attrsOf (oneOf [ bool int str ]);
default = {};
example = literalExample ''
{

View file

@ -7,7 +7,7 @@ let
cfg = config.services.davmail;
configType = with types;
either (either (attrsOf configType) str) (either int bool) // {
oneOf [ (attrsOf configType) str int bool ] // {
description = "davmail config type (str, int, bool or attribute set thereof)";
};

View file

@ -447,7 +447,7 @@ in
};
config = mkOption {
type = with types; attrsOf (either bool (either str (listOf str)));
type = with types; attrsOf (oneOf [ bool str (listOf str) ]);
description = ''
The main.cf configuration file as key value set.
'';

View file

@ -331,7 +331,7 @@ in
};
config = mkOption {
type = with types; attrsOf (either bool (either str (listOf str)));
type = with types; attrsOf (oneOf [ bool str (listOf str) ]);
description = ''
Addon to postfix configuration
'';

View file

@ -30,7 +30,7 @@ in {
};
config = mkOption {
type = with types; attrsOf (either str (either int bool));
type = with types; attrsOf (oneOf [ str int bool ]);
default = {};
description = ''
The configuration to give rss2email.

View file

@ -62,9 +62,9 @@ let
concatStringsSep "\n" (toLines cfg.config);
semanticTypes = with types; rec {
zncAtom = nullOr (either (either int bool) str);
zncAtom = nullOr (oneOf [ int bool str ]);
zncAttr = attrsOf (nullOr zncConf);
zncAll = either (either zncAtom (listOf zncAtom)) zncAttr;
zncAll = oneOf [ zncAtom (listOf zncAtom) zncAttr ];
zncConf = attrsOf (zncAll // {
# Since this is a recursive type and the description by default contains
# the description of its subtypes, infinite recursion would occur without

View file

@ -36,7 +36,7 @@ in {
};
config = mkOption {
type = attrsOf (nullOr (either (either bool int) str));
type = attrsOf (nullOr (oneOf [ bool int str ]));
default = {};
example = literalExample ''
{

View file

@ -14,7 +14,7 @@ let
pkg = pkgs.limesurvey;
configType = with types; either (either (attrsOf configType) str) (either int bool) // {
configType = with types; oneOf [ (attrsOf configType) str int bool ] // {
description = "limesurvey config type (str, int, bool or attribute set thereof)";
};

View file

@ -215,7 +215,7 @@ in {
};
settings = let
configTypes = with types; either bool (either int (either float str));
configTypes = with types; oneOf [ bool int float str ];
# types.loaOf converts lists to sets
loaOf = t: with types; either (listOf t) (attrsOf t);
in mkOption {

View file

@ -226,7 +226,7 @@ in rec {
environment = mkOption {
default = {};
type = with types; attrsOf (nullOr (either str (either path package)));
type = with types; attrsOf (nullOr (oneOf [ str path package ]));
example = { PATH = "/foo/bar/bin"; LANG = "nl_NL.UTF-8"; };
description = "Environment variables passed to the service's processes.";
};

View file

@ -520,7 +520,7 @@ in
};
systemd.globalEnvironment = mkOption {
type = with types; attrsOf (nullOr (either str (either path package)));
type = with types; attrsOf (nullOr (oneOf [ str path package ]));
default = {};
example = { TZ = "CET"; };
description = ''