nixpkgs mirror (for testing) github.com/NixOS/nixpkgs
nix
at python-updates 2249 lines 52 kB view raw
1/** 2 Operations on attribute sets. 3*/ 4{ lib }: 5 6let 7 inherit (builtins) head length typeOf; 8 inherit (lib.asserts) assertMsg; 9 inherit (lib.trivial) oldestSupportedReleaseIsAtLeast mergeAttrs; 10 inherit (lib.strings) 11 concatStringsSep 12 concatMapStringsSep 13 escapeNixIdentifier 14 sanitizeDerivationName 15 ; 16 inherit (lib.lists) 17 filter 18 foldr 19 foldl' 20 concatMap 21 elemAt 22 all 23 partition 24 groupBy 25 take 26 foldl 27 ; 28in 29 30rec { 31 inherit (builtins) 32 attrNames 33 listToAttrs 34 hasAttr 35 isAttrs 36 getAttr 37 removeAttrs 38 intersectAttrs 39 ; 40 41 /** 42 Returns an attribute from nested attribute sets. 43 44 Nix has an [attribute selection operator `.`](https://nixos.org/manual/nix/stable/language/operators#attribute-selection) which is sufficient for such queries, as long as the number of attributes is static. For example: 45 46 ```nix 47 (x.a.b or 6) == attrByPath ["a" "b"] 6 x 48 # and 49 (x.${f p}."example.com" or 6) == attrByPath [ (f p) "example.com" ] 6 x 50 ``` 51 52 # Inputs 53 54 `attrPath` 55 56 : A list of strings representing the attribute path to return from `set` 57 58 `default` 59 60 : Default value if `attrPath` does not resolve to an existing value 61 62 `set` 63 64 : The nested attribute set to select values from 65 66 # Type 67 68 ``` 69 attrByPath :: [String] -> Any -> AttrSet -> Any 70 ``` 71 72 # Examples 73 :::{.example} 74 ## `lib.attrsets.attrByPath` usage example 75 76 ```nix 77 x = { a = { b = 3; }; } 78 # ["a" "b"] is equivalent to x.a.b 79 # 6 is a default value to return if the path does not exist in attrset 80 attrByPath ["a" "b"] 6 x 81 => 3 82 attrByPath ["z" "z"] 6 x 83 => 6 84 ``` 85 86 ::: 87 */ 88 attrByPath = 89 attrPath: default: set: 90 let 91 lenAttrPath = length attrPath; 92 attrByPath' = 93 n: s: 94 ( 95 if n == lenAttrPath then 96 s 97 else 98 ( 99 let 100 attr = elemAt attrPath n; 101 in 102 if s ? ${attr} then attrByPath' (n + 1) s.${attr} else default 103 ) 104 ); 105 in 106 attrByPath' 0 set; 107 108 /** 109 Returns if an attribute from nested attribute set exists. 110 111 Nix has a [has attribute operator `?`](https://nixos.org/manual/nix/stable/language/operators#has-attribute), which is sufficient for such queries, as long as the number of attributes is static. For example: 112 113 ```nix 114 (x?a.b) == hasAttrByPath ["a" "b"] x 115 # and 116 (x?${f p}."example.com") == hasAttrByPath [ (f p) "example.com" ] x 117 ``` 118 119 **Laws**: 120 1. ```nix 121 hasAttrByPath [] x == true 122 ``` 123 124 # Inputs 125 126 `attrPath` 127 128 : A list of strings representing the attribute path to check from `set` 129 130 `set` 131 132 : The nested attribute set to check 133 134 # Type 135 136 ``` 137 hasAttrByPath :: [String] -> AttrSet -> Bool 138 ``` 139 140 # Examples 141 :::{.example} 142 ## `lib.attrsets.hasAttrByPath` usage example 143 144 ```nix 145 x = { a = { b = 3; }; } 146 hasAttrByPath ["a" "b"] x 147 => true 148 hasAttrByPath ["z" "z"] x 149 => false 150 hasAttrByPath [] (throw "no need") 151 => true 152 ``` 153 154 ::: 155 */ 156 hasAttrByPath = 157 attrPath: e: 158 let 159 lenAttrPath = length attrPath; 160 hasAttrByPath' = 161 n: s: 162 ( 163 n == lenAttrPath 164 || ( 165 let 166 attr = elemAt attrPath n; 167 in 168 if s ? ${attr} then hasAttrByPath' (n + 1) s.${attr} else false 169 ) 170 ); 171 in 172 hasAttrByPath' 0 e; 173 174 /** 175 Returns the longest prefix of an attribute path that refers to an existing attribute in a nesting of attribute sets. 176 177 Can be used after [`mapAttrsRecursiveCond`](#function-library-lib.attrsets.mapAttrsRecursiveCond) to apply a condition, 178 although this will evaluate the predicate function on sibling attributes as well. 179 180 Note that the empty attribute path is valid for all values, so this function only throws an exception if any of its inputs does. 181 182 **Laws**: 183 1. ```nix 184 attrsets.longestValidPathPrefix [] x == [] 185 ``` 186 187 2. ```nix 188 hasAttrByPath (attrsets.longestValidPathPrefix p x) x == true 189 ``` 190 191 # Inputs 192 193 `attrPath` 194 195 : A list of strings representing the longest possible path that may be returned. 196 197 `v` 198 199 : The nested attribute set to check. 200 201 # Type 202 203 ``` 204 attrsets.longestValidPathPrefix :: [String] -> Value -> [String] 205 ``` 206 207 # Examples 208 :::{.example} 209 ## `lib.attrsets.longestValidPathPrefix` usage example 210 211 ```nix 212 x = { a = { b = 3; }; } 213 attrsets.longestValidPathPrefix ["a" "b" "c"] x 214 => ["a" "b"] 215 attrsets.longestValidPathPrefix ["a"] x 216 => ["a"] 217 attrsets.longestValidPathPrefix ["z" "z"] x 218 => [] 219 attrsets.longestValidPathPrefix ["z" "z"] (throw "no need") 220 => [] 221 ``` 222 223 ::: 224 */ 225 longestValidPathPrefix = 226 attrPath: v: 227 let 228 lenAttrPath = length attrPath; 229 getPrefixForSetAtIndex = 230 # The nested attribute set to check, if it is an attribute set, which 231 # is not a given. 232 remainingSet: 233 # The index of the attribute we're about to check, as well as 234 # the length of the prefix we've already checked. 235 remainingPathIndex: 236 237 if remainingPathIndex == lenAttrPath then 238 # All previously checked attributes exist, and no attr names left, 239 # so we return the whole path. 240 attrPath 241 else 242 let 243 attr = elemAt attrPath remainingPathIndex; 244 in 245 if remainingSet ? ${attr} then 246 getPrefixForSetAtIndex remainingSet.${attr} # advance from the set to the attribute value 247 (remainingPathIndex + 1) # advance the path 248 else 249 # The attribute doesn't exist, so we return the prefix up to the 250 # previously checked length. 251 take remainingPathIndex attrPath; 252 in 253 getPrefixForSetAtIndex v 0; 254 255 /** 256 Create a new attribute set with `value` set at the nested attribute location specified in `attrPath`. 257 258 # Inputs 259 260 `attrPath` 261 262 : A list of strings representing the attribute path to set 263 264 `value` 265 266 : The value to set at the location described by `attrPath` 267 268 # Type 269 270 ``` 271 setAttrByPath :: [String] -> Any -> AttrSet 272 ``` 273 274 # Examples 275 :::{.example} 276 ## `lib.attrsets.setAttrByPath` usage example 277 278 ```nix 279 setAttrByPath ["a" "b"] 3 280 => { a = { b = 3; }; } 281 ``` 282 283 ::: 284 */ 285 setAttrByPath = 286 attrPath: value: 287 let 288 len = length attrPath; 289 atDepth = n: if n == len then value else { ${elemAt attrPath n} = atDepth (n + 1); }; 290 in 291 atDepth 0; 292 293 /** 294 Like `attrByPath`, but without a default value. If it doesn't find the 295 path it will throw an error. 296 297 Nix has an [attribute selection operator](https://nixos.org/manual/nix/stable/language/operators#attribute-selection) which is sufficient for such queries, as long as the number of attributes is static. For example: 298 299 ```nix 300 x.a.b == getAttrFromPath ["a" "b"] x 301 # and 302 x.${f p}."example.com" == getAttrFromPath [ (f p) "example.com" ] x 303 ``` 304 305 # Inputs 306 307 `attrPath` 308 309 : A list of strings representing the attribute path to get from `set` 310 311 `set` 312 313 : The nested attribute set to find the value in. 314 315 # Type 316 317 ``` 318 getAttrFromPath :: [String] -> AttrSet -> Any 319 ``` 320 321 # Examples 322 :::{.example} 323 ## `lib.attrsets.getAttrFromPath` usage example 324 325 ```nix 326 x = { a = { b = 3; }; } 327 getAttrFromPath ["a" "b"] x 328 => 3 329 getAttrFromPath ["z" "z"] x 330 => error: cannot find attribute `z.z' 331 ``` 332 333 ::: 334 */ 335 getAttrFromPath = 336 attrPath: set: 337 attrByPath attrPath (abort ("cannot find attribute '" + concatStringsSep "." attrPath + "'")) set; 338 339 /** 340 Map each attribute in the given set and merge them into a new attribute set. 341 342 # Inputs 343 344 `f` 345 346 : 1\. Function argument 347 348 `v` 349 350 : 2\. Function argument 351 352 # Type 353 354 ``` 355 concatMapAttrs :: (String -> a -> AttrSet) -> AttrSet -> AttrSet 356 ``` 357 358 # Examples 359 :::{.example} 360 ## `lib.attrsets.concatMapAttrs` usage example 361 362 ```nix 363 concatMapAttrs 364 (name: value: { 365 ${name} = value; 366 ${name + value} = value; 367 }) 368 { x = "a"; y = "b"; } 369 => { x = "a"; xa = "a"; y = "b"; yb = "b"; } 370 ``` 371 372 ::: 373 */ 374 concatMapAttrs = f: v: foldl' mergeAttrs { } (attrValues (mapAttrs f v)); 375 376 /** 377 Update or set specific paths of an attribute set. 378 379 Takes a list of updates to apply and an attribute set to apply them to, 380 and returns the attribute set with the updates applied. Updates are 381 represented as `{ path = ...; update = ...; }` values, where `path` is a 382 list of strings representing the attribute path that should be updated, 383 and `update` is a function that takes the old value at that attribute path 384 as an argument and returns the new 385 value it should be. 386 387 Properties: 388 389 - Updates to deeper attribute paths are applied before updates to more 390 shallow attribute paths 391 392 - Multiple updates to the same attribute path are applied in the order 393 they appear in the update list 394 395 - If any but the last `path` element leads into a value that is not an 396 attribute set, an error is thrown 397 398 - If there is an update for an attribute path that doesn't exist, 399 accessing the argument in the update function causes an error, but 400 intermediate attribute sets are implicitly created as needed 401 402 # Type 403 404 ``` 405 updateManyAttrsByPath :: [{ path :: [String]; update :: (Any -> Any); }] -> AttrSet -> AttrSet 406 ``` 407 408 # Examples 409 :::{.example} 410 ## `lib.attrsets.updateManyAttrsByPath` usage example 411 412 ```nix 413 updateManyAttrsByPath [ 414 { 415 path = [ "a" "b" ]; 416 update = old: { d = old.c; }; 417 } 418 { 419 path = [ "a" "b" "c" ]; 420 update = old: old + 1; 421 } 422 { 423 path = [ "x" "y" ]; 424 update = old: "xy"; 425 } 426 ] { a.b.c = 0; } 427 => { a = { b = { d = 1; }; }; x = { y = "xy"; }; } 428 ``` 429 430 ::: 431 */ 432 updateManyAttrsByPath = 433 let 434 # When recursing into attributes, instead of updating the `path` of each 435 # update using `tail`, which needs to allocate an entirely new list, 436 # we just pass a prefix length to use and make sure to only look at the 437 # path without the prefix length, so that we can reuse the original list 438 # entries. 439 go = 440 prefixLength: hasValue: value: updates: 441 let 442 # Splits updates into ones on this level (split.right) 443 # And ones on levels further down (split.wrong) 444 split = partition (el: length el.path == prefixLength) updates; 445 446 # Groups updates on further down levels into the attributes they modify 447 nested = groupBy (el: elemAt el.path prefixLength) split.wrong; 448 449 # Applies only nested modification to the input value 450 withNestedMods = 451 # Return the value directly if we don't have any nested modifications 452 if split.wrong == [ ] then 453 if hasValue then 454 value 455 else 456 # Throw an error if there is no value. This `head` call here is 457 # safe, but only in this branch since `go` could only be called 458 # with `hasValue == false` for nested updates, in which case 459 # it's also always called with at least one update 460 let 461 updatePath = (head split.right).path; 462 in 463 throw ( 464 "updateManyAttrsByPath: Path '${showAttrPath updatePath}' does " 465 + "not exist in the given value, but the first update to this " 466 + "path tries to access the existing value." 467 ) 468 else 469 # If there are nested modifications, try to apply them to the value 470 if !hasValue then 471 # But if we don't have a value, just use an empty attribute set 472 # as the value, but simplify the code a bit 473 mapAttrs (name: go (prefixLength + 1) false null) nested 474 else if isAttrs value then 475 # If we do have a value and it's an attribute set, override it 476 # with the nested modifications 477 value // mapAttrs (name: go (prefixLength + 1) (value ? ${name}) value.${name}) nested 478 else 479 # However if it's not an attribute set, we can't apply the nested 480 # modifications, throw an error 481 let 482 updatePath = (head split.wrong).path; 483 in 484 throw ( 485 "updateManyAttrsByPath: Path '${showAttrPath updatePath}' needs to " 486 + "be updated, but path '${showAttrPath (take prefixLength updatePath)}' " 487 + "of the given value is not an attribute set, so we can't " 488 + "update an attribute inside of it." 489 ); 490 491 # We get the final result by applying all the updates on this level 492 # after having applied all the nested updates 493 # We use foldl instead of foldl' so that in case of multiple updates, 494 # intermediate values aren't evaluated if not needed 495 in 496 foldl (acc: el: el.update acc) withNestedMods split.right; 497 498 in 499 updates: value: go 0 true value updates; 500 501 /** 502 Returns the specified attributes from a set. 503 504 # Inputs 505 506 `nameList` 507 508 : The list of attributes to fetch from `set`. Each attribute name must exist on the attribute set 509 510 `set` 511 512 : The set to get attribute values from 513 514 # Type 515 516 ``` 517 attrVals :: [String] -> AttrSet -> [Any] 518 ``` 519 520 # Examples 521 :::{.example} 522 ## `lib.attrsets.attrVals` usage example 523 524 ```nix 525 attrVals ["a" "b" "c"] as 526 => [as.a as.b as.c] 527 ``` 528 529 ::: 530 */ 531 attrVals = nameList: set: map (x: set.${x}) nameList; 532 533 /** 534 Returns the values of all attributes in the given set, sorted by 535 attribute name. 536 537 # Type 538 539 ``` 540 attrValues :: AttrSet -> [Any] 541 ``` 542 543 # Examples 544 :::{.example} 545 ## `lib.attrsets.attrValues` usage example 546 547 ```nix 548 attrValues {c = 3; a = 1; b = 2;} 549 => [1 2 3] 550 ``` 551 552 ::: 553 */ 554 attrValues = builtins.attrValues; 555 556 /** 557 Given a set of attribute names, return the set of the corresponding 558 attributes from the given set. 559 560 # Inputs 561 562 `names` 563 564 : A list of attribute names to get out of `set` 565 566 `set` 567 568 : The set to get the named attributes from 569 570 # Type 571 572 ``` 573 getAttrs :: [String] -> AttrSet -> AttrSet 574 ``` 575 576 # Examples 577 :::{.example} 578 ## `lib.attrsets.getAttrs` usage example 579 580 ```nix 581 getAttrs [ "a" "b" ] { a = 1; b = 2; c = 3; } 582 => { a = 1; b = 2; } 583 ``` 584 585 ::: 586 */ 587 getAttrs = names: attrs: genAttrs names (name: attrs.${name}); 588 589 /** 590 Collect each attribute named `attr` from a list of attribute 591 sets. Sets that don't contain the named attribute are ignored. 592 593 # Inputs 594 595 `attr` 596 597 : The attribute name to get out of the sets. 598 599 `list` 600 601 : The list of attribute sets to go through 602 603 # Type 604 605 ``` 606 catAttrs :: String -> [AttrSet] -> [Any] 607 ``` 608 609 # Examples 610 :::{.example} 611 ## `lib.attrsets.catAttrs` usage example 612 613 ```nix 614 catAttrs "a" [{a = 1;} {b = 0;} {a = 2;}] 615 => [1 2] 616 ``` 617 618 ::: 619 */ 620 catAttrs = builtins.catAttrs; 621 622 /** 623 Filter an attribute set by removing all attributes for which the 624 given predicate return false. 625 626 # Inputs 627 628 `pred` 629 630 : Predicate taking an attribute name and an attribute value, which returns `true` to include the attribute, or `false` to exclude the attribute. 631 632 <!-- TIP --> 633 If possible, decide on `name` first and on `value` only if necessary. 634 This avoids evaluating the value if the name is already enough, making it possible, potentially, to have the argument reference the return value. 635 (Depending on context, that could still be considered a self reference by users; a common pattern in Nix.) 636 637 <!-- TIP --> 638 `filterAttrs` is occasionally the cause of infinite recursion in configuration systems that allow self-references. 639 To support the widest range of user-provided logic, perform the `filterAttrs` call as late as possible. 640 Typically that's right before using it in a derivation, as opposed to an implicit conversion whose result is accessible to the user's expressions. 641 642 `set` 643 644 : The attribute set to filter 645 646 # Type 647 648 ``` 649 filterAttrs :: (String -> Any -> Bool) -> AttrSet -> AttrSet 650 ``` 651 652 # Examples 653 :::{.example} 654 ## `lib.attrsets.filterAttrs` usage example 655 656 ```nix 657 filterAttrs (n: v: n == "foo") { foo = 1; bar = 2; } 658 => { foo = 1; } 659 ``` 660 661 ::: 662 */ 663 filterAttrs = pred: set: removeAttrs set (filter (name: !pred name set.${name}) (attrNames set)); 664 665 /** 666 Filter an attribute set recursively by removing all attributes for 667 which the given predicate return false. 668 669 # Inputs 670 671 `pred` 672 673 : Predicate taking an attribute name and an attribute value, which returns `true` to include the attribute, or `false` to exclude the attribute. 674 675 `set` 676 677 : The attribute set to filter 678 679 # Type 680 681 ``` 682 filterAttrsRecursive :: (String -> Any -> Bool) -> AttrSet -> AttrSet 683 ``` 684 685 # Examples 686 :::{.example} 687 ## `lib.attrsets.filterAttrsRecursive` usage example 688 689 ```nix 690 filterAttrsRecursive (n: v: v != null) { foo = { bar = null; }; } 691 => { foo = {}; } 692 ``` 693 694 ::: 695 */ 696 filterAttrsRecursive = 697 pred: set: 698 listToAttrs ( 699 concatMap ( 700 name: 701 let 702 v = set.${name}; 703 in 704 if pred name v then 705 [ 706 (nameValuePair name (if isAttrs v then filterAttrsRecursive pred v else v)) 707 ] 708 else 709 [ ] 710 ) (attrNames set) 711 ); 712 713 /** 714 Like [`lib.lists.foldl'`](#function-library-lib.lists.foldl-prime) but for attribute sets. 715 Iterates over every name-value pair in the given attribute set. 716 The result of the callback function is often called `acc` for accumulator. It is passed between callbacks from left to right and the final `acc` is the return value of `foldlAttrs`. 717 718 ::: {.note} 719 There is a completely different function `lib.foldAttrs` 720 which has nothing to do with this function, despite the similar name. 721 ::: 722 723 # Inputs 724 725 `f` 726 727 : 1\. Function argument 728 729 `init` 730 731 : 2\. Function argument 732 733 `set` 734 735 : 3\. Function argument 736 737 # Type 738 739 ``` 740 foldlAttrs :: ( a -> String -> b -> a ) -> a -> { ... :: b } -> a 741 ``` 742 743 # Examples 744 :::{.example} 745 ## `lib.attrsets.foldlAttrs` usage example 746 747 ```nix 748 foldlAttrs 749 (acc: name: value: { 750 sum = acc.sum + value; 751 names = acc.names ++ [name]; 752 }) 753 { sum = 0; names = []; } 754 { 755 foo = 1; 756 bar = 10; 757 } 758 -> 759 { 760 sum = 11; 761 names = ["bar" "foo"]; 762 } 763 764 foldlAttrs 765 (throw "function not needed") 766 123 767 {}; 768 -> 769 123 770 771 foldlAttrs 772 (acc: _: _: acc) 773 3 774 { z = throw "value not needed"; a = throw "value not needed"; }; 775 -> 776 3 777 778 The accumulator doesn't have to be an attrset. 779 It can be as simple as a number or string. 780 781 foldlAttrs 782 (acc: _: v: acc * 10 + v) 783 1 784 { z = 1; a = 2; }; 785 -> 786 121 787 ``` 788 789 ::: 790 */ 791 foldlAttrs = 792 f: init: set: 793 foldl' (acc: name: f acc name set.${name}) init (attrNames set); 794 795 /** 796 Apply fold functions to values grouped by key. 797 798 # Inputs 799 800 `op` 801 802 : A function, given a value and a collector combines the two. 803 804 `nul` 805 806 : The starting value. 807 808 `list_of_attrs` 809 810 : A list of attribute sets to fold together by key. 811 812 # Type 813 814 ``` 815 foldAttrs :: (Any -> Any -> Any) -> Any -> [AttrSets] -> Any 816 ``` 817 818 # Examples 819 :::{.example} 820 ## `lib.attrsets.foldAttrs` usage example 821 822 ```nix 823 foldAttrs (item: acc: [item] ++ acc) [] [{ a = 2; } { a = 3; }] 824 => { a = [ 2 3 ]; } 825 ``` 826 827 ::: 828 */ 829 foldAttrs = 830 op: nul: list_of_attrs: 831 foldr ( 832 n: a: foldr (name: o: o // { ${name} = op n.${name} (a.${name} or nul); }) a (attrNames n) 833 ) { } list_of_attrs; 834 835 /** 836 Recursively collect sets that verify a given predicate named `pred` 837 from the set `attrs`. The recursion is stopped when the predicate is 838 verified. 839 840 # Inputs 841 842 `pred` 843 844 : Given an attribute's value, determine if recursion should stop. 845 846 `attrs` 847 848 : The attribute set to recursively collect. 849 850 # Type 851 852 ``` 853 collect :: (AttrSet -> Bool) -> AttrSet -> [x] 854 ``` 855 856 # Examples 857 :::{.example} 858 ## `lib.attrsets.collect` usage example 859 860 ```nix 861 collect isList { a = { b = ["b"]; }; c = [1]; } 862 => [["b"] [1]] 863 864 collect (x: x ? outPath) 865 { a = { outPath = "a/"; }; b = { outPath = "b/"; }; } 866 => [{ outPath = "a/"; } { outPath = "b/"; }] 867 ``` 868 869 ::: 870 */ 871 collect = 872 pred: attrs: 873 if pred attrs then 874 [ attrs ] 875 else if isAttrs attrs then 876 concatMap (collect pred) (attrValues attrs) 877 else 878 [ ]; 879 880 /** 881 Return the cartesian product of attribute set value combinations. 882 883 # Inputs 884 885 `attrsOfLists` 886 887 : Attribute set with attributes that are lists of values 888 889 # Type 890 891 ``` 892 cartesianProduct :: AttrSet -> [AttrSet] 893 ``` 894 895 # Examples 896 :::{.example} 897 ## `lib.attrsets.cartesianProduct` usage example 898 899 ```nix 900 cartesianProduct { a = [ 1 2 ]; b = [ 10 20 ]; } 901 => [ 902 { a = 1; b = 10; } 903 { a = 1; b = 20; } 904 { a = 2; b = 10; } 905 { a = 2; b = 20; } 906 ] 907 ``` 908 909 ::: 910 */ 911 cartesianProduct = 912 attrsOfLists: 913 foldl' ( 914 listOfAttrs: attrName: 915 concatMap ( 916 attrs: map (listValue: attrs // { ${attrName} = listValue; }) attrsOfLists.${attrName} 917 ) listOfAttrs 918 ) [ { } ] (attrNames attrsOfLists); 919 920 /** 921 Return the result of function `f` applied to the cartesian product of attribute set value combinations. 922 Equivalent to using `cartesianProduct` followed by `map`. 923 924 # Inputs 925 926 `f` 927 928 : A function, given an attribute set, it returns a new value. 929 930 `attrsOfLists` 931 932 : Attribute set with attributes that are lists of values 933 934 # Type 935 936 ``` 937 mapCartesianProduct :: (AttrSet -> a) -> AttrSet -> [a] 938 ``` 939 940 # Examples 941 :::{.example} 942 ## `lib.attrsets.mapCartesianProduct` usage example 943 944 ```nix 945 mapCartesianProduct ({a, b}: "${a}-${b}") { a = [ "1" "2" ]; b = [ "3" "4" ]; } 946 => [ "1-3" "1-4" "2-3" "2-4" ] 947 ``` 948 949 ::: 950 */ 951 mapCartesianProduct = f: attrsOfLists: map f (cartesianProduct attrsOfLists); 952 953 /** 954 Utility function that creates a `{name, value}` pair as expected by `builtins.listToAttrs`. 955 956 # Inputs 957 958 `name` 959 960 : Attribute name 961 962 `value` 963 964 : Attribute value 965 966 # Type 967 968 ``` 969 nameValuePair :: String -> Any -> { name :: String; value :: Any; } 970 ``` 971 972 # Examples 973 :::{.example} 974 ## `lib.attrsets.nameValuePair` usage example 975 976 ```nix 977 nameValuePair "some" 6 978 => { name = "some"; value = 6; } 979 ``` 980 981 ::: 982 */ 983 nameValuePair = name: value: { inherit name value; }; 984 985 /** 986 Apply a function to each element in an attribute set, creating a new attribute set. 987 988 # Inputs 989 990 `f` 991 992 : A function that takes an attribute name and its value, and returns the new value for the attribute. 993 994 `attrset` 995 996 : The attribute set to iterate through. 997 998 # Type 999 1000 ``` 1001 mapAttrs :: (String -> Any -> Any) -> AttrSet -> AttrSet 1002 ``` 1003 1004 # Examples 1005 :::{.example} 1006 ## `lib.attrsets.mapAttrs` usage example 1007 1008 ```nix 1009 mapAttrs (name: value: name + "-" + value) 1010 { x = "foo"; y = "bar"; } 1011 => { x = "x-foo"; y = "y-bar"; } 1012 ``` 1013 1014 ::: 1015 */ 1016 mapAttrs = builtins.mapAttrs; 1017 1018 /** 1019 Like `mapAttrs`, but allows the name of each attribute to be 1020 changed in addition to the value. The applied function should 1021 return both the new name and value as a `nameValuePair`. 1022 1023 # Inputs 1024 1025 `f` 1026 1027 : A function, given an attribute's name and value, returns a new `nameValuePair`. 1028 1029 `set` 1030 1031 : Attribute set to map over. 1032 1033 # Type 1034 1035 ``` 1036 mapAttrs' :: (String -> Any -> { name :: String; value :: Any; }) -> AttrSet -> AttrSet 1037 ``` 1038 1039 # Examples 1040 :::{.example} 1041 ## `lib.attrsets.mapAttrs'` usage example 1042 1043 ```nix 1044 mapAttrs' (name: value: nameValuePair ("foo_" + name) ("bar-" + value)) 1045 { x = "a"; y = "b"; } 1046 => { foo_x = "bar-a"; foo_y = "bar-b"; } 1047 ``` 1048 1049 ::: 1050 */ 1051 mapAttrs' = f: set: listToAttrs (mapAttrsToList f set); 1052 1053 /** 1054 Call a function for each attribute in the given set and return 1055 the result in a list. 1056 1057 # Inputs 1058 1059 `f` 1060 1061 : A function, given an attribute's name and value, returns a new value. 1062 1063 `attrs` 1064 1065 : Attribute set to map over. 1066 1067 # Type 1068 1069 ``` 1070 mapAttrsToList :: (String -> a -> b) -> AttrSet -> [b] 1071 ``` 1072 1073 # Examples 1074 :::{.example} 1075 ## `lib.attrsets.mapAttrsToList` usage example 1076 1077 ```nix 1078 mapAttrsToList (name: value: name + value) 1079 { x = "a"; y = "b"; } 1080 => [ "xa" "yb" ] 1081 ``` 1082 1083 ::: 1084 */ 1085 mapAttrsToList = f: attrs: attrValues (mapAttrs f attrs); 1086 1087 /** 1088 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). 1089 Each element of the resulting list is an attribute set with these attributes: 1090 - `name` (string): The name of the attribute 1091 - `value` (any): The value of the attribute 1092 1093 The following is always true: 1094 ```nix 1095 builtins.listToAttrs (attrsToList attrs) == attrs 1096 ``` 1097 1098 :::{.warning} 1099 The opposite is not always true. In general expect that 1100 ```nix 1101 attrsToList (builtins.listToAttrs list) != list 1102 ``` 1103 1104 This is because the `listToAttrs` removes duplicate names and doesn't preserve the order of the list. 1105 ::: 1106 1107 # Inputs 1108 1109 `set` 1110 1111 : The attribute set to deconstruct. 1112 1113 # Type 1114 1115 ``` 1116 attrsToList :: AttrSet -> [ { name :: String; value :: Any; } ] 1117 ``` 1118 1119 # Examples 1120 :::{.example} 1121 ## `lib.attrsets.attrsToList` usage example 1122 1123 ```nix 1124 attrsToList { foo = 1; bar = "asdf"; } 1125 => [ { name = "bar"; value = "asdf"; } { name = "foo"; value = 1; } ] 1126 ``` 1127 1128 ::: 1129 */ 1130 attrsToList = mapAttrsToList nameValuePair; 1131 1132 /** 1133 Like `mapAttrs`, except that it recursively applies itself to the *leaf* attributes of a potentially-nested attribute set: 1134 the second argument of the function will never be an attrset. 1135 Also, the first argument of the mapping function is a *list* of the attribute names that form the path to the leaf attribute. 1136 1137 For a function that gives you control over what counts as a leaf, see `mapAttrsRecursiveCond`. 1138 1139 :::{#map-attrs-recursive-example .example} 1140 # Map over leaf attributes 1141 1142 ```nix 1143 mapAttrsRecursive (path: value: concatStringsSep "-" (path ++ [value])) 1144 { n = { a = "A"; m = { b = "B"; c = "C"; }; }; d = "D"; } 1145 ``` 1146 evaluates to 1147 ```nix 1148 { n = { a = "n-a-A"; m = { b = "n-m-b-B"; c = "n-m-c-C"; }; }; d = "d-D"; } 1149 ``` 1150 ::: 1151 1152 # Type 1153 ``` 1154 mapAttrsRecursive :: ([String] -> a -> b) -> AttrSet -> AttrSet 1155 ``` 1156 */ 1157 mapAttrsRecursive = f: set: mapAttrsRecursiveCond (as: true) f set; 1158 1159 /** 1160 Like `mapAttrsRecursive`, but it takes an additional predicate that tells it whether to recurse into an attribute set. 1161 If the predicate returns false, `mapAttrsRecursiveCond` does not recurse, but instead applies the mapping function. 1162 If the predicate returns true, it does recurse, and does not apply the mapping function. 1163 1164 :::{#map-attrs-recursive-cond-example .example} 1165 # Map over an leaf attributes defined by a condition 1166 1167 Map derivations to their `name` attribute. 1168 Derivatons are identified as attribute sets that contain `{ type = "derivation"; }`. 1169 ```nix 1170 mapAttrsRecursiveCond 1171 (as: !(as ? "type" && as.type == "derivation")) 1172 (path: x: x.name) 1173 attrs 1174 ``` 1175 ::: 1176 1177 # Type 1178 ``` 1179 mapAttrsRecursiveCond :: (AttrSet -> Bool) -> ([String] -> a -> b) -> AttrSet -> AttrSet 1180 ``` 1181 */ 1182 mapAttrsRecursiveCond = 1183 cond: f: set: 1184 let 1185 recurse = 1186 path: 1187 mapAttrs ( 1188 name: value: 1189 if isAttrs value && cond value then recurse (path ++ [ name ]) value else f (path ++ [ name ]) value 1190 ); 1191 in 1192 recurse [ ] set; 1193 1194 /** 1195 Apply a function to each leaf (nonattributeset attribute) of a tree of 1196 nested attribute sets, returning the results of the function as a list, 1197 ordered lexicographically by their attribute paths. 1198 1199 Like `mapAttrsRecursive`, but concatenates the mapping function results 1200 into a list. 1201 1202 # Inputs 1203 1204 `f` 1205 1206 : Mapping function which, given an attributes path and value, returns a 1207 new value. 1208 1209 This value will be an element of the list returned by 1210 `mapAttrsToListRecursive`. 1211 1212 The first argument to the mapping function is a list of attribute names 1213 forming the path to the leaf attribute. The second argument is the leaf 1214 attribute value, which will never be an attribute set. 1215 1216 `set` 1217 1218 : Attribute set to map over. 1219 1220 # Type 1221 1222 ``` 1223 mapAttrsToListRecursive :: ([String] -> a -> b) -> AttrSet -> [b] 1224 ``` 1225 1226 # Examples 1227 :::{.example} 1228 ## `lib.attrsets.mapAttrsToListRecursive` usage example 1229 1230 ```nix 1231 mapAttrsToListRecursive (path: value: "${concatStringsSep "." path}=${value}") 1232 { n = { a = "A"; m = { b = "B"; c = "C"; }; }; d = "D"; } 1233 => [ "n.a=A" "n.m.b=B" "n.m.c=C" "d=D" ] 1234 ``` 1235 ::: 1236 */ 1237 mapAttrsToListRecursive = mapAttrsToListRecursiveCond (_: _: true); 1238 1239 /** 1240 Determine the nodes of a tree of nested attribute sets by applying a 1241 predicate, then apply a function to the leaves, returning the results 1242 as a list, ordered lexicographically by their attribute paths. 1243 1244 Like `mapAttrsToListRecursive`, but takes an additional predicate to 1245 decide whether to recurse into an attribute set. 1246 1247 Unlike `mapAttrsRecursiveCond` this predicate receives the attribute path 1248 as its first argument, in addition to the attribute set. 1249 1250 # Inputs 1251 1252 `pred` 1253 1254 : Predicate to decide whether to recurse into an attribute set. 1255 1256 If the predicate returns true, `mapAttrsToListRecursiveCond` recurses into 1257 the attribute set. If the predicate returns false, it does not recurse 1258 but instead applies the mapping function, treating the attribute set as 1259 a leaf. 1260 1261 The first argument to the predicate is a list of attribute names forming 1262 the path to the attribute set. The second argument is the attribute set. 1263 1264 `f` 1265 1266 : Mapping function which, given an attributes path and value, returns a 1267 new value. 1268 1269 This value will be an element of the list returned by 1270 `mapAttrsToListRecursiveCond`. 1271 1272 The first argument to the mapping function is a list of attribute names 1273 forming the path to the leaf attribute. The second argument is the leaf 1274 attribute value, which may be an attribute set if the predicate returned 1275 false. 1276 1277 `set` 1278 1279 : Attribute set to map over. 1280 1281 # Type 1282 ``` 1283 mapAttrsToListRecursiveCond :: ([String] -> AttrSet -> Bool) -> ([String] -> a -> b) -> AttrSet -> [b] 1284 ``` 1285 1286 # Examples 1287 :::{.example} 1288 ## `lib.attrsets.mapAttrsToListRecursiveCond` usage example 1289 1290 ```nix 1291 mapAttrsToListRecursiveCond 1292 (path: as: !(lib.isDerivation as)) 1293 (path: value: "--set=${lib.concatStringsSep "." path}=${toString value}") 1294 { 1295 rust.optimize = 2; 1296 target = { 1297 riscv64-unknown-linux-gnu.linker = pkgs.lld; 1298 }; 1299 } 1300 => [ "--set=rust.optimize=2" "--set=target.riscv64-unknown-linux-gnu.linker=/nix/store/sjw4h1k" ] 1301 ``` 1302 ::: 1303 */ 1304 mapAttrsToListRecursiveCond = 1305 pred: f: set: 1306 let 1307 mapRecursive = 1308 path: value: if isAttrs value && pred path value then recurse path value else [ (f path value) ]; 1309 recurse = path: set: concatMap (name: mapRecursive (path ++ [ name ]) set.${name}) (attrNames set); 1310 in 1311 recurse [ ] set; 1312 1313 /** 1314 Generate an attribute set by mapping a function over a list of 1315 attribute names. 1316 1317 # Inputs 1318 1319 `names` 1320 1321 : Names of values in the resulting attribute set. 1322 1323 `f` 1324 1325 : A function, given the name of the attribute, returns the attribute's value. 1326 1327 # Type 1328 1329 ``` 1330 genAttrs :: [ String ] -> (String -> Any) -> AttrSet 1331 ``` 1332 1333 # Examples 1334 :::{.example} 1335 ## `lib.attrsets.genAttrs` usage example 1336 1337 ```nix 1338 genAttrs [ "foo" "bar" ] (name: "x_" + name) 1339 => { foo = "x_foo"; bar = "x_bar"; } 1340 ``` 1341 1342 ::: 1343 */ 1344 genAttrs = names: f: genAttrs' names (n: nameValuePair n (f n)); 1345 1346 /** 1347 Like `genAttrs`, but allows the name of each attribute to be specified in addition to the value. 1348 The applied function should return both the new name and value as a `nameValuePair`. 1349 ::: {.warning} 1350 In case of attribute name collision the first entry determines the value, 1351 all subsequent conflicting entries for the same name are silently ignored. 1352 ::: 1353 1354 # Inputs 1355 1356 `xs` 1357 1358 : A list of strings `s` used as generator. 1359 1360 `f` 1361 1362 : A function, given a string `s` from the list `xs`, returns a new `nameValuePair`. 1363 1364 # Type 1365 1366 ``` 1367 genAttrs' :: [ Any ] -> (Any -> { name :: String; value :: Any; }) -> AttrSet 1368 ``` 1369 1370 # Examples 1371 :::{.example} 1372 ## `lib.attrsets.genAttrs'` usage example 1373 1374 ```nix 1375 genAttrs' [ "foo" "bar" ] (s: nameValuePair ("x_" + s) ("y_" + s)) 1376 => { x_foo = "y_foo"; x_bar = "y_bar"; } 1377 ``` 1378 1379 ::: 1380 */ 1381 genAttrs' = xs: f: listToAttrs (map f xs); 1382 1383 /** 1384 Check whether the argument is a derivation. Any set with 1385 `{ type = "derivation"; }` counts as a derivation. 1386 1387 # Inputs 1388 1389 `value` 1390 1391 : Value to check. 1392 1393 # Type 1394 1395 ``` 1396 isDerivation :: Any -> Bool 1397 ``` 1398 1399 # Examples 1400 :::{.example} 1401 ## `lib.attrsets.isDerivation` usage example 1402 1403 ```nix 1404 nixpkgs = import <nixpkgs> {} 1405 isDerivation nixpkgs.ruby 1406 => true 1407 isDerivation "foobar" 1408 => false 1409 ``` 1410 1411 ::: 1412 */ 1413 isDerivation = value: value.type or null == "derivation"; 1414 1415 /** 1416 Converts a store path to a fake derivation. 1417 1418 # Inputs 1419 1420 `path` 1421 1422 : A store path to convert to a derivation. 1423 1424 # Type 1425 1426 ``` 1427 toDerivation :: Path -> Derivation 1428 ``` 1429 */ 1430 toDerivation = 1431 path: 1432 let 1433 path' = builtins.storePath path; 1434 res = { 1435 type = "derivation"; 1436 name = sanitizeDerivationName (builtins.substring 33 (-1) (baseNameOf path')); 1437 outPath = path'; 1438 outputs = [ "out" ]; 1439 out = res; 1440 outputName = "out"; 1441 }; 1442 in 1443 res; 1444 1445 /** 1446 If `cond` is true, return the attribute set `as`, 1447 otherwise an empty attribute set. 1448 1449 # Inputs 1450 1451 `cond` 1452 1453 : Condition under which the `as` attribute set is returned. 1454 1455 `as` 1456 1457 : The attribute set to return if `cond` is `true`. 1458 1459 # Type 1460 1461 ``` 1462 optionalAttrs :: Bool -> AttrSet -> AttrSet 1463 ``` 1464 1465 # Examples 1466 :::{.example} 1467 ## `lib.attrsets.optionalAttrs` usage example 1468 1469 ```nix 1470 optionalAttrs (true) { my = "set"; } 1471 => { my = "set"; } 1472 optionalAttrs (false) { my = "set"; } 1473 => { } 1474 ``` 1475 1476 ::: 1477 */ 1478 optionalAttrs = cond: as: if cond then as else { }; 1479 1480 /** 1481 Merge sets of attributes and use the function `f` to merge attributes 1482 values. 1483 1484 # Inputs 1485 1486 `names` 1487 1488 : List of attribute names to zip. 1489 1490 `f` 1491 1492 : A function, accepts an attribute name, all the values, and returns a combined value. 1493 1494 `sets` 1495 1496 : List of values from the list of attribute sets. 1497 1498 # Type 1499 1500 ``` 1501 zipAttrsWithNames :: [ String ] -> (String -> [ Any ] -> Any) -> [ AttrSet ] -> AttrSet 1502 ``` 1503 1504 # Examples 1505 :::{.example} 1506 ## `lib.attrsets.zipAttrsWithNames` usage example 1507 1508 ```nix 1509 zipAttrsWithNames ["a"] (name: vs: vs) [{a = "x";} {a = "y"; b = "z";}] 1510 => { a = ["x" "y"]; } 1511 ``` 1512 1513 ::: 1514 */ 1515 zipAttrsWithNames = 1516 names: f: sets: 1517 listToAttrs ( 1518 map (name: { 1519 inherit name; 1520 value = f name (catAttrs name sets); 1521 }) names 1522 ); 1523 1524 /** 1525 Merge sets of attributes and use the function `f` to merge attribute values. 1526 Like `lib.attrsets.zipAttrsWithNames` with all key names are passed for `names`. 1527 1528 Implementation note: Common names appear multiple times in the list of 1529 names, hopefully this does not affect the system because the maximal 1530 laziness avoid computing twice the same expression and `listToAttrs` does 1531 not care about duplicated attribute names. 1532 1533 # Type 1534 1535 ``` 1536 zipAttrsWith :: (String -> [ Any ] -> Any) -> [ AttrSet ] -> AttrSet 1537 ``` 1538 1539 # Examples 1540 :::{.example} 1541 ## `lib.attrsets.zipAttrsWith` usage example 1542 1543 ```nix 1544 zipAttrsWith (name: values: values) [{a = "x";} {a = "y"; b = "z";}] 1545 => { a = ["x" "y"]; b = ["z"]; } 1546 ``` 1547 1548 ::: 1549 */ 1550 zipAttrsWith = 1551 builtins.zipAttrsWith or (f: sets: zipAttrsWithNames (concatMap attrNames sets) f sets); 1552 1553 /** 1554 Merge sets of attributes and combine each attribute value in to a list. 1555 1556 Like `lib.attrsets.zipAttrsWith` with `(name: values: values)` as the function. 1557 1558 # Type 1559 1560 ``` 1561 zipAttrs :: [ AttrSet ] -> AttrSet 1562 ``` 1563 1564 # Examples 1565 :::{.example} 1566 ## `lib.attrsets.zipAttrs` usage example 1567 1568 ```nix 1569 zipAttrs [{a = "x";} {a = "y"; b = "z";}] 1570 => { a = ["x" "y"]; b = ["z"]; } 1571 ``` 1572 1573 ::: 1574 */ 1575 zipAttrs = zipAttrsWith (name: values: values); 1576 1577 /** 1578 Merge a list of attribute sets together using the `//` operator. 1579 In case of duplicate attributes, values from later list elements take precedence over earlier ones. 1580 The result is the same as `foldl mergeAttrs { }`, but the performance is better for large inputs. 1581 For n list elements, each with an attribute set containing m unique attributes, the complexity of this operation is O(nm log n). 1582 1583 # Inputs 1584 1585 `list` 1586 1587 : 1\. Function argument 1588 1589 # Type 1590 1591 ``` 1592 mergeAttrsList :: [ Attrs ] -> Attrs 1593 ``` 1594 1595 # Examples 1596 :::{.example} 1597 ## `lib.attrsets.mergeAttrsList` usage example 1598 1599 ```nix 1600 mergeAttrsList [ { a = 0; b = 1; } { c = 2; d = 3; } ] 1601 => { a = 0; b = 1; c = 2; d = 3; } 1602 mergeAttrsList [ { a = 0; } { a = 1; } ] 1603 => { a = 1; } 1604 ``` 1605 1606 ::: 1607 */ 1608 mergeAttrsList = 1609 list: 1610 let 1611 # `binaryMerge start end` merges the elements at indices `index` of `list` such that `start <= index < end` 1612 # Type: Int -> Int -> Attrs 1613 binaryMerge = 1614 start: end: 1615 # assert start < end; # Invariant 1616 if end - start >= 2 then 1617 # If there's at least 2 elements, split the range in two, recurse on each part and merge the result 1618 # The invariant is satisfied because each half will have at least 1 element 1619 binaryMerge start (start + (end - start) / 2) // binaryMerge (start + (end - start) / 2) end 1620 else 1621 # Otherwise there will be exactly 1 element due to the invariant, in which case we just return it directly 1622 elemAt list start; 1623 in 1624 if list == [ ] then 1625 # Calling binaryMerge as below would not satisfy its invariant 1626 { } 1627 else 1628 binaryMerge 0 (length list); 1629 1630 /** 1631 Update `lhs` so that `rhs` wins for any given attribute path that occurs in both. 1632 1633 Unlike the `//` (update) operator, which operates on a single attribute set, 1634 This function views its operands `lhs` and `rhs` as a mapping from attribute *paths* 1635 to values. 1636 1637 The caller-provided function `pred` decides whether any given path is one of the following: 1638 1639 - `true`: a value in the mapping 1640 - `false`: an attribute set whose purpose is to create the nesting structure. 1641 1642 # Inputs 1643 1644 `pred` 1645 1646 : Predicate function (of type `List String -> Any -> Any -> Bool`) 1647 1648 Inputs: 1649 1650 - `path : List String`: the path to the current attribute as a list of strings for attribute names 1651 - `lhsAtPath : Any`: the value at that path in `lhs`; same as `getAttrFromPath path lhs` 1652 - `rhsAtPath : Any`: the value at that path in `rhs`; same as `getAttrFromPath path rhs` 1653 1654 Output: 1655 1656 - `true`: `path` points to a value in the mapping, and `rhsAtPath` will appear in the return value of `recursiveUpdateUntil` 1657 - `false`: `path` is part of the nesting structure and will be an attrset in the return value of `recursiveUpdateUntil` 1658 1659 `pred` is only called for `path`s that extend prefixes for which `pred` returned `false`. 1660 1661 `lhs` 1662 1663 : Left attribute set of the update. 1664 1665 `rhs` 1666 1667 : Right attribute set of the update. 1668 1669 # Type 1670 1671 ``` 1672 recursiveUpdateUntil :: ( [ String ] -> AttrSet -> AttrSet -> Bool ) -> AttrSet -> AttrSet -> AttrSet 1673 ``` 1674 1675 # Examples 1676 :::{.example} 1677 ## `lib.attrsets.recursiveUpdateUntil` usage example 1678 1679 ```nix 1680 recursiveUpdateUntil (path: lhs: rhs: path == ["foo"]) { 1681 # left attribute set 1682 foo.bar = 1; 1683 foo.baz = 2; 1684 bar = 3; 1685 } { 1686 # right attribute set 1687 foo.bar = 1; 1688 foo.quz = 2; 1689 baz = 4; 1690 } 1691 1692 => { 1693 foo.bar = 1; # 'foo.*' from the 'right' set 1694 foo.quz = 2; # 1695 bar = 3; # 'bar' from the 'left' set 1696 baz = 4; # 'baz' from the 'right' set 1697 } 1698 ``` 1699 1700 ::: 1701 */ 1702 recursiveUpdateUntil = 1703 pred: lhs: rhs: 1704 let 1705 f = 1706 attrPath: 1707 zipAttrsWith ( 1708 name: values: 1709 let 1710 here = attrPath ++ [ name ]; 1711 in 1712 if length values == 1 || pred here (elemAt values 1) (head values) then 1713 head values 1714 else 1715 f here values 1716 ); 1717 in 1718 f [ ] [ rhs lhs ]; 1719 1720 /** 1721 A recursive variant of the update operator `//`. The recursion 1722 stops when one of the attribute values is not an attribute set, 1723 in which case the right hand side value takes precedence over the 1724 left hand side value. 1725 1726 # Inputs 1727 1728 `lhs` 1729 1730 : Left attribute set of the merge. 1731 1732 `rhs` 1733 1734 : Right attribute set of the merge. 1735 1736 # Type 1737 1738 ``` 1739 recursiveUpdate :: AttrSet -> AttrSet -> AttrSet 1740 ``` 1741 1742 # Examples 1743 :::{.example} 1744 ## `lib.attrsets.recursiveUpdate` usage example 1745 1746 ```nix 1747 recursiveUpdate { 1748 boot.loader.grub.enable = true; 1749 boot.loader.grub.device = "/dev/hda"; 1750 } { 1751 boot.loader.grub.device = ""; 1752 } 1753 1754 returns: { 1755 boot.loader.grub.enable = true; 1756 boot.loader.grub.device = ""; 1757 } 1758 ``` 1759 1760 ::: 1761 */ 1762 recursiveUpdate = 1763 lhs: rhs: 1764 recursiveUpdateUntil ( 1765 path: lhs: rhs: 1766 !(isAttrs lhs && isAttrs rhs) 1767 ) lhs rhs; 1768 1769 /** 1770 Recurse into every attribute set of the first argument and check that: 1771 - Each attribute path also exists in the second argument. 1772 - If the attribute's value is not a nested attribute set, it must have the same value in the right argument. 1773 1774 # Inputs 1775 1776 `pattern` 1777 1778 : Attribute set structure to match 1779 1780 `attrs` 1781 1782 : Attribute set to check 1783 1784 # Type 1785 1786 ``` 1787 matchAttrs :: AttrSet -> AttrSet -> Bool 1788 ``` 1789 1790 # Examples 1791 :::{.example} 1792 ## `lib.attrsets.matchAttrs` usage example 1793 1794 ```nix 1795 matchAttrs { cpu = {}; } { cpu = { bits = 64; }; } 1796 => true 1797 ``` 1798 1799 ::: 1800 */ 1801 matchAttrs = 1802 pattern: attrs: 1803 assert isAttrs pattern; 1804 all ( 1805 # Compare equality between `pattern` & `attrs`. 1806 attr: 1807 # Missing attr, not equal. 1808 attrs ? ${attr} 1809 && ( 1810 let 1811 lhs = pattern.${attr}; 1812 rhs = attrs.${attr}; 1813 in 1814 # If attrset check recursively 1815 if isAttrs lhs then isAttrs rhs && matchAttrs lhs rhs else lhs == rhs 1816 ) 1817 ) (attrNames pattern); 1818 1819 /** 1820 Override only the attributes that are already present in the old set 1821 useful for deep-overriding. 1822 1823 # Inputs 1824 1825 `old` 1826 1827 : Original attribute set 1828 1829 `new` 1830 1831 : Attribute set with attributes to override in `old`. 1832 1833 # Type 1834 1835 ``` 1836 overrideExisting :: AttrSet -> AttrSet -> AttrSet 1837 ``` 1838 1839 # Examples 1840 :::{.example} 1841 ## `lib.attrsets.overrideExisting` usage example 1842 1843 ```nix 1844 overrideExisting {} { a = 1; } 1845 => {} 1846 overrideExisting { b = 2; } { a = 1; } 1847 => { b = 2; } 1848 overrideExisting { a = 3; b = 2; } { a = 1; } 1849 => { a = 1; b = 2; } 1850 ``` 1851 1852 ::: 1853 */ 1854 overrideExisting = old: new: mapAttrs (name: value: new.${name} or value) old; 1855 1856 /** 1857 Turns a list of strings into a human-readable description of those 1858 strings represented as an attribute path. The result of this function is 1859 not intended to be machine-readable. 1860 Create a new attribute set with `value` set at the nested attribute location specified in `attrPath`. 1861 1862 # Inputs 1863 1864 `path` 1865 1866 : Attribute path to render to a string 1867 1868 # Type 1869 1870 ``` 1871 showAttrPath :: [String] -> String 1872 ``` 1873 1874 # Examples 1875 :::{.example} 1876 ## `lib.attrsets.showAttrPath` usage example 1877 1878 ```nix 1879 showAttrPath [ "foo" "10" "bar" ] 1880 => "foo.\"10\".bar" 1881 showAttrPath [] 1882 => "<root attribute path>" 1883 ``` 1884 1885 ::: 1886 */ 1887 showAttrPath = 1888 path: 1889 if path == [ ] then "<root attribute path>" else concatMapStringsSep "." escapeNixIdentifier path; 1890 1891 /** 1892 Get a package output. 1893 If no output is found, fallback to `.out` and then to the default. 1894 The function is idempotent: `getOutput "b" (getOutput "a" p) == getOutput "a" p`. 1895 1896 # Inputs 1897 1898 `output` 1899 1900 : 1\. Function argument 1901 1902 `pkg` 1903 1904 : 2\. Function argument 1905 1906 # Type 1907 1908 ``` 1909 getOutput :: String -> :: Derivation -> Derivation 1910 ``` 1911 1912 # Examples 1913 :::{.example} 1914 ## `lib.attrsets.getOutput` usage example 1915 1916 ```nix 1917 "${getOutput "dev" pkgs.openssl}" 1918 => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-dev" 1919 ``` 1920 1921 ::: 1922 */ 1923 getOutput = 1924 output: pkg: 1925 if !pkg ? outputSpecified || !pkg.outputSpecified then pkg.${output} or pkg.out or pkg else pkg; 1926 1927 /** 1928 Get the first of the `outputs` provided by the package, or the default. 1929 This function is aligned with `_overrideFirst()` from the `multiple-outputs.sh` setup hook. 1930 Like `getOutput`, the function is idempotent. 1931 1932 # Inputs 1933 1934 `outputs` 1935 1936 : 1\. Function argument 1937 1938 `pkg` 1939 1940 : 2\. Function argument 1941 1942 # Type 1943 1944 ``` 1945 getFirstOutput :: [String] -> Derivation -> Derivation 1946 ``` 1947 1948 # Examples 1949 :::{.example} 1950 ## `lib.attrsets.getFirstOutput` usage example 1951 1952 ```nix 1953 "${getFirstOutput [ "include" "dev" ] pkgs.openssl}" 1954 => "/nix/store/00000000000000000000000000000000-openssl-1.0.1r-dev" 1955 ``` 1956 1957 ::: 1958 */ 1959 getFirstOutput = 1960 candidates: pkg: 1961 let 1962 outputs = builtins.filter (name: hasAttr name pkg) candidates; 1963 output = builtins.head outputs; 1964 in 1965 if pkg.outputSpecified or false || outputs == [ ] then pkg else pkg.${output}; 1966 1967 /** 1968 Get a package's `bin` output. 1969 If the output does not exist, fallback to `.out` and then to the default. 1970 1971 # Inputs 1972 1973 `pkg` 1974 1975 : The package whose `bin` output will be retrieved. 1976 1977 # Type 1978 1979 ``` 1980 getBin :: Derivation -> Derivation 1981 ``` 1982 1983 # Examples 1984 :::{.example} 1985 ## `lib.attrsets.getBin` usage example 1986 1987 ```nix 1988 "${getBin pkgs.openssl}" 1989 => "/nix/store/00000000000000000000000000000000-openssl-1.0.1r" 1990 ``` 1991 1992 ::: 1993 */ 1994 getBin = getOutput "bin"; 1995 1996 /** 1997 Get a package's `lib` output. 1998 If the output does not exist, fallback to `.out` and then to the default. 1999 2000 # Inputs 2001 2002 `pkg` 2003 2004 : The package whose `lib` output will be retrieved. 2005 2006 # Type 2007 2008 ``` 2009 getLib :: Derivation -> Derivation 2010 ``` 2011 2012 # Examples 2013 :::{.example} 2014 ## `lib.attrsets.getLib` usage example 2015 2016 ```nix 2017 "${getLib pkgs.openssl}" 2018 => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-lib" 2019 ``` 2020 2021 ::: 2022 */ 2023 getLib = getOutput "lib"; 2024 2025 /** 2026 Get a package's `static` output. 2027 If the output does not exist, fallback to `.lib`, then to `.out`, and then to the default. 2028 2029 # Inputs 2030 2031 `pkg` 2032 2033 : The package whose `static` output will be retrieved. 2034 2035 # Type 2036 2037 ``` 2038 getStatic :: Derivation -> Derivation 2039 ``` 2040 2041 # Examples 2042 :::{.example} 2043 ## `lib.attrsets.getStatic` usage example 2044 2045 ```nix 2046 "${lib.getStatic pkgs.glibc}" 2047 => "/nix/store/00000000000000000000000000000000-glibc-2.39-52-static" 2048 ``` 2049 2050 ::: 2051 */ 2052 getStatic = getFirstOutput [ 2053 "static" 2054 "lib" 2055 "out" 2056 ]; 2057 2058 /** 2059 Get a package's `dev` output. 2060 If the output does not exist, fallback to `.out` and then to the default. 2061 2062 # Inputs 2063 2064 `pkg` 2065 2066 : The package whose `dev` output will be retrieved. 2067 2068 # Type 2069 2070 ``` 2071 getDev :: Derivation -> Derivation 2072 ``` 2073 2074 # Examples 2075 :::{.example} 2076 ## `lib.attrsets.getDev` usage example 2077 2078 ```nix 2079 "${getDev pkgs.openssl}" 2080 => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-dev" 2081 ``` 2082 2083 ::: 2084 */ 2085 getDev = getOutput "dev"; 2086 2087 /** 2088 Get a package's `include` output. 2089 If the output does not exist, fallback to `.dev`, then to `.out`, and then to the default. 2090 2091 # Inputs 2092 2093 `pkg` 2094 2095 : The package whose `include` output will be retrieved. 2096 2097 # Type 2098 2099 ``` 2100 getInclude :: Derivation -> Derivation 2101 ``` 2102 2103 # Examples 2104 :::{.example} 2105 ## `lib.attrsets.getInclude` usage example 2106 2107 ```nix 2108 "${getInclude pkgs.openssl}" 2109 => "/nix/store/00000000000000000000000000000000-openssl-1.0.1r-dev" 2110 ``` 2111 2112 ::: 2113 */ 2114 getInclude = getFirstOutput [ 2115 "include" 2116 "dev" 2117 "out" 2118 ]; 2119 2120 /** 2121 Get a package's `man` output. 2122 If the output does not exist, fallback to `.out` and then to the default. 2123 2124 # Inputs 2125 2126 `pkg` 2127 2128 : The package whose `man` output will be retrieved. 2129 2130 # Type 2131 2132 ``` 2133 getMan :: Derivation -> Derivation 2134 ``` 2135 2136 # Examples 2137 :::{.example} 2138 ## `lib.attrsets.getMan` usage example 2139 2140 ```nix 2141 "${getMan pkgs.openssl}" 2142 => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-man" 2143 ``` 2144 2145 ::: 2146 */ 2147 getMan = getOutput "man"; 2148 2149 /** 2150 Pick the outputs of packages to place in `buildInputs` 2151 2152 # Inputs 2153 2154 `pkgs` 2155 2156 : List of packages. 2157 2158 # Type 2159 2160 ``` 2161 chooseDevOutputs :: [Derivation] -> [Derivation] 2162 ``` 2163 */ 2164 chooseDevOutputs = map getDev; 2165 2166 /** 2167 Make various Nix tools consider the contents of the resulting 2168 attribute set when looking for what to build, find, etc. 2169 2170 This function only affects a single attribute set; it does not 2171 apply itself recursively for nested attribute sets. 2172 2173 # Inputs 2174 2175 `attrs` 2176 2177 : An attribute set to scan for derivations. 2178 2179 # Type 2180 2181 ``` 2182 recurseIntoAttrs :: AttrSet -> AttrSet 2183 ``` 2184 2185 # Examples 2186 :::{.example} 2187 ## `lib.attrsets.recurseIntoAttrs` usage example 2188 2189 ```nix 2190 { pkgs ? import <nixpkgs> {} }: 2191 { 2192 myTools = pkgs.lib.recurseIntoAttrs { 2193 inherit (pkgs) hello figlet; 2194 }; 2195 } 2196 ``` 2197 2198 ::: 2199 */ 2200 recurseIntoAttrs = attrs: attrs // { recurseForDerivations = true; }; 2201 2202 /** 2203 Undo the effect of `recurseIntoAttrs`. 2204 2205 # Inputs 2206 2207 `attrs` 2208 2209 : An attribute set to not scan for derivations. 2210 2211 # Type 2212 2213 ``` 2214 dontRecurseIntoAttrs :: AttrSet -> AttrSet 2215 ``` 2216 */ 2217 dontRecurseIntoAttrs = attrs: attrs // { recurseForDerivations = false; }; 2218 2219 /** 2220 `unionOfDisjoint x y` is equal to `x // y`, but accessing attributes present 2221 in both `x` and `y` will throw an error. This operator is commutative, unlike `//`. 2222 2223 # Inputs 2224 2225 `x` 2226 2227 : 1\. Function argument 2228 2229 `y` 2230 2231 : 2\. Function argument 2232 2233 # Type 2234 2235 ``` 2236 unionOfDisjoint :: AttrSet -> AttrSet -> AttrSet 2237 ``` 2238 */ 2239 unionOfDisjoint = 2240 x: y: 2241 let 2242 intersection = builtins.intersectAttrs x y; 2243 collisions = lib.concatStringsSep " " (builtins.attrNames intersection); 2244 mask = builtins.mapAttrs ( 2245 name: value: throw "unionOfDisjoint: collision on ${name}; complete list: ${collisions}" 2246 ) intersection; 2247 in 2248 (x // y) // mask; 2249}