-
-
Notifications
You must be signed in to change notification settings - Fork 14.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
lib.modules: Let module declare options directly in bare submodule #156533
Changes from all commits
d030e21
58a8a48
0c09eb3
81f342d
11537c9
8baea8b
6b077c4
28aeae2
2050669
db08290
e162ed8
c90844a
c4b3870
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
{ lib, ... }: | ||
let | ||
inherit (lib) mkOption types; | ||
in | ||
{ | ||
options.bare-submodule.deep = mkOption { | ||
type = types.int; | ||
default = 2; | ||
}; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
{ lib, ... }: | ||
let | ||
inherit (lib) mkOption types; | ||
in | ||
{ | ||
options.bare-submodule.deep = mkOption { | ||
type = types.int; | ||
default = 2; | ||
}; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
{ config, lib, ... }: | ||
let | ||
inherit (lib) mkOption types; | ||
in | ||
{ | ||
options.bare-submodule = mkOption { | ||
type = types.submoduleWith { | ||
shorthandOnlyDefinesConfig = config.shorthandOnlyDefinesConfig; | ||
modules = [ | ||
{ | ||
options.nested = mkOption { | ||
type = types.int; | ||
default = 1; | ||
}; | ||
} | ||
]; | ||
}; | ||
}; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
{ config, lib, ... }: | ||
let | ||
inherit (lib) mkOption types; | ||
in | ||
{ | ||
options.bare-submodule = mkOption { | ||
type = types.submoduleWith { | ||
modules = [ ]; | ||
shorthandOnlyDefinesConfig = config.shorthandOnlyDefinesConfig; | ||
}; | ||
default = {}; | ||
}; | ||
|
||
# config-dependent options: won't recommend, but useful for making this test parameterized | ||
options.shorthandOnlyDefinesConfig = mkOption { | ||
default = false; | ||
}; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
{ lib, ... }: | ||
|
||
{ | ||
options.set = lib.mkOption { | ||
default = { }; | ||
example = { a = 1; }; | ||
type = lib.types.attrsOf lib.types.int; | ||
description = '' | ||
Some descriptive text | ||
''; | ||
}; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
bare-submodule.nested = 42; | ||
bare-submodule.deep = 420; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
{ shorthandOnlyDefinesConfig = true; } |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -562,14 +562,18 @@ rec { | |
let | ||
inherit (lib.modules) evalModules; | ||
|
||
coerce = unify: value: if isFunction value | ||
then setFunctionArgs (args: unify (value args)) (functionArgs value) | ||
else unify (if shorthandOnlyDefinesConfig then { config = value; } else value); | ||
shorthandToModule = if shorthandOnlyDefinesConfig == false | ||
then value: value | ||
else value: { config = value; }; | ||
|
||
allModules = defs: imap1 (n: { value, file }: | ||
if isAttrs value || isFunction value then | ||
# Annotate the value with the location of its definition for better error messages | ||
coerce (lib.modules.unifyModuleSyntax file "${toString file}-${toString n}") value | ||
if isFunction value | ||
then setFunctionArgs | ||
(args: lib.modules.unifyModuleSyntax file "${toString file}-${toString n}" (value args)) | ||
(functionArgs value) | ||
else if isAttrs value | ||
then | ||
lib.modules.unifyModuleSyntax file "${toString file}-${toString n}" (shorthandToModule value) | ||
else value | ||
) defs; | ||
|
||
|
@@ -637,7 +641,11 @@ rec { | |
then lhs.specialArgs // rhs.specialArgs | ||
else throw "A submoduleWith option is declared multiple times with the same specialArgs \"${toString (attrNames intersecting)}\""; | ||
shorthandOnlyDefinesConfig = | ||
if lhs.shorthandOnlyDefinesConfig == rhs.shorthandOnlyDefinesConfig | ||
if lhs.shorthandOnlyDefinesConfig == null | ||
then rhs.shorthandOnlyDefinesConfig | ||
else if rhs.shorthandOnlyDefinesConfig == null | ||
then lhs.shorthandOnlyDefinesConfig | ||
else if lhs.shorthandOnlyDefinesConfig == rhs.shorthandOnlyDefinesConfig | ||
Comment on lines
+644
to
+648
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since let
lib = import ./lib;
in lib.evalModules {
modules = [
{
options.foo = lib.mkOption {
type = lib.types.submoduleWith {
modules = [];
shorthandOnlyDefinesConfig = null;
};
};
config.foo.bar = 10;
}
];
} with this PR currently throws
it should instead be something like
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I disagree. You'd have to read the implementation to find that null is acceptable in some situations. To keep things simple and, I've decided to default it to |
||
then lhs.shorthandOnlyDefinesConfig | ||
else throw "A submoduleWith option is declared multiple times with conflicting shorthandOnlyDefinesConfig values"; | ||
}; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should have a comment explaining the reasoning behind this: How it's a bit hacky but needed as a default, that
null
is only an internally valid value, that it's only safe here because of the merging function patch and because it's always going to be merged with at least one other module.In the future this might become obsolete with #162398
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added