[Nix-dev] [patch] Python proposal + composableDerivation

Marc Weber marco-oweber at gmx.de
Thu Nov 20 12:45:00 CET 2008


Hi,

I've finished my proposal. You can get all those patches by running
$git clone git://mawercer.de/nixpkgs; git checkout python-proposal

pitivi still doesn't find module gtk (the check passes though!)
I don't know why yet, do you?

I'm introducing several things hereby:
a) composableDerivation 
b) prepareDerivationArgs 
c) applyAndFun
d) mergeAttrByFunc
e) some debuging function (traceCall{,2,3})

a) is simple using b,c,d. it can be used like stdenv.mkDerivation, but if you
   want you can add flags, inherit or override stuff etc.
   That's my preferred way to do things now. It supersedes all the old crap
   found at the end of lib/default.nix.
b) is handling flags. If the flag is set the given attrs is merged in.
  Instead of specifying attrs you can define a function mapping the existing
  attrs. Eg:
  flags = {
    map = {
      unset = attrs : removeAttrs attrs ["foo"];
    }
  };

I've talked about most new things already in
http://mail.cs.uu.nl/pipermail/nix-dev/2008-November/001463.html
However I've replaced foldArgs by applyAndFun which does also support fix now.
(search ".fixed" in this patch to see the real world example)

Enjoy and write feedback.

Marc Weber


>From d8013c0157f33d2afa2ee4af6a026da6ec378fa5 Mon Sep 17 00:00:00 2001
From: Marc Weber <marco-oweber at gmx.de>
Date: Thu, 20 Nov 2008 00:09:48 +0100
Subject: [PATCH] added debug functions tracing function arguments and result

---
 pkgs/lib/default.nix |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/pkgs/lib/default.nix b/pkgs/lib/default.nix
index e5247c5..6d69c05 100644
--- a/pkgs/lib/default.nix
+++ b/pkgs/lib/default.nix
@@ -496,6 +496,11 @@ rec {
       else if (x == false) then "x is boolean false"
       else if (x == null) then "x is null"
       else "x is probably a string starting, starting characters: ${__substring 0 50 x}..";
+  # trace the arguments passed to function and its result 
+  traceCall  = n : f : a : let t = n2 : x : traceMarked "${n} ${n2}:" x; in t "result" (f (t "arg 1" a));
+  traceCall2 = n : f : a : b : let t = n2 : x : traceMarked "${n} ${n2}:" x; in t "result" (f (t "arg 1" a) (t "arg 2" b));
+  traceCall3 = n : f : a : b : c : let t = n2 : x : traceMarked "${n} ${n2}:" x; in t "result" (f (t "arg 1" a) (t "arg 2" b) (t "arg 3" c));
+
 
 
   innerClosePropagation = ready: list: if list == [] then ready else
-- 
1.6.0.2.GIT

>From 2b1b81c8738d4738aedc7cddaf1d1464e7882954 Mon Sep 17 00:00:00 2001
From: Marc Weber <marco-oweber at gmx.de>
Date: Thu, 20 Nov 2008 00:11:42 +0100
Subject: [PATCH] enhancing whatis trace function

---
 pkgs/lib/default.nix |    7 ++++---
 1 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/pkgs/lib/default.nix b/pkgs/lib/default.nix
index 6d69c05..a3038a9 100644
--- a/pkgs/lib/default.nix
+++ b/pkgs/lib/default.nix
@@ -485,10 +485,11 @@ rec {
   # this can help debug your code as well - designed to not produce thousands of lines
   traceWhatis = x : __trace (whatis x) x;
   traceMarked = str: x: __trace (str + (whatis x)) x;
-  whatis = x : 
+  attrNamesToStr = a : concatStringsSep "; " (map (x : "${x}=") (__attrNames a));
+  whatis = x :
       if (__isAttrs x) then
-          if (x ? outPath) then "x is a derivation with name ${x.name}"
-          else "x is an attr set with attributes ${builtins.toString (__attrNames x)}"
+          if (x ? outPath) then "x is a derivation, name ${if x ? name then x.name else "<no name>"}, { ${attrNamesToStr x} }"
+          else "x is attr set { ${attrNamesToStr x} }"
       else if (__isFunction x) then "x is a function"
       else if (x == []) then "x is an empty list"
       else if (__isList x) then "x is a list, first item is : ${whatis (__head x)}"
-- 
1.6.0.2.GIT

>From fac9e686d39c04987b930c144a752a02ea019dfa Mon Sep 17 00:00:00 2001
From: Marc Weber <marco-oweber at gmx.de>
Date: Thu, 20 Nov 2008 00:16:46 +0100
Subject: [PATCH] added mergeAttr and concatList functions giving // and ++ a name

---
 pkgs/lib/default.nix |    7 ++++---
 1 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/pkgs/lib/default.nix b/pkgs/lib/default.nix
index a3038a9..a521d18 100644
--- a/pkgs/lib/default.nix
+++ b/pkgs/lib/default.nix
@@ -81,8 +81,8 @@ rec {
 
     
   # Concatenate a list of lists.
-  concatLists =
-    fold (x: y: x ++ y) [];
+  concatList = x : y : x ++ y;
+  concatLists = fold concatList [];
 
 
   # Concatenate a list of strings.
@@ -555,7 +555,8 @@ rec {
   # iterates over a list of attributes collecting the attribute attr if it exists
   catAttrs = attr : l : fold ( s : l : if (hasAttr attr s) then [(builtins.getAttr attr s)] ++ l else l) [] l;
 
-  mergeAttrs = fold ( x : y : x // y) {};
+  mergeAttr = x : y : x // y;
+  mergeAttrs = fold mergeAttr {};
 
   attrVals = nameList : attrSet :
     map (x: builtins.getAttr x attrSet) nameList;
-- 
1.6.0.2.GIT

>From a77eafaa6a85268b148d93232a43cf9e16bd7537 Mon Sep 17 00:00:00 2001
From: Marc Weber <marco-oweber at gmx.de>
Date: Thu, 20 Nov 2008 00:19:22 +0100
Subject: [PATCH] depreceating functions which have been sud by me only replacements are in the following commits.. I still have to remove and adopt the code using them

---
 pkgs/lib/default.nix |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/pkgs/lib/default.nix b/pkgs/lib/default.nix
index a521d18..4e57470 100644
--- a/pkgs/lib/default.nix
+++ b/pkgs/lib/default.nix
@@ -533,6 +533,7 @@ rec {
       takeTillSlash (__sub (__stringLength s) 1) 1 s;
 
   # calls a function (f attr value ) for each record item. returns a list
+  # should be renamed to mapAttrsFlatten
   mapRecordFlatten = f : r : map (attr: f attr (builtins.getAttr attr r) ) (attrNames r);
 
   # maps a function on each attr value
@@ -580,6 +581,7 @@ rec {
   # { buildInputs = [a b]; }
   # merging buildPhase does'nt really make sense. The cases will be rare where appending /prefixing will fit your needs?
   # in these cases the first buildPhase will override the second one
+  # ! depreceated, use mergeAttrByFunc instead
   mergeAttrsNoOverride = { mergeLists ? ["buildInputs" "propagatedBuildInputs"],
                            overrideSnd ? [ "buildPhase" ]
                          } : attrs1 : attrs2 :
@@ -604,6 +606,7 @@ rec {
       subset_attr_names );
 
 # Marc 2nd proposal: (not everything has been tested in detail yet..)
+# depreceated because it's too complicated. use prepareDerivationArgs instead
 
   # usage / example
   # flagConfig = {
-- 
1.6.0.2.GIT

>From e0933aa255765fb397a6c6dee3ec3f57be7382ad Mon Sep 17 00:00:00 2001
From: Marc Weber <marco-oweber at gmx.de>
Date: Thu, 20 Nov 2008 00:26:35 +0100
Subject: [PATCH] adding mergeAttrsByFunc function - its easiy to customize how a name should be merged - the merge function is passed by the attr set itself (and can be overridden/ extended this way) This code can probably be shortened using zip and the like as proposed by Nicolas Pierron (mailinglist)

---
 pkgs/lib/default.nix |   39 +++++++++++++++++++++++++++++++++++++++
 1 files changed, 39 insertions(+), 0 deletions(-)

diff --git a/pkgs/lib/default.nix b/pkgs/lib/default.nix
index 4e57470..0a52e17 100644
--- a/pkgs/lib/default.nix
+++ b/pkgs/lib/default.nix
@@ -595,6 +595,45 @@ rec {
               else throw "error mergeAttrsNoOverride, attribute ${n} given in both attributes - no merge func defined"
             else __getAttr n attrs2 # add attribute not existing in attr1
            )) attrs1 (__attrNames attrs2);
+
+
+  # example usage:
+  # mergeAttrByFunc  {
+  #   inherit mergeAttrBy; # defined below
+  #   buildInputs = [ a b ];
+  # } {
+  #  buildInputs = [ c d ];
+  # };
+  # will result in
+  # { mergeAttrsBy = [...]; buildInputs = [ a b c d ]; }
+  # is used by prepareDerivationArgs and can be used when composing using
+  # foldArgs, composedArgsAndFun or applyAndFun. Example: composableDerivation in all-packages.nix
+  mergeAttrByFunc = x : y :
+    let
+          mergeAttrBy2 = { mergeAttrBy=mergeAttr; }
+                      // (maybeAttr "mergeAttrBy" {} x)
+                      // (maybeAttr "mergeAttrBy" {} y); in
+    mergeAttrs [
+      x y
+      (mapAttrs ( a : v : # merge special names using given functions
+          if (__hasAttr a x)
+             then if (__hasAttr a y)
+               then v (__getAttr a x) (__getAttr a y) # both have attr, use merge func
+               else (__getAttr a x) # only x has attr
+             else (__getAttr a y) # only y has attr)
+          ) (removeAttrs mergeAttrBy2
+                         # don't merge attrs which are neither in x nor y
+                         (filter (a : (! __hasAttr a x) && (! __hasAttr a y) )
+                                 (__attrNames mergeAttrBy2))
+            )
+      )
+    ];
+  mergeAttrsByFunc = fold mergeAttrByFunc {};
+  # sane defaults (same name as attr name so that inherit can be used)
+  mergeAttrBy = # { buildInputs = concatList; [...]; passthru = mergeAttr; [..]; }
+    listToAttrs (map (n : nv n concatList) [ "buildInputs" "propagatedBuildInputs" "configureFlags" "prePhases" "postAll" ])
+    // listToAttrs (map (n : nv n mergeAttr) [ "passthru" "meta" ]);
+
   # returns atribute values as a list 
   flattenAttrs = set : map ( attr : builtins.getAttr attr set) (attrNames set);
   mapIf = cond : f :  fold ( x : l : if (cond x) then [(f x)] ++ l else l) [];
-- 
1.6.0.2.GIT

>From ff7504cdfc48c435c8df84ce67fab91b54fb46fd Mon Sep 17 00:00:00 2001
From: Marc Weber <marco-oweber at gmx.de>
Date: Thu, 20 Nov 2008 00:37:03 +0100
Subject: [PATCH] added prepareDerivationArgs

---
 pkgs/lib/default.nix |   55 ++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 55 insertions(+), 0 deletions(-)

diff --git a/pkgs/lib/default.nix b/pkgs/lib/default.nix
index 0a52e17..f87826a 100644
--- a/pkgs/lib/default.nix
+++ b/pkgs/lib/default.nix
@@ -644,6 +644,61 @@ rec {
           then r ++ [ (  nv attr ( f (__getAttr attr attrs) ) ) ] else r ) []
       subset_attr_names );
 
+  # prepareDerivationArgs tries to make writing configurable derivations easier
+  # example:
+  #  prepareDerivationArgs {
+  #    mergeAttrBy = {
+  #       myScript = x : y : x ++ "\n" ++ y;
+  #    };
+  #    cfg = {
+  #      readlineSupport = true;
+  #    };
+  #    flags = {
+  #      readline = {
+  #        set = {
+  #           configureFlags = [ "--with-compiler=${compiler}" ];
+  #           buildInputs = [ compiler ];
+  #           pass = { inherit compiler; READLINE=1; };
+  #           assertion = compiler.dllSupport;
+  #           myScript = "foo";
+  #        };
+  #        unset = { configureFlags = ["--without-compiler"]; };
+  #      };
+  #    };
+  #    src = ...
+  #    buildPhase = '' ... '';
+  #    name = ...
+  #    myScript = "bar";
+  #  };
+  # if you don't have need for unset you can omit the surrounding set = { .. } attr
+  # all attrs except flags cfg and mergeAttrBy will be merged with the
+  # additional data from flags depending on config settings
+  # It's used in composableDerivation in all-packages.nix. It's also used
+  # heavily in the new python and libs implementation
+  prepareDerivationArgs = args:
+    let args2 = { cfg = {}; flags = {}; } // args;
+        flagName = name : "${name}Support";
+        cfgWithDefaults = (listToAttrs (map (n : nv (flagName n) false) (attrNames args2.flags)))
+                          // args2.cfg;
+        opts = flattenAttrs (mapAttrs (a : v :
+                let v2 = if (v ? set || v ? unset) then v else { set = v; };
+                    n = if (__getAttr (flagName a) cfgWithDefaults) then "set" else "unset";
+                    attr = maybeAttr n {} v2; in
+                if (maybeAttr "assertion" true attr)
+                  then attr
+                  else throw "assertion of flag ${a} of derivation ${args.name} failed"
+               ) args2.flags );
+    in removeAttrs
+      (mergeAttrsByFunc ([args] ++ opts))
+      ["flags" "cfg" "mergeAttrBy" ];
+  # supportFlag functions for convinience
+  sFlagEnable = { name, buildInputs ? [], propagatedBuildInputs ? [] } : {
+      set = { configureFlags = "--enable-${name}"; inherit buildInputs; inherit propagatedBuildInputs; };
+      unset = { configureFlags = "--disable-${name}"; };
+    };
+
+
+
 # Marc 2nd proposal: (not everything has been tested in detail yet..)
 # depreceated because it's too complicated. use prepareDerivationArgs instead
 
-- 
1.6.0.2.GIT

>From 35883af94fd1d6be6617c1a0c3ea398dc1d9268c Mon Sep 17 00:00:00 2001
From: Marc Weber <marco-oweber at gmx.de>
Date: Thu, 20 Nov 2008 10:47:51 +0100
Subject: [PATCH] adding lib function composableDerivation
 providing easy setups of flags and configurations for derivations.
 configuration is passed via passthru automatically,
 additional names can be merged with final attrs in an automatic sensible way
 even supporting fix.
 fun and funMerge idea by Michael Raskin

---
 pkgs/lib/default.nix            |   21 +++++++++++++++++++--
 pkgs/top-level/all-packages.nix |   14 ++++++++++++++
 2 files changed, 33 insertions(+), 2 deletions(-)

diff --git a/pkgs/lib/default.nix b/pkgs/lib/default.nix
index f87826a..6cf3425 100644
--- a/pkgs/lib/default.nix
+++ b/pkgs/lib/default.nix
@@ -43,7 +43,24 @@ rec {
     let arg=(merger init (defaultMergeArg init x)); in  
       # now add the function with composed args already applied to the final attrs
     setAttrMerge "passthru" {} (f arg) ( x : x // { function = foldArgs merger f arg; } );
- 
+
+  # returns f x // { passthru.fun = y : f (merge x y); } while preserving other passthru names.
+  # example: let ex = applyAndFun (x : removeAttrs x ["fixed"])  (mergeOrApply mergeAttr) {name = 6;};
+  #              usage1 = ex.passthru.fun { name = 7; };    # result: { name = 7;}
+  #              usage2 = ex.passthru.fun (a: a // {name = __add a.name 1; }); # result: { a = 7; }
+  # fix usage:
+  #              usage3a = ex.passthru.fun (a: a // {name2 = a.fixed.toBePassed; }); # usage3a will fail because toBePassed is not yet given
+  #              usage3b usage3a.passthru.fun { toBePassed = "foo";}; # result { name = 7; name2 = "foo"; toBePassed = "foo"; fixed = <this attrs>; }
+  applyAndFun = f : merge : x : assert (__isAttrs x || __isFunction x);
+    let takeFix = if (__isFunction x) then x else (attr: merge attr x); in
+    setAttrMerge "passthru" {} (fix (fixed : f (takeFix {inherit fixed;})))
+      ( y : y //
+        {
+          fun = z : applyAndFun f merge (fixed: merge (takeFix fixed) z);
+          funMerge = z : applyAndFun f merge (fixed: let e = takeFix fixed; in e // merge e z);
+        } );
+  mergeOrApply = merge : x : y : if (__isFunction y) then  y x else merge x y;
+
   # rec { # an example of how composedArgsAndFun can be used
   #  a  = composedArgsAndFun (x : x) { a = ["2"]; meta = { d = "bar";}; };
   #  # meta.d will be lost ! It's your task to preserve it (eg using a merge function)
@@ -690,7 +707,7 @@ rec {
                ) args2.flags );
     in removeAttrs
       (mergeAttrsByFunc ([args] ++ opts))
-      ["flags" "cfg" "mergeAttrBy" ];
+      ["flags" "cfg" "mergeAttrBy" "fixed" ]; # fixed may be passed as fix argument or such
   # supportFlag functions for convinience
   sFlagEnable = { name, buildInputs ? [], propagatedBuildInputs ? [] } : {
       set = { configureFlags = "--enable-${name}"; inherit buildInputs; inherit propagatedBuildInputs; };
diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix
index 904c90e..59cb5a5 100644
--- a/pkgs/top-level/all-packages.nix
+++ b/pkgs/top-level/all-packages.nix
@@ -470,6 +470,20 @@ let
     inherit pkgs;
   };
 
+  # 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);
 
   ### TOOLS
 
-- 
1.6.0.2.GIT

>From a83868e5c2ebf25cbe992e261d6d99323148f3ab Mon Sep 17 00:00:00 2001
From: Marc Weber <marco-oweber at gmx.de>
Date: Thu, 20 Nov 2008 12:11:52 +0100
Subject: [PATCH] python 25 proposal

---
 .../interpreters/python-new/2.5/default.nix        |  306 ++++++++++++++++++++
 .../python-new/2.5/nix-find-sites-2.5.patch        |   33 ++
 .../interpreters/python-new/2.5/python.nix         |   69 +++++
 .../interpreters/python-new/2.5/search-path.patch  |   28 ++
 pkgs/top-level/all-packages.nix                    |   10 +
 5 files changed, 446 insertions(+), 0 deletions(-)
 create mode 100644 pkgs/development/interpreters/python-new/2.5/default.nix
 create mode 100644 pkgs/development/interpreters/python-new/2.5/nix-find-sites-2.5.patch
 create mode 100644 pkgs/development/interpreters/python-new/2.5/python.nix
 create mode 100644 pkgs/development/interpreters/python-new/2.5/search-path.patch

diff --git a/pkgs/development/interpreters/python-new/2.5/default.nix b/pkgs/development/interpreters/python-new/2.5/default.nix
new file mode 100644
index 0000000..e75d5c3
--- /dev/null
+++ b/pkgs/development/interpreters/python-new/2.5/default.nix
@@ -0,0 +1,306 @@
+# the nix-python way..
+
+# By default python looks in the $prefix/lib/python-$version/site-packages directory
+# and reads the .pth files to add the library paths to sys.path. 
+# Using PYHTONPATH is not enough because it doesn't make python read the .pth files
+# telling python where to find additional modules. PYTHONUSERBASE would suffice, but
+# it only supports *one* user location. That's why I've added the new env var NIX_PYTHON_SITES
+# containing a colon separated list of modules telling python where to look
+# for imports and also read the .pth files
+
+p: # p = pkgs
+let 
+  inherit (p) lib fetchurl stdenv getConfig;
+in
+  lib.fix ( t : { # t = this attrs
+
+    version = "2.5";
+    versionAttr = "python25";
+
+    # see pythonFull.
+    pythonMinimal = ( (import ./python.nix) {
+      name = "python-${t.version}";
+      inherit (p) fetchurl stdenv lib bzip2 ncurses composableDerivation;
+      inherit  (p) zlib sqlite db4 readline openssl gdbm;
+    });
+
+    # python wiht all features enabled.
+    # if you really need a stripped version we should add __overides
+    # so that you can replace it the way it's done in all-packages.nix
+    pythonFull = t.pythonMinimal.passthru.fun {
+     name = "python-${t.version}-full";
+      cfg = {
+        zlibSupport = true;
+        sqliteSupport = true;
+        db4Support = true;
+        readlineSupport = true;
+        opensslSupport = true;
+        gdbmSupport = true;
+      };
+    };
+
+    # python wrapper. You should install this
+    # It automatically wrapps python adding NIX_PYTHON_SITES so that you can use all the libraries
+    # when running the wrapper from the console.
+    # configuration:
+    # python25 = { wrapperLibs = let p = pkgs.python25New; in [ p.wxPython25 p.name p.name2 ]; }; 
+    # python25 = { wrapperLibs = [ "all" ]; }; # install all libraries provided by this file
+    # TODO: does pydoc find stuff from libraries?
+    pythonWrapper = stdenv.mkDerivation {
+      name = "${t.pythonFull.name}-wrapper";
+      # [1] using full because I feel installing various versions isn't any better
+      phases = "buildPhase";
+      buildInputs = [ p.makeWrapper ] 
+        ++ lib.concatMap (x: if x == "all" then t.all else [x]) (getConfig [t.versionAttr "wrapperLibs"] []);
+
+      buildPhase = ''
+        ensureDir $out/bin
+        cat >> $out/bin/python << EOF
+        export NIX_PYTHON_SITES=\$NIX_PYTHON_SITES:$NIX_PYTHON_SITES
+        exec ${t.pythonFull}/bin/python "\$@"
+        EOF
+        chmod +x $out/bin/python
+      '';
+    };
+
+    ### basic support for installing python libraries
+    # set pyCheck to a small python snippet importing all modules of this python
+    # lib to verify it works
+    # You can define { python25 { debugCmd = "DISPLAY=:0.0 pathtoxterm"; }
+    # in your config for easier debugging..
+    pythonLibStub = p.composableDerivation {
+      initial = {
+          propagatedBuildInputs = [ t.pythonFull ]; # see [1]
+          postPhases = ["postAll"]; # using new name so that you dno't override this phase by accident
+          prePhases = ["defineValidatingEval"];
+          # ensure phases are run or a non zero exit status is caused (if there are any syntax errors such as eval "while")
+          defineValidatingEval = ''
+            eval(){
+              e="$(type eval | { read; while read line; do echo $line; done })"
+              unset eval;
+              local evalSucc="failure"
+              eval "evalSucc=ok;""$1"
+              eval "$e"
+              [ $evalSucc = "failure" ] && { echo "eval failed, snippet:"; echo "$1"; return 1; }
+            }
+          '';
+          postAll = ''
+            ensureDir $out/nix-support
+            echo "export NIX_PYTHON_SITES=\"$out:\$NIX_PYTHON_SITES\"" >> $out/nix-support/setup-hook 
+            # run check
+            [ -n "$pyCheck" ] \
+              && ( . $out/nix-support/setup-hook
+                   mkdir $TMP/new-test; cd $TMP/new-test
+                   echo PYTHONPATH=$PYTHONPATH
+                   echo NIX_PYTHON_SITES=$NIX_PYTHON_SITES
+                   script="$(echo -e "import sys\nprint sys.path\npyCheck\nprint \"check ok\"")"
+                   script="''${script/pyCheck/$pyCheck}"
+                   echo "check script is"; echo "$script"
+                   echo "$script" | /var/run/current-system/sw/bin/strace -o $TMP/strace -f python || { ${ getConfig [t.versionAttr "debugCmd"] ":"} ; exit 1; }
+                   )'';
+          passthru = {
+            libPython = t.version; # used to find all python libraries fitting this version (-> see name all below)
+          };
+          mergeAttrBy = {
+            postCheck = x : y : "${x}\n${y}";
+          };
+      };
+    };
+
+    # same as pythonLibStub, but runs default python setup.py actions
+    pythonLibSetup = t.pythonLibStub.passthru.fun {
+      buildPhase = ''python setup.py $setupFlags build'';
+      installPhase = ''python setup.py $setupFlags install --prefix=$out'';
+      mergeAttrBy = {
+        setupFlags = lib.concatList;
+      };
+    };
+
+    ### python libraries:
+
+    wxPythonBaseFun = (t.pythonLibSetup.passthru.funMerge (a :
+      let inherit (a.fixed) wxGTK version; in
+        {
+          buildInputs = [p.pkgconfig wxGTK (wxGTK.gtk)];
+          setupFlags=["WXPORT=gtk2 NO_HEADERS=1 BUILD_GLCANVAS=0 BUILD_OGL=0 UNICODE=1"];
+          configurePhase = ''cd wxPython'';
+          pyCheck = "import wx";
+          name = "wxPython-${version}";
+          meta = { # 2.6.x and 2.8.x
+            description="A blending of the wxWindows C++ class library with Python";
+            homepage="http://www.wxpython.org/";
+            license="wxWinLL-3";
+          };
+        }
+    )).passthru.fun;
+
+    wxPython26 = t.wxPythonBaseFun {
+      version = "2.6.3.3";
+      passthru = { wxGTK = p.wxGTK26; };
+      src = fetchurl {
+        url = mirror://sourceforge/wxpython/wxPython-src-2.6.3.3.tar.bz2;
+        md5 = "66b9c5f8e20a9505c39dab1a1234daa9";
+      };
+    };
+
+    # compilation errors
+    #wxPython28 = t.wxPythonBaseFun {
+    #  version = "2.8.9.1";
+    #  passthru = { wxGTK = wxGTK28; };
+    #  src = fetchurl {
+    #    url = mirror://sourceforge.net/sourceforge/wxpython/wxPython-src-2.8.9.1.tar.bz2;
+    #    sha256 = "1yp7l2c2lfpwc2x5lk5pawmzq2bqajzhbzqs1p10jd211slwhjsq";
+    #  };
+    #};
+
+    # couldn't download source
+    #foursuite = pythonLibSetup.passthru.fun {
+    #  version = "1.0.2";
+    #  name = "4suite-${version}";
+    #  src = fetchurl {
+    #    url = "mirror://sourceforge/foursuite/4Suite-XML-${version}.tar.bz2";
+    #    sha256 = "0g5cyqxhhiqnvqk457k8sb97r18pwgx6gff18q5296xd3zf4cias";
+    #  };
+    #};
+
+    #bsddb3 = t.pythonLibSetup.passthru.fun {
+    #  version = "1.0.2";
+    #  name = "bsddb3-4.5.0";
+    #  setupFlags = ["--berkeley-db=${p.db4}"];
+    #  src = fetchurl {
+    #    url = mirror://sourceforge/pybsddb/bsddb3-4.5.0.tar.gz;
+    #    sha256 = "1h09kij32iikr9racp5p7qrb4li2gf2hs0lyq6d312qarja4d45v";
+    #  };
+    #};
+
+  pygobject = t.pythonLibStub.passthru.fun {
+    name = "pygobject-2.15.4";
+    flags = { libffi = { buildInputs = [p.libffi];}; };
+    cfg = { libffi = true; };
+    buildInputs = [ p.pkgconfig p.gtkLibs.glib];
+    src = fetchurl {
+      url = "http://ftp.gnome.org/pub/GNOME/sources/pygobject/2.15/pygobject-2.15.4.tar.bz2";
+      sha256 = "19vxczy01xyss2f5aqf93al3jzrxn50srgzkl4w7ivdz50rnjin7";
+    };
+    pyCheck = "import gobject";
+  };
+
+  pygtkBaseFun = (t.pythonLibStub.passthru.funMerge (a :
+    let inherit (a.fixed) glib gtk version; in {
+      name = "pygtk-${version}";
+      buildInputs = [p.pkgconfig glib gtk];
+      propagatedBuildInputs = [t.pygobject t.pycairo ];
+      flags = {
+        cairo = { buildInputs = [ p.cairo ]; }; # TODO add pyCheck
+        glade = { buildInputs = [ p.glade ]; }; # TODO add pyCheck
+      };
+      cfg = {
+        glade = true;
+        cairo = true;
+      };
+    }
+  )).passthru.fun;
+
+  #pygtk213 = t.pygtkBaseFun {
+  #  version = "2.13.0";
+  #  src = fetchurl {
+  #    url = http://ftp.gnome.org/pub/GNOME/sources/pygtk/2.13/pygtk-2.13.0.tar.bz2;
+  #    sha256 = "0644ll48hi8kwfng37b0k5qgb0fbiy298r7sxd4j7ag7lj4bgic0";
+  #  };
+  #  passthru = { inherit (p.gtkLibs) glib gitk; };
+  #  pyCheck = ''
+  #    import pygtk; pygtk.require('2.0')
+  #    import gtk
+  #  '';
+  #};
+
+  pygtk212 = t.pygtkBaseFun {
+    version = "2.12.1";
+    src = fetchurl {
+      url = http://ftp.acc.umu.se/pub/GNOME/sources/pygtk/2.12/pygtk-2.12.1.tar.bz2;
+      sha256 = "0gg13xgr7y9sppw8bdys042928nc66czn74g60333c4my95ys021";
+    };
+    passthru = { inherit (p.gtkLibs) glib gtk; };
+    pyCheck = ''
+      import pygtk; pygtk.require('2.0')
+      import gtk
+    '';
+    patches = [ ./pygtk-2.12.1-fix-amd64-from-gentoo.patch ];
+  };
+
+  pycairo = t.pythonLibStub.passthru.fun {
+    name = "pycairo-1.8.0";
+    buildInputs = [ p.pkgconfig p.cairo p.x11 ];
+    src = fetchurl {
+      url = http://www.cairographics.org/releases/pycairo-1.6.4.tar.gz;
+      md5 = "2c3aa21e6e610321498f9f81f7b625df";
+    };
+    pyCheck = "import cairo";
+  };
+
+  gstPython = t.pythonLibStub.passthru.fun {
+    name = "gst-python-0.10.13";
+    src = fetchurl {
+      url = http://gstreamer.freedesktop.org/src/gst-python/gst-python-0.10.13.tar.gz;
+      sha256 = "0yin36acr5ryfpmhlb4rlagabgxrjcmbpizwrc8csadmxzmigb86";
+    };
+    buildInputs =[ p.flex2535 p.pkgconfig];
+    propagatedBuildInputs = [
+          t.pygtk212
+          p.gst_all.gstreamer
+          p.gst_all.gstPluginsBase
+          p.gst_all.gstPluginsGood
+        ];
+    pyCheck = ''
+      import pygst
+      pygst.require('0.10')
+      import gst
+    '';
+    meta = {
+      description = "python gstreamer bindings";
+      homepage = http://gstreamer.freedesktop.org/modules/gst-python.html;
+      license = "GPLv2.1";
+    };
+  };
+
+  ### python applications
+
+  pythonExStub = p.composableDerivation {
+    initial = {
+      buildInputs = [p.makeWrapper];
+      postPhases = ["wrapExecutables"];
+      propagatedBuildInputs = [ t.pythonFull ]; # see [1]
+      wrapExecutables = ''
+        for prog in $out/bin/*; do
+        wrapProgram "$prog"     \
+                     --set NIX_PYTHON_SITES "$NIX_PYTHON_SITES"
+        done
+      '';
+    };
+  };
+
+  pitivi = t.pythonExStub.passthru.fun {
+    name = "pitivi-0.11.2";
+    src = fetchurl {
+      url = http://ftp.gnome.org/pub/GNOME/sources/pitivi/0.11/pitivi-0.11.2.tar.bz2;
+      sha256 = "0d3bqgfp60qm5bf904k477bd8jhxizj1klv84wbxsz9vhjwx9zcl";
+    };
+    buildInputs =[ t.pygtk212 t.gstPython p.intltool p.gettext p.makeWrapper p.gettext ];
+    # why do have to add gtk-2.0 explicitely?
+    meta = {
+        description = "A non-linear video editor using the GStreamer multimedia framework";
+        homepage = http://www.pitivi.org/wiki/Downloads;
+        license = "LGPL-2.1";
+    };
+    postInstall = ''
+      # set the python which has been used to compile this package
+      sed -i -e 's@#!.*@#!'"$(which python)@" $out/bin/pitivi
+    '';
+  };
+
+  all = lib.filter (x: 
+                   (__isAttrs x)
+                && ((lib.maybeAttr "libPython" false x) == t.version)
+                && (lib.maybeAttr "name" false x != false) # don't collect pythonLibStub etc
+        ) (lib.flattenAttrs (removeAttrs t ["all"])); # nix is not yet lazy enough, so I've to remove all first
+})
diff --git a/pkgs/development/interpreters/python-new/2.5/nix-find-sites-2.5.patch b/pkgs/development/interpreters/python-new/2.5/nix-find-sites-2.5.patch
new file mode 100644
index 0000000..2fa610f
--- /dev/null
+++ b/pkgs/development/interpreters/python-new/2.5/nix-find-sites-2.5.patch
@@ -0,0 +1,33 @@
+--- a/site.py    2008-11-19 14:48:49.000000000 +0100
+--- Python-2.5-orig/Lib/site.py        2008-05-10 19:36:24.000000000 +0200
++++ Python-2.5/Lib/site.py     2008-11-17 05:37:02.000000000 +0100
+@@ -390,6 +390,20 @@
+     except ImportError:
+         pass
+ 
++def addnixsitepackages(known_paths):
++    """
++    used to add multiple site packages for /nix/store to sys.path also
++    evaluating the .pth files (http://docs.python.org/library/site.html#module-site)
++    """
++    env_nix_sites = os.environ.get("NIX_PYTHON_SITES", None)
++    if env_nix_sites:
++      for path in env_nix_sites.split(":"):
++        if os.path.isdir(path):
++          NIX_SITE = os.path.join(path, "lib",
++                                 "python" + sys.version[:3],
++                                 "site-packages")
++          addsitedir(NIX_SITE, known_paths)
++    return known_paths
+ 
+ def main():
+     abs__file__()
+@@ -400,6 +414,7 @@
+     paths_in_sys = addsitepackages(paths_in_sys)
+     if sys.platform == 'os2emx':
+         setBEGINLIBPATH()
++    paths_in_sys = addnixsitepackages(paths_in_sys)
+     setquit()
+     setcopyright()
+     sethelper()
+
diff --git a/pkgs/development/interpreters/python-new/2.5/python.nix b/pkgs/development/interpreters/python-new/2.5/python.nix
new file mode 100644
index 0000000..6ae5ffb
--- /dev/null
+++ b/pkgs/development/interpreters/python-new/2.5/python.nix
@@ -0,0 +1,69 @@
+args: with args;
+let inherit (lib) optional prepareDerivationArgs concatStringsSep fix;  in
+
+composableDerivation {
+  f = args: let attr = lib.prepareDerivationArgs args; in stdenv.mkDerivation ( attr // {
+      C_INCLUDE_PATH = concatStringsSep ":" (map (p: "${p}/include") attr.buildInputs);
+      LIBRARY_PATH = concatStringsSep ":" (map (p: "${p}/lib") attr.buildInputs);
+    });
+  initial = {
+
+    postPhases = ["runCheck"];
+
+    mergeAttrBy = { pyCheck = x : y : "${x}\n${y}"; };
+
+    # should be last because it sources setup-hook of this package itself
+    runCheck = ''
+      PATH=$out/bin:$PATH; . $out/nix-support/setup-hook;
+      echo -e "import sys\n$pyCheck\nprint \"import pyCheck ok\"" | python
+    '';
+
+    inherit (args) name;
+
+    # everything can be overriden by composedArgsAndFun additional args 
+    # assuming that if a module can be loaded that it does also work..
+    flags = {
+      zlib = { buildInputs = [ zlib ]; pyCheck = "import zlib"; };
+      gdbm = { buildInputs = [ gdbm ]; pyCheck = "import gdbm"; };
+      sqlite = { buildInputs = [ sqlite ]; pyCheck = "import sqlite3"; };
+      db4 = { buildInputs = [ db4 ]; }; # TODO add pyCheck
+      readline = { buildInputs = [ readline ]; }; # doesn't work yet (?)
+      openssl = { buildInputs = [ openssl ]; pyCheck ="import socket\nsocket.ssl"; };
+    };
+
+    src = fetchurl {
+      url = http://www.python.org/ftp/python/2.5.2/Python-2.5.2.tar.bz2;
+      sha256 = "0gh8bvs56vdv8qmlfmiwyczjpldj0y3zbzd0zyhyjfd0c8m0xy7j";
+    };
+
+    configureFlags = ["--enable-shared" "--with-wctype-functions"];
+
+    buildInputs =
+      optional (stdenv ? gcc && stdenv.gcc.libc != null) stdenv.gcc.libc ++
+      [bzip2 ncurses];
+
+    patches = [
+      # Look in C_INCLUDE_PATH and LIBRARY_PATH for stuff.
+      ./search-path.patch
+
+
+      # make python know about libraries reading .pth files
+      # http://docs.python.org/library/site.html#module-site
+      # TODO: think about security (see the other code contained in site.py)
+      ./nix-find-sites-2.5.patch
+    ];
+
+    preConfigure = ''
+      # Purity.
+      for i in /usr /sw /opt /pkg; do 
+        substituteInPlace ./setup.py --replace $i /no-such-path
+      done
+      export NIX_LDFLAGS="$NIX_LDFLAGS -lncurses"
+    '';
+    
+    postInstall = "
+      rm -rf $out/lib/python2.5/test
+    ";
+
+  };
+}
diff --git a/pkgs/development/interpreters/python-new/2.5/search-path.patch b/pkgs/development/interpreters/python-new/2.5/search-path.patch
new file mode 100644
index 0000000..8fcddcb
--- /dev/null
+++ b/pkgs/development/interpreters/python-new/2.5/search-path.patch
@@ -0,0 +1,28 @@
+diff -rc Python-2.4.4-orig/setup.py Python-2.4.4/setup.py
+*** Python-2.4.4-orig/setup.py 2006-10-08 19:41:25.000000000 +0200
+--- Python-2.4.4/setup.py      2007-05-27 16:04:54.000000000 +0200
+***************
+*** 279,288 ****
+          # Check for AtheOS which has libraries in non-standard locations
+          if platform == 'atheos':
+              lib_dirs += ['/system/libs', '/atheos/autolnk/lib']
+-             lib_dirs += os.getenv('LIBRARY_PATH', '').split(os.pathsep)
+              inc_dirs += ['/system/include', '/atheos/autolnk/include']
+-             inc_dirs += os.getenv('C_INCLUDE_PATH', '').split(os.pathsep)
+  
+          # OSF/1 and Unixware have some stuff in /usr/ccs/lib (like -ldb)
+          if platform in ['osf1', 'unixware7', 'openunix8']:
+              lib_dirs += ['/usr/ccs/lib']
+--- 279,289 ----
+          # Check for AtheOS which has libraries in non-standard locations
+          if platform == 'atheos':
+              lib_dirs += ['/system/libs', '/atheos/autolnk/lib']
+              inc_dirs += ['/system/include', '/atheos/autolnk/include']
+  
++         lib_dirs += os.getenv('LIBRARY_PATH', '').split(os.pathsep)
++         inc_dirs += os.getenv('C_INCLUDE_PATH', '').split(os.pathsep)
++         
+          # OSF/1 and Unixware have some stuff in /usr/ccs/lib (like -ldb)
+          if platform in ['osf1', 'unixware7', 'openunix8']:
+              lib_dirs += ['/usr/ccs/lib']
+
diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix
index 59cb5a5..cebdadb 100644
--- a/pkgs/top-level/all-packages.nix
+++ b/pkgs/top-level/all-packages.nix
@@ -2078,6 +2078,16 @@ let
     openssl = if getConfig ["python" "opensslSupport"] true then openssl else null;
   };
 
+  # new python and lib proposal
+  # - adding a python lib to buildinputs should be enough 
+  #   (handles .pth files by patching site.py   
+  #    while introducing NIX_PYTHON_SITES describing list of modules)
+  # - adding pyCheck = "import foo" test scripts to ensure libraries can be imported
+  # - providing pythonWrapper so that you can run python and import the selected libraries
+  # feel free to comment on this (experimental)
+  python25New = recurseIntoAttrs ((import ../development/interpreters/python-new/2.5) pkgs);
+  pythonNew = python25New; # the default python
+
   pyrex = pyrex095;
 
   pyrex095 = import ../development/interpreters/pyrex/0.9.5.nix {
-- 
1.6.0.2.GIT




More information about the nix-dev mailing list