fake.modules transposition for aspect-oriented Dendritic Nix. with cross-aspect dependencies. Discussions: https://oeiuwq.zulipchat.com/join/nqp26cd4kngon6mo3ncgnuap/ dendrix.oeiuwq.com/Dendritic.html
dendritic nix aspect oriented

Revert "Split tests (#19)"

This reverts commit 72ffc008e2df05daf041bbf6511d17aa94e869a3.

+518 -622
+509 -58
checkmate/modules/tests.nix
··· 1 - { inputs, lib, ... }: 2 - let 3 - targetNix = "${inputs.target}/nix"; 4 - targetLib = "${inputs.target}/nix/lib.nix"; 5 - targetMod = "${inputs.target}/nix/flakeModule.nix"; 1 + { inputs, ... }: 2 + { 3 + perSystem = 4 + { lib, ... }: 5 + let 6 + transpose = import ../../nix { inherit lib; }; 6 7 7 - transpose = import targetNix { inherit lib; }; 8 + mkFlake = 9 + mod: 10 + inputs.flake-parts.lib.mkFlake 11 + { 12 + inputs.self = [ ]; 13 + } 14 + { 15 + systems = [ ]; 16 + imports = [ 17 + ../../nix/flakeModule.nix 18 + inputs.flake-parts.flakeModules.modules 19 + mod 20 + (fooMod "aspectOne") 21 + (fooMod "aspectTwo") 22 + (fooMod "aspectThree") 23 + ]; 24 + }; 8 25 9 - mkFlake = 10 - mod: 11 - inputs.flake-parts.lib.mkFlake 12 - { 13 - inputs.self = [ ]; 14 - } 15 - { 16 - systems = [ ]; 26 + fooMod = aspect: { 17 27 imports = [ 18 - targetMod 19 - inputs.flake-parts.flakeModules.modules 20 - mod 21 - (fooMod "aspectOne") 22 - (fooMod "aspectTwo") 23 - (fooMod "aspectThree") 28 + { flake.modules.classOne.${aspect}.imports = [ fooOpt ]; } 29 + { flake.modules.classTwo.${aspect}.imports = [ fooOpt ]; } 30 + { flake.modules.classThree.${aspect}.imports = [ fooOpt ]; } 24 31 ]; 25 32 }; 26 33 27 - fooMod = aspect: { 28 - imports = [ 29 - { flake.modules.classOne.${aspect}.imports = [ fooOpt ]; } 30 - { flake.modules.classTwo.${aspect}.imports = [ fooOpt ]; } 31 - { flake.modules.classThree.${aspect}.imports = [ fooOpt ]; } 32 - ]; 33 - }; 34 + fooOpt = { 35 + options.foo = lib.mkOption { 36 + type = lib.types.str; 37 + default = "<unset>"; 38 + }; 39 + options.bar = lib.mkOption { 40 + type = lib.types.listOf lib.types.str; 41 + default = [ ]; 42 + }; 43 + options.baz = lib.mkOption { 44 + type = lib.types.lazyAttrsOf lib.types.str; 45 + default = { }; 46 + }; 47 + }; 48 + 49 + evalMod = 50 + class: mod: 51 + (lib.evalModules { 52 + inherit class; 53 + modules = [ mod ]; 54 + }).config; 55 + in 56 + { 57 + nix-unit.tests = { 58 + transpose."test swaps parent and child attrNames" = { 59 + expr = transpose { a.b.c = 1; }; 60 + expected = { 61 + b.a.c = 1; 62 + }; 63 + }; 64 + 65 + transpose."test common childs become one parent" = { 66 + expr = transpose { 67 + a.b = 1; 68 + c.b = 2; 69 + }; 70 + expected.b = { 71 + a = 1; 72 + c = 2; 73 + }; 74 + }; 75 + 76 + new-scope."test usage without flakes" = 77 + let 78 + flake-aspects-lib = import ../../nix/lib.nix lib; 79 + # first eval is like evaling the flake. 80 + first = lib.evalModules { 81 + modules = [ 82 + (flake-aspects-lib.new-scope "hello") 83 + { 84 + hello.aspects = 85 + { aspects, ... }: 86 + { 87 + a.b.c = [ "world" ]; 88 + a.includes = [ aspects.x ]; 89 + x.b = 90 + { lib, ... }: 91 + { 92 + c = lib.splitString " " "mundo cruel"; 93 + }; 94 + }; 95 + } 96 + ]; 97 + }; 98 + # second eval is like evaling its nixosConfiguration 99 + second = lib.evalModules { 100 + modules = [ 101 + { options.c = lib.mkOption { type = lib.types.listOf lib.types.str; }; } 102 + first.config.hello.modules.b.a 103 + ]; 104 + }; 105 + expr = lib.sort (a: b: a < b) second.config.c; 106 + expected = [ 107 + "cruel" 108 + "mundo" 109 + "world" 110 + ]; 111 + in 112 + { 113 + inherit expr expected; 114 + }; 115 + 116 + aspects."test provides default" = 117 + let 118 + flake = 119 + inputs.flake-parts.lib.mkFlake 120 + { 121 + inputs.self = [ ]; 122 + moduleLocation = builtins.toString ./.; 123 + } 124 + { 125 + systems = [ ]; 126 + imports = [ 127 + ../../nix/flakeModule.nix 128 + inputs.flake-parts.flakeModules.modules 129 + ]; 130 + }; 131 + expr = flake.modules; 132 + expected = { }; 133 + in 134 + { 135 + inherit expr expected; 136 + }; 137 + 138 + aspects."test transposes to flake.modules" = 139 + let 140 + flake = mkFlake { 141 + flake.aspects.aspectOne = { 142 + classOne.foo = "niri"; 143 + classTwo.foo = "paper.spoon"; 144 + }; 145 + }; 146 + expr = { 147 + classOne = (evalMod "classOne" flake.modules.classOne.aspectOne).foo; 148 + classTwo = (evalMod "classTwo" flake.modules.classTwo.aspectOne).foo; 149 + }; 150 + expected = { 151 + classOne = "niri"; 152 + classTwo = "paper.spoon"; 153 + }; 154 + in 155 + { 156 + inherit expr expected; 157 + }; 158 + 159 + aspects."test dependencies on aspects" = 160 + let 161 + flake = mkFlake { 162 + flake.aspects = 163 + { aspects, ... }: 164 + { 165 + aspectOne = { 166 + description = "os config"; 167 + includes = with aspects; [ aspectTwo ]; 168 + classOne.bar = [ "os" ]; 169 + }; 170 + 171 + aspectTwo = { 172 + description = "user config at os level"; 173 + classOne.bar = [ "user" ]; 174 + }; 175 + }; 176 + }; 177 + expr = lib.sort (a: b: a < b) (evalMod "classOne" flake.modules.classOne.aspectOne).bar; 178 + expected = [ 179 + "os" 180 + "user" 181 + ]; 182 + in 183 + { 184 + inherit expr expected; 185 + }; 186 + 187 + aspects."test resolve aspect-chain" = 188 + let 189 + flake = mkFlake { 190 + flake.aspects = 191 + { aspects, ... }: 192 + { 193 + aspectOne = { 194 + name = "one"; 195 + includes = [ aspects.aspectOne.provides.dos ]; 196 + classOne.bar = [ "zzz" ]; 197 + provides.dos = 198 + { aspect-chain, ... }: 199 + { 200 + name = "dos"; 201 + includes = [ aspects.aspectOne.provides.tres ]; 202 + classOne.bar = map (x: x.name) aspect-chain; 203 + }; 204 + 205 + provides.tres = 206 + { aspect-chain, ... }: 207 + { 208 + name = "tres"; 209 + classOne.bar = [ (lib.last aspect-chain).name ]; 210 + }; 211 + }; 212 + }; 213 + }; 214 + mod = { 215 + imports = [ 216 + fooOpt 217 + (flake.aspects.aspectOne.resolve { class = "classOne"; }) 218 + ]; 219 + }; 220 + expr = lib.sort (a: b: a < b) (evalMod "classOne" mod).bar; 221 + expected = [ 222 + "dos" 223 + "one" 224 + "zzz" 225 + ]; 226 + in 227 + { 228 + inherit expr expected; 229 + }; 230 + 231 + aspects."test modules resolved" = 232 + let 233 + flake = mkFlake { 234 + flake.aspects = 235 + { aspects, ... }: 236 + { 237 + aspectOne = { 238 + name = "one"; 239 + includes = [ aspects.aspectOne.provides.dos ]; 240 + classOne.bar = [ "zzz" ]; 241 + provides.dos = 242 + { aspect-chain, ... }: 243 + { 244 + name = "dos"; 245 + includes = [ aspects.aspectOne.provides.tres ]; 246 + classOne.bar = map (x: x.name) aspect-chain; 247 + }; 248 + 249 + provides.tres = 250 + { aspect-chain, ... }: 251 + { 252 + name = "tres"; 253 + classOne.bar = [ (lib.last aspect-chain).name ]; 254 + }; 255 + }; 256 + }; 257 + }; 258 + mod = { 259 + imports = [ 260 + fooOpt 261 + (flake.aspects.aspectOne.modules.classOne) 262 + ]; 263 + }; 264 + expr = lib.sort (a: b: a < b) (evalMod "classOne" mod).bar; 265 + expected = [ 266 + "dos" 267 + "one" 268 + "zzz" 269 + ]; 270 + in 271 + { 272 + inherit expr expected; 273 + }; 274 + 275 + aspects."test provides" = 276 + let 277 + flake = mkFlake { 278 + flake.aspects = 279 + { aspects, ... }: 280 + { 281 + aspectOne.includes = with aspects.aspectTwo.provides; [ 282 + foo 283 + bar 284 + ]; 285 + aspectOne.classOne = { }; # must be present for mixing dependencies. 286 + aspectTwo = { 287 + classOne.bar = [ "class one not included" ]; 288 + classTwo.bar = [ "class two not included" ]; 289 + provides.foo = 290 + { class, aspect-chain }: 291 + { 292 + name = "aspectTwo.foo"; 293 + description = "aspectTwo foo provided"; 294 + includes = [ 295 + aspects.aspectThree.provides.moo 296 + aspects.aspectTwo.provides.baz 297 + ]; 298 + classOne.bar = [ "two:${class}:${lib.concatStringsSep "/" (lib.map (x: x.name) aspect-chain)}" ]; 299 + classTwo.bar = [ "foo class two not included" ]; 300 + }; 301 + # a provider can be immediately an aspect object. 302 + provides.bar = { 303 + # classOne is missing on bar 304 + classTwo.bar = [ "bar class two not included" ]; 305 + }; 306 + # _ is an shortcut alias of provides. 307 + _.baz = { 308 + # classOne is missing on bar 309 + classTwo.bar = [ "baz" ]; 310 + }; 311 + }; 312 + aspectThree.provides.moo = 313 + { aspect-chain, class }: 314 + { 315 + classOne.bar = [ "three:${class}:${lib.concatStringsSep "/" (lib.map (x: x.name) aspect-chain)}" ]; 316 + }; 317 + }; 318 + }; 319 + expr = lib.sort (a: b: a < b) (evalMod "classOne" flake.modules.classOne.aspectOne).bar; 320 + expected = [ 321 + "three:classOne:aspectOne/aspectTwo.foo" 322 + "two:classOne:aspectOne" 323 + ]; 324 + in 325 + { 326 + inherit expr expected; 327 + }; 328 + 329 + aspects."test provides using fixpoints" = 330 + let 331 + flake = mkFlake { 332 + flake.aspects = 333 + { aspects, ... }: 334 + { 335 + aspectOne = { 336 + classOne.bar = [ "1" ]; 337 + includes = [ 338 + aspects.aspectTwo 339 + ]; 340 + }; 341 + 342 + aspectTwo = { 343 + classOne.bar = [ "2" ]; 344 + includes = [ aspects.aspectTwo.provides.three-and-four-and-five ]; 345 + provides = 346 + { provides, ... }: 347 + { 348 + three-and-four-and-five = { 349 + classOne.bar = [ "3" ]; 350 + includes = [ 351 + provides.four 352 + aspects.five 353 + ]; 354 + }; 355 + four = { 356 + classOne.bar = [ "4" ]; 357 + }; 358 + }; 359 + }; 360 + 361 + five.classOne.bar = [ "5" ]; 362 + }; 363 + }; 364 + 365 + expr = lib.sort (a: b: a < b) (evalMod "classOne" flake.modules.classOne.aspectOne).bar; 366 + expected = [ 367 + "1" 368 + "2" 369 + "3" 370 + "4" 371 + "5" 372 + ]; 373 + in 374 + { 375 + inherit expr expected; 376 + }; 377 + 378 + aspects."test provides parametrized modules" = 379 + let 380 + flake = mkFlake { 381 + flake.aspects = 382 + { aspects, ... }: 383 + { 384 + aspectOne.includes = [ (aspects.aspectTwo.provides.hello "mundo") ]; 385 + aspectOne.classOne.bar = [ "1" ]; 386 + 387 + aspectTwo.provides.hello = world: { 388 + classOne.bar = [ world ]; 389 + }; 390 + }; 391 + }; 392 + 393 + expr = lib.sort (a: b: a < b) (evalMod "classOne" flake.modules.classOne.aspectOne).bar; 394 + expected = [ 395 + "1" 396 + "mundo" 397 + ]; 398 + in 399 + { 400 + inherit expr expected; 401 + }; 402 + 403 + aspects."test override default provider" = 404 + let 405 + flake = mkFlake { 406 + flake.aspects = 407 + { aspects, ... }: 408 + { 409 + aspectOne = 410 + { aspect, ... }: 411 + { 412 + includes = [ (aspects.aspectTwo { message = "hello ${aspect.name}"; }) ]; 413 + classOne = { }; # required for propagation 414 + }; 415 + 416 + aspectTwo.__functor = 417 + _: 418 + { message }: # args must be always named 419 + { class, aspect-chain }: 420 + { aspect, ... }: 421 + { 422 + classOne.bar = [ 423 + "foo" 424 + aspect.name 425 + message 426 + class 427 + ] 428 + ++ (lib.map (x: x.name) aspect-chain); 429 + }; 430 + aspectTwo.classOne.bar = [ "itself not included" ]; 431 + }; 432 + }; 433 + 434 + expr = (evalMod "classOne" flake.modules.classOne.aspectOne).bar; 435 + expected = [ 436 + "foo" 437 + "<function body>" 438 + "hello aspectOne" 439 + "classOne" 440 + "aspectOne" 441 + ]; 442 + in 443 + { 444 + inherit expr expected; 445 + }; 446 + 447 + aspects."test override default provider includes" = 448 + let 449 + flake = mkFlake { 450 + flake.aspects = 451 + { aspects, ... }: 452 + { 453 + aspectOne = { 454 + classOne.bar = [ "should-not-be-present" ]; 455 + includes = [ aspects.aspectTwo ]; 456 + __functor = aspect: { 457 + includes = [ 458 + { classOne.bar = [ "from-functor" ]; } 459 + ] 460 + ++ map (f: f { message = "hello"; }) aspect.includes; 461 + }; 462 + }; 463 + aspectTwo.__functor = 464 + _aspect: 465 + { message }: 466 + { 467 + classOne.bar = [ message ]; 468 + }; 469 + }; 470 + }; 471 + 472 + expr = (evalMod "classOne" flake.modules.classOne.aspectOne).bar; 473 + expected = [ 474 + "hello" 475 + "from-functor" 476 + ]; 477 + in 478 + { 479 + inherit expr expected; 480 + }; 481 + 482 + aspects."test define top-level context-aware aspect" = 483 + let 484 + flake = mkFlake { 485 + flake.aspects = 486 + { aspects, ... }: 487 + { 488 + aspectOne = { 489 + classOne.bar = [ "should-not-be-present" ]; 490 + includes = [ aspects.aspectTwo ]; 491 + __functor = aspect: { 492 + includes = [ 493 + { classOne.bar = [ "from-functor" ]; } 494 + ] 495 + ++ map (f: f { message = "hello"; }) aspect.includes; 496 + }; 497 + }; 498 + aspectTwo = 499 + { message }: 500 + { 501 + classOne.bar = [ message ]; 502 + }; 503 + }; 504 + }; 34 505 35 - fooOpt = { 36 - options.foo = lib.mkOption { 37 - type = lib.types.str; 38 - default = "<unset>"; 39 - }; 40 - options.bar = lib.mkOption { 41 - type = lib.types.listOf lib.types.str; 42 - default = [ ]; 43 - }; 44 - options.baz = lib.mkOption { 45 - type = lib.types.lazyAttrsOf lib.types.str; 46 - default = { }; 47 - }; 48 - }; 506 + expr = (evalMod "classOne" flake.modules.classOne.aspectOne).bar; 507 + expected = [ 508 + "hello" 509 + "from-functor" 510 + ]; 511 + in 512 + { 513 + inherit expr expected; 514 + }; 515 + }; 49 516 50 - evalMod = 51 - class: mod: 52 - (lib.evalModules { 53 - inherit class; 54 - modules = [ mod ]; 55 - }).config; 56 - in 57 - { 58 - _module.args = { 59 - inherit 60 - transpose 61 - targetLib 62 - targetMod 63 - targetNix 64 - ; 65 - inherit mkFlake evalMod fooOpt; 66 - }; 517 + }; 67 518 }
-53
checkmate/modules/tests/aspect_chain.nix
··· 1 - { 2 - lib, 3 - mkFlake, 4 - evalMod, 5 - fooOpt, 6 - ... 7 - }: 8 - { 9 - 10 - flake.tests."test resolve aspect-chain" = 11 - let 12 - flake = mkFlake { 13 - flake.aspects = 14 - { aspects, ... }: 15 - { 16 - aspectOne = { 17 - name = "one"; 18 - includes = [ aspects.aspectOne.provides.dos ]; 19 - classOne.bar = [ "zzz" ]; 20 - provides.dos = 21 - { aspect-chain, ... }: 22 - { 23 - name = "dos"; 24 - includes = [ aspects.aspectOne.provides.tres ]; 25 - classOne.bar = map (x: x.name) aspect-chain; 26 - }; 27 - 28 - provides.tres = 29 - { aspect-chain, ... }: 30 - { 31 - name = "tres"; 32 - classOne.bar = [ (lib.last aspect-chain).name ]; 33 - }; 34 - }; 35 - }; 36 - }; 37 - mod = { 38 - imports = [ 39 - fooOpt 40 - (flake.aspects.aspectOne.resolve { class = "classOne"; }) 41 - ]; 42 - }; 43 - expr = lib.sort (a: b: a < b) (evalMod "classOne" mod).bar; 44 - expected = [ 45 - "dos" 46 - "one" 47 - "zzz" 48 - ]; 49 - in 50 - { 51 - inherit expr expected; 52 - }; 53 - }
-53
checkmate/modules/tests/aspect_default_provider_functor.nix
··· 1 - { 2 - mkFlake, 3 - evalMod, 4 - lib, 5 - ... 6 - }: 7 - { 8 - 9 - flake.tests."test override default provider" = 10 - let 11 - flake = mkFlake { 12 - flake.aspects = 13 - { aspects, ... }: 14 - { 15 - aspectOne = 16 - { aspect, ... }: 17 - { 18 - includes = [ (aspects.aspectTwo { message = "hello ${aspect.name}"; }) ]; 19 - classOne = { }; # required for propagation 20 - }; 21 - 22 - aspectTwo.__functor = 23 - _: 24 - { message }: # args must be always named 25 - { class, aspect-chain }: 26 - { aspect, ... }: 27 - { 28 - classOne.bar = [ 29 - "foo" 30 - aspect.name 31 - message 32 - class 33 - ] 34 - ++ (lib.map (x: x.name) aspect-chain); 35 - }; 36 - aspectTwo.classOne.bar = [ "itself not included" ]; 37 - }; 38 - }; 39 - 40 - expr = (evalMod "classOne" flake.modules.classOne.aspectOne).bar; 41 - expected = [ 42 - "foo" 43 - "<function body>" 44 - "hello aspectOne" 45 - "classOne" 46 - "aspectOne" 47 - ]; 48 - in 49 - { 50 - inherit expr expected; 51 - }; 52 - 53 - }
-42
checkmate/modules/tests/aspect_default_provider_override.nix
··· 1 - { 2 - mkFlake, 3 - evalMod, 4 - ... 5 - }: 6 - { 7 - 8 - flake.tests."test override default provider includes" = 9 - let 10 - flake = mkFlake { 11 - flake.aspects = 12 - { aspects, ... }: 13 - { 14 - aspectOne = { 15 - classOne.bar = [ "should-not-be-present" ]; 16 - includes = [ aspects.aspectTwo ]; 17 - __functor = aspect: { 18 - includes = [ 19 - { classOne.bar = [ "from-functor" ]; } 20 - ] 21 - ++ map (f: f { message = "hello"; }) aspect.includes; 22 - }; 23 - }; 24 - aspectTwo.__functor = 25 - _aspect: 26 - { message }: 27 - { 28 - classOne.bar = [ message ]; 29 - }; 30 - }; 31 - }; 32 - 33 - expr = (evalMod "classOne" flake.modules.classOne.aspectOne).bar; 34 - expected = [ 35 - "hello" 36 - "from-functor" 37 - ]; 38 - in 39 - { 40 - inherit expr expected; 41 - }; 42 - }
-37
checkmate/modules/tests/aspect_dependencies.nix
··· 1 - { 2 - mkFlake, 3 - evalMod, 4 - lib, 5 - ... 6 - }: 7 - { 8 - 9 - flake.tests."test dependencies on aspects" = 10 - let 11 - flake = mkFlake { 12 - flake.aspects = 13 - { aspects, ... }: 14 - { 15 - aspectOne = { 16 - description = "os config"; 17 - includes = with aspects; [ aspectTwo ]; 18 - classOne.bar = [ "os" ]; 19 - }; 20 - 21 - aspectTwo = { 22 - description = "user config at os level"; 23 - classOne.bar = [ "user" ]; 24 - }; 25 - }; 26 - }; 27 - expr = lib.sort (a: b: a < b) (evalMod "classOne" flake.modules.classOne.aspectOne).bar; 28 - expected = [ 29 - "os" 30 - "user" 31 - ]; 32 - in 33 - { 34 - inherit expr expected; 35 - }; 36 - 37 - }
-58
checkmate/modules/tests/aspect_fixpoint.nix
··· 1 - { 2 - lib, 3 - mkFlake, 4 - evalMod, 5 - ... 6 - }: 7 - { 8 - 9 - flake.tests."test provides using fixpoints" = 10 - let 11 - flake = mkFlake { 12 - flake.aspects = 13 - { aspects, ... }@top: 14 - { 15 - aspectOne = { 16 - classOne.bar = [ "1" ]; 17 - includes = [ 18 - aspects.aspectTwo 19 - ]; 20 - }; 21 - 22 - aspectTwo = { 23 - classOne.bar = [ "2" ]; 24 - includes = [ aspects.aspectTwo.provides.three-and-four-and-five ]; 25 - provides = 26 - { aspects, ... }: 27 - { 28 - three-and-four-and-five = { 29 - classOne.bar = [ "3" ]; 30 - includes = [ 31 - aspects.four 32 - top.aspects.five 33 - ]; 34 - }; 35 - four = { 36 - classOne.bar = [ "4" ]; 37 - }; 38 - }; 39 - }; 40 - 41 - five.classOne.bar = [ "5" ]; 42 - }; 43 - }; 44 - 45 - expr = lib.sort (a: b: a < b) (evalMod "classOne" flake.modules.classOne.aspectOne).bar; 46 - expected = [ 47 - "1" 48 - "2" 49 - "3" 50 - "4" 51 - "5" 52 - ]; 53 - in 54 - { 55 - inherit expr expected; 56 - }; 57 - 58 - }
-54
checkmate/modules/tests/aspect_modules_resolved.nix
··· 1 - { 2 - lib, 3 - mkFlake, 4 - evalMod, 5 - fooOpt, 6 - ... 7 - }: 8 - { 9 - 10 - flake.tests."test modules resolved" = 11 - let 12 - flake = mkFlake { 13 - flake.aspects = 14 - { aspects, ... }: 15 - { 16 - aspectOne = { 17 - name = "one"; 18 - includes = [ aspects.aspectOne.provides.dos ]; 19 - classOne.bar = [ "zzz" ]; 20 - provides.dos = 21 - { aspect-chain, ... }: 22 - { 23 - name = "dos"; 24 - includes = [ aspects.aspectOne.provides.tres ]; 25 - classOne.bar = map (x: x.name) aspect-chain; 26 - }; 27 - 28 - provides.tres = 29 - { aspect-chain, ... }: 30 - { 31 - name = "tres"; 32 - classOne.bar = [ (lib.last aspect-chain).name ]; 33 - }; 34 - }; 35 - }; 36 - }; 37 - mod = { 38 - imports = [ 39 - fooOpt 40 - (flake.aspects.aspectOne.modules.classOne) 41 - ]; 42 - }; 43 - expr = lib.sort (a: b: a < b) (evalMod "classOne" mod).bar; 44 - expected = [ 45 - "dos" 46 - "one" 47 - "zzz" 48 - ]; 49 - in 50 - { 51 - inherit expr expected; 52 - }; 53 - 54 - }
-34
checkmate/modules/tests/aspect_parametric.nix
··· 1 - { 2 - mkFlake, 3 - evalMod, 4 - lib, 5 - ... 6 - }: 7 - { 8 - 9 - flake.tests."test provides parametrized modules" = 10 - let 11 - flake = mkFlake { 12 - flake.aspects = 13 - { aspects, ... }: 14 - { 15 - aspectOne.includes = [ (aspects.aspectTwo.provides.hello "mundo") ]; 16 - aspectOne.classOne.bar = [ "1" ]; 17 - 18 - aspectTwo.provides.hello = world: { 19 - classOne.bar = [ world ]; 20 - }; 21 - }; 22 - }; 23 - 24 - expr = lib.sort (a: b: a < b) (evalMod "classOne" flake.modules.classOne.aspectOne).bar; 25 - expected = [ 26 - "1" 27 - "mundo" 28 - ]; 29 - in 30 - { 31 - inherit expr expected; 32 - }; 33 - 34 - }
-63
checkmate/modules/tests/aspect_provides.nix
··· 1 - { 2 - lib, 3 - mkFlake, 4 - evalMod, 5 - ... 6 - }: 7 - { 8 - 9 - flake.tests."test provides" = 10 - let 11 - flake = mkFlake { 12 - flake.aspects = 13 - { aspects, ... }: 14 - { 15 - aspectOne.includes = with aspects.aspectTwo.provides; [ 16 - foo 17 - bar 18 - ]; 19 - aspectOne.classOne = { }; # must be present for mixing dependencies. 20 - aspectTwo = { 21 - classOne.bar = [ "class one not included" ]; 22 - classTwo.bar = [ "class two not included" ]; 23 - provides.foo = 24 - { class, aspect-chain }: 25 - { 26 - name = "aspectTwo.foo"; 27 - description = "aspectTwo foo provided"; 28 - includes = [ 29 - aspects.aspectThree.provides.moo 30 - aspects.aspectTwo.provides.baz 31 - ]; 32 - classOne.bar = [ "two:${class}:${lib.concatStringsSep "/" (lib.map (x: x.name) aspect-chain)}" ]; 33 - classTwo.bar = [ "foo class two not included" ]; 34 - }; 35 - # a provider can be immediately an aspect object. 36 - provides.bar = { 37 - # classOne is missing on bar 38 - classTwo.bar = [ "bar class two not included" ]; 39 - }; 40 - # _ is an shortcut alias of provides. 41 - _.baz = { 42 - # classOne is missing on bar 43 - classTwo.bar = [ "baz" ]; 44 - }; 45 - }; 46 - aspectThree.provides.moo = 47 - { aspect-chain, class }: 48 - { 49 - classOne.bar = [ "three:${class}:${lib.concatStringsSep "/" (lib.map (x: x.name) aspect-chain)}" ]; 50 - }; 51 - }; 52 - }; 53 - expr = lib.sort (a: b: a < b) (evalMod "classOne" flake.modules.classOne.aspectOne).bar; 54 - expected = [ 55 - "three:classOne:aspectOne/aspectTwo.foo" 56 - "two:classOne:aspectOne" 57 - ]; 58 - in 59 - { 60 - inherit expr expected; 61 - }; 62 - 63 - }
-41
checkmate/modules/tests/aspect_toplevel_parametric.nix
··· 1 - { 2 - mkFlake, 3 - evalMod, 4 - ... 5 - }: 6 - { 7 - 8 - flake.tests."test define top-level context-aware aspect" = 9 - let 10 - flake = mkFlake { 11 - flake.aspects = 12 - { aspects, ... }: 13 - { 14 - aspectOne = { 15 - classOne.bar = [ "should-not-be-present" ]; 16 - includes = [ aspects.aspectTwo ]; 17 - __functor = aspect: { 18 - includes = [ 19 - { classOne.bar = [ "from-functor" ]; } 20 - ] 21 - ++ map (f: f { message = "hello"; }) aspect.includes; 22 - }; 23 - }; 24 - aspectTwo = 25 - { message }: 26 - { 27 - classOne.bar = [ message ]; 28 - }; 29 - }; 30 - }; 31 - 32 - expr = (evalMod "classOne" flake.modules.classOne.aspectOne).bar; 33 - expected = [ 34 - "hello" 35 - "from-functor" 36 - ]; 37 - in 38 - { 39 - inherit expr expected; 40 - }; 41 - }
-29
checkmate/modules/tests/default_empty.nix
··· 1 - { 2 - inputs, 3 - targetMod, 4 - ... 5 - }: 6 - { 7 - 8 - flake.tests."test provides default" = 9 - let 10 - flake = 11 - inputs.flake-parts.lib.mkFlake 12 - { 13 - inputs.self = [ ]; 14 - moduleLocation = builtins.toString ./.; 15 - } 16 - { 17 - systems = [ ]; 18 - imports = [ 19 - targetMod 20 - inputs.flake-parts.flakeModules.modules 21 - ]; 22 - }; 23 - expr = flake.modules; 24 - expected = { }; 25 - in 26 - { 27 - inherit expr expected; 28 - }; 29 - }
-28
checkmate/modules/tests/tranpose_flake_modules.nix
··· 1 - { 2 - mkFlake, 3 - evalMod, 4 - ... 5 - }: 6 - { 7 - 8 - flake.tests."test transposes to flake.modules" = 9 - let 10 - flake = mkFlake { 11 - flake.aspects.aspectOne = { 12 - classOne.foo = "niri"; 13 - classTwo.foo = "paper.spoon"; 14 - }; 15 - }; 16 - expr = { 17 - classOne = (evalMod "classOne" flake.modules.classOne.aspectOne).foo; 18 - classTwo = (evalMod "classTwo" flake.modules.classTwo.aspectOne).foo; 19 - }; 20 - expected = { 21 - classOne = "niri"; 22 - classTwo = "paper.spoon"; 23 - }; 24 - in 25 - { 26 - inherit expr expected; 27 - }; 28 - }
-15
checkmate/modules/tests/transpose_common.nix
··· 1 - { transpose, ... }: 2 - { 3 - 4 - flake.tests."test transpose common childs become one parent" = { 5 - expr = transpose { 6 - a.b = 1; 7 - c.b = 2; 8 - }; 9 - expected.b = { 10 - a = 1; 11 - c = 2; 12 - }; 13 - }; 14 - 15 - }
-10
checkmate/modules/tests/transpose_swap.nix
··· 1 - { transpose, ... }: 2 - { 3 - 4 - flake.tests."test transpose swaps parent and child attrNames" = { 5 - expr = transpose { a.b.c = 1; }; 6 - expected = { 7 - b.a.c = 1; 8 - }; 9 - }; 10 - }
-44
checkmate/modules/tests/without_flakes.nix
··· 1 - { lib, targetLib, ... }: 2 - { 3 - 4 - flake.tests."test usage without flakes" = 5 - let 6 - flake-aspects-lib = import targetLib lib; 7 - # first eval is like evaling the flake. 8 - first = lib.evalModules { 9 - modules = [ 10 - (flake-aspects-lib.new-scope "hello") 11 - { 12 - hello.aspects = 13 - { aspects, ... }: 14 - { 15 - a.b.c = [ "world" ]; 16 - a.includes = [ aspects.x ]; 17 - x.b = 18 - { lib, ... }: 19 - { 20 - c = lib.splitString " " "mundo cruel"; 21 - }; 22 - }; 23 - } 24 - ]; 25 - }; 26 - # second eval is like evaling its nixosConfiguration 27 - second = lib.evalModules { 28 - modules = [ 29 - { options.c = lib.mkOption { type = lib.types.listOf lib.types.str; }; } 30 - first.config.hello.modules.b.a 31 - ]; 32 - }; 33 - expr = lib.sort (a: b: a < b) second.config.c; 34 - expected = [ 35 - "cruel" 36 - "mundo" 37 - "world" 38 - ]; 39 - in 40 - { 41 - inherit expr expected; 42 - }; 43 - 44 - }
+9 -3
nix/types.nix
··· 5 5 aspectsType = lib.types.submodule ( 6 6 { config, ... }: 7 7 { 8 - freeformType = lib.types.attrsOf providerType; 8 + freeformType = lib.types.attrsOf (lib.types.either aspectSubmoduleAttrs providerType); 9 9 config._module.args.aspects = config; 10 10 } 11 11 ); ··· 30 30 ); 31 31 32 32 functionProviderType = lib.types.either functionToAspect (lib.types.functionTo providerType); 33 - providerType = lib.types.either aspectSubmoduleAttrs functionProviderType; 33 + providerType = lib.types.either functionProviderType aspectSubmodule; 34 34 35 35 aspectSubmoduleAttrs = lib.types.addCheck aspectSubmodule ( 36 36 m: (!builtins.isFunction m) || (isAspectSubmoduleFn m) ··· 78 78 options.provides = lib.mkOption { 79 79 description = "Providers of aspect for other aspects"; 80 80 default = { }; 81 - type = aspectsType; 81 + type = lib.types.submodule ( 82 + { config, ... }: 83 + { 84 + freeformType = lib.types.attrsOf providerType; 85 + config._module.args.provides = config; 86 + } 87 + ); 82 88 }; 83 89 options.__functor = lib.mkOption { 84 90 internal = true;