Unverified Commit 5323fbf7 authored by Silvan Mosberger's avatar Silvan Mosberger Committed by GitHub
Browse files

Merge pull request #254452 from flyingcircusio/lib-attrsToList

lib.attrsets.attrsToList: add function
parents 26858d74 d70633f9
Loading
Loading
Loading
Loading
+30 −0
Original line number Diff line number Diff line
@@ -542,6 +542,36 @@ rec {
    attrs:
    map (name: f name attrs.${name}) (attrNames attrs);

  /*
    Deconstruct an attrset to a list of name-value pairs as expected by [`builtins.listToAttrs`](https://nixos.org/manual/nix/stable/language/builtins.html#builtins-listToAttrs).
    Each element of the resulting list is an attribute set with these attributes:
    - `name` (string): The name of the attribute
    - `value` (any): The value of the attribute

    The following is always true:
    ```nix
    builtins.listToAttrs (attrsToList attrs) == attrs
    ```

    :::{.warning}
    The opposite is not always true. In general expect that
    ```nix
    attrsToList (builtins.listToAttrs list) != list
    ```

    This is because the `listToAttrs` removes duplicate names and doesn't preserve the order of the list.
    :::

    Example:
      attrsToList { foo = 1; bar = "asdf"; }
      => [ { name = "bar"; value = "asdf"; } { name = "foo"; value = 1; } ]

    Type:
      attrsToList :: AttrSet -> [ { name :: String; value :: Any; } ]

  */
  attrsToList = mapAttrsToList nameValuePair;


  /* Like `mapAttrs`, except that it recursively applies itself to
     the *leaf* attributes of a potentially-nested attribute set:
+2 −2
Original line number Diff line number Diff line
@@ -81,8 +81,8 @@ let
    inherit (self.attrsets) attrByPath hasAttrByPath setAttrByPath
      getAttrFromPath attrVals attrValues getAttrs catAttrs filterAttrs
      filterAttrsRecursive foldlAttrs foldAttrs collect nameValuePair mapAttrs
      mapAttrs' mapAttrsToList concatMapAttrs mapAttrsRecursive mapAttrsRecursiveCond
      genAttrs isDerivation toDerivation optionalAttrs
      mapAttrs' mapAttrsToList attrsToList concatMapAttrs mapAttrsRecursive
      mapAttrsRecursiveCond genAttrs isDerivation toDerivation optionalAttrs
      zipAttrsWithNames zipAttrsWith zipAttrs recursiveUpdateUntil
      recursiveUpdate matchAttrs overrideExisting showAttrPath getOutput getBin
      getLib getDev getMan chooseDevOutputs zipWithNames zip
+24 −0
Original line number Diff line number Diff line
@@ -20,6 +20,10 @@ let
    expr = (builtins.tryEval (builtins.seq expr "didn't throw"));
    expected = { success = false; value = false; };
  };
  testingEval = expr: {
    expr = (builtins.tryEval expr).success;
    expected = true;
  };
  testingDeepThrow = expr: testingThrow (builtins.deepSeq expr expr);

  testSanitizeDerivationName = { name, expected }:
@@ -816,6 +820,26 @@ runTests {
    expected = { a = 1; b = 2; };
  };

  testListAttrsReverse = let
    exampleAttrs = {foo=1; bar="asdf"; baz = [1 3 3 7]; fnord=null;};
    exampleSingletonList = [{name="foo"; value=1;}];
  in {
    expr = {
      isReverseToListToAttrs = builtins.listToAttrs (attrsToList exampleAttrs) == exampleAttrs;
      isReverseToAttrsToList = attrsToList (builtins.listToAttrs exampleSingletonList) == exampleSingletonList;
      testDuplicatePruningBehaviour = attrsToList (builtins.listToAttrs [{name="a"; value=2;} {name="a"; value=1;}]);
    };
    expected = {
      isReverseToAttrsToList = true;
      isReverseToListToAttrs = true;
      testDuplicatePruningBehaviour = [{name="a"; value=2;}];
    };
  };

  testAttrsToListsCanDealWithFunctions = testingEval (
    attrsToList { someFunc= a: a + 1;}
  );

# GENERATORS
# these tests assume attributes are converted to lists
# in alphabetical order