[Nix-dev] python proposal

Marc Weber marco-oweber at gmx.de
Tue Dec 2 15:11:27 CET 2008


On Tue, Dec 02, 2008 at 01:51:51PM +0100, Eelco Dolstra wrote:
> Marc Weber wrote:
> 
> > I've comitted my work now.
> > Let me know what you think about it.
> > If there is any trouble tell me to fix it immediately :)
> > 
> > I've told you about the basic features in previous posts.
> > Would you benefit of a small composableDerivation tutorial?
> 
> Please do.  What does it do?  (I'm kind of concerned that we get yet another
> style of writing expressions only used by some small subset of packages that I
> don't really understand...)

Don't mind. I'll remove my *old* one in favour of the new one.
And it has been desigen to almost look and feel like the default
stdenv.mkDerivation. But you can use additional features if you have to.

By the way: would it make sense to have kind of lib_test.nix file.
It could test the functions and also serve as example usage ?

topics:

  composableDerivation is made up of
    a) mergeAttrsByFuncDefaults
             mergeAttrsByFuncDefaults = foldl mergeAttrByFunc { inherit mergeAttrBy; };
    b) prepareDerivationArgs
    c) applyAndFun
    d) composableDerivation calling those above

long description is following now:

  a) mergeAttrsByFuncDefaults is calling mergeAttrsByFunc with some
    defaults.
    I think an example usage does show best how it's used:
        mergeAttrsByFuncDefaults [
        {
          A = 10;
          B = 10;
          mergeAttrBy = {
            B = x : y : __add x y;
          };
        }
        {
          A = 20;
          B = 20;
          # [2]
        }
        ]
     will result in
     {A = 20; B = 30;} because B has a merge func. 
     the merge func can be overridden eg at [2].
     for common names there are sane defaults (// or ++) (-> mergeAttrBy in lib)

  b) prepareDerivationArgs is a helper function handling configuration
     options. The best way to learn about it is having a look at an
     example:

    composableDerivation { #0
      name = "gst-python-0.10.13";
      flags = {
        pluginsGood = { propagatedBuildInputs = [C]; }; #1
        ffmpeg = { propagatedBuildInputs = [B]; }; #2
      };
      cfg = {
        pluginsGoodSupport = true;
        ffmpegSupport = true;
      };
      propagatedBuildInputs = [ A ];
    };

    The main attr #0 is merged by a) with sub attrs #1 and #2 only when the
    configuration option has been set to true.
    In this example both are set to true so the result of

    composableDerivation looks like this:
    {
      name = ...;
      propagatedBuildInputs = [ A B C ];
      passthru = { pluginsGoodSupport = true; ffmpegSupport = true; }
    }

    Note that passthru has been set automatically for you so that you can
    check for features in depending derivations.

        ffmpeg = { propagatedBuildInputs = [B]; }; #2
    is a shortcut for
        ffmpeg = { 
          set = {
            propagatedBuildInputs = [B]; 
          };
          unset = {
          };
        }

    This way you can pass things if a flag is not set as well.
    example:
      flags = {
        ffmpeg = {
            unset = {
              configureFlags = ["--disabel-feature"];
              assert = !dep.xySupport; #a
            }; 
        };
      };

    Configurations even supports kind of assertion (#a)
    Will trigger this error
        throw "assertion of flag ${a} of derivation ${args.name} failed"

  c) applyAndFun is function based on the work and ideas by Michael Raskin.
    Basic idea: compose arguments before passing them to function.

    The first design (by Michael R.) looked like this:
      name f { attrs } { attrs } null;

    which has been superseded by this design (Michael R again)
      deriv = composedArgsAndFun mkDerivation { name = .. ; buildInputs = ..; };
      myDeriv = deriv.passthru.function {
        # additional args to be merged.
      }

    So there is no longer a "null" termination  but a
    .passthru.function composition continuation. Basically its' the same.
    But there is no longer the need to explain what "null" does :-)

    Here another exapmle to make it most obvious how it works:
      ( ( (name f { attrs }).passthru.function 
        { attrs2 }).passthru.function 
        { attrs3 }).passthru.function )

    How attrs, attrs2, attrs3 are merged depends on which merge function
    has been specified resulting in function "name". In both cases
    (composedArgsAndFun and my applyAndFun) version you can also pass a
    function instead of an attr set. Eg replace { attrs 3 } in the exapmle
    above by (composition : { foo = composition.A }) to access things
    which has been passed before.

    So how does applyAndFun differ from composedArgsAndFun ?
      * It let's you remove attrs as well
      * Its stripped down a little bit because you don't have to pass an
        initial attrs (see definition of composedArgsAndFun which gets
        passed an empty attr set )
      * it implements fix (more bloat again :-)

    fix feature of applyAndFun
    =========================
    start = applyAndFun mkDerivation {
      start = foo;
    };
    deriv = ( composition: {
      foo = composition.fixed.bar; # << fixed is used here
      start2 = composition.start; # you can use what has been passed without "fixed"
    });
    final = deriv.passthru.fun {
      bar = "this value is used above";
    }
      
    Merging is the behaviour you want most often. That's why I've been
    following the idea of Michael Raskin again by introducing an
    additional function: .passthru.funMerge which does merge by default.
    
    summary / comparison:
    =====================
    composedArgsAndFun:
      - interface:
          .passthru.function (does merge automatically)
      - you can pass a function or attrs

    applyAndFun (my new version of composedArgsAndFun):
      - interface:
          .passthru.funMerge (does merge automatically - only matters when passing a function)
          .passthru.fun      (doesn't merge. passing (x : {}) will remove all attrs)
      - you can pass a function or attrs
      - fix feature: you have .passthru.funMerge (x : x.fixed ) availible..

  d)  composableDerivation
    You know what ? You already know what it does:

    It let's you compose args by applyAndFun, applying the result to
    prepareDerivationArgs (handling configuration options) passing that
    result to mkDerivation.

    So as long as you don't use
    .passthru.fun(Merge) or cfg = {...} or  flags = {..} or fixed
    it should behave exactly like stdenv.mkDerivation does except that you
    have to use composableDerivation { initial = { name = ...; meta =...; } ; }

    The implementation looks like this:

        # see new python derivations for example..
        # You should be able to override anything you like easily
        composableDerivation = {
                # modify args before applying stdenv.mkDerivation, this should
                # remove at least attrs removeAttrsBy
              f ? lib.prepareDerivationArgs,
              stdenv ? pkgs.stdenv,
                # initial set of arguments to be passed to stdenv.mkDerivation
                # passing prepareDerivationArgs by default
              initial ? {},
                # example func :  (x: x // { x.buildInputs ++ ["foo"] }), but
                # see mergeAttrByFunc which does this for you
              merge ? (lib.mergeOrApply lib.mergeAttrByFunc)
            }: lib.applyAndFun
                  (args: stdenv.mkDerivation (f args))
                  merge
                  (merge { inherit (lib) mergeAttrBy; } initial);
      
Hopefully you're able to read the new python derivations now?

Sincerly
Marc Weber



More information about the nix-dev mailing list