!wfudwzqQUiJYJnqfSY:nixos.org

NixOS Module System

151 Members
33 Servers

Load older messages


SenderMessageTime
14 Nov 2024
@nbp:mozilla.orgnbp *

enum are externally extendable in the module system. This is how desktopManagers / windowManagers are handled. Or why they got added a while back.
The idea of enums is that every module can add the new entry to enable it-self.

type = lib.types.enum [ "this-service-name" ];

makes sense, as opposed to many other languages, because options can be extended by multiple modules. Thus if all providers were to add extra declarations, you could have an option which enumerate all services which could be used as a provider.

16:48:23
@nbp:mozilla.orgnbp

Here is an example, where a module declare an enum with no "implementation":
https://github.com/NixOS/nixpkgs/blob/9956df1047bba4e000354f77229b0066d7f364e0/nixos/modules/virtualisation/podman/network-socket.nix#L33-L39

And another module provide an implementation for it:
https://github.com/NixOS/nixpkgs/blob/9956df1047bba4e000354f77229b0066d7f364e0/nixos/modules/virtualisation/podman/network-socket-ghostunnel.nix#L12C50-L18

16:59:10
@nbp:mozilla.orgnbp The module which declare the enum [] is equivalent to a contract and the module which declares it as enum [ "its-own-name" ] is equivalent to a provider. 17:02:09
@ibizaman:matrix.orgibizamanThat’s interesting. I have no idea how to compare both solutions, what’s their respective drawbacks and advantages. I took the structural typing approach because I knew that from my programming in Python and Go and it sticked with me. One potential drawback is discoverability although there’s surely a way to remediate to that.19:12:56
15 Nov 2024
@zoechi:matrix.orgzoechi joined the room.10:17:04
@nazarewk:matrix.orgkdn joined the room.15:08:21
17 Nov 2024
@orzklv:matrix.orgOrzklv joined the room.02:28:12
@frontear:matrix.orgfrontear joined the room.02:38:28
@frontear:matrix.orgfrontearApologies in advance for the massive text block, I'm gonna drop this here because I suspect I'll eventually get more visibility from people who can answer this.02:56:13
@frontear:matrix.orgfrontear

Could I get some insight into how the module system evaluates a type attrs of differing priorities? I've been working on a little thing that has descending attrsets with reducing priority, in hopes that when they merge some lower attrsets would be erased due to the priority difference but that doesnt seem to be happening. Not sure if I'm operating on a misunderstanding of priorities and merging or not though.

Here's a very minimal example of my issue including a description of what I'm expecting to happen.

let
  lib = import <nixpkgs/lib>;
in lib.evalModules {
  modules = [( { lib, ... }: {
    options = {
      foo = lib.mkOption {
        type = with lib.types; attrs;
      };
    };

    config = lib.mkMerge [
      { foo.bar = lib.mkForce {}; }
      { foo.bar.baz = lib.mkForce {}; }
    ];
  })];
}

You can save the above and use nix eval --file name.nix config or nix repl to view what happens as well, but this is what I get on my system:

nix-repl> :p (import ./test.nix).config
{
  foo = {
    bar = {
      baz = {
        _type = "override";
        content = { };
        priority = 50;
      };
    };
  };
}

From what I understand about both priorities and merging, bar from foo.bar should have a priority of "50" as defined by lib.mkForce, whereas bar from foo.bar.baz should have whatever the default priority is, since foo.bar.baz is the same as foo = { bar = { baz = ...; }; };, which won't have any priority. In that case, I expected foo.bar's priority to overrule foo.bar.baz from merging baz into it, and yet for some reason it does.

The weirdest part is yet to come.. when I switch them around, as in declare foo.bar.baz first and then foo.bar next, it correctly overrides. What's going on here? As far as I know merging is commutative and overriding wouldn't have been affected by it, and yet I'm seeing a sign of it not being the case. This is why I'm first suspecting that I have a misunderstanding regarding how merging works with and without overrides. Does anyone have insight into why this happens?

02:56:21
18 Nov 2024
@nbp:mozilla.orgnbpFrom my point of view the fact that the priority leaks in the value is an issue on its own. This should not be the case. All properties should have been discharged before calling the merge function … except when evaluating submodules, and even then this is open for debate.10:38:57
@nbp:mozilla.orgnbp Then the update (//) operator is not commutatif, as such the merging of values from the same priority should be ordered.
Use mkOrder / mkBefore / mkAfter to determine this order.
The order in which NixOS compute values is deliberately left undefined.
10:40:49
@nbp:mozilla.orgnbp

Oh … how did I missed it …

Properties are evaluated at options, not after, which is why using the value { bar = lib.mkForce {}; } and the value { bar.baz = lib.mkForce {}; } appears in the result, and that we can have one override the other as the update operator defines. Simply because properties are not evaluated, but the value are simply merged.

nix-repl> opt = { options.foo = lib.mkOption { type = lib.types.attrs; }; }
nix-repl> d0 = { foo = lib.mkForce { bar = {}; }; }
nix-repl> d1 = { foo = lib.mkForce { bar.baz = {}; }; }
nix-repl> :p (lib.evalModules { modules = [ opt d0 d1 ]; }).config
{ foo = { bar = { }; }; }
nix-repl> :p (lib.evalModules { modules = [ opt d1 d0 ]; }).config
{ foo = { bar = { baz = { }; }; }; }

Which does not have the priority leaking in the value of the option.

12:58:17
@frontear:matrix.orgfrontearoh my it was so obvious too21:38:52
@frontear:matrix.orgfrontearthanks for the response thats honestly somewhat embarrassing that i didnt catch that earlier21:39:14
@frontear:matrix.orgfrontear because like you said, the priority being there was a big sign 21:39:26
19 Nov 2024
@ibizaman:matrix.orgibizaman
In reply to @frontear:matrix.org
thanks for the response thats honestly somewhat embarrassing that i didnt catch that earlier
Hey sometimes you’re too much in the weeds, seeing the big picture becomes hard. Definitely happened to me more than once.
12:39:21
20 Nov 2024
@inayet:matrix.orginayet removed their profile picture.00:59:38
21 Nov 2024
@nerves:bark.lgbtJason Odoom changed their profile picture.02:51:47
@oddlama:matrix.orgoddlama joined the room.13:46:18
25 Nov 2024
@nullcube:matrix.orgNullCube joined the room.10:00:58
27 Nov 2024
@jopejoe1:matrix.orgjopejoe1 changed their display name from jopejoe1 to jopejoe1 [4094].18:19:03
6 Dec 2024
@cafkafk:fem.ggcafkafk 🏳️‍⚧️ changed their profile picture.03:43:51
11 Dec 2024
@dminca:matrix.orgdminca left the room.14:19:11
12 Dec 2024
@nam3l33ss:matrix.org·☽•Nameless☆•777 · ± changed their profile picture.14:34:25
13 Dec 2024
@getchoo:matrix.orggetchoo joined the room.09:28:33
@getchoo:matrix.orggetchoo

Hi all

I've come across a fun problem recently. I maintain a set of modules, and previously I had an option in a submodule, but now I've made it a regular (top-level) option. Per usual with changes like this, I wanted to use mkRenamedOptionModule to alias that option submodule option into the top-level option, but I got a nasty surprise with a cannot find attribute <old attribute name> error message

After doing some digging, I'm assuming this is because submodules sort of strip out the regular option data of their inner values, and only expose the fully evaluated configuration. Am I right here? Is there a good way around this?

Here's a minimum repro:

# repro.nix
let
  lib = import <nixpkgs/lib>;
in

lib.evalModules {
  modules = [
    {
      options = {
        # Create a submodule option
        aSubmodule = lib.mkOption {
          type = lib.types.submodule {
            options = {
              # With an inner option
              someSubmoduleOption = lib.mkEnableOption "something";
            };
          };

          default = { };
        };

        # And a top-level option
        aRegularOption = lib.mkEnableOption "something";
      };
    }

    # Alias them
    (lib.mkRenamedOptionModule [ "aSubmodule" "someSubmoduleOption" ] [ "aRegularOption" ])

    {
      # Test the alias
      # `nix eval --file repro.nix config.aRegularOption`
      aSubmodule.someSubmoduleOption = true;
      # ...but instead you get
      # error: evaluation aborted with the following error message: 'cannot find attribute `aSubmodule.someSubmoduleOption''
    }
  ];
}
09:33:27
@getchoo:matrix.orggetchoo *

Hi all

I've come across a fun problem recently. I maintain a set of modules, and previously I had an option in a submodule, but now I've made it a regular (top-level) option. Per usual with changes like this, I wanted to use mkRenamedOptionModule to alias that submodule option into the top-level option, but I got a nasty surprise with a cannot find attribute <old attribute name> error message

After doing some digging, I'm assuming this is because submodules sort of strip out the regular option data of their inner values, and only expose the fully evaluated configuration. Am I right here? Is there a good way around this?

Here's a minimum repro:

# repro.nix
let
  lib = import <nixpkgs/lib>;
in

lib.evalModules {
  modules = [
    {
      options = {
        # Create a submodule option
        aSubmodule = lib.mkOption {
          type = lib.types.submodule {
            options = {
              # With an inner option
              someSubmoduleOption = lib.mkEnableOption "something";
            };
          };

          default = { };
        };

        # And a top-level option
        aRegularOption = lib.mkEnableOption "something";
      };
    }

    # Alias them
    (lib.mkRenamedOptionModule [ "aSubmodule" "someSubmoduleOption" ] [ "aRegularOption" ])

    {
      # Test the alias
      # `nix eval --file repro.nix config.aRegularOption`
      aSubmodule.someSubmoduleOption = true;
      # ...but instead you get
      # error: evaluation aborted with the following error message: 'cannot find attribute `aSubmodule.someSubmoduleOption''
    }
  ];
}
09:33:54
@infinisil:matrix.orginfinisil

@getchoo:matrix.org Can't see a way around that problem tbh! Seems like you'll have to manually set it up

09:55:07
@nbp:mozilla.orgnbpThe problem likely comes from the fact that renamed options aggregate the values from the old definitions, ... Except that we have not yet defined a standard way to gather for 'any' type of submodules. Thus we do not have a set of option sets to work with. Submodules no longer expose the option set as part of their results. If you were to add it back locally, It might be possible to extend the doRename function to work with a set of options.10:20:01

Show newer messages


Back to Room ListRoom Version: 10