-
-
Notifications
You must be signed in to change notification settings - Fork 16.7k
lib/types.nix: implement getSubOptions for either #422272
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
base: master
Are you sure you want to change the base?
Conversation
@@ -205,6 +212,7 @@ let | |||
optionFlags = lib.mkOption { | |||
type = with lib.types; listOf str; | |||
default = [ ]; | |||
internal = true; |
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.
I'm not entirely sure about this one, from my reading of the module it looks like flags
isn't supposed to be set by users directly, it's calculated from the per-flag attributes.
A few thoughts on this PR:
|
I tested out the "make Alternatively this also suggests we could just update the 2 affected types in Edit: actually, the fully recursive change hurts some of the Also we can't just trivially update those two types in |
Another thing to consider here is With that context, we could consider changing |
6fe4329
to
21241df
Compare
The changes to
|
Also implement getSubModules and substSubModules. Because either is key to any recursively-defined type (such as `(pkgs.formats.json {}).type`), we can't just blindly recurse into both sides or we'll hit infinite recursion on a recursive type. To that end, this implementation only recurses into a child type if that type is submodule or another either. This means we'll generate documentation for `either str submodule` but not for `either str (attrsOf submodule)`. This change allows us to generate documentation for a bunch of options that are currently being missed.
The `example` key of a couple of options didn't evaluate, and this went unnoticed as this option wasn't part of generated documentation before.
Also fix usage of a deprecated function, as the documentation builder complains about that.
21241df
to
8726a0e
Compare
Rebased to fix merge conflict (conflict was due to the tor module being formatted) |
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.
Could you split the changes in types.nix and non-lib related things into a speerate PR? I.e. the fixes on some modules should be seperated. This is a common practise for us to avoid mixing lib changes with nixos fixes. I'll spend a bit more time these days looking at this. I fear that the changes in nixos might be due to a breaking change in the either type. Which me must preserve for downstream users. Moving the lib change out of this PR would make it more clear to us.
Mixing isn't so bad by itself. |
I certainly can split this up, though the non- If I split this up, would it be better to do one PR for all the non- |
To clarify on this point, the changes in nixos are to fix code that is currently broken but that brokenness wasn't noticed because the options aren't rendered into documentation until the All of this stuff could be detected by using the repl to poke around at the module structure, but it went unnoticed because none of these options ended up in the documentation manual before. So technically this |
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.
After looking into this for a short bit i am not sure if implementing getSubOptions
for either is the right approach to solve the documentation problem. getSubOptions
is only meant to documentation to automatically traverse options and types via `optionAttrSetToDocList´ with either (and derived types such as oneOf) it is possible to create recursive types.
In case of those reursive types there is no formally correct way to stop / break on a certain point. Thats why we didn't implement getSubOptions
historically i think.
Even before this PR either was already broken on recursive types - take this simple recursive type for example:
simpleJson = types.oneOf [ # renders into a tree of either
types.str
(types.attrsOf simpleJson)
(types.listOf simpleJson)
];
#... a module
{
options.foo = mkOption {
type = simpleJson;
};
}
This would fail to produce docs, because either has a recursive description, which would yield an infinitely long string in this case.
The actual JSON type solves this by overriding the description (this is also not ideal):
valueType =
nullOr (oneOf [
#...
])
// {
description = "JSON value";
};
We could maybe think about other solutions such as providing documentation hints, instead of trying to smartly recurse an infinite structure.
Some ideas how to solve this problem: Add something like a docsModel
/ docsType
which requires to be finite and is provided through the interface while creating the type?
This implements
getSubOptions
,getSubModules
, andsubstSubModules
for theeither
type. This allows us to generate documentation for a bunch of options that were getting missed before.Because
either
is the key to making recursive types, I had to be careful about the implementation here to avoid breaking on a type like(pkgs.formats.json {}).type
. To that end, this implementation only looks at child types if they'resubmodule
or anothereither
. This does mean types likeeither str (listOf submodule)
will still be missed, but I'm not sure how else to handle this besides recursively searching all nested types to see if any are equal (==
) to the current type, and I don't like that solution. I also considered simply stopping onattrsOf
andlistOf
and allowing other children (this would allow e.g.either str (nullOr submodule)
) but I thought that was sufficiently fragile. And I considered looking for any recursively-defined type in nixpkgs and overridinggetSubOptions
/getSubModules
explicitly, but that would mean types defined outside of nixpkgs could still be broken by this.For the case of
either submodule submodule
I decided thatgetSubOptions
should merge all returned options, butgetSubModules
andsubstSubModules
should ensure only one child actually has submodules. I don't expect this to matter because a type like that isn't really going to work, this logic makes more sense for something likeeither submodule (attrsOf submodule)
except for the fact that we won't recurse into theattrsOf
(to avoid problems on recursive types).With this change, I found a number of options whose documentation were missing or broken. Fixes for each of those modules are included as separate commits. Most of them were pretty straightforward, but the
tor
module had a lot of generated options and it wasn't always clear what the best way to handle it was.I tested this with
nix-build nixos/release.nix -A manual.aarch64-linux
, I'm not sure if there's any other documentation set that I should have tested too. I also didn't touch the lib tests, I'm not sure if this change should have an explicit test written for it, but I did make surelib/tests/modules.sh
passes. I'm also not sure if this change warrants a release note.Things done
nix.conf
? (See Nix manual)sandbox = relaxed
sandbox = true
nix-shell -p nixpkgs-review --run "nixpkgs-review rev HEAD"
. Note: all changes have to be committed, also see nixpkgs-review usage./result/bin/
)Add a 👍 reaction to pull requests you find important.