summary refs log tree commit diff
path: root/pkgs/applications/science
diff options
context:
space:
mode:
authorTimo Kaufmann <timokau@zoho.com>2018-04-24 23:53:36 +0200
committerTimo Kaufmann <timokau@zoho.com>2018-06-30 01:21:31 +0200
commit17e6b391eb6b524331bce29c01467dc055c8543b (patch)
tree7571e12466aa757abc5c27ca4486f8c39ee89d93 /pkgs/applications/science
parent84d89a1ec600de59447ed2a914ce167f51c21089 (diff)
downloadnixpkgs-17e6b391eb6b524331bce29c01467dc055c8543b.tar
nixpkgs-17e6b391eb6b524331bce29c01467dc055c8543b.tar.gz
nixpkgs-17e6b391eb6b524331bce29c01467dc055c8543b.tar.bz2
nixpkgs-17e6b391eb6b524331bce29c01467dc055c8543b.tar.lz
nixpkgs-17e6b391eb6b524331bce29c01467dc055c8543b.tar.xz
nixpkgs-17e6b391eb6b524331bce29c01467dc055c8543b.tar.zst
nixpkgs-17e6b391eb6b524331bce29c01467dc055c8543b.zip
sage: 8.1 -> 8.2, use system packages
Diffstat (limited to 'pkgs/applications/science')
-rw-r--r--pkgs/applications/science/math/sage/README.md117
-rw-r--r--pkgs/applications/science/math/sage/default.nix443
-rw-r--r--pkgs/applications/science/math/sage/env-locations.nix46
-rw-r--r--pkgs/applications/science/math/sage/env.patch22
-rwxr-xr-xpkgs/applications/science/math/sage/fetch-mirrors.sh11
-rw-r--r--pkgs/applications/science/math/sage/flask-oldsessions.nix36
-rw-r--r--pkgs/applications/science/math/sage/flask-openid.nix28
-rw-r--r--pkgs/applications/science/math/sage/openblas-pc.nix18
-rw-r--r--pkgs/applications/science/math/sage/patchSageShebangs.sh51
-rw-r--r--pkgs/applications/science/math/sage/patches/dochtml-optional.patch127
-rw-r--r--pkgs/applications/science/math/sage/patches/eclib-regulator-precision.patch98
-rw-r--r--pkgs/applications/science/math/sage/patches/matplotlib-normed-deprecated.patch12
-rw-r--r--pkgs/applications/science/math/sage/patches/maxima-5.41.0-doctests.patch48
-rw-r--r--pkgs/applications/science/math/sage/patches/numpy-1.14.3.patch812
-rw-r--r--pkgs/applications/science/math/sage/patches/pari-stackwarn.patch20
-rw-r--r--pkgs/applications/science/math/sage/patches/python-5755-hotpatch.patch28
-rw-r--r--pkgs/applications/science/math/sage/patches/python3-syntax-without-write.patch40
-rw-r--r--pkgs/applications/science/math/sage/patches/revert-269c1e1551285.patch14
-rw-r--r--pkgs/applications/science/math/sage/patches/sagenb-sphinx-1.7.patch31
-rw-r--r--pkgs/applications/science/math/sage/patches/sphinx-1.7.patch62
-rw-r--r--pkgs/applications/science/math/sage/patches/zn_poly_version.patch13
-rw-r--r--pkgs/applications/science/math/sage/pybrial.nix29
-rw-r--r--pkgs/applications/science/math/sage/python-openid.nix42
-rw-r--r--pkgs/applications/science/math/sage/sage-env.nix162
-rw-r--r--pkgs/applications/science/math/sage/sage-src.nix197
-rw-r--r--pkgs/applications/science/math/sage/sage-with-env.nix129
-rw-r--r--pkgs/applications/science/math/sage/sage-wrapper.nix41
-rw-r--r--pkgs/applications/science/math/sage/sage.nix32
-rw-r--r--pkgs/applications/science/math/sage/sagedoc.nix97
-rw-r--r--pkgs/applications/science/math/sage/sagelib.nix139
-rw-r--r--pkgs/applications/science/math/sage/sagenb.nix49
-rw-r--r--pkgs/applications/science/math/sage/shebangs.patch36
-rw-r--r--pkgs/applications/science/math/sage/spkg-giac.patch20
-rw-r--r--pkgs/applications/science/math/sage/spkg-git.patch18
-rw-r--r--pkgs/applications/science/math/sage/spkg-python.patch13
-rw-r--r--pkgs/applications/science/math/sage/spkg-singular.patch18
36 files changed, 2689 insertions, 410 deletions
diff --git a/pkgs/applications/science/math/sage/README.md b/pkgs/applications/science/math/sage/README.md
new file mode 100644
index 00000000000..46496664f28
--- /dev/null
+++ b/pkgs/applications/science/math/sage/README.md
@@ -0,0 +1,117 @@
+# Sage on nixos
+
+Sage is a pretty complex package that depends on many other complex packages and patches some of those. As a result, the sage nix package is also quite complex.
+
+Don't feel discouraged to fix, simplify or improve things though. Here's a quick overview over the functions of the individual files:
+
+- `sage-src.nix`  
+  Downloads the source code and applies patches. This makes sure that all the other files work with the same sage source. If you want to apply a patch to sage or update sage to a new version, this is the place to do it.
+
+- `env-locations.nix`  
+  Creates a bash file that sets a bunch of environment variables telling sage where to find various packages and files. The definitions of those environment variables can be found in the sage source in the `src/env.py` file. This bash file needs to be sourced before sage is started (done in `sage-env.nix` and `sagedoc.nix`).
+
+- `sage-env.nix`  
+  Sets all environment variables sage needs to run. This includes the package locations defined in `env-locations.nix` as well as the location of sage itself and its various subdirectories.
+
+- `sagelib.nix`  
+  Defines the main sage package (without setting the necessary environments or running any tests).
+
+- `sage-with-env.nix`  
+  Wraps sage in the necessary environment.
+
+- `sage.nix`  
+  Runs sages doctests.
+
+- `sage-wrapper.nix`  
+  Optionally tells sage where do find the docs.
+
+- `sagedoc.nix`  
+  Builds and tests the sage html documentation. Can be used for offline documentation viewing as well as the sage `browse_sage_doc` and `search_doc` functions.
+
+- `sagenb.nix`  
+  The (semi deprecated) sage notebook.
+
+- `default.nix`  
+  Introduces necessary overrides, defines new packages and ties everything together (returning the `sage` package).
+
+- `flask-oldsessions.nix`, `flask-openid.nix`, `python-openid.nix`
+  These are python packages that were rejected from the main nixpkgs tree because they appear unmaintained. They are needed for the (semi-deprecated) sage notebook. Since that notebook is still needed to run the sage doctests, these packages are included but not exposed to the rest of nixpkgs.
+
+- `pybrial.nix`  
+  pybrial is a dependency of sage. However, pybrial itself also has sage as a dependency. Because of that circular dependency, pybrial is hidden from the rest of nixpkgs (just as the flask packages and python-openid.
+
+- `openblas-pc.nix`  
+  This creates a `.pc` file to be read by `pkg-config` that allows openblas to take on different roles, like `cblas` or `lapack`.
+
+## The sage build is broken
+
+First you should find out which change to nixpkgs is at fault (if you don't already know). You can use `git-bisect` for that (see the manpage).
+
+If the build broke as a result of a package update, try those solutions in order:
+
+- search the [sage trac](https://trac.sagemath.org/) for keywords like "Upgrade <package>". Maybe somebody has already proposed a patch that fixes the issue. You can then add a `fetchpatch` to `sage-src.nix`.
+
+- check if [gentoo](https://github.com/cschwan/sage-on-gentoo/tree/master/sci-mathematics/sage), [debian](https://salsa.debian.org/science-team/sagemath/tree/master/debian) or [arch linux](https://git.archlinux.org/svntogit/community.git/tree/trunk?h=packages/sagemath) already solved the problem. You can then again add a `fetchpatch` to `sage-src.nix`. If applicable you should also [propose the patch upstream](#proposing-a-sage-patch).
+
+- fix the problem yourself. First clone the sagemath source and then check out the sage version you want to patch:
+
+```
+[user@localhost ~]$ git clone git://github.com/sagemath/sage.git
+[user@localhost ~]$ cd sage
+[user@localhost sage]$ git checkout 8.2 # substitute the relevant version here
+```
+
+Then make the needed changes and generate a patch with `git diff`:
+
+```
+[user@localhost ~]$ <make changes>
+[user@localhost ~]$ git diff -u > /path/to/nixpkgs/pkgs/applications/science/math/sage/patches/name-of-patch.patch
+```
+
+Now just add the patch to `sage-src.nix` and test your changes. If they fix the problem, [propose them upstream](#proposing-a-sage-patch) and add a link to the trac ticket.
+
+- pin the package version in `default.nix` and add a note that explains why that is necessary.
+
+
+## Proposing a sage patch
+
+You can [login the sage trac using GitHub](https://trac.sagemath.org/login). Your username will then be `gh-<your-github-name>`. The only other way is to request a trac account via email. After that refer to [git the hard way](http://doc.sagemath.org/html/en/developer/manual_git.html#chapter-manual-git) in the sage documentation. The "easy way" requires a non-GitHub account (requested via email) and a special tool. The "hard way" is really not all that hard if you're a bit familiar with git.
+
+Here's the gist, assuming you want to use ssh key authentication. First, [add your public ssh key](https://trac.sagemath.org/prefs/sshkeys). Then:
+
+```
+[user@localhost ~]$ git clone git://github.com/sagemath/sage.git
+[user@localhost ~]$ cd sage
+[user@localhost sage]$ git remote add trac git@trac.sagemath.org:sage.git -t master
+[user@localhost sage]$ git checkout -b u/gh-<your-github-username>/<your-branch-name> develop
+[user@localhost sage]$ <make changes>
+[user@localhost sage]$ git add .
+[user@localhost sage]$ git commit
+[user@localhost sage]$ git show # review your changes
+[user@localhost sage]$ git push --set-upstream trac u/gh-<your-github-username>/<your-branch-name>
+```
+
+You now created a branch on the trac server (you *must* follow the naming scheme as you only have push access to branches with the `u/gh-<your-github-username>/` prefix).
+Now you can [create a new trac ticket](https://trac.sagemath.org/newticket).
+- Write a description of the change
+- set the type and component as appropriate
+- write your real name in the "Authors" field
+- write `u/gh-<your-github-username>/<your-branch-name>` in the "Branch" field
+- click "Create ticket"
+- click "Modify" on the top right of your ticket (for some reason you can only change the ticket status after you have created it)
+- set the ticket status from `new` to `needs_review`
+- click "Save changes"
+
+Refer to sages [Developer's Guide](http://doc.sagemath.org/html/en/developer/index.html) for further details.
+
+## I want to update sage
+
+You'll need to change the `version` field in `sage-src.nix`. Afterwards just try to build and let nix tell you which patches no longer apply (hopefully because they were adopted upstream). Remove those.
+
+Hopefully the build will succeed now. If it doesn't and the problem is obvious, fix it as described in [The sage build is broken](#the-sage-build-is-broken).
+If the problem is not obvious, you can try to first update sage to an intermediate version (remember that you can also set the `version` field to any git revision of sage) and locate the sage commit that introduced the issue. You can even use `git-bisect` for that (it will only be a bit tricky to keep track of which patches to apply). Hopefully after that the issue will be obvious.
+
+## Well, that didn't help!
+
+If you couldn't fix the problem, create a GitHub issue on the nixpkgs repo and ping @timokau (or whoever is listed in the `maintainers` list of the sage package).
+Describe what you did and why it didn't work. Afterwards it would be great if you help the next guy out and improve this documentation!
diff --git a/pkgs/applications/science/math/sage/default.nix b/pkgs/applications/science/math/sage/default.nix
index 7f101bac147..4e84a18f4f2 100644
--- a/pkgs/applications/science/math/sage/default.nix
+++ b/pkgs/applications/science/math/sage/default.nix
@@ -1,230 +1,231 @@
-# TODO
-# - consider writing a script to convert spkgs to nix packages, similar to vim
-#   or cabal2nix. This would allow a more efficient and "cleaner" build, greater
-#   flexibility and the possibility to select which dependencies to add and which
-#   to remove. It would also allow to use system packages for some dependencies
-#   and recompile others (optimized for the system) without recompiling everything.
-# - add optdeps:
-#   - imagemagick
-#   - texlive full for documentation
-#   - ...
-# - further seperate build outputs. Also maybe run `make doc`.
-#   Configure flags like --bindir and --libdir oculd also be used for that, see
-#   ./configure --help`.
-
-# Other resources:
-# - https://wiki.debian.org/DebianScience/Sage
-# - https://github.com/cschwan/sage-on-gentoo
-# - https://git.archlinux.org/svntogit/community.git/tree/trunk?h=packages/sagemath
-
-{ stdenv
-, bash
-, fetchurl
-, perl
-, gfortran6
-, python
-, autoreconfHook
-, gettext
-, which
-, texlive
-, texinfo
-, hevea
-, buildDocs ? false
-, optimize ? false # optimize sage to the current system (obviously impure)
+{ nixpkgs
+, withDoc ? false
 }:
 
-stdenv.mkDerivation rec {
-  version = "8.1";
-  name = "sage-${version}";
-
-  # Modified version of patchShebangs that patches to the sage-internal version if possible
-  # and falls back to the system version if not.
-  patchSageShebangs = ./patchSageShebangs.sh;
-  src = fetchurl {
-    # Note that the source is *not* fetched from github, since that doesn't
-    # the upstream folder with all the source tarballs of the spkgs.
-    # If those are not present they are fetched at build time, which breaks
-    # when building in a sandbox (and probably only works if you install the
-    # latest sage version).
-    urls = [
-      "http://mirrors.mit.edu/sage/src/sage-${version}.tar.gz"
-      "ftp://ftp.fu-berlin.de/unix/misc/sage/src/sage-${version}.tar.gz"
-      "http://sagemath.polytechnic.edu.na/src/sage-${version}.tar.gz"
-      "ftp://ftp.sun.ac.za/pub/mirrors/www.sagemath.org/src/sage-${version}.tar.gz"
-      "http://sagemath.mirror.ac.za/src/sage-${version}.tar.gz"
-      "https://ftp.leg.uct.ac.za/pub/packages/sage/src/sage-${version}.tar.gz"
-      "http://mirror.ufs.ac.za/sagemath/src/sage-${version}.tar.gz"
-      "https://mirrors-usa.go-parts.com/sage/sagemath/src/sage-${version}.tar.gz"
-      "http://www.cecm.sfu.ca/sage/src/sage-${version}.tar.gz"
-      "http://files.sagemath.org/src/sage-${version}.tar.gz"
-      "https://mirrors.xmission.com/sage/src/sage-${version}.tar.gz"
-      "http://sagemath.c3sl.ufpr.br/src/sage-${version}.tar.gz"
-      "http://linorg.usp.br/sage/src/sage-${version}.tar.gz"
-      "http://mirror.hust.edu.cn/sagemath/src/sage-${version}.tar.gz"
-      "https://ftp.iitm.ac.in/sage/src/sage-${version}.tar.gz"
-      "http://ftp.kaist.ac.kr/sage/src/sage-${version}.tar.gz"
-      "https://ftp.riken.jp/sagemath/src/sage-${version}.tar.gz"
-      "https://mirrors.tuna.tsinghua.edu.cn/sagemath/src/sage-${version}.tar.gz"
-      "https://mirrors.ustc.edu.cn/sagemath/src/sage-${version}.tar.gz"
-      "http://ftp.tsukuba.wide.ad.jp/software/sage/src/sage-${version}.tar.gz"
-      "https://ftp.yz.yamagata-u.ac.jp/pub/math/sage/src/sage-${version}.tar.gz"
-      "https://mirror.yandex.ru/mirrors/sage.math.washington.edu/src/sage-${version}.tar.gz"
-      "https://mirror.aarnet.edu.au/pub/sage/src/sage-${version}.tar.gz"
-      "https://sage.mirror.garr.it/mirrors/sage/src/sage-${version}.tar.gz"
-      "https://www.mirrorservice.org/sites/www.sagemath.org/src/sage-${version}.tar.gz"
-      "http://mirror.switch.ch/mirror/sagemath/src/sage-${version}.tar.gz"
-      "https://mirrors.up.pt/pub/sage/src/sage-${version}.tar.gz"
-      "http://www-ftp.lip6.fr/pub/math/sagemath/src/sage-${version}.tar.gz"
-      "http://ftp.ntua.gr/pub/sagemath/src/sage-${version}.tar.gz"
-    ];
-    sha256 = "1cpcs1mr0yii64s152xmxyd450bfzjb22jjj0zh9y3n6g9alzpyq";
+let
+  inherit (nixpkgs) fetchpatch fetchurl symlinkJoin fetchFromGitHub callPackage nodePackages_8_x;
+
+  # https://trac.sagemath.org/ticket/15980 for tracking of python3 support
+  python = nixpkgs.python2.override {
+    packageOverrides = self: super: {
+      cypari2 = super.cypari2.override { inherit pari; };
+
+      cysignals = super.cysignals.override { inherit pari; };
+
+      cvxopt = super.cvxopt.override { inherit glpk; };
+
+      # https://github.com/sagemath/sagenb/issues/437
+      flask-babel = super.flask-babel.overridePythonAttrs (attrs: rec {
+        version = "0.9";
+        src = attrs.src.override {
+          inherit version;
+          sha256 = "0k7vk4k54y55ma0nx2k5s0phfqbriwslhy5shh3b0d046q7ibzaa";
+        };
+        doCheck = false;
+      });
+
+      # python packages that appear unmaintained and were not accepted into the nixpkgs
+      # tree because of that. These packages are only dependencies of the more-or-less
+      # deprecated sagenb. However sagenb is still a default dependency and the doctests
+      # depend on it.
+      # See https://github.com/NixOS/nixpkgs/pull/38787 for a discussion.
+      flask-oldsessions = self.callPackage ./flask-oldsessions.nix {};
+      flask-openid = self.callPackage ./flask-openid.nix {};
+      python-openid = self.callPackage ./python-openid.nix {};
+
+      pybrial = self.callPackage ./pybrial.nix {};
+
+      sagelib = self.callPackage ./sagelib.nix {
+        inherit flint ecl pari glpk eclib;
+        inherit sage-src openblas-blas-pc openblas-cblas-pc openblas-lapack-pc pynac singular;
+        linbox = nixpkgs.linbox.override { withSage = true; };
+        # tracking: https://trac.sagemath.org/ticket/24927
+        arb = nixpkgs.arb.overrideAttrs (attrs: rec {
+          name = "arb-${version}";
+          version = "2.12.0";
+          doCheck = false; # https://github.com/fredrik-johansson/arb/issues/194
+          src = fetchFromGitHub {
+            owner = "fredrik-johansson";
+            repo = attrs.pname;
+            rev = version;
+            sha256 = "18bwxlcbqb70cj7l9x6w1h4yghrqfhmbhdby373q8vdrdfx58niq";
+          };
+        });
+      };
+
+      sagenb = self.callPackage ./sagenb.nix {
+        mathjax = nodePackages_8_x.mathjax;
+      };
+
+      sagedoc = self.callPackage ./sagedoc.nix {
+        inherit sage-src;
+      };
+
+      env-locations = self.callPackage ./env-locations.nix {
+        inherit pari_data ecl pari;
+        inherit singular;
+        three = nodePackages_8_x.three;
+        mathjax = nodePackages_8_x.mathjax;
+      };
+
+      sage-env = self.callPackage ./sage-env.nix {
+        inherit sage-src python rWrapper openblas-cblas-pc glpk ecl singular eclib pari palp flint pynac pythonEnv;
+        pkg-config = nixpkgs.pkgconfig; # not to confuse with pythonPackages.pkgconfig
+      };
+
+      sage-with-env = self.callPackage ./sage-with-env.nix {
+        inherit pari eclib pythonEnv;
+        inherit sage-src openblas-blas-pc openblas-cblas-pc openblas-lapack-pc pynac singular;
+        pkg-config = nixpkgs.pkgconfig; # not to confuse with pythonPackages.pkgconfig
+        three = nodePackages_8_x.three;
+      };
+
+      sage = self.callPackage ./sage.nix { };
+
+      sage-wrapper = self.callPackage ./sage-wrapper.nix {
+        inherit sage-src withDoc;
+      };
+    };
   };
 
-  postPatch = ''
-    substituteAllInPlace src/bin/sage-env
-    bash=${bash} substituteAllInPlace build/bin/sage-spkg
-  '';
-
-  installPhase = ''
-    # Sage installs during first `make`, `make install` is no-op and just takes time.
-  '';
-
-  outputs = [ "out" ] ++ stdenv.lib.optionals (buildDocs) [ "doc" ];
-
-  buildInputs = [
-    bash # needed for the build
-    perl # needed for the build
-    python # needed for the build
-    gfortran6 # needed to build giac, openblas
-    autoreconfHook # needed to configure sage with prefix
-    gettext # needed to build the singular spkg
-    which # needed in configure of mpir
-    texinfo # needed to build maxima
-  ] ++ stdenv.lib.optionals(buildDocs) [
-    hevea # needed to build the docs of the giac spkg
-    (texlive.combine { inherit (texlive)
-      scheme-basic
-      collection-pstricks # needed by giac
-      times # font needed by giac
-      stmaryrd # needed by giac
-      babel-greek # optional for giac, otherwise throws a bunch of latex command not founds
-      ;
-    })
-  ];
-
-  nativeBuildInputs = [ gfortran6 perl which ];
-
-  patches = [
-    # fix usages of /bin/rm
-    ./spkg-singular.patch
-    # help python find the crypt library
-    # patches python3 and indirectly python2, since those installation files are symlinked
-    ./spkg-python.patch
-    # fix usages of /usr/bin/perl
-    ./spkg-git.patch
-    # fix usages of /bin/cp and add necessary argument to function call
-    ./spkg-giac.patch
-    # environment
-    ./env.patch
-    # adjust wrapper shebang and patch shebangs after each spkg build
-    ./shebangs.patch
+  openblas-blas-pc = callPackage ./openblas-pc.nix { name = "blas"; };
+  openblas-cblas-pc = callPackage ./openblas-pc.nix { name = "cblas"; };
+  openblas-lapack-pc = callPackage ./openblas-pc.nix { name = "lapack"; };
+
+  sage-src = callPackage ./sage-src.nix {};
+
+  pythonRuntimeDeps = with python.pkgs; [
+    sagelib
+    pybrial
+    sagenb
+    cvxopt
+    networkx
+    service-identity
+    psutil
+    sympy
+    fpylll
+    matplotlib
+    scipy
+    ipywidgets
+    rpy2
+    sphinx
+    typing
+    pillow
   ];
 
-  enableParallelBuilding = true;
+  pythonEnv = python.buildEnv.override {
+    extraLibs = pythonRuntimeDeps;
+    ignoreCollisions = true;
+  } // { extraLibs = pythonRuntimeDeps; }; # make the libs accessible
+
+  # needs to be rWrapper, standard "R" doesn't include default packages
+  rWrapper = nixpkgs.rWrapper.override {
+    # https://trac.sagemath.org/ticket/25674
+    R = nixpkgs.R.overrideAttrs (attrs: rec {
+      name = "R-3.4.4";
+      src = fetchurl {
+        url = "http://cran.r-project.org/src/base/R-3/${name}.tar.gz";
+        sha256 = "0dq3jsnwsb5j3fhl0wi3p5ycv8avf8s5j1y4ap3d2mkjmcppvsdk";
+      };
+    });
+  };
 
-  hardeningDisable = [
-    "format" # needed to build palp, for lines like `printf(ctime(&_NFL->TIME))`
-    # TODO could be patched with `sed s|printf(ctime(\(.*\)))|%s... or fixed upstream
-  ];
+  # update causes issues
+  # https://groups.google.com/forum/#!topic/sage-packaging/cS3v05Q0zso
+  # https://trac.sagemath.org/ticket/24735
+  singular = nixpkgs.singular.overrideAttrs (oldAttrs: {
+    name = "singular-4.1.0p3";
+    src = fetchurl {
+      url = "http://www.mathematik.uni-kl.de/ftp/pub/Math/Singular/SOURCES/4-1-0/singular-4.1.0p3.tar.gz";
+      sha256 = "105zs3zk46b1cps403ap9423rl48824ap5gyrdgmg8fma34680a4";
+    };
+  });
+
+  # *not* to confuse with the python package "pynac"
+  # https://trac.sagemath.org/ticket/24838 (depends on arb update)
+  pynac = (nixpkgs.pynac.override { inherit singular; }).overrideAttrs (oldAttrs: rec {
+    name = "pynac-0.7.16";
+    src = fetchFromGitHub {
+      owner = "pynac";
+      repo = "pynac";
+      rev = name;
+      sha256 = "106an189sg4rpgzfrmy3699271vg4ddazw9wvh51wx7qnm1v86ik";
+    };
+  });
+
+  eclib = nixpkgs.eclib.override { inherit pari; };
+
+  # With openblas (64 bit), the tests fail the same way as when sage is build with
+  # openblas instead of openblasCompat. Apparently other packages somehow use flints
+  # blas when it is available. Alternative would be to override flint to use
+  # openblasCompat.
+  flint = nixpkgs.flint.override { withBlas = false; };
+
+  # Multiple palp dimensions need to be available and sage expects them all to be
+  # in the same folder.
+  palp = symlinkJoin {
+    name = "palp-${nixpkgs.palp.version}";
+    paths = [
+      (nixpkgs.palp.override { dimensions = 4; doSymlink = false; })
+      (nixpkgs.palp.override { dimensions = 5; doSymlink = false; })
+      (nixpkgs.palp.override { dimensions = 6; doSymlink = true; })
+      (nixpkgs.palp.override { dimensions = 11; doSymlink = false; })
+    ];
+  };
 
-  configureFlags = stdenv.lib.optionals(buildDocs) [ "--docdir=$(doc)" ];
-  preConfigure = ''
-    export SAGE_NUM_THREADS="$NIX_BUILD_CORES"
-
-    export HOME=/tmp/sage-home
-    export SAGE_ROOT="$PWD"
-    export SAGE_SRC="$PWD"
-
-    mkdir -p "$HOME"
-    mkdir -p "$out"
-
-    # we need to keep the source around
-    dir="$PWD"
-    cd ..
-    mv "$dir" "$out/sage-root"
-
-    export SAGE_SPKG_INSTALL_DOCS='no'
-    cd "$out/sage-root" # build in target dir, since `make` is also `make install`
-  ''
-  + stdenv.lib.optionalString (buildDocs) ''
-    mkdir -p "$doc"
-    export SAGE_DOC="$doc"
-    export SAGE_DOCBUILD_OPTS="--no-pdf-links -k"
-  ''
-  + stdenv.lib.optionalString (!optimize) ''
-    export SAGE_FAT_BINARY=yes
-  '';
-
-  buildFlags = if (buildDocs) then "doc" else "build";
-
-  # for reference: http://doc.sagemath.org/html/en/installation/source.html
-  preBuild = ''
-    # symlink python to make sure the shebangs are patched to the sage path
-    # while still being able to use python before building it
-    # (this is important because otherwise sage will try to install python
-    # packages globally later on)
-    ln -s "${python}/bin/python2" $out/bin/python2
-    ln -s "$out/bin/python2" $out/bin/python
-    touch $out/bin/python3
-    bash $patchSageShebangs .
-  '';
-
-  postBuild = ''
-    # Clean up
-    rm -r "$out/sage-root/upstream" # don't keep the sources of all the spkgs
-    rm -rf "$out/sage-root/src/build"
-    rm -rf "$out/sage-root/src/autom4te.cache"
-    rm -rf "$out/sage-root/src/config"
-    rm -rf "$out/sage-root/src/m4"
-    rm -rf "$out/sage-root/.git"
-    rm -r "$out/sage-root/logs"
-    rm -r "$out"/lib/python*/test
-    # Fix dependency cycle between out and doc
-    rm -f "$out/sage-root/config.log"
-    rm -f "$out/sage-root/config.status"
-    rm -f "$out/sage-root/build/make/Makefile-auto"
-    rm -f "$out/sage-home/.sage/gap/libgap-workspace-"*
-    # Make sure unnessessary packages don't end up in the build closure
-    find "$out" \
-        -iname 'config.log' \
-        -delete \
-        -or -iname 'Makefile' \
-        -delete
-    rm -f "$out/lib/R/etc/Renviron"
-    # Make sure all shebangs are properly patched
-    bash $patchSageShebangs $out
-  '';
-
-  # TODO there are some doctest failures, which seem harmless.
-  # We should figure out a way to fix the failures or ignore only those tests.
-  doCheck = false;
-
-  checkTarget = "ptestalllong"; # all long tests in parallell
-  preCheck = ''
-    export SAGE_TIMEOUT=0 # no timeout
-    export SAGE_TIMEOUT_LONG=0 # no timeout
-  '';
-
-  meta = {
-    homepage = http://www.sagemath.org;
-    description = "A free open source mathematics software system";
-    # taken from the homepage
-    longDescription = ''
-      SageMath is a free open-source mathematics software system licensed under the GPL. It builds on top of many existing open-source packages: NumPy, SciPy, matplotlib, Sympy, Maxima, GAP, FLINT, R and many more. Access their combined power through a common, Python-based language or directly via interfaces or wrappers.
-      Mission: Creating a viable free open source alternative to Magma, Maple, Mathematica and Matlab.
-    '';
-    license = stdenv.lib.licenses.gpl2Plus;
-    platforms = ["x86_64-linux" "i686-linux"];
-    maintainers = with stdenv.lib.maintainers; [ timokau ];
+  # Sage expects those in the same directory.
+  pari_data = symlinkJoin {
+    name = "pari_data";
+    paths = with nixpkgs; [
+      pari-galdata
+      pari-seadata-small
+    ];
   };
-}
+
+  # https://trac.sagemath.org/ticket/22191
+  ecl = nixpkgs.ecl_16_1_2;
+
+  # sage currently uses an unreleased version of pari
+  pari = (nixpkgs.pari.override { withThread = false; }).overrideAttrs (attrs: rec {
+    version = "2.10-1280-g88fb5b3"; # on update remove pari-stackwarn patch from `sage-src.nix`
+    src = fetchurl {
+      url = "mirror://sageupstream/pari/pari-${version}.tar.gz";
+      sha256 = "19gbsm8jqq3hraanbmsvzkbh88iwlqbckzbnga3y76r7k42akn7m";
+    };
+  });
+
+  # https://trac.sagemath.org/ticket/24824
+  glpk = nixpkgs.glpk.overrideAttrs (attrs: rec {
+    version = "4.63";
+    name = "glpk-${version}";
+    src = fetchurl {
+      url = "mirror://gnu/glpk/${name}.tar.gz";
+      sha256 = "1xp7nclmp8inp20968bvvfcwmz3mz03sbm0v3yjz8aqwlpqjfkci";
+    };
+    patches = (attrs.patches or []) ++ [
+      # Alternatively patch sage with debians
+      # https://sources.debian.org/data/main/s/sagemath/8.1-7/debian/patches/t-version-glpk-4.60-extra-hack-fixes.patch
+      # The header of that debian patch contains a good description of the issue. The gist of it:
+      # > If GLPK in Sage causes one error, and this is caught by Sage and recovered from, then
+      # > later (because upstream GLPK does not clear the "error" flag) Sage will append
+      # > all subsequent terminal output of GLPK into the error_message string but not
+      # > actually forward it to the user's terminal. This breaks some doctests.
+      (fetchpatch {
+        name = "error_recovery.patch";
+        url = "https://git.sagemath.org/sage.git/plain/build/pkgs/glpk/patches/error_recovery.patch?id=07d6c37d18811e2b377a9689790a7c5e24da16ba";
+        sha256 = "0z99z9gd31apb6x5n5n26411qzx0ma3s6dnznc4x61x86bhq31qf";
+      })
+
+      # Allow setting a exact verbosity level (OFF|ERR|ON|ALL|DBG)
+      (fetchpatch {
+        name = "exact_verbosity.patch";
+        url = "https://git.sagemath.org/sage.git/plain/build/pkgs/glpk/patches/glp_exact_verbosity.patch?id=07d6c37d18811e2b377a9689790a7c5e24da16ba";
+        sha256 = "15gm5i2alqla3m463i1qq6jx6c0ns6lip7njvbhp37pgxg4s9hx8";
+      })
+    ];
+  });
+in
+  python.pkgs.sage-wrapper // {
+    doc = python.pkgs.sagedoc;
+    lib = python.pkgs.sagelib;
+  }
diff --git a/pkgs/applications/science/math/sage/env-locations.nix b/pkgs/applications/science/math/sage/env-locations.nix
new file mode 100644
index 00000000000..2ed079ab32b
--- /dev/null
+++ b/pkgs/applications/science/math/sage/env-locations.nix
@@ -0,0 +1,46 @@
+{ stdenv
+, writeTextFile
+, pari_data
+, pari
+, singular
+, maxima-ecl
+, conway_polynomials
+, graphs
+, elliptic_curves
+, polytopes_db
+, gap-libgap-compatible
+, ecl
+, combinatorial_designs
+, jmol
+, mathjax
+, three
+, cysignals
+}:
+
+writeTextFile rec {
+  name = "sage-env-locations";
+  destination = "/${name}";
+  text = ''
+    export GP_DATA_DIR="${pari_data}/share/pari"
+    export PARI_DATA_DIR="${pari_data}"
+    export GPHELP="${pari}/bin/gphelp"
+    export GPDOCDIR="${pari}/share/pari/doc"
+    export SINGULARPATH='${singular}/share/singular'
+    export SINGULAR_SO='${singular}/lib/libSingular.so'
+    export SINGULAR_EXECUTABLE='${singular}/bin/Singular'
+    export MAXIMA_FAS='${maxima-ecl}/lib/maxima/${maxima-ecl.version}/binary-ecl/maxima.fas'
+    export MAXIMA_PREFIX="${maxima-ecl}"
+    export CONWAY_POLYNOMIALS_DATA_DIR='${conway_polynomials}/share/conway_polynomials'
+    export GRAPHS_DATA_DIR='${graphs}/share/graphs'
+    export ELLCURVE_DATA_DIR='${elliptic_curves}/share/ellcurves'
+    export POLYTOPE_DATA_DIR='${polytopes_db}/share/reflexive_polytopes'
+    export GAP_ROOT_DIR='${gap-libgap-compatible}/share/gap/build-dir'
+    export ECLDIR='${ecl}/lib/ecl-${ecl.version}/'
+    export COMBINATORIAL_DESIGN_DATA_DIR="${combinatorial_designs}/share/combinatorial_designs"
+    export CREMONA_MINI_DATA_DIR="${elliptic_curves}/share/cremona"
+    export JMOL_DIR="${jmol}"
+    export MATHJAX_DIR="${mathjax}/lib/node_modules/mathjax"
+    export THREEJS_DIR="${three}/lib/node_modules/three"
+    export SAGE_INCLUDE_DIRECTORIES="${cysignals}/lib/python2.7/site-packages"
+  '';
+}
diff --git a/pkgs/applications/science/math/sage/env.patch b/pkgs/applications/science/math/sage/env.patch
deleted file mode 100644
index a7f8538eac3..00000000000
--- a/pkgs/applications/science/math/sage/env.patch
+++ /dev/null
@@ -1,22 +0,0 @@
-diff --git a/src/bin/sage-env b/src/bin/sage-env
-index ead308f861..ed8db9f9b7 100644
---- a/src/bin/sage-env
-+++ b/src/bin/sage-env
-@@ -111,6 +111,8 @@ resolvelinks() {
- }
- 
- 
-+SAGE_ROOT="@out@/sage-root"
-+
- # New value for SAGE_ROOT: either SAGE_ROOT (if given)
- # or a guessed value based on pwd.
- if [ -n "$SAGE_ROOT" ]; then
-@@ -185,6 +187,8 @@ fi
- export SAGE_ENV_SOURCED=$SAGE_ENV_VERSION
- 
- export SAGE_ROOT="$NEW_SAGE_ROOT"
-+export SAGE_LOCAL='@out@/'
-+export PYTHONPATH="@out@/lib/python2.7/site-packages:$PYTHONPATH"
- 
- 
- # sage-env must know where the Sage's script files are.
diff --git a/pkgs/applications/science/math/sage/fetch-mirrors.sh b/pkgs/applications/science/math/sage/fetch-mirrors.sh
deleted file mode 100755
index a1103e86beb..00000000000
--- a/pkgs/applications/science/math/sage/fetch-mirrors.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-#! /usr/bin/env nix-shell
-#! nix-shell -i bash -p curl go-pup
-
-# Fetches a list of all available source mirrors from the sage homepage.
-# Note that the list is sorted by country, but fetchurl doesn't offer an option
-# to customize mirror preference.
-
-curl -s http://www.sagemath.org/download-source.html \
-    | pup 'table#mirror'  \
-    | pup 'a attr{href}' \
-    | sed -e 's/index\.html/sage-${version}.tar.gz/'
diff --git a/pkgs/applications/science/math/sage/flask-oldsessions.nix b/pkgs/applications/science/math/sage/flask-oldsessions.nix
new file mode 100644
index 00000000000..85e35736d03
--- /dev/null
+++ b/pkgs/applications/science/math/sage/flask-oldsessions.nix
@@ -0,0 +1,36 @@
+{ stdenv
+, buildPythonPackage
+, fetchFromGitHub
+, python
+, flask
+}:
+
+buildPythonPackage rec {
+  pname = "Flask-OldSessions";
+  version = "0.10";
+
+  # no artifact on pypi: https://github.com/mitsuhiko/flask-oldsessions/issues/1
+  src = fetchFromGitHub {
+    owner = "mitsuhiko";
+    repo = "flask-oldsessions";
+    rev = "${version}";
+    sha256 = "04b5m8njjiwld9a0zw55iqwvyjgwcpdbhz1cic8nyhgcmypbicqn";
+  };
+
+  propagatedBuildInputs = [
+    flask
+  ];
+
+  # missing module flask.testsuite, probably assumes an old version of flask
+  doCheck = false;
+  checkPhase = ''
+    ${python.interpreter} run-tests.py
+  '';
+
+  meta = with stdenv.lib; {
+    description = "Provides a session class that works like the one in Flask before 0.10.";
+    license = licenses.bsd2;
+    maintainers = with maintainers; [ timokau ];
+    homepage = https://github.com/mitsuhiko/flask-oldsessions;
+  };
+}
diff --git a/pkgs/applications/science/math/sage/flask-openid.nix b/pkgs/applications/science/math/sage/flask-openid.nix
new file mode 100644
index 00000000000..9043fabd9b4
--- /dev/null
+++ b/pkgs/applications/science/math/sage/flask-openid.nix
@@ -0,0 +1,28 @@
+{ stdenv
+, buildPythonPackage
+, fetchPypi
+, flask
+, python-openid
+}:
+
+buildPythonPackage rec {
+  pname = "Flask-OpenID";
+  version = "1.2.5";
+
+  src = fetchPypi {
+    inherit pname version;
+    sha256 = "1aycwmwi7ilcaa5ab8hm0bp6323zl8z25q9ha0gwrl8aihfgx3ss";
+  };
+
+  propagatedBuildInputs = [
+    flask
+    python-openid
+  ];
+
+  meta = with stdenv.lib; {
+    description = "Adds openid support to flask applications";
+    license = licenses.bsd2;
+    maintainers = with maintainers; [ timokau ];
+    homepage = https://pythonhosted.org/Flask-OpenID/;
+  };
+}
diff --git a/pkgs/applications/science/math/sage/openblas-pc.nix b/pkgs/applications/science/math/sage/openblas-pc.nix
new file mode 100644
index 00000000000..ba46850bbc6
--- /dev/null
+++ b/pkgs/applications/science/math/sage/openblas-pc.nix
@@ -0,0 +1,18 @@
+{ stdenv
+, openblasCompat
+, writeTextFile
+, name
+}:
+
+writeTextFile {
+  name = "openblas-${name}-pc-${openblasCompat.version}";
+  destination = "/lib/pkgconfig/${name}.pc";
+  text = ''
+    Name: ${name}
+    Version: ${openblasCompat.version}
+
+    Description: ${name} for SageMath, provided by the OpenBLAS package.
+    Cflags: -I${openblasCompat}/include
+    Libs: -L${openblasCompat}/lib -lopenblas
+  '';
+}
diff --git a/pkgs/applications/science/math/sage/patchSageShebangs.sh b/pkgs/applications/science/math/sage/patchSageShebangs.sh
deleted file mode 100644
index 6ddf93af011..00000000000
--- a/pkgs/applications/science/math/sage/patchSageShebangs.sh
+++ /dev/null
@@ -1,51 +0,0 @@
-# This is a slightly modified version of nix's default patchShebangs
-
-dir="$1"
-
-echo "patching sage internal script interpreter paths in $( readlink -f "$dir")"
-
-find "$dir" -type f -perm -0100 | while read f; do
-    if [ "$(head -1 "$f" | head -c+2)" != '#!' ]; then
-        # missing shebang => not a script
-        continue
-    fi
-
-    oldInterpreterLine=$(head -1 "$f" | tail -c+3)
-    read -r oldPath arg0 args <<< "$oldInterpreterLine"
-
-    if $(echo "$oldPath" | grep -q "/bin/env$"); then
-        # Check for unsupported 'env' functionality:
-        # - options: something starting with a '-'
-        # - environment variables: foo=bar
-        if $(echo "$arg0" | grep -q -- "^-.*\|.*=.*"); then
-            echo "unsupported interpreter directive \"$oldInterpreterLine\" (set dontPatchShebangs=1 and handle shebang patching yourself)"
-            exit 1
-        fi
-        executable="$arg0"
-    else
-        if [ "$oldPath" = "" ]; then
-            # If no interpreter is specified linux will use /bin/sh. Set
-            # oldpath="/bin/sh" so that we get /nix/store/.../sh.
-            oldPath="/bin/sh"
-        fi
-        executable="$(basename "$oldPath")"
-        args="$arg0 $args"
-    fi
-
-    newPath="$(echo "$out/bin/$executable $args" | sed 's/[[:space:]]*$//')"
-    if [[ ! -x "$newPath" ]] ; then
-        newPath="$(command -v "$executable" || true)"
-    fi
-
-    # Strip trailing whitespace introduced when no arguments are present
-    newInterpreterLine="$(echo "$newPath $args" | sed 's/[[:space:]]*$//')"
-
-    if [ -n "$oldPath" -a "${oldPath:0:${#NIX_STORE}}" != "$NIX_STORE" ]; then
-        if [ -n "$newPath" -a "$newPath" != "$oldPath" ]; then
-            echo "$f: sage interpreter directive changed from \"$oldInterpreterLine\" to \"$newInterpreterLine\""
-            # escape the escape chars so that sed doesn't interpret them
-            escapedInterpreterLine=$(echo "$newInterpreterLine" | sed 's|\\|\\\\|g')
-            sed -i -e "1 s|.*|#\!$escapedInterpreterLine|" "$f"
-        fi
-    fi
-done
diff --git a/pkgs/applications/science/math/sage/patches/dochtml-optional.patch b/pkgs/applications/science/math/sage/patches/dochtml-optional.patch
new file mode 100644
index 00000000000..a51e30312ed
--- /dev/null
+++ b/pkgs/applications/science/math/sage/patches/dochtml-optional.patch
@@ -0,0 +1,127 @@
+diff --git a/src/doc/common/conf.py b/src/doc/common/conf.py
+index 25f94f7b7d..9f6139ea4a 100644
+--- a/src/doc/common/conf.py
++++ b/src/doc/common/conf.py
+@@ -622,9 +622,9 @@ def call_intersphinx(app, env, node, contnode):
+     Check that the link from the thematic tutorials to the reference
+     manual is relative, see :trac:`20118`::
+ 
+-        sage: from sage.env import SAGE_DOC
+-        sage: thematic_index = os.path.join(SAGE_DOC, "html", "en", "thematic_tutorials", "index.html")
+-        sage: for line in open(thematic_index).readlines():
++        sage: from sage.env import SAGE_DOC  # optional - dochtml
++        sage: thematic_index = os.path.join(SAGE_DOC, "html", "en", "thematic_tutorials", "index.html")  # optional - dochtml
++        sage: for line in open(thematic_index).readlines():  # optional - dochtml
+         ....:     if "padics" in line:
+         ....:         sys.stdout.write(line)
+         <li><a class="reference external" href="../reference/padics/sage/rings/padics/tutorial.html#sage-rings-padics-tutorial" title="(in Sage Reference Manual: p-Adics ...)"><span>Introduction to the -adics</span></a></li>
+diff --git a/src/sage/doctest/control.py b/src/sage/doctest/control.py
+index 4236fd05e0..8e499cbaf7 100644
+--- a/src/sage/doctest/control.py
++++ b/src/sage/doctest/control.py
+@@ -87,7 +87,7 @@ class DocTestDefaults(SageObject):
+         self.sagenb = False
+         self.long = False
+         self.warn_long = None
+-        self.optional = set(['sage']) | auto_optional_tags
++        self.optional = set(['sage', 'dochtml']) | auto_optional_tags
+         self.randorder = None
+         self.global_iterations = 1  # sage-runtests default is 0
+         self.file_iterations = 1    # sage-runtests default is 0
+@@ -343,7 +343,8 @@ class DocTestController(SageObject):
+                     if not optionaltag_regex.search(o):
+                         raise ValueError('invalid optional tag {!r}'.format(o))
+ 
+-                options.optional |= auto_optional_tags
++                if "sage" in options.optional:
++                    options.optional |= auto_optional_tags
+ 
+         self.options = options
+         self.files = args
+@@ -741,7 +742,7 @@ class DocTestController(SageObject):
+             sage: DC = DocTestController(DD, [dirname])
+             sage: DC.expand_files_into_sources()
+             sage: sorted(DC.sources[0].options.optional)  # abs tol 1
+-            ['guava', 'magma', 'py3']
++            ['guava', 'magma']
+ 
+         We check that files are skipped appropriately::
+ 
+@@ -968,7 +969,7 @@ class DocTestController(SageObject):
+             sage: from sage.doctest.control import DocTestDefaults, DocTestController
+             sage: DC = DocTestController(DocTestDefaults(), [])
+             sage: DC._optional_tags_string()
+-            'sage'
++            'dochtml,sage'
+             sage: DC = DocTestController(DocTestDefaults(optional="all,and,some,more"), [])
+             sage: DC._optional_tags_string()
+             'all'
+diff --git a/src/sage/misc/sagedoc.py b/src/sage/misc/sagedoc.py
+index 9255aa848f..cc4712d3ec 100644
+--- a/src/sage/misc/sagedoc.py
++++ b/src/sage/misc/sagedoc.py
+@@ -18,9 +18,9 @@ TESTS:
+ Check that argspecs of extension function/methods appear correctly,
+ see :trac:`12849`::
+ 
+-    sage: from sage.env import SAGE_DOC
+-    sage: docfilename = os.path.join(SAGE_DOC, 'html', 'en', 'reference', 'calculus', 'sage', 'symbolic', 'expression.html')
+-    sage: with open(docfilename) as fobj:
++    sage: from sage.env import SAGE_DOC  # optional - dochtml
++    sage: docfilename = os.path.join(SAGE_DOC, 'html', 'en', 'reference', 'calculus', 'sage', 'symbolic', 'expression.html')  # optional - dochtml
++    sage: with open(docfilename) as fobj:  # optional - dochtml
+     ....:     for line in fobj:
+     ....:         if "#sage.symbolic.expression.Expression.numerical_approx" in line:
+     ....:             print(line)
+@@ -790,11 +790,12 @@ def _search_src_or_doc(what, string, extra1='', extra2='', extra3='',
+ 
+     ::
+ 
+-        sage: len(_search_src_or_doc('src', r'matrix\(', 'incidence_structures', 'self', 'combinat', interact=False).splitlines()) > 1
++        sage: from sage.misc.sagedoc import _search_src_or_doc  # optional - dochtml
++        sage: len(_search_src_or_doc('src', r'matrix\(', 'incidence_structures', 'self', 'combinat', interact=False).splitlines()) > 1  # optional - dochtml
+         True
+-        sage: 'abvar/homology' in _search_src_or_doc('doc', 'homology', 'variety', interact=False)  # long time (4s on sage.math, 2012)
++        sage: 'abvar/homology' in _search_src_or_doc('doc', 'homology', 'variety', interact=False)  # optional - dochtml, long time (4s on sage.math, 2012)
+         True
+-        sage: 'divisors' in _search_src_or_doc('src', '^ *def prime', interact=False)
++        sage: 'divisors' in _search_src_or_doc('src', '^ *def prime', interact=False)  # optional - dochtml
+         True
+     """
+     # process keywords
+@@ -1160,9 +1161,9 @@ def search_doc(string, extra1='', extra2='', extra3='', extra4='',
+     counting the length of ``search_doc('tree',
+     interact=False).splitlines()`` gives the number of matches. ::
+ 
+-        sage: len(search_doc('tree', interact=False).splitlines()) > 4000  # long time
++        sage: len(search_doc('tree', interact=False).splitlines()) > 4000  # optional - dochtml, long time
+         True
+-        sage: len(search_doc('tree', whole_word=True, interact=False).splitlines()) < 2000  # long time
++        sage: len(search_doc('tree', whole_word=True, interact=False).splitlines()) < 2000  # optional - dochtml, long time
+         True
+     """
+     return _search_src_or_doc('doc', string, extra1=extra1, extra2=extra2,
+@@ -1332,9 +1333,9 @@ class _sage_doc:
+ 
+     EXAMPLES::
+ 
+-        sage: browse_sage_doc._open("reference", testing=True)[0]  # indirect doctest
++        sage: browse_sage_doc._open("reference", testing=True)[0]  # optional - dochtml, indirect doctest
+         'http://localhost:8000/doc/live/reference/index.html'
+-        sage: browse_sage_doc(identity_matrix, 'rst')[-107:-47]
++        sage: browse_sage_doc(identity_matrix, 'rst')[-107:-47]  # optional - dochtml
+         'Full MatrixSpace of 3 by 3 sparse matrices over Integer Ring'
+     """
+     def __init__(self):
+@@ -1494,9 +1495,9 @@ class _sage_doc:
+ 
+         EXAMPLES::
+ 
+-            sage: browse_sage_doc._open("reference", testing=True)[0]
++            sage: browse_sage_doc._open("reference", testing=True)[0]  # optional - dochtml
+             'http://localhost:8000/doc/live/reference/index.html'
+-            sage: browse_sage_doc._open("tutorial", testing=True)[1]
++            sage: browse_sage_doc._open("tutorial", testing=True)[1]  # optional - dochtml
+             '.../html/en/tutorial/index.html'
+         """
+         url = self._base_url + os.path.join(name, "index.html")
diff --git a/pkgs/applications/science/math/sage/patches/eclib-regulator-precision.patch b/pkgs/applications/science/math/sage/patches/eclib-regulator-precision.patch
new file mode 100644
index 00000000000..a1464b8fe31
--- /dev/null
+++ b/pkgs/applications/science/math/sage/patches/eclib-regulator-precision.patch
@@ -0,0 +1,98 @@
+diff --git a/src/sage/libs/eclib/interface.py b/src/sage/libs/eclib/interface.py
+index f77000c478..9d17d412ae 100644
+--- a/src/sage/libs/eclib/interface.py
++++ b/src/sage/libs/eclib/interface.py
+@@ -1014,7 +1014,7 @@ class mwrank_MordellWeil(SageObject):
+             WARNING: saturation at primes p > 2 will not be done;
+             ...
+             Gained index 2
+-            New regulator =  93.857300720636393209
++            New regulator =  93.85730...
+             (False, 2, '[ ]')
+             sage: EQ.points()
+             [[-2, 3, 1], [2707496766203306, 864581029138191, 2969715140223272], [-13422227300, -49322830557, 12167000000]]
+@@ -1025,7 +1025,7 @@ class mwrank_MordellWeil(SageObject):
+             WARNING: saturation at primes p > 3 will not be done;
+             ...
+             Gained index 3
+-            New regulator =  10.4285889689595992455
++            New regulator =  10.42858...
+             (False, 3, '[ ]')
+             sage: EQ.points()
+             [[-2, 3, 1], [-14, 25, 8], [-13422227300, -49322830557, 12167000000]]
+@@ -1036,7 +1036,7 @@ class mwrank_MordellWeil(SageObject):
+             WARNING: saturation at primes p > 5 will not be done;
+             ...
+             Gained index 5
+-            New regulator =  0.417143558758383969818
++            New regulator =  0.41714...
+             (False, 5, '[ ]')
+             sage: EQ.points()
+             [[-2, 3, 1], [-14, 25, 8], [1, -1, 1]]
+@@ -1221,7 +1221,7 @@ class mwrank_MordellWeil(SageObject):
+             WARNING: saturation at primes p > 2 will not be done;
+             ...
+             Gained index 2
+-            New regulator =  93.857300720636393209
++            New regulator =  93.85730...
+             (False, 2, '[ ]')
+             sage: EQ
+             Subgroup of Mordell-Weil group: [[-2:3:1], [2707496766203306:864581029138191:2969715140223272], [-13422227300:-49322830557:12167000000]]
+@@ -1235,7 +1235,7 @@ class mwrank_MordellWeil(SageObject):
+             WARNING: saturation at primes p > 3 will not be done;
+             ...
+             Gained index 3
+-            New regulator =  10.4285889689595992455
++            New regulator =  10.42858...
+             (False, 3, '[ ]')
+             sage: EQ
+             Subgroup of Mordell-Weil group: [[-2:3:1], [-14:25:8], [-13422227300:-49322830557:12167000000]]
+@@ -1249,7 +1249,7 @@ class mwrank_MordellWeil(SageObject):
+             WARNING: saturation at primes p > 5 will not be done;
+             ...
+             Gained index 5
+-            New regulator =  0.417143558758383969818
++            New regulator =  0.41714...
+             (False, 5, '[ ]')
+             sage: EQ
+             Subgroup of Mordell-Weil group: [[-2:3:1], [-14:25:8], [1:-1:1]]
+diff --git a/src/sage/libs/eclib/mwrank.pyx b/src/sage/libs/eclib/mwrank.pyx
+index a4f89e1ca5..f8a22d2f55 100644
+--- a/src/sage/libs/eclib/mwrank.pyx
++++ b/src/sage/libs/eclib/mwrank.pyx
+@@ -1234,9 +1234,9 @@ cdef class _two_descent:
+             sage: D2.saturate()
+             Searching for points (bound = 8)...done:
+               found points which generate a subgroup of rank 3
+-              and regulator 0.417143558758383969817119544618093396749810106098479
++              and regulator 0.41714...
+             Processing points found during 2-descent...done:
+-              now regulator = 0.417143558758383969817119544618093396749810106098479
++              now regulator = 0.41714...
+             No saturation being done
+             sage: D2.getbasis()
+             '[[1:-1:1], [-2:3:1], [-14:25:8]]'
+@@ -1281,9 +1281,9 @@ cdef class _two_descent:
+             sage: D2.saturate()
+             Searching for points (bound = 8)...done:
+               found points which generate a subgroup of rank 3
+-              and regulator 0.417143558758383969817119544618093396749810106098479
++              and regulator 0.41714...
+             Processing points found during 2-descent...done:
+-              now regulator = 0.417143558758383969817119544618093396749810106098479
++              now regulator = 0.41714...
+             No saturation being done
+             sage: D2.getbasis()
+             '[[1:-1:1], [-2:3:1], [-14:25:8]]'
+@@ -1329,9 +1329,9 @@ cdef class _two_descent:
+             sage: D2.saturate()
+             Searching for points (bound = 8)...done:
+               found points which generate a subgroup of rank 3
+-              and regulator 0.417143558758383969817119544618093396749810106098479
++              and regulator 0.41714...
+             Processing points found during 2-descent...done:
+-              now regulator = 0.417143558758383969817119544618093396749810106098479
++              now regulator = 0.41714...
+             No saturation being done
+             sage: D2.getbasis()
+             '[[1:-1:1], [-2:3:1], [-14:25:8]]'
diff --git a/pkgs/applications/science/math/sage/patches/matplotlib-normed-deprecated.patch b/pkgs/applications/science/math/sage/patches/matplotlib-normed-deprecated.patch
new file mode 100644
index 00000000000..41747635cac
--- /dev/null
+++ b/pkgs/applications/science/math/sage/patches/matplotlib-normed-deprecated.patch
@@ -0,0 +1,12 @@
+diff --git a/src/sage/all.py b/src/sage/all.py
+index 14cec431f1..25a35a0522 100644
+--- a/src/sage/all.py
++++ b/src/sage/all.py
+@@ -310,6 +310,7 @@ warnings.filters.remove(('ignore', None, DeprecationWarning, None, 0))
+ # Ignore all deprecations from IPython etc.
+ warnings.filterwarnings('ignore',
+     module='.*(IPython|ipykernel|jupyter_client|jupyter_core|nbformat|notebook|ipywidgets|storemagic)')
++warnings.filterwarnings('ignore', "The 'normed' kwarg is deprecated, and has been replaced by the 'density' kwarg.") # matplotlib normed deprecation
+ # However, be sure to keep OUR deprecation warnings
+ warnings.filterwarnings('default',
+     '[\s\S]*See http://trac.sagemath.org/[0-9]* for details.')
diff --git a/pkgs/applications/science/math/sage/patches/maxima-5.41.0-doctests.patch b/pkgs/applications/science/math/sage/patches/maxima-5.41.0-doctests.patch
new file mode 100644
index 00000000000..fad434e52ad
--- /dev/null
+++ b/pkgs/applications/science/math/sage/patches/maxima-5.41.0-doctests.patch
@@ -0,0 +1,48 @@
+diff --git a/src/sage/interfaces/maxima_abstract.py b/src/sage/interfaces/maxima_abstract.py
+index 961c20aaac..3d601d8939 100644
+--- a/src/sage/interfaces/maxima_abstract.py
++++ b/src/sage/interfaces/maxima_abstract.py
+@@ -1743,7 +1743,7 @@ class MaximaAbstractElement(ExtraTabCompletion, InterfaceElement):
+             sage: y,d = var('y,d')
+             sage: f = function('f')
+             sage: latex(maxima(derivative(f(x*y), x)))
+-            \left(\left.{{{\it \partial}}\over{{\it \partial}\,  {\it t_0}}}\,f\left({\it t_0}\right)  \right|_{{\it t_0}={\it x}\,  {\it y}}\right)\,{\it y}
++            \left(\left.{{{\it \partial}}\over{{\it \partial}\,  {\it t}_{0}}}\,f\left({\it t}_{0}\right)  \right|_{{\it t}_{0}={\it x}\,  {\it y}}\right)\,{\it y}
+             sage: latex(maxima(derivative(f(x,y,d), d,x,x,y)))
+             {{{\it \partial}^4}\over{{\it \partial}\,{\it d}\,  {\it \partial}\,{\it x}^2\,{\it \partial}\,  {\it y}}}\,f\left({\it x} ,  {\it y} , {\it d}\right)
+             sage: latex(maxima(d/(d-2)))
+diff --git a/src/sage/manifolds/differentiable/metric.py b/src/sage/manifolds/differentiable/metric.py
+index 3cd6ad3235..1e18af1a6b 100644
+--- a/src/sage/manifolds/differentiable/metric.py
++++ b/src/sage/manifolds/differentiable/metric.py
+@@ -993,7 +993,7 @@ class PseudoRiemannianMetric(TensorField):
+              2-dimensional differentiable manifold S^2
+             sage: g.riemann()[:]
+             [[[[0, 0], [0, 0]], [[0, sin(th)^2], [-sin(th)^2, 0]]],
+-             [[[0, (cos(th)^2 - 1)/sin(th)^2], [1, 0]], [[0, 0], [0, 0]]]]
++             [[[0, -1], [1, 0]], [[0, 0], [0, 0]]]]
+ 
+         In dimension 2, the Riemann tensor can be expressed entirely in terms of
+         the Ricci scalar `r`:
+diff --git a/src/sage/symbolic/expression.pyx b/src/sage/symbolic/expression.pyx
+index dfb8751467..27402e54ab 100644
+--- a/src/sage/symbolic/expression.pyx
++++ b/src/sage/symbolic/expression.pyx
+@@ -7154,7 +7154,7 @@ cdef class Expression(CommutativeRingElement):
+             sage: ex = lcm(sin(x)^2 - 1, sin(x)^2 + sin(x)); ex
+             (sin(x)^2 + sin(x))*(sin(x)^2 - 1)/(sin(x) + 1)
+             sage: ex.simplify_full()
+-            -cos(x)^2*sin(x)
++            sin(x)^3 - sin(x)
+ 
+         TESTS:
+ 
+@@ -10004,7 +10004,7 @@ cdef class Expression(CommutativeRingElement):
+ 
+             sage: f=tan(3*x)
+             sage: f.simplify_trig()
+-            (4*cos(x)^2 - 1)*sin(x)/(4*cos(x)^3 - 3*cos(x))
++            -(4*cos(x)^2 - 1)*sin(x)/(4*cos(x)*sin(x)^2 - cos(x))
+             sage: f.simplify_trig(False)
+             sin(3*x)/cos(3*x)
+ 
diff --git a/pkgs/applications/science/math/sage/patches/numpy-1.14.3.patch b/pkgs/applications/science/math/sage/patches/numpy-1.14.3.patch
new file mode 100644
index 00000000000..5927bc11609
--- /dev/null
+++ b/pkgs/applications/science/math/sage/patches/numpy-1.14.3.patch
@@ -0,0 +1,812 @@
+diff --git a/src/doc/en/faq/faq-usage.rst b/src/doc/en/faq/faq-usage.rst
+index 79b4205fd3..9a89bd2136 100644
+--- a/src/doc/en/faq/faq-usage.rst
++++ b/src/doc/en/faq/faq-usage.rst
+@@ -338,7 +338,7 @@ ints. For example::
+     sage: RealNumber = float; Integer = int
+     sage: from scipy import stats
+     sage: stats.ttest_ind(list([1,2,3,4,5]),list([2,3,4,5,.6]))
+-    Ttest_indResult(statistic=0.076752955645333687, pvalue=0.94070490247380478)
++    Ttest_indResult(statistic=0.0767529..., pvalue=0.940704...)
+     sage: stats.uniform(0,15).ppf([0.5,0.7])
+     array([  7.5,  10.5])
+ 
+diff --git a/src/doc/en/thematic_tutorials/numerical_sage/cvxopt.rst b/src/doc/en/thematic_tutorials/numerical_sage/cvxopt.rst
+index 314811c42b..e5f54ec4c2 100644
+--- a/src/doc/en/thematic_tutorials/numerical_sage/cvxopt.rst
++++ b/src/doc/en/thematic_tutorials/numerical_sage/cvxopt.rst
+@@ -48,11 +48,13 @@ we could do the following.
+     sage: B = numpy.array([1.0]*5)
+     sage: B.shape=(5,1)
+     sage: print(B)
+-    [[ 1.]
+-     [ 1.]
+-     [ 1.]
+-     [ 1.]
+-     [ 1.]]
++    [[1.]
++     [1.]
++     [1.]
++     [1.]
++     [1.]]
++
++
+     sage: print(A)
+     [ 2.00e+00  3.00e+00     0         0         0    ]
+     [ 3.00e+00     0      4.00e+00     0      6.00e+00]
+diff --git a/src/doc/en/thematic_tutorials/numerical_sage/numpy.rst b/src/doc/en/thematic_tutorials/numerical_sage/numpy.rst
+index 5b89cd75ee..e50b2ea5d4 100644
+--- a/src/doc/en/thematic_tutorials/numerical_sage/numpy.rst
++++ b/src/doc/en/thematic_tutorials/numerical_sage/numpy.rst
+@@ -84,7 +84,7 @@ well as take slices
+     sage: l[3]
+     3.0
+     sage: l[3:6]
+-    array([ 3.,  4.,  5.])
++    array([3., 4., 5.])
+ 
+ You can do basic arithmetic operations
+ 
+@@ -147,11 +147,11 @@ also do matrix vector multiplication, and matrix addition
+     sage: n = numpy.matrix([[1,2],[3,4]],dtype=float)
+     sage: v = numpy.array([[1],[2]],dtype=float)
+     sage: n*v
+-    matrix([[  5.],
+-            [ 11.]])
++    matrix([[ 5.],
++            [11.]])
+     sage: n+n
+-    matrix([[ 2.,  4.],
+-            [ 6.,  8.]])
++    matrix([[2., 4.],
++            [6., 8.]])
+ 
+ If ``n`` was created with :meth:`numpy.array`, then to do matrix vector
+ multiplication, you would use ``numpy.dot(n,v)``.
+@@ -170,11 +170,11 @@ to manipulate
+             22.,  23.,  24.])
+     sage: n.shape=(5,5)
+     sage: n
+-    array([[  0.,   1.,   2.,   3.,   4.],
+-           [  5.,   6.,   7.,   8.,   9.],
+-           [ 10.,  11.,  12.,  13.,  14.],
+-           [ 15.,  16.,  17.,  18.,  19.],
+-           [ 20.,  21.,  22.,  23.,  24.]])
++    array([[ 0.,  1.,  2.,  3.,  4.],
++           [ 5.,  6.,  7.,  8.,  9.],
++           [10., 11., 12., 13., 14.],
++           [15., 16., 17., 18., 19.],
++           [20., 21., 22., 23., 24.]])
+ 
+ This changes the one-dimensional array into a `5\times 5` array.
+ 
+@@ -187,8 +187,8 @@ NumPy arrays can be sliced as well
+     sage: n=numpy.array(range(25),dtype=float)
+     sage: n.shape=(5,5)
+     sage: n[2:4,1:3]
+-    array([[ 11.,  12.],
+-           [ 16.,  17.]])
++    array([[11., 12.],
++           [16., 17.]])
+ 
+ It is important to note that the sliced matrices are references to
+ the original
+@@ -224,8 +224,8 @@ Some particularly useful commands are
+ 
+     sage: x=numpy.arange(0,2,.1,dtype=float)
+     sage: x
+-    array([ 0. ,  0.1,  0.2,  0.3,  0.4,  0.5,  0.6,  0.7,  0.8,  0.9,  1. ,
+-            1.1,  1.2,  1.3,  1.4,  1.5,  1.6,  1.7,  1.8,  1.9])
++    array([0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1. , 1.1, 1.2,
++           1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9])
+ 
+ You can see that :meth:`numpy.arange` creates an array of floats increasing by 0.1
+ from 0 to 2. There is a useful command :meth:`numpy.r_` that is best explained by example
+@@ -240,10 +240,11 @@ from 0 to 2. There is a useful command :meth:`numpy.r_` that is best explained b
+     sage: Integer=int
+     sage: n=r_[0.0:5.0]
+     sage: n
+-    array([ 0.,  1.,  2.,  3.,  4.])
++    array([0., 1., 2., 3., 4.])
+     sage: n=r_[0.0:5.0, [0.0]*5]
+     sage: n
+-    array([ 0.,  1.,  2.,  3.,  4.,  0.,  0.,  0.,  0.,  0.])
++    array([0., 1., 2., 3., 4., 0., 0., 0., 0., 0.])
++
+ 
+ :meth:`numpy.r_` provides a shorthand for constructing NumPy arrays efficiently.
+ Note in the above ``0.0:5.0`` was shorthand for ``0.0, 1.0, 2.0, 3.0, 4.0``.
+@@ -255,7 +256,7 @@ intervals. We can do this as follows
+ ::
+ 
+     sage: r_[0.0:5.0:11*j]
+-    array([ 0. ,  0.5,  1. ,  1.5,  2. ,  2.5,  3. ,  3.5,  4. ,  4.5,  5. ])
++    array([0. , 0.5, 1. , 1.5, 2. , 2.5, 3. , 3.5, 4. , 4.5, 5. ])
+ 
+ The notation ``0.0:5.0:11*j`` expands to a list of 11 equally space
+ points between 0 and 5 including both endpoints. Note that ``j`` is the
+@@ -287,23 +288,23 @@ an equally spaced grid with `\Delta x = \Delta y = .25` for
+     sage: y=numpy.r_[0.0:1.0:5*j]
+     sage: xx,yy= meshgrid(x,y)
+     sage: xx
+-    array([[ 0.  ,  0.25,  0.5 ,  0.75,  1.  ],
+-           [ 0.  ,  0.25,  0.5 ,  0.75,  1.  ],
+-           [ 0.  ,  0.25,  0.5 ,  0.75,  1.  ],
+-           [ 0.  ,  0.25,  0.5 ,  0.75,  1.  ],
+-           [ 0.  ,  0.25,  0.5 ,  0.75,  1.  ]])
++    array([[0.  , 0.25, 0.5 , 0.75, 1.  ],
++           [0.  , 0.25, 0.5 , 0.75, 1.  ],
++           [0.  , 0.25, 0.5 , 0.75, 1.  ],
++           [0.  , 0.25, 0.5 , 0.75, 1.  ],
++           [0.  , 0.25, 0.5 , 0.75, 1.  ]])
+     sage: yy
+-    array([[ 0.  ,  0.  ,  0.  ,  0.  ,  0.  ],
+-           [ 0.25,  0.25,  0.25,  0.25,  0.25],
+-           [ 0.5 ,  0.5 ,  0.5 ,  0.5 ,  0.5 ],
+-           [ 0.75,  0.75,  0.75,  0.75,  0.75],
+-           [ 1.  ,  1.  ,  1.  ,  1.  ,  1.  ]])
++    array([[0.  , 0.  , 0.  , 0.  , 0.  ],
++           [0.25, 0.25, 0.25, 0.25, 0.25],
++           [0.5 , 0.5 , 0.5 , 0.5 , 0.5 ],
++           [0.75, 0.75, 0.75, 0.75, 0.75],
++           [1.  , 1.  , 1.  , 1.  , 1.  ]])
+     sage: f(xx,yy)
+-    array([[ 0.    ,  0.0625,  0.25  ,  0.5625,  1.    ],
+-           [ 0.0625,  0.125 ,  0.3125,  0.625 ,  1.0625],
+-           [ 0.25  ,  0.3125,  0.5   ,  0.8125,  1.25  ],
+-           [ 0.5625,  0.625 ,  0.8125,  1.125 ,  1.5625],
+-           [ 1.    ,  1.0625,  1.25  ,  1.5625,  2.    ]])
++    array([[0.    , 0.0625, 0.25  , 0.5625, 1.    ],
++           [0.0625, 0.125 , 0.3125, 0.625 , 1.0625],
++           [0.25  , 0.3125, 0.5   , 0.8125, 1.25  ],
++           [0.5625, 0.625 , 0.8125, 1.125 , 1.5625],
++           [1.    , 1.0625, 1.25  , 1.5625, 2.    ]])
+ 
+ You can see that :meth:`numpy.meshgrid` produces a pair of matrices, here denoted
+ `xx` and `yy`, such that `(xx[i,j],yy[i,j])` has coordinates
+@@ -324,7 +325,7 @@ equation `Ax=b` do
+     sage: b=numpy.array(range(1,6))
+     sage: x=linalg.solve(A,b)
+     sage: numpy.dot(A,x)
+-    array([ 1.,  2.,  3.,  4., 5.])
++    array([1., 2., 3., 4., 5.])
+ 
+ This creates a random 5x5 matrix ``A``, and solves `Ax=b` where
+ ``b=[0.0,1.0,2.0,3.0,4.0]``. There are many other routines in the :mod:`numpy.linalg`
+diff --git a/src/sage/calculus/riemann.pyx b/src/sage/calculus/riemann.pyx
+index df85cce43d..34ea164be0 100644
+--- a/src/sage/calculus/riemann.pyx
++++ b/src/sage/calculus/riemann.pyx
+@@ -1191,30 +1191,30 @@ cpdef complex_to_spiderweb(np.ndarray[COMPLEX_T, ndim = 2] z_values,
+         sage: zval = numpy.array([[0, 1, 1000],[.2+.3j,1,-.3j],[0,0,0]],dtype = numpy.complex128)
+         sage: deriv = numpy.array([[.1]],dtype = numpy.float64)
+         sage: complex_to_spiderweb(zval, deriv,deriv, 4,4,[0,0,0],1,False,0.001)
+-        array([[[ 1.,  1.,  1.],
+-                [ 1.,  1.,  1.],
+-                [ 1.,  1.,  1.]],
++        array([[[1., 1., 1.],
++                [1., 1., 1.],
++                [1., 1., 1.]],
+         <BLANKLINE>
+-               [[ 1.,  1.,  1.],
+-                [ 0.,  0.,  0.],
+-                [ 1.,  1.,  1.]],
++               [[1., 1., 1.],
++                [0., 0., 0.],
++                [1., 1., 1.]],
+         <BLANKLINE>
+-               [[ 1.,  1.,  1.],
+-                [ 1.,  1.,  1.],
+-                [ 1.,  1.,  1.]]])
++               [[1., 1., 1.],
++                [1., 1., 1.],
++                [1., 1., 1.]]])
+ 
+         sage: complex_to_spiderweb(zval, deriv,deriv, 4,4,[0,0,0],1,True,0.001)
+-        array([[[ 1.        ,  1.        ,  1.        ],
+-                [ 1.        ,  0.05558355,  0.05558355],
+-                [ 0.17301243,  0.        ,  0.        ]],
++        array([[[1.        , 1.        , 1.        ],
++                [1.        , 0.05558355, 0.05558355],
++                [0.17301243, 0.        , 0.        ]],
+         <BLANKLINE>
+-               [[ 1.        ,  0.96804683,  0.48044583],
+-                [ 0.        ,  0.        ,  0.        ],
+-                [ 0.77351965,  0.5470393 ,  1.        ]],
++               [[1.        , 0.96804683, 0.48044583],
++                [0.        , 0.        , 0.        ],
++                [0.77351965, 0.5470393 , 1.        ]],
+         <BLANKLINE>
+-               [[ 1.        ,  1.        ,  1.        ],
+-                [ 1.        ,  1.        ,  1.        ],
+-                [ 1.        ,  1.        ,  1.        ]]])
++               [[1.        , 1.        , 1.        ],
++                [1.        , 1.        , 1.        ],
++                [1.        , 1.        , 1.        ]]])
+      """
+     cdef Py_ssize_t i, j, imax, jmax
+     cdef FLOAT_T x, y, mag, arg, width, target, precision, dmag, darg
+@@ -1279,14 +1279,14 @@ cpdef complex_to_rgb(np.ndarray[COMPLEX_T, ndim = 2] z_values):
+         sage: from sage.calculus.riemann import complex_to_rgb
+         sage: import numpy
+         sage: complex_to_rgb(numpy.array([[0, 1, 1000]], dtype = numpy.complex128))
+-        array([[[ 1.        ,  1.        ,  1.        ],
+-                [ 1.        ,  0.05558355,  0.05558355],
+-                [ 0.17301243,  0.        ,  0.        ]]])
++        array([[[1.        , 1.        , 1.        ],
++                [1.        , 0.05558355, 0.05558355],
++                [0.17301243, 0.        , 0.        ]]])
+ 
+         sage: complex_to_rgb(numpy.array([[0, 1j, 1000j]], dtype = numpy.complex128))
+-        array([[[ 1.        ,  1.        ,  1.        ],
+-                [ 0.52779177,  1.        ,  0.05558355],
+-                [ 0.08650622,  0.17301243,  0.        ]]])
++        array([[[1.        , 1.        , 1.        ],
++                [0.52779177, 1.        , 0.05558355],
++                [0.08650622, 0.17301243, 0.        ]]])
+ 
+ 
+     TESTS::
+diff --git a/src/sage/combinat/fully_packed_loop.py b/src/sage/combinat/fully_packed_loop.py
+index 61b1003002..4baee9cbbd 100644
+--- a/src/sage/combinat/fully_packed_loop.py
++++ b/src/sage/combinat/fully_packed_loop.py
+@@ -72,11 +72,11 @@ def _make_color_list(n, colors=None,  color_map=None, randomize=False):
+         sage: _make_color_list(5, ['blue', 'red'])
+         ['blue', 'red', 'blue', 'red', 'blue']
+         sage: _make_color_list(5, color_map='summer')
+-        [(0.0, 0.5, 0.40000000000000002),
+-         (0.25098039215686274, 0.62549019607843137, 0.40000000000000002),
+-         (0.50196078431372548, 0.75098039215686274, 0.40000000000000002),
+-         (0.75294117647058822, 0.87647058823529411, 0.40000000000000002),
+-         (1.0, 1.0, 0.40000000000000002)]
++        [(0.0, 0.5, 0.4),
++         (0.25098039215686274, 0.6254901960784314, 0.4),
++         (0.5019607843137255, 0.7509803921568627, 0.4),
++         (0.7529411764705882, 0.8764705882352941, 0.4),
++         (1.0, 1.0, 0.4)]
+         sage: _make_color_list(8, ['blue', 'red'], randomize=True)
+         ['blue', 'blue', 'red', 'blue', 'red', 'red', 'red', 'blue']
+     """
+diff --git a/src/sage/finance/time_series.pyx b/src/sage/finance/time_series.pyx
+index c37700d14e..49b7298d0b 100644
+--- a/src/sage/finance/time_series.pyx
++++ b/src/sage/finance/time_series.pyx
+@@ -109,8 +109,8 @@ cdef class TimeSeries:
+ 
+             sage: import numpy
+             sage: v = numpy.array([[1,2], [3,4]], dtype=float); v
+-            array([[ 1.,  2.],
+-                   [ 3.,  4.]])
++            array([[1., 2.],
++                   [3., 4.]])
+             sage: finance.TimeSeries(v)
+             [1.0000, 2.0000, 3.0000, 4.0000]
+             sage: finance.TimeSeries(v[:,0])
+@@ -2098,14 +2098,14 @@ cdef class TimeSeries:
+ 
+             sage: w[0] = 20
+             sage: w
+-            array([ 20. ,  -3. ,   4.5,  -2. ])
++            array([20. , -3. ,  4.5, -2. ])
+             sage: v
+             [20.0000, -3.0000, 4.5000, -2.0000]
+ 
+         If you want a separate copy do not give the ``copy=False`` option. ::
+ 
+             sage: z = v.numpy(); z
+-            array([ 20. ,  -3. ,   4.5,  -2. ])
++            array([20. , -3. ,  4.5, -2. ])
+             sage: z[0] = -10
+             sage: v
+             [20.0000, -3.0000, 4.5000, -2.0000]
+diff --git a/src/sage/functions/hyperbolic.py b/src/sage/functions/hyperbolic.py
+index 931a4b41e4..bf33fc483d 100644
+--- a/src/sage/functions/hyperbolic.py
++++ b/src/sage/functions/hyperbolic.py
+@@ -214,7 +214,7 @@ class Function_coth(GinacFunction):
+             sage: import numpy
+             sage: a = numpy.arange(2, 5)
+             sage: coth(a)
+-            array([ 1.03731472,  1.00496982,  1.00067115])
++            array([1.03731472, 1.00496982, 1.00067115])
+         """
+         return 1.0 / tanh(x)
+ 
+@@ -267,7 +267,7 @@ class Function_sech(GinacFunction):
+             sage: import numpy
+             sage: a = numpy.arange(2, 5)
+             sage: sech(a)
+-            array([ 0.26580223,  0.09932793,  0.03661899])
++            array([0.26580223, 0.09932793, 0.03661899])
+         """
+         return 1.0 / cosh(x)
+ 
+@@ -318,7 +318,7 @@ class Function_csch(GinacFunction):
+             sage: import numpy
+             sage: a = numpy.arange(2, 5)
+             sage: csch(a)
+-            array([ 0.27572056,  0.09982157,  0.03664357])
++            array([0.27572056, 0.09982157, 0.03664357])
+         """
+         return 1.0 / sinh(x)
+ 
+@@ -586,7 +586,7 @@ class Function_arccoth(GinacFunction):
+             sage: import numpy
+             sage: a = numpy.arange(2,5)
+             sage: acoth(a)
+-            array([ 0.54930614,  0.34657359,  0.25541281])
++            array([0.54930614, 0.34657359, 0.25541281])
+         """
+         return arctanh(1.0 / x)
+ 
+diff --git a/src/sage/functions/orthogonal_polys.py b/src/sage/functions/orthogonal_polys.py
+index 017c85a96f..33fbb499c5 100644
+--- a/src/sage/functions/orthogonal_polys.py
++++ b/src/sage/functions/orthogonal_polys.py
+@@ -810,12 +810,12 @@ class Func_chebyshev_T(ChebyshevFunction):
+             sage: z2 = numpy.array([[1,2],[1,2]])
+             sage: z3 = numpy.array([1,2,3.])
+             sage: chebyshev_T(1,z)
+-            array([ 1.,  2.])
++            array([1., 2.])
+             sage: chebyshev_T(1,z2)
+-            array([[ 1.,  2.],
+-                   [ 1.,  2.]])
++            array([[1., 2.],
++                   [1., 2.]])
+             sage: chebyshev_T(1,z3)
+-            array([ 1.,  2.,  3.])
++            array([1., 2., 3.])
+             sage: chebyshev_T(z,0.1)
+             array([ 0.1 , -0.98])
+         """
+@@ -1095,12 +1095,12 @@ class Func_chebyshev_U(ChebyshevFunction):
+             sage: z2 = numpy.array([[1,2],[1,2]])
+             sage: z3 = numpy.array([1,2,3.])
+             sage: chebyshev_U(1,z)
+-            array([ 2.,  4.])
++            array([2., 4.])
+             sage: chebyshev_U(1,z2)
+-            array([[ 2.,  4.],
+-                   [ 2.,  4.]])
++            array([[2., 4.],
++                   [2., 4.]])
+             sage: chebyshev_U(1,z3)
+-            array([ 2.,  4.,  6.])
++            array([2., 4., 6.])
+             sage: chebyshev_U(z,0.1)
+             array([ 0.2 , -0.96])
+         """
+diff --git a/src/sage/functions/other.py b/src/sage/functions/other.py
+index 679384c907..d63b295a4c 100644
+--- a/src/sage/functions/other.py
++++ b/src/sage/functions/other.py
+@@ -390,7 +390,7 @@ class Function_ceil(BuiltinFunction):
+             sage: import numpy
+             sage: a = numpy.linspace(0,2,6)
+             sage: ceil(a)
+-            array([ 0.,  1.,  1.,  2.,  2.,  2.])
++            array([0., 1., 1., 2., 2., 2.])
+ 
+         Test pickling::
+ 
+@@ -539,7 +539,7 @@ class Function_floor(BuiltinFunction):
+             sage: import numpy
+             sage: a = numpy.linspace(0,2,6)
+             sage: floor(a)
+-            array([ 0.,  0.,  0.,  1.,  1.,  2.])
++            array([0., 0., 0., 1., 1., 2.])
+             sage: floor(x)._sympy_()
+             floor(x)
+ 
+@@ -840,7 +840,7 @@ def sqrt(x, *args, **kwds):
+             sage: import numpy
+             sage: a = numpy.arange(2,5)
+             sage: sqrt(a)
+-            array([ 1.41421356,  1.73205081,  2.        ])
++            array([1.41421356, 1.73205081, 2.        ])
+         """
+         if isinstance(x, float):
+             return math.sqrt(x)
+diff --git a/src/sage/functions/trig.py b/src/sage/functions/trig.py
+index e7e7a311cd..e7ff78a9de 100644
+--- a/src/sage/functions/trig.py
++++ b/src/sage/functions/trig.py
+@@ -731,7 +731,7 @@ class Function_arccot(GinacFunction):
+             sage: import numpy
+             sage: a = numpy.arange(2, 5)
+             sage: arccot(a)
+-            array([ 0.46364761,  0.32175055,  0.24497866])
++            array([0.46364761, 0.32175055, 0.24497866])
+         """
+         return math.pi/2 - arctan(x)
+ 
+@@ -787,7 +787,7 @@ class Function_arccsc(GinacFunction):
+             sage: import numpy
+             sage: a = numpy.arange(2, 5)
+             sage: arccsc(a)
+-            array([ 0.52359878,  0.33983691,  0.25268026])
++            array([0.52359878, 0.33983691, 0.25268026])
+         """
+         return arcsin(1.0/x)
+ 
+@@ -845,7 +845,7 @@ class Function_arcsec(GinacFunction):
+             sage: import numpy
+             sage: a = numpy.arange(2, 5)
+             sage: arcsec(a)
+-            array([ 1.04719755,  1.23095942,  1.31811607])
++            array([1.04719755, 1.23095942, 1.31811607])
+         """
+         return arccos(1.0/x)
+ 
+@@ -920,13 +920,13 @@ class Function_arctan2(GinacFunction):
+             sage: a = numpy.linspace(1, 3, 3)
+             sage: b = numpy.linspace(3, 6, 3)
+             sage: atan2(a, b)
+-            array([ 0.32175055,  0.41822433,  0.46364761])
++            array([0.32175055, 0.41822433, 0.46364761])
+ 
+             sage: atan2(1,a)
+-            array([ 0.78539816,  0.46364761,  0.32175055])
++            array([0.78539816, 0.46364761, 0.32175055])
+ 
+             sage: atan2(a, 1)
+-            array([ 0.78539816,  1.10714872,  1.24904577])
++            array([0.78539816, 1.10714872, 1.24904577])
+ 
+         TESTS::
+ 
+diff --git a/src/sage/matrix/constructor.pyx b/src/sage/matrix/constructor.pyx
+index 19a1d37df0..5780dfae1c 100644
+--- a/src/sage/matrix/constructor.pyx
++++ b/src/sage/matrix/constructor.pyx
+@@ -494,8 +494,8 @@ class MatrixFactory(object):
+         [7 8 9]
+         Full MatrixSpace of 3 by 3 dense matrices over Integer Ring
+         sage: n = matrix(QQ, 2, 2, [1, 1/2, 1/3, 1/4]).numpy(); n
+-        array([[ 1.        ,  0.5       ],
+-               [ 0.33333333,  0.25      ]])
++        array([[1.        , 0.5       ],
++               [0.33333333, 0.25      ]])
+         sage: matrix(QQ, n)
+         [  1 1/2]
+         [1/3 1/4]
+diff --git a/src/sage/matrix/matrix_double_dense.pyx b/src/sage/matrix/matrix_double_dense.pyx
+index 48e0a8a97f..1be5d35b19 100644
+--- a/src/sage/matrix/matrix_double_dense.pyx
++++ b/src/sage/matrix/matrix_double_dense.pyx
+@@ -2546,7 +2546,7 @@ cdef class Matrix_double_dense(Matrix_dense):
+             sage: P.is_unitary(algorithm='orthonormal')
+             Traceback (most recent call last):
+             ...
+-            ValueError: failed to create intent(cache|hide)|optional array-- must have defined dimensions but got (0,)
++            error: ((lwork==-1)||(lwork >= MAX(1,2*n))) failed for 3rd keyword lwork: zgees:lwork=0
+ 
+         TESTS::
+ 
+@@ -3662,8 +3662,8 @@ cdef class Matrix_double_dense(Matrix_dense):
+             [0.0 1.0 2.0]
+             [3.0 4.0 5.0]
+             sage: m.numpy()
+-            array([[ 0.,  1.,  2.],
+-                   [ 3.,  4.,  5.]])
++            array([[0., 1., 2.],
++                   [3., 4., 5.]])
+ 
+         Alternatively, numpy automatically calls this function (via
+         the magic :meth:`__array__` method) to convert Sage matrices
+@@ -3674,16 +3674,16 @@ cdef class Matrix_double_dense(Matrix_dense):
+             [0.0 1.0 2.0]
+             [3.0 4.0 5.0]
+             sage: numpy.array(m)
+-            array([[ 0.,  1.,  2.],
+-                   [ 3.,  4.,  5.]])
++            array([[0., 1., 2.],
++                   [3., 4., 5.]])
+             sage: numpy.array(m).dtype
+             dtype('float64')
+             sage: m = matrix(CDF, 2, range(6)); m
+             [0.0 1.0 2.0]
+             [3.0 4.0 5.0]
+             sage: numpy.array(m)
+-            array([[ 0.+0.j,  1.+0.j,  2.+0.j],
+-                   [ 3.+0.j,  4.+0.j,  5.+0.j]])
++            array([[0.+0.j, 1.+0.j, 2.+0.j],
++                   [3.+0.j, 4.+0.j, 5.+0.j]])
+             sage: numpy.array(m).dtype
+             dtype('complex128')
+ 
+diff --git a/src/sage/matrix/special.py b/src/sage/matrix/special.py
+index c698ba5e97..b743bab354 100644
+--- a/src/sage/matrix/special.py
++++ b/src/sage/matrix/special.py
+@@ -705,7 +705,7 @@ def diagonal_matrix(arg0=None, arg1=None, arg2=None, sparse=True):
+ 
+         sage: import numpy
+         sage: entries = numpy.array([1.2, 5.6]); entries
+-        array([ 1.2,  5.6])
++        array([1.2, 5.6])
+         sage: A = diagonal_matrix(3, entries); A
+         [1.2 0.0 0.0]
+         [0.0 5.6 0.0]
+@@ -715,7 +715,7 @@ def diagonal_matrix(arg0=None, arg1=None, arg2=None, sparse=True):
+ 
+         sage: j = numpy.complex(0,1)
+         sage: entries = numpy.array([2.0+j, 8.1, 3.4+2.6*j]); entries
+-        array([ 2.0+1.j ,  8.1+0.j ,  3.4+2.6j])
++        array([2. +1.j , 8.1+0.j , 3.4+2.6j])
+         sage: A = diagonal_matrix(entries); A
+         [2.0 + 1.0*I         0.0         0.0]
+         [        0.0         8.1         0.0]
+diff --git a/src/sage/modules/free_module_element.pyx b/src/sage/modules/free_module_element.pyx
+index 230f142117..2ab1c0ae68 100644
+--- a/src/sage/modules/free_module_element.pyx
++++ b/src/sage/modules/free_module_element.pyx
+@@ -982,7 +982,7 @@ cdef class FreeModuleElement(Vector):   # abstract base class
+             sage: v.numpy()
+             array([1, 2, 5/6], dtype=object)
+             sage: v.numpy(dtype=float)
+-            array([ 1.        ,  2.        ,  0.83333333])
++            array([1.        , 2.        , 0.83333333])
+             sage: v.numpy(dtype=int)
+             array([1, 2, 0])
+             sage: import numpy
+@@ -993,7 +993,7 @@ cdef class FreeModuleElement(Vector):   # abstract base class
+         be more efficient but may have unintended consequences::
+ 
+             sage: v.numpy(dtype=None)
+-            array([ 1.        ,  2.        ,  0.83333333])
++            array([1.        , 2.        , 0.83333333])
+ 
+             sage: w = vector(ZZ, [0, 1, 2^63 -1]); w
+             (0, 1, 9223372036854775807)
+diff --git a/src/sage/modules/vector_double_dense.pyx b/src/sage/modules/vector_double_dense.pyx
+index 39fc2970de..2badf98284 100644
+--- a/src/sage/modules/vector_double_dense.pyx
++++ b/src/sage/modules/vector_double_dense.pyx
+@@ -807,13 +807,13 @@ cdef class Vector_double_dense(FreeModuleElement):
+ 
+             sage: v = vector(CDF,4,range(4))
+             sage: v.numpy()
+-            array([ 0.+0.j,  1.+0.j,  2.+0.j,  3.+0.j])
++            array([0.+0.j, 1.+0.j, 2.+0.j, 3.+0.j])
+             sage: v = vector(CDF,0)
+             sage: v.numpy()
+             array([], dtype=complex128)
+             sage: v = vector(RDF,4,range(4))
+             sage: v.numpy()
+-            array([ 0.,  1.,  2.,  3.])
++            array([0., 1., 2., 3.])
+             sage: v = vector(RDF,0)
+             sage: v.numpy()
+             array([], dtype=float64)
+@@ -823,11 +823,11 @@ cdef class Vector_double_dense(FreeModuleElement):
+             sage: import numpy
+             sage: v = vector(CDF, 3, range(3))
+             sage: v.numpy()
+-            array([ 0.+0.j,  1.+0.j,  2.+0.j])
++            array([0.+0.j, 1.+0.j, 2.+0.j])
+             sage: v.numpy(dtype=numpy.float64)
+-            array([ 0.,  1.,  2.])
++            array([0., 1., 2.])
+             sage: v.numpy(dtype=numpy.float32)
+-            array([ 0.,  1.,  2.], dtype=float32)
++            array([0., 1., 2.], dtype=float32)
+         """
+         if dtype is None or dtype is self._vector_numpy.dtype:
+             from copy import copy
+diff --git a/src/sage/numerical/optimize.py b/src/sage/numerical/optimize.py
+index 17b5ebb84b..92ce35c502 100644
+--- a/src/sage/numerical/optimize.py
++++ b/src/sage/numerical/optimize.py
+@@ -486,9 +486,9 @@ def minimize_constrained(func,cons,x0,gradient=None,algorithm='default', **args)
+                 else:
+                     min = optimize.fmin_tnc(f, x0, approx_grad=True, bounds=cons, messages=0, **args)[0]
+         elif isinstance(cons[0], function_type) or isinstance(cons[0], Expression):
+-            min = optimize.fmin_cobyla(f, x0, cons, iprint=0, **args)
++            min = optimize.fmin_cobyla(f, x0, cons, disp=0, **args)
+     elif isinstance(cons, function_type) or isinstance(cons, Expression):
+-        min = optimize.fmin_cobyla(f, x0, cons, iprint=0, **args)
++        min = optimize.fmin_cobyla(f, x0, cons, disp=0, **args)
+     return vector(RDF, min)
+ 
+ 
+diff --git a/src/sage/plot/complex_plot.pyx b/src/sage/plot/complex_plot.pyx
+index ad9693da62..758fb709b7 100644
+--- a/src/sage/plot/complex_plot.pyx
++++ b/src/sage/plot/complex_plot.pyx
+@@ -61,9 +61,9 @@ cdef inline double mag_to_lightness(double r):
+ 
+         sage: from sage.plot.complex_plot import complex_to_rgb
+         sage: complex_to_rgb([[0, 1, 10]])
+-        array([[[ 0.        ,  0.        ,  0.        ],
+-                [ 0.77172568,  0.        ,  0.        ],
+-                [ 1.        ,  0.22134776,  0.22134776]]])
++        array([[[0.        , 0.        , 0.        ],
++                [0.77172568, 0.        , 0.        ],
++                [1.        , 0.22134776, 0.22134776]]])
+     """
+     return atan(log(sqrt(r)+1)) * (4/PI) - 1
+ 
+@@ -82,13 +82,13 @@ def complex_to_rgb(z_values):
+ 
+         sage: from sage.plot.complex_plot import complex_to_rgb
+         sage: complex_to_rgb([[0, 1, 1000]])
+-        array([[[ 0.        ,  0.        ,  0.        ],
+-                [ 0.77172568,  0.        ,  0.        ],
+-                [ 1.        ,  0.64421177,  0.64421177]]])
++        array([[[0.        , 0.        , 0.        ],
++                [0.77172568, 0.        , 0.        ],
++                [1.        , 0.64421177, 0.64421177]]])
+         sage: complex_to_rgb([[0, 1j, 1000j]])
+-        array([[[ 0.        ,  0.        ,  0.        ],
+-                [ 0.38586284,  0.77172568,  0.        ],
+-                [ 0.82210588,  1.        ,  0.64421177]]])
++        array([[[0.        , 0.        , 0.        ],
++                [0.38586284, 0.77172568, 0.        ],
++                [0.82210588, 1.        , 0.64421177]]])
+     """
+     import numpy
+     cdef unsigned int i, j, imax, jmax
+diff --git a/src/sage/plot/line.py b/src/sage/plot/line.py
+index 23f5e61446..3b1b51d7cf 100644
+--- a/src/sage/plot/line.py
++++ b/src/sage/plot/line.py
+@@ -502,14 +502,12 @@ def line2d(points, **options):
+     from sage.plot.all import Graphics
+     from sage.plot.plot import xydata_from_point_list
+     from sage.rings.all import CC, CDF
++    points = list(points) # make sure points is a python list
+     if points in CC or points in CDF:
+         pass
+     else:
+-        try:
+-            if not points:
+-                return Graphics()
+-        except ValueError: # numpy raises a ValueError if not empty
+-            pass
++        if len(points) == 0:
++            return Graphics()
+     xdata, ydata = xydata_from_point_list(points)
+     g = Graphics()
+     g._set_extra_kwds(Graphics._extract_kwds_for_show(options))
+diff --git a/src/sage/plot/plot_field.py b/src/sage/plot/plot_field.py
+index 0025098a8d..23c80902f3 100644
+--- a/src/sage/plot/plot_field.py
++++ b/src/sage/plot/plot_field.py
+@@ -49,9 +49,10 @@ class PlotField(GraphicPrimitive):
+             sage: r.xpos_array
+             [0.0, 0.0, 1.0, 1.0]
+             sage: r.yvec_array
+-            masked_array(data = [0.0 0.70710678118... 0.70710678118... 0.89442719...],
+-                         mask = [False False False False],
+-                   fill_value = 1e+20)
++            masked_array(data=[0.0, 0.70710678118..., 0.70710678118...,
++                               0.89442719...],
++                         mask=[False, False, False, False],
++                   fill_value=1e+20)
+ 
+         TESTS:
+ 
+diff --git a/src/sage/plot/streamline_plot.py b/src/sage/plot/streamline_plot.py
+index f3da57c370..3806f4b32f 100644
+--- a/src/sage/plot/streamline_plot.py
++++ b/src/sage/plot/streamline_plot.py
+@@ -38,16 +38,14 @@ class StreamlinePlot(GraphicPrimitive):
+             sage: r.options()['plot_points']
+             2
+             sage: r.xpos_array
+-            array([ 0.,  1.])
++            array([0., 1.])
+             sage: r.yvec_array
+-            masked_array(data =
+-             [[1.0 1.0]
+-             [0.5403023058681398 0.5403023058681398]],
+-                         mask =
+-             [[False False]
+-             [False False]],
+-                   fill_value = 1e+20)
+-            <BLANKLINE>
++            masked_array(
++              data=[[1.0, 1.0],
++                    [0.5403023058681398, 0.5403023058681398]],
++              mask=[[False, False],
++                    [False, False]],
++              fill_value=1e+20)
+ 
+         TESTS:
+ 
+diff --git a/src/sage/probability/probability_distribution.pyx b/src/sage/probability/probability_distribution.pyx
+index f66cd898b9..35995886d5 100644
+--- a/src/sage/probability/probability_distribution.pyx
++++ b/src/sage/probability/probability_distribution.pyx
+@@ -130,7 +130,17 @@ cdef class ProbabilityDistribution:
+              0.0,
+              1.4650000000000003]
+             sage: b
+-            [0.0, 0.20000000000000001, 0.40000000000000002, 0.60000000000000009, 0.80000000000000004, 1.0, 1.2000000000000002, 1.4000000000000001, 1.6000000000000001, 1.8, 2.0]
++            [0.0,
++             0.2,
++             0.4,
++             0.6000000000000001,
++             0.8,
++             1.0,
++             1.2000000000000002,
++             1.4000000000000001,
++             1.6,
++             1.8,
++             2.0]
+         """
+         import pylab
+         l = [float(self.get_random_element()) for _ in range(num_samples)]
+diff --git a/src/sage/rings/rational.pyx b/src/sage/rings/rational.pyx
+index a0bfe080f5..7d95e7a1a8 100644
+--- a/src/sage/rings/rational.pyx
++++ b/src/sage/rings/rational.pyx
+@@ -1056,7 +1056,7 @@ cdef class Rational(sage.structure.element.FieldElement):
+             dtype('O')
+ 
+             sage: numpy.array([1, 1/2, 3/4])
+-            array([ 1.  ,  0.5 ,  0.75])
++            array([1.  , 0.5 , 0.75])
+         """
+         if mpz_cmp_ui(mpq_denref(self.value), 1) == 0:
+             if mpz_fits_slong_p(mpq_numref(self.value)):
+diff --git a/src/sage/rings/real_mpfr.pyx b/src/sage/rings/real_mpfr.pyx
+index 4c630867a4..64e2187f5b 100644
+--- a/src/sage/rings/real_mpfr.pyx
++++ b/src/sage/rings/real_mpfr.pyx
+@@ -1438,7 +1438,7 @@ cdef class RealNumber(sage.structure.element.RingElement):
+ 
+             sage: import numpy
+             sage: numpy.arange(10.0)
+-            array([ 0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9.])
++            array([0., 1., 2., 3., 4., 5., 6., 7., 8., 9.])
+             sage: numpy.array([1.0, 1.1, 1.2]).dtype
+             dtype('float64')
+             sage: numpy.array([1.000000000000000000000000000000000000]).dtype
+diff --git a/src/sage/schemes/elliptic_curves/height.py b/src/sage/schemes/elliptic_curves/height.py
+index 3d270ebf9d..1144f168e3 100644
+--- a/src/sage/schemes/elliptic_curves/height.py
++++ b/src/sage/schemes/elliptic_curves/height.py
+@@ -1623,18 +1623,18 @@ class EllipticCurveCanonicalHeight:
+         even::
+ 
+             sage: H.wp_on_grid(v,4)
+-            array([[ 25.43920182,   5.28760943,   5.28760943,  25.43920182],
+-            [  6.05099485,   1.83757786,   1.83757786,   6.05099485],
+-            [  6.05099485,   1.83757786,   1.83757786,   6.05099485],
+-            [ 25.43920182,   5.28760943,   5.28760943,  25.43920182]])
++            array([[25.43920182,  5.28760943,  5.28760943, 25.43920182],
++                   [ 6.05099485,  1.83757786,  1.83757786,  6.05099485],
++                   [ 6.05099485,  1.83757786,  1.83757786,  6.05099485],
++                   [25.43920182,  5.28760943,  5.28760943, 25.43920182]])
+ 
+         The array of values on the half-grid::
+ 
+             sage: H.wp_on_grid(v,4,True)
+-            array([[ 25.43920182,   5.28760943],
+-            [  6.05099485,   1.83757786],
+-            [  6.05099485,   1.83757786],
+-            [ 25.43920182,   5.28760943]])
++            array([[25.43920182,  5.28760943],
++                   [ 6.05099485,  1.83757786],
++                   [ 6.05099485,  1.83757786],
++                   [25.43920182,  5.28760943]])
+         """
+         tau = self.tau(v)
+         fk, err = self.fk_intervals(v, 15, CDF)
+diff --git a/src/sage/symbolic/ring.pyx b/src/sage/symbolic/ring.pyx
+index 2dcb0492b9..2b1a06385c 100644
+--- a/src/sage/symbolic/ring.pyx
++++ b/src/sage/symbolic/ring.pyx
+@@ -1135,7 +1135,7 @@ cdef class NumpyToSRMorphism(Morphism):
+         sage: cos(numpy.int('2'))
+         cos(2)
+         sage: numpy.cos(numpy.int('2'))
+-        -0.41614683654714241
++        -0.4161468365471424
+     """
+     cdef _intermediate_ring
+ 
diff --git a/pkgs/applications/science/math/sage/patches/pari-stackwarn.patch b/pkgs/applications/science/math/sage/patches/pari-stackwarn.patch
new file mode 100644
index 00000000000..49cdfd189b9
--- /dev/null
+++ b/pkgs/applications/science/math/sage/patches/pari-stackwarn.patch
@@ -0,0 +1,20 @@
+diff --git a/src/sage/doctest/parsing.py b/src/sage/doctest/parsing.py
+index 6bdc9a0..31fc780 100644
+--- a/src/sage/doctest/parsing.py
++++ b/src/sage/doctest/parsing.py
+@@ -40,6 +40,7 @@ from .external import available_software
+ 
+ float_regex = re.compile('\s*([+-]?\s*((\d*\.?\d+)|(\d+\.?))([eE][+-]?\d+)?)')
+ optional_regex = re.compile(r'(py2|py3|long time|not implemented|not tested|known bug)|([^ a-z]\s*optional\s*[:-]*((\s|\w)*))')
++pari_stack_warning_regex = re.compile(r'\s*\*\*\*.*(Warning: increasing stack size to )\d+\.')
+ find_sage_prompt = re.compile(r"^(\s*)sage: ", re.M)
+ find_sage_continuation = re.compile(r"^(\s*)\.\.\.\.:", re.M)
+ random_marker = re.compile('.*random', re.I)
+@@ -935,6 +936,7 @@ class SageOutputChecker(doctest.OutputChecker):
+             <type 'float'>
+         """
+         got = self.human_readable_escape_sequences(got)
++        got = pari_stack_warning_regex.sub('', got)
+         if isinstance(want, MarkedOutput):
+             if want.random:
+                 return True
diff --git a/pkgs/applications/science/math/sage/patches/python-5755-hotpatch.patch b/pkgs/applications/science/math/sage/patches/python-5755-hotpatch.patch
new file mode 100644
index 00000000000..1b64f39fe60
--- /dev/null
+++ b/pkgs/applications/science/math/sage/patches/python-5755-hotpatch.patch
@@ -0,0 +1,28 @@
+diff --git a/src/sage/all.py b/src/sage/all.py
+index ca309ef..be3186b 100644
+--- a/src/sage/all.py
++++ b/src/sage/all.py
+@@ -298,6 +298,23 @@ warnings.filterwarnings('ignore', module='matplotlib[.]font_manager')
+ warnings.filterwarnings('default',
+     '[\s\S]*See http://trac.sagemath.org/[0-9]* for details.')
+ 
++# Hotpatch around https://bugs.python.org/issue5755 which won't be fixed for
++# python 2.7. Idea by https://stackoverflow.com/a/36293331.
++from distutils.command.build_ext import build_ext
++from distutils.sysconfig import customize_compiler
++
++_build_extensions = build_ext.build_extensions
++
++def build_extensions_patched(self):
++    customize_compiler(self.compiler)
++    try:
++        self.compiler.compiler_so.remove("-Wstrict-prototypes")
++    except (AttributeError, ValueError):
++        pass
++    _build_extensions(self)
++
++build_ext.build_extensions = build_extensions_patched
++
+ 
+ # Set a new random number seed as the very last thing
+ # (so that printing initial_seed() and using that seed
diff --git a/pkgs/applications/science/math/sage/patches/python3-syntax-without-write.patch b/pkgs/applications/science/math/sage/patches/python3-syntax-without-write.patch
new file mode 100644
index 00000000000..ff1dcd22acf
--- /dev/null
+++ b/pkgs/applications/science/math/sage/patches/python3-syntax-without-write.patch
@@ -0,0 +1,40 @@
+diff --git a/src/sage/tests/py3_syntax.py b/src/sage/tests/py3_syntax.py
+index e564860b48..86ab3725f9 100644
+--- a/src/sage/tests/py3_syntax.py
++++ b/src/sage/tests/py3_syntax.py
+@@ -179,15 +179,30 @@ class Python3SyntaxTest(SortedDirectoryWalkerABC):
+             sage: py3_syntax = Python3SyntaxTest()
+             sage: py3_syntax.test(src.name)
+             Invalid Python 3 syntax found:
+-              File "...py", line 1
+-                print "invalid print statement"
+-                                              ^
+-            SyntaxError: Missing parentheses in call to 'print'
++            Missing parentheses in call to 'print'...
+             sage: os.unlink(src.name)
+         """
++
++        # compile all given files in memory, printing all errors
++        # inspired by the py_compile module (but without writing to file)
++        script = """
++import sys
++import importlib.machinery
++rv = 0
++for file in sys.argv[1:]:
++    loader = importlib.machinery.SourceFileLoader('<sage_test>', file)
++    source_bytes = loader.get_data(file)
++    try:
++        code = loader.source_to_code(source_bytes, file)
++    except Exception as err:
++        print(err)
++        rv = 1
++sys.exit(rv)
++"""
+         cmd = [
+             'python3',
+-            '-m', 'py_compile'
++            '-c',
++            script,
+         ] + list(filenames)
+         process = subprocess.Popen(
+             cmd,
diff --git a/pkgs/applications/science/math/sage/patches/revert-269c1e1551285.patch b/pkgs/applications/science/math/sage/patches/revert-269c1e1551285.patch
new file mode 100644
index 00000000000..b57e48b86de
--- /dev/null
+++ b/pkgs/applications/science/math/sage/patches/revert-269c1e1551285.patch
@@ -0,0 +1,14 @@
+reverted:
+--- b/src/sage/geometry/polyhedron/backend_cdd.py
++++ a/src/sage/geometry/polyhedron/backend_cdd.py
+@@ -154,7 +154,9 @@
+             ...    [0.62, -1.38, 0.38],[0.144, -1.04, 0.04],
+             ...    [0.1309090909, -1.0290909091, 0.04]]
+             sage: Polyhedron(point_list)
++            Traceback (most recent call last):
++            ...
++            ValueError: *Error: Numerical inconsistency is found.  Use the GMP exact arithmetic.
+-            A 3-dimensional polyhedron in RDF^3 defined as the convex hull of 14 vertices
+             sage: Polyhedron(point_list, base_ring=QQ)
+             A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 14 vertices
+         """
diff --git a/pkgs/applications/science/math/sage/patches/sagenb-sphinx-1.7.patch b/pkgs/applications/science/math/sage/patches/sagenb-sphinx-1.7.patch
new file mode 100644
index 00000000000..42deef4eab0
--- /dev/null
+++ b/pkgs/applications/science/math/sage/patches/sagenb-sphinx-1.7.patch
@@ -0,0 +1,31 @@
+From 7419e0246230594ebfd5e7a2fe6b80d67abfc98a Mon Sep 17 00:00:00 2001
+From: Jeroen Demeyer <jdemeyer@cage.ugent.be>
+Date: Tue, 20 Mar 2018 10:40:41 +0100
+Subject: Fix sphinxify doctests
+
+---
+ sagenb/misc/sphinxify.py | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/sagenb/misc/sphinxify.py b/sagenb/misc/sphinxify.py
+index 4f76d41..15623d9 100644
+--- a/sagenb/misc/sphinxify.py
++++ b/sagenb/misc/sphinxify.py
+@@ -47,11 +47,11 @@ def sphinxify(docstring, format='html'):
+ 
+         sage: from sage.misc.sphinxify import sphinxify
+         sage: sphinxify('A test')
+-        '...<div class="docstring">\n    \n  <p>A test</p>\n\n\n</div>'
++        '<div class="docstring">\n    \n  <p>A test</p>\n\n\n</div>'
+         sage: sphinxify('**Testing**\n`monospace`')
+-        '...<div class="docstring"...<strong>Testing</strong>\n<span class="math"...</p>\n\n\n</div>'
++        '<div class="docstring"...<strong>Testing</strong>\n<span class="math notranslate"...</p>\n\n\n</div>'
+         sage: sphinxify('`x=y`')
+-        '...<div class="docstring">\n    \n  <p><span class="math">x=y</span></p>\n\n\n</div>'
++        '<div class="docstring">\n    \n  <p><span class="math notranslate">x=y</span></p>\n\n\n</div>'
+         sage: sphinxify('`x=y`', format='text')
+         'x=y\n'
+         sage: sphinxify(':math:`x=y`', format='text')
+-- 
+cgit v1.0-1-gd88e
+
diff --git a/pkgs/applications/science/math/sage/patches/sphinx-1.7.patch b/pkgs/applications/science/math/sage/patches/sphinx-1.7.patch
new file mode 100644
index 00000000000..c67b8942e28
--- /dev/null
+++ b/pkgs/applications/science/math/sage/patches/sphinx-1.7.patch
@@ -0,0 +1,62 @@
+diff --git a/src/bin/sage b/src/bin/sage
+index 397f30cbed..3fc473c343 100755
+--- a/src/bin/sage
++++ b/src/bin/sage
+@@ -980,8 +980,11 @@ if [ "$1" = '-rsyncdist' -o "$1" = "--rsyncdist" ]; then
+ fi
+ 
+ if [ "$1" = "-docbuild" -o "$1" = "--docbuild" ]; then
++    # Redirect stdin from /dev/null. This helps with running TeX which
++    # tends to ask interactive questions if something goes wrong. These
++    # cause the build to hang. If stdin is /dev/null, TeX just aborts.
+     shift
+-    exec sage-python23 -m "sage_setup.docbuild" "$@"
++    exec sage-python23 -m sage_setup.docbuild "$@" </dev/null
+ fi
+ 
+ if [ "$1" = '-gdb' -o "$1" = "--gdb" ]; then
+diff --git a/src/doc/common/conf.py b/src/doc/common/conf.py
+index 25f94f7b7d..3f07474d9b 100644
+--- a/src/doc/common/conf.py
++++ b/src/doc/common/conf.py
+@@ -627,7 +627,7 @@ def call_intersphinx(app, env, node, contnode):
+         sage: for line in open(thematic_index).readlines():
+         ....:     if "padics" in line:
+         ....:         sys.stdout.write(line)
+-        <li><a class="reference external" href="../reference/padics/sage/rings/padics/tutorial.html#sage-rings-padics-tutorial" title="(in Sage Reference Manual: p-Adics ...)"><span>Introduction to the -adics</span></a></li>
++        <li><a class="reference external" href="../reference/padics/sage/rings/padics/tutorial.html#sage-rings-padics-tutorial" title="(in Sage Reference Manual: p-Adics v...)"><span>Introduction to the -adics</span></a></li>
+     """
+     debug_inf(app, "???? Trying intersphinx for %s"%node['reftarget'])
+     builder = app.builder
+diff --git a/src/sage/misc/sphinxify.py b/src/sage/misc/sphinxify.py
+index 4f76d4113a..8f426b5989 100644
+--- a/src/sage/misc/sphinxify.py
++++ b/src/sage/misc/sphinxify.py
+@@ -47,11 +47,11 @@ def sphinxify(docstring, format='html'):
+ 
+         sage: from sage.misc.sphinxify import sphinxify
+         sage: sphinxify('A test')
+-        '...<div class="docstring">\n    \n  <p>A test</p>\n\n\n</div>'
++        '<div class="docstring">\n    \n  <p>A test</p>\n\n\n</div>'
+         sage: sphinxify('**Testing**\n`monospace`')
+-        '...<div class="docstring"...<strong>Testing</strong>\n<span class="math"...</p>\n\n\n</div>'
++        '<div class="docstring"...<strong>Testing</strong>\n<span class="math...</p>\n\n\n</div>'
+         sage: sphinxify('`x=y`')
+-        '...<div class="docstring">\n    \n  <p><span class="math">x=y</span></p>\n\n\n</div>'
++        '<div class="docstring">\n    \n  <p><span class="math notranslate nohighlight">x=y</span></p>\n\n\n</div>'
+         sage: sphinxify('`x=y`', format='text')
+         'x=y\n'
+         sage: sphinxify(':math:`x=y`', format='text')
+diff --git a/src/sage_setup/docbuild/sphinxbuild.py b/src/sage_setup/docbuild/sphinxbuild.py
+index fda76a4174..d3413239dd 100644
+--- a/src/sage_setup/docbuild/sphinxbuild.py
++++ b/src/sage_setup/docbuild/sphinxbuild.py
+@@ -207,7 +207,7 @@ def runsphinx():
+     try:
+         sys.stdout = SageSphinxLogger(sys.stdout, os.path.basename(output_dir))
+         sys.stderr = SageSphinxLogger(sys.stderr, os.path.basename(output_dir))
+-        sphinx.cmdline.main(sys.argv)
++        sphinx.cmdline.main(sys.argv[1:])
+     finally:
+         sys.stdout = saved_stdout
+         sys.stderr = saved_stderr
diff --git a/pkgs/applications/science/math/sage/patches/zn_poly_version.patch b/pkgs/applications/science/math/sage/patches/zn_poly_version.patch
new file mode 100644
index 00000000000..92ea4303e47
--- /dev/null
+++ b/pkgs/applications/science/math/sage/patches/zn_poly_version.patch
@@ -0,0 +1,13 @@
+diff --git a/src/sage/misc/package.py b/src/sage/misc/package.py
+index 7ff4f21675..1d72168833 100644
+--- a/src/sage/misc/package.py
++++ b/src/sage/misc/package.py
+@@ -350,7 +350,7 @@ def package_versions(package_type, local=False):
+         sage: 'gap' in std
+         True
+         sage: std['zn_poly']
+-        ('0.9.p11', '0.9.p11')
++        ('0.9', '0.9.p11')
+     """
+     return {pkg['name']: (pkg['installed_version'], pkg['remote_version']) for pkg in list_packages(package_type, local=local).values()}
+ 
diff --git a/pkgs/applications/science/math/sage/pybrial.nix b/pkgs/applications/science/math/sage/pybrial.nix
new file mode 100644
index 00000000000..f5cb39603c3
--- /dev/null
+++ b/pkgs/applications/science/math/sage/pybrial.nix
@@ -0,0 +1,29 @@
+{ stdenv
+, fetchFromGitHub
+, buildPythonPackage
+}:
+# This has a cyclic dependency with sage. I don't include sage in the
+# buildInputs and let python figure it out at runtime. Because of this,
+# I don't include the package in the main nipxkgs tree. It wouldn't be useful
+# outside of sage anyways (as you could just directly depend on sage and use
+# it).
+buildPythonPackage rec {
+    pname = "pyBRiAl";
+    version = "1.2.3";
+
+    # included with BRiAl source
+    src = fetchFromGitHub {
+      owner = "BRiAl";
+      repo = "BRiAl";
+      rev = "${version}";
+      sha256 = "0qy4cwy7qrk4zg151cmws5cglaa866z461cnj9wdnalabs7v7qbg";
+    };
+
+    sourceRoot = "source/sage-brial";
+
+    meta = with stdenv.lib; {
+      description = "python implementation of BRiAl";
+      license = licenses.gpl2;
+      maintainers = with maintainers; [ timokau ];
+    };
+}
diff --git a/pkgs/applications/science/math/sage/python-openid.nix b/pkgs/applications/science/math/sage/python-openid.nix
new file mode 100644
index 00000000000..184eaf29bdd
--- /dev/null
+++ b/pkgs/applications/science/math/sage/python-openid.nix
@@ -0,0 +1,42 @@
+{ stdenv
+, buildPythonPackage
+, fetchPypi
+, isPy3k
+, django
+, nose
+, twill
+, pycrypto
+}:
+
+buildPythonPackage rec {
+  pname = "python-openid";
+  version = "2.2.5";
+
+  disabled = isPy3k;
+
+  src = fetchPypi {
+    inherit pname version;
+    sha256 = "1vvhxlghjan01snfdc4k7ykd80vkyjgizwgg9bncnin8rqz1ricj";
+  };
+
+  propagatedBuildInputs = [
+    django
+    twill
+    pycrypto
+  ];
+
+  # Cannot access the djopenid example module.
+  # I don't know how to fix that (adding the examples dir to PYTHONPATH doesn't work)
+  doCheck = false;
+  checkInputs = [ nose ];
+  checkPhase = ''
+    nosetests
+  '';
+
+  meta = with stdenv.lib; {
+    description = "OpenID library for Python";
+    license = licenses.asl20;
+    maintainers = with maintainers; [ timokau ];
+    homepage = https://github.com/openid/python-openid/;
+  };
+}
diff --git a/pkgs/applications/science/math/sage/sage-env.nix b/pkgs/applications/science/math/sage/sage-env.nix
new file mode 100644
index 00000000000..317eb6e16c4
--- /dev/null
+++ b/pkgs/applications/science/math/sage/sage-env.nix
@@ -0,0 +1,162 @@
+{ stdenv
+, lib
+, writeTextFile
+, python
+, sage-src
+, sagelib
+, env-locations
+, gfortran
+, bash
+, coreutils
+, gnused
+, gnugrep
+, binutils
+, pythonEnv
+, python3
+, pkg-config
+, pari
+, gap-libgap-compatible
+, libgap
+, ecl
+, maxima-ecl
+, singular
+, giac
+, palp
+, rWrapper
+, gfan
+, cddlib
+, jmol
+, tachyon
+, glpk
+, eclib
+, sympow
+, nauty
+, sqlite
+, ppl
+, ecm
+, lcalc
+, rubiks
+, flintqs
+, openblas-cblas-pc
+, flint
+, gmp
+, mpfr
+, pynac
+, zlib
+, gsl
+, ntl
+}:
+
+let
+  runtimepath = (lib.makeBinPath ([
+    "@sage-local@"
+    "@sage-local@/build"
+    pythonEnv
+    # empty python env to add python wrapper that clears PYTHONHOME (see
+    # wrapper.nix). This is necessary because sage will call the python3 binary
+    # (from python2 code). The python2 PYTHONHOME (again set in wrapper.nix)
+    # will then confuse python3, if it is not overwritten.
+    python3.buildEnv
+    gfortran # for inline fortran
+    stdenv.cc # for cython
+    bash
+    coreutils
+    gnused
+    gnugrep
+    binutils.bintools
+    pkg-config
+    pari
+    gap-libgap-compatible
+    libgap
+    ecl
+    maxima-ecl
+    singular
+    giac
+    palp
+    rWrapper
+    gfan
+    cddlib
+    jmol
+    tachyon
+    glpk
+    eclib
+    sympow
+    nauty
+    sqlite
+    ppl
+    ecm
+    lcalc
+    rubiks
+    flintqs
+  ]
+  ));
+in
+writeTextFile rec {
+  name = "sage-env";
+  destination = "/${name}";
+  text = ''
+    export PKG_CONFIG_PATH='${lib.concatStringsSep ":" (map (pkg: "${pkg}/lib/pkgconfig") [
+        # This is only needed in the src/sage/misc/cython.py test and I'm not sure if there's really a use-case
+        # for it outside of the tests. However since singular and openblas are runtime dependencies anyways
+        # and openblas-cblas-pc is tiny, it doesn't really hurt to include.
+        singular
+        openblas-cblas-pc
+      ])
+    }'
+    export SAGE_ROOT='${sage-src}'
+    export SAGE_LOCAL='@sage-local@'
+    export SAGE_SHARE='${sagelib}/share'
+    orig_path="$PATH"
+    export PATH='${runtimepath}'
+
+    # set dependent vars, like JUPYTER_CONFIG_DIR
+    source "${sage-src}/src/bin/sage-env"
+    export PATH="${runtimepath}:$orig_path" # sage-env messes with PATH
+
+    export SAGE_LOGS="$TMPDIR/sage-logs"
+    export SAGE_DOC="''${SAGE_DOC_OVERRIDE:-doc-placeholder}"
+    export SAGE_DOC_SRC="''${SAGE_DOC_SRC_OVERRIDE:-${sage-src}/src/doc}"
+
+    # set locations of dependencies
+    . ${env-locations}/sage-env-locations
+
+    # needed for cython
+    export CC='${stdenv.cc}/bin/${stdenv.cc.targetPrefix}cc'
+    # cython needs to find these libraries, otherwise will fail with `ld: cannot find -lflint` or similar
+    export LDFLAGS='${
+      lib.concatStringsSep " " (map (pkg: "-L${pkg}/lib") [
+        flint
+        libgap
+        glpk
+        gmp
+        mpfr
+        pari
+        pynac
+        zlib
+        eclib
+        gsl
+        ntl
+        jmol
+        sympow
+      ])
+    }'
+    export CFLAGS='${
+      lib.concatStringsSep " " (map (pkg: "-isystem ${pkg}/include") [
+        singular
+        gmp.dev
+        glpk
+        flint
+        libgap
+        pynac
+        mpfr.dev
+      ])
+    }'
+
+    export SAGE_LIB='${sagelib}/${python.sitePackages}'
+
+    export SAGE_EXTCODE='${sage-src}/src/ext'
+
+    # for find_library
+    export DYLD_LIBRARY_PATH="${lib.makeLibraryPath [stdenv.cc.libc singular]}:$DYLD_LIBRARY_PATH"
+  '';
+}
diff --git a/pkgs/applications/science/math/sage/sage-src.nix b/pkgs/applications/science/math/sage/sage-src.nix
new file mode 100644
index 00000000000..44b81794467
--- /dev/null
+++ b/pkgs/applications/science/math/sage/sage-src.nix
@@ -0,0 +1,197 @@
+{ stdenv
+, fetchFromGitHub
+, fetchpatch
+}:
+stdenv.mkDerivation rec {
+  version = "8.2";
+  name = "sage-src-${version}";
+
+  src = fetchFromGitHub {
+    owner = "sagemath";
+    repo = "sage";
+    rev = version;
+    sha256 = "0d7vc16s7dj23an2cb8v5bhbnc6nsw20qhnnxr0xh8qg629027b8";
+  };
+
+  nixPatches = [
+    # https://trac.sagemath.org/ticket/25309
+    (fetchpatch {
+      name = "spkg-paths.patch";
+      url = "https://git.sagemath.org/sage.git/patch/?h=97f06fddee920399d4fcda65aa9b0925774aec69&id=a86151429ccce1ddd085e8090ada8ebdf02f3310";
+      sha256 = "1xb9108rzzkdhn71vw44525620d3ww9jv1fph5a77v9y7nf9wgr7";
+    })
+    (fetchpatch {
+      name = "maxima-fas.patch";
+      url = "https://git.sagemath.org/sage.git/patch/?h=97f06fddee920399d4fcda65aa9b0925774aec69";
+      sha256 = "14s50yg3hpw9cp3v581dx7zfmpm2j972im7x30iwki8k45mjvk3i";
+    })
+
+    # https://trac.sagemath.org/ticket/25328
+    (fetchpatch {
+      name = "respect-jupyter-path.patch";
+      url = "https://git.sagemath.org/sage.git/patch?id2=8bdc326ba57d1bb9664f63cf165a9e9920cc1afc&id=029123097d79f2c67bca2d725c470ef667a88ca2";
+      sha256 = "0qw9p541ip0kn2gfvn4i05a06p50f3q46847gqfjjgzxhn62znfw";
+    })
+
+    # https://trac.sagemath.org/ticket/25358
+    (fetchpatch {
+      name = "safe-directory-test-without-patch.patch";
+      url = "https://git.sagemath.org/sage.git/patch?id2=8bdc326ba57d1bb9664f63cf165a9e9920cc1afc&id=dc673c17555efca611f68398d5013b66e9825463";
+      sha256 = "1hhannz7xzprijakn2w2d0rhd5zv2zikik9p51i87bas3nc658f7";
+    })
+
+    # https://trac.sagemath.org/ticket/25357 rebased on 8.2
+    ./patches/python3-syntax-without-write.patch
+
+    # https://trac.sagemath.org/ticket/25314
+    (fetchpatch {
+      name = "make-qepcad-test-optional.patch";
+      url = "https://git.sagemath.org/sage.git/patch/?h=fe294c58bd035ef427e268901d54a6faa0058138";
+      sha256 = "003d5baf5c0n5rfg010ijwkwz8kg0s414cxwczs2vhdayxdixbix";
+    })
+
+    # https://trac.sagemath.org/ticket/25316
+    ./patches/python-5755-hotpatch.patch
+
+    # https://trac.sagemath.org/ticket/25354
+    # https://trac.sagemath.org/ticket/25531
+    (fetchpatch {
+      name = "cysignals-include.patch";
+      url = "https://git.sagemath.org/sage.git/patch/?h=28778bd25a37c80884d2b24e0683fb2989300cef";
+      sha256 = "0fiiiw91pgs8avm9ggj8hb64bhqzl6jcw094d94nhirmh8w2jmc5";
+    })
+
+    # https://trac.sagemath.org/ticket/25315
+    (fetchpatch {
+      name = "find-libraries-in-dyld-library-path.patch";
+      url = "https://git.sagemath.org/sage.git/patch/?h=20d4593876ce9c6004eac2ab6fd61786d0d96a06";
+      sha256 = "1k3afq3qlzmgqwx6rzs5wv153vv9dsf5rk8pi61g57l3r3npbjmc";
+    })
+
+    # Pari upstream has since accepted a patch, so this patch won't be necessary once sage updates pari.
+    # https://trac.sagemath.org/ticket/25312
+    ./patches/pari-stackwarn.patch
+
+    # https://trac.sagemath.org/ticket/25311
+    ./patches/zn_poly_version.patch
+
+    # https://trac.sagemath.org/ticket/25345
+    # (upstream patch doesn't apply on 8.2 source)
+    ./patches/dochtml-optional.patch
+  ];
+
+  packageUpgradePatches = [
+    # matplotlib 2.2.2 deprecated `normed` (replaced by `density`).
+    # This patch only ignores the warning. It would be equally easy to fix it
+    # (by replacing all mentions of `normed` by `density`), but its better to
+    # stay close to sage upstream. I didn't open an upstream ticket about it
+    # because the matplotlib update also requires a new dependency (kiwisolver)
+    # and I don't want to invest the time to learn how to add it.
+    ./patches/matplotlib-normed-deprecated.patch
+
+    # Update to 20171219 broke the doctests because of insignificant precision
+    # changes, make the doctests less fragile.
+    # I didn't open an upstream ticket because its not entirely clear if
+    # 20171219 is really "released" yet. It is listed on the github releases
+    # page, but not marked as "latest release" and the homepage still links to
+    # the last version.
+    ./patches/eclib-regulator-precision.patch
+
+    # sphinx 1.6 -> 1.7 upgrade
+    # https://trac.sagemath.org/ticket/24935
+    ./patches/sphinx-1.7.patch
+
+    # https://trac.sagemath.org/ticket/25320
+    (fetchpatch {
+      name = "zero_division_error_formatting.patch";
+      url = "https://git.sagemath.org/sage.git/patch/?h=f79070ddd09fa0ad6b340b097bd8d690a7aa35f0";
+      sha256 = "02wsc3wbp8g8dk5jcjyv18d9v537h3zp5v8lwir46j4na4kj0dlb";
+    })
+
+    # Adapt hashes to new boost version
+    # https://trac.sagemath.org/ticket/22243
+    # (this ticket doesn't only upgrade boost but also avoids this problem in the future)
+    (fetchpatch {
+      name = "boost-upgrade.patch";
+      url = "https://git.sagemath.org/sage.git/patch?id=a24a9c6b30b93957333a3116196214a931325b69";
+      sha256 = "0z3870g2ms2a81vnw08dc2i4k7jr62w8fggvcdwaavgd1wvdxwfl";
+    })
+
+    # gfan 0.6.2
+    # https://trac.sagemath.org/ticket/23353
+    (fetchpatch {
+      name = "gfan-update.patch";
+      url = "https://git.sagemath.org/sage.git/patch/?h=420215fc469cde733ec7a339e59b78ad6eec804c&id=112498a293ea2bf563e41aed35f1aa608f01b349";
+      sha256 = "0ga3hkx8cr23dpc919lgvpi5lmy0d728jkq9z6kf0fl9s8g31mxb";
+    })
+
+    # New glpk version has new warnings, filter those out until upstream sage has found a solution
+    # https://trac.sagemath.org/ticket/24824
+    (fetchpatch {
+      url = "https://salsa.debian.org/science-team/sagemath/raw/58bbba93a807ca2933ca317501d093a1bb4b84db/debian/patches/dt-version-glpk-4.65-ignore-warnings.patch";
+      sha256 = "0b9293v73wb4x13wv5zwyjgclc01zn16msccfzzi6znswklgvddp";
+      stripLen = 1;
+    })
+
+    # https://trac.sagemath.org/ticket/25329
+    (fetchpatch {
+      name = "dont-check-exact-glpk-version.patch";
+      url = "https://git.sagemath.org/sage.git/patch?id2=8bdc326ba57d1bb9664f63cf165a9e9920cc1afc&id=89d068d8d77316bfffa6bf8e9ebf70b3b3b88e5c";
+      sha256 = "00knwxs6fmymfgfl0q5kcavmxm9sf90a4r76y35n5s55gj8pl918";
+    })
+
+    # https://trac.sagemath.org/ticket/25355
+    (fetchpatch {
+      name = "maxima-5.41.0.patch";
+      url = "https://git.sagemath.org/sage.git/patch/?id=87328023c4739abdf24108038201e3fa9bdfc739";
+      sha256 = "0hxi7qr5mfx1bc32r8j7iba4gzd7c6v63asylyf5cbyp86azpb7i";
+    })
+
+    # Update cddlib from 0.94g to 0.94h.
+    # https://trac.sagemath.org/ticket/25341 (doesn't apply to 8.2 sources)
+    (fetchpatch {
+      url = "https://salsa.debian.org/science-team/sagemath/raw/58bbba93a807ca2933ca317501d093a1bb4b84db/debian/patches/u2-version-cddlib-094h.patch";
+      sha256 = "0fmw7pzbaxs2dshky6iw9pr8i23p9ih2y2lw661qypdrxh5xw03k";
+      stripLen = 1;
+    })
+    ./patches/revert-269c1e1551285.patch
+
+
+    # Only formatting changes.
+    # https://trac.sagemath.org/ticket/25260
+    ./patches/numpy-1.14.3.patch
+
+    # https://trac.sagemath.org/ticket/24374
+    (fetchpatch {
+      name = "networkx-2.1.patch";
+      url = "https://salsa.debian.org/science-team/sagemath/raw/487df9ae48ca1d93d9b1cb3af8745d31e30fb741/debian/patches/u0-version-networkx-2.1.patch";
+      sha256 = "1xxxawygbgxgvlv7b4w8hhzgdnva4rhmgdxaiaa3pwdwln0yc750";
+      stripLen = 1;
+    })
+
+  ];
+
+  patches = nixPatches ++ packageUpgradePatches;
+
+  postPatch = ''
+    # make sure shebangs etc are fixed, but sage-python23 still works
+    find . -type f -exec sed \
+      -e 's/sage-python23/python/g' \
+      -i {} \;
+
+    echo '#!${stdenv.shell}
+    python "$@"' > build/bin/sage-python23
+
+    # Do not use sage-env-config (generated by ./configure).
+    # Instead variables are set manually.
+    echo '# do nothing' >  src/bin/sage-env-config
+  '';
+
+  configurePhase = "# do nothing";
+
+  buildPhase = "# do nothing";
+
+  installPhase = ''
+    cp -r . "$out"
+  '';
+}
diff --git a/pkgs/applications/science/math/sage/sage-with-env.nix b/pkgs/applications/science/math/sage/sage-with-env.nix
new file mode 100644
index 00000000000..3d1ebe87c6b
--- /dev/null
+++ b/pkgs/applications/science/math/sage/sage-with-env.nix
@@ -0,0 +1,129 @@
+{ stdenv
+, lib
+, makeWrapper
+, sage-env
+, sage-src
+, sagelib
+, sagedoc
+, openblasCompat
+, openblas-blas-pc
+, openblas-cblas-pc
+, openblas-lapack-pc
+, pkg-config
+, three
+, singular
+, libgap
+, gap-libgap-compatible
+, gcc
+, giac
+, maxima-ecl
+, pari
+, gmp
+, gfan
+, python2
+, flintqs
+, eclib
+, ntl
+, ecm
+, pynac
+, pythonEnv
+}:
+
+let
+  buildInputs = [
+    pythonEnv # for patchShebangs
+    makeWrapper
+    pkg-config
+    openblasCompat # lots of segfaults with regular (64 bit) openblas
+    openblas-blas-pc
+    openblas-cblas-pc
+    openblas-lapack-pc
+    singular
+    three
+    pynac
+    giac
+    libgap
+    gap-libgap-compatible
+    pari
+    gmp
+    gfan
+    maxima-ecl
+    eclib
+    flintqs
+    ntl
+    ecm
+  ];
+
+  # remove python prefix, replace "-" in the name by "_", apply patch_names
+  # python2.7-some-pkg-1.0 -> some_pkg-1.0
+  pkg_to_spkg_name = pkg: patch_names: let
+    parts = lib.splitString "-" pkg.name;
+    # remove python2.7-
+    stripped_parts = if (builtins.head parts) == python2.libPrefix then builtins.tail parts else parts;
+    version = lib.last stripped_parts;
+    orig_pkgname = lib.init stripped_parts;
+    pkgname = patch_names (lib.concatStringsSep "_" orig_pkgname);
+  in pkgname + "-" + version;
+
+
+  # return the names of all dependencies in the transitive closure
+  transitiveClosure = dep:
+  if isNull dep then
+    # propagatedBuildInputs might contain null
+    # (although that might be considered a programming error in the derivation)
+    []
+  else
+    [ dep ] ++ (
+      if builtins.hasAttr "propagatedBuildInputs" dep then
+        lib.unique (builtins.concatLists (map transitiveClosure dep.propagatedBuildInputs))
+      else
+      []
+    );
+
+  allInputs = lib.remove null (buildInputs ++ pythonEnv.extraLibs);
+  transitiveDeps = lib.unique (builtins.concatLists (map transitiveClosure allInputs ));
+  # fix differences between spkg and sage names
+  # (could patch sage instead, but this is more lightweight and also works for packages depending on sage)
+  patch_names = builtins.replaceStrings [
+    "zope.interface"
+    "node_three"
+  ] [
+    "zope_interface"
+    "threejs"
+  ];
+  # spkg names (this_is_a_package-version) of all transitive deps
+  input_names = map (dep: pkg_to_spkg_name dep patch_names) transitiveDeps;
+in
+stdenv.mkDerivation rec {
+  version = sage-src.version;
+  name = "sage-with-env-${version}";
+
+  inherit buildInputs;
+
+  src = sage-src;
+
+  configurePhase = "#do nothing";
+
+  buildPhase = ''
+    mkdir installed
+    for pkg in ${lib.concatStringsSep " " input_names}; do
+      touch "installed/$pkg"
+    done
+  '';
+
+  installPhase = ''
+    mkdir -p "$out/var/lib/sage"
+    cp -r installed $out/var/lib/sage
+
+    mkdir -p "$out/etc"
+    # sage tests will try to create this file if it doesn't exist
+    touch "$out/etc/sage-started.txt"
+
+    mkdir -p "$out/build"
+    cp -r src/bin "$out/bin"
+    cp -r build/bin "$out/build/bin"
+    cp -f '${sage-env}/sage-env' "$out/bin/sage-env"
+    substituteInPlace "$out/bin/sage-env" \
+      --subst-var-by sage-local "$out"
+  '';
+}
diff --git a/pkgs/applications/science/math/sage/sage-wrapper.nix b/pkgs/applications/science/math/sage/sage-wrapper.nix
new file mode 100644
index 00000000000..06b667f426f
--- /dev/null
+++ b/pkgs/applications/science/math/sage/sage-wrapper.nix
@@ -0,0 +1,41 @@
+{ stdenv
+, makeWrapper
+, sage
+, sage-src
+, sagedoc
+, withDoc
+}:
+
+stdenv.mkDerivation rec {
+  version = sage.version;
+  name = "sage-wrapper-${version}";
+
+  buildInputs = [
+    makeWrapper
+  ];
+
+  unpackPhase = "#do nothing";
+  configurePhase = "#do nothing";
+  buildPhase = "#do nothing";
+
+  installPhase = ''
+    mkdir -p "$out/bin"
+    makeWrapper "${sage}/bin/sage" "$out/bin/sage" \
+      --set SAGE_DOC_SRC_OVERRIDE "${sage-src}/src/doc" ${
+      stdenv.lib.optionalString withDoc "--set SAGE_DOC_OVERRIDE ${sagedoc}/share/doc/sage"
+    }
+  '';
+
+  doInstallCheck = withDoc;
+  installCheckPhase = ''
+    export HOME="$TMPDIR/sage-home"
+    mkdir -p "$HOME"
+    "$out/bin/sage" -c 'browse_sage_doc._open("reference", testing=True)'
+  '';
+
+  meta = with stdenv.lib; {
+    description = "Open Source Mathematics Software, free alternative to Magma, Maple, Mathematica, and Matlab";
+    license = licenses.gpl2;
+    maintainers = with maintainers; [ timokau ];
+  };
+}
diff --git a/pkgs/applications/science/math/sage/sage.nix b/pkgs/applications/science/math/sage/sage.nix
new file mode 100644
index 00000000000..b1e5d7278b0
--- /dev/null
+++ b/pkgs/applications/science/math/sage/sage.nix
@@ -0,0 +1,32 @@
+{ stdenv
+, sage-with-env
+, makeWrapper
+}:
+
+stdenv.mkDerivation rec {
+  version = sage-with-env.version;
+  name = "sage-${version}";
+
+  buildInputs = [
+    makeWrapper
+  ];
+
+  unpackPhase = "#do nothing";
+  configurePhase = "#do nothing";
+  buildPhase = "#do nothing";
+
+  installPhase = ''
+    mkdir -p "$out/bin"
+    # Like a symlink, but make sure that $0 points to the original.
+    makeWrapper "${sage-with-env}/bin/sage" "$out/bin/sage"
+  '';
+
+  doInstallCheck = true;
+  installCheckPhase = ''
+    export HOME="$TMPDIR/sage-home"
+    mkdir -p "$HOME"
+
+    # "--long" tests are in the order of 1h, without "--long" its 1/2h
+    "$out/bin/sage" -t --nthreads "$NIX_BUILD_CORES" --optional=sage --long --all
+  '';
+}
diff --git a/pkgs/applications/science/math/sage/sagedoc.nix b/pkgs/applications/science/math/sage/sagedoc.nix
new file mode 100644
index 00000000000..7b280e9e028
--- /dev/null
+++ b/pkgs/applications/science/math/sage/sagedoc.nix
@@ -0,0 +1,97 @@
+{ pkgs
+, stdenv
+, sage-src
+, env-locations
+, sage-with-env
+, sagelib
+, python2
+, psutil
+, future
+, sphinx
+, sagenb
+, maxima-ecl
+, networkx
+, scipy
+, sympy
+, matplotlib
+, pillow
+, ipykernel
+, jupyter_client
+, tachyon
+, jmol
+, ipywidgets
+, typing
+, cddlib
+, pybrial
+}:
+
+stdenv.mkDerivation rec {
+  version = sage-src.version;
+  name = "sagedoc-${version}";
+
+
+  # Building the documentation has many dependencies, because all documented
+  # modules are imported and because matplotlib is used to produce plots.
+  buildInputs = [
+    sagelib
+    python2
+    psutil
+    future
+    sphinx
+    sagenb
+    maxima-ecl
+    networkx
+    scipy
+    sympy
+    matplotlib
+    pillow
+    ipykernel
+    jupyter_client
+    tachyon
+    jmol
+    ipywidgets
+    typing
+    cddlib
+    pybrial
+  ];
+
+  unpackPhase = ''
+    export SAGE_DOC_OVERRIDE="$PWD/share/doc/sage"
+    export SAGE_DOC_SRC_OVERRIDE="$PWD/docsrc"
+
+    cp -r "${sage-src}/src/doc" "$SAGE_DOC_SRC_OVERRIDE"
+    chmod -R 755 "$SAGE_DOC_SRC_OVERRIDE"
+  '';
+
+  buildPhase = ''
+    export SAGE_NUM_THREADS="$NIX_BUILD_CORES"
+    export HOME="$TMPDIR/sage_home"
+    mkdir -p "$HOME"
+
+    ${sage-with-env}/bin/sage -python -m sage_setup.docbuild \
+      --mathjax \
+      --no-pdf-links \
+      all html
+  '';
+
+  installPhase = ''
+    cd "$SAGE_DOC_OVERRIDE"
+
+    mkdir -p "$out/share/doc/sage"
+    cp -r html "$out"/share/doc/sage
+
+    # Replace duplicated files by symlinks (Gentoo)
+    cd "$out"/share/doc/sage
+    mv html/en/_static{,.tmp}
+    for _dir in `find -name _static` ; do
+          rm -r $_dir
+          ln -s /share/doc/sage/html/en/_static $_dir
+    done
+    mv html/en/_static{.tmp,}
+  '';
+
+  doCheck = true;
+  checkPhase = ''
+    ${sage-with-env}/bin/sage -t --optional=dochtml --all
+  '';
+}
diff --git a/pkgs/applications/science/math/sage/sagelib.nix b/pkgs/applications/science/math/sage/sagelib.nix
new file mode 100644
index 00000000000..a053d997bf9
--- /dev/null
+++ b/pkgs/applications/science/math/sage/sagelib.nix
@@ -0,0 +1,139 @@
+{ stdenv
+, sage-src
+, perl
+, buildPythonPackage
+, arb
+, openblasCompat
+, openblas-blas-pc
+, openblas-cblas-pc
+, openblas-lapack-pc
+, brial
+, cliquer
+, cypari2
+, cysignals
+, cython
+, ecl
+, eclib
+, ecm
+, flint
+, gd
+, givaro
+, glpk
+, gsl
+, iml
+, jinja2
+, lcalc
+, lrcalc
+, libgap
+, linbox
+, m4ri
+, m4rie
+, libmpc
+, mpfi
+, ntl
+, numpy
+, pari
+, pkgconfig
+, planarity
+, ppl
+, pynac
+, python
+, ratpoints
+, readline
+, rankwidth
+, symmetrica
+, zn_poly
+, fflas-ffpack
+, boost
+, singular
+, pip
+, jupyter_core
+}:
+
+buildPythonPackage rec {
+  format = "other";
+  version = sage-src.version;
+  pname = "sagelib";
+
+  src = sage-src;
+
+  nativeBuildInputs = [
+    iml
+    perl
+    openblas-blas-pc
+    openblas-cblas-pc
+    openblas-lapack-pc
+    jupyter_core
+  ];
+
+  buildInputs = [
+    gd
+    readline
+  ];
+
+  propagatedBuildInputs = [
+    cypari2
+    jinja2
+    numpy
+    pkgconfig
+    boost
+    arb
+    brial
+    cliquer
+    ecl
+    eclib
+    ecm
+    fflas-ffpack
+    flint
+    givaro
+    glpk
+    gsl
+    lcalc
+    libgap
+    libmpc
+    linbox
+    lrcalc
+    m4ri
+    m4rie
+    mpfi
+    ntl
+    openblasCompat
+    pari
+    planarity
+    ppl
+    pynac
+    rankwidth
+    ratpoints
+    singular
+    symmetrica
+    zn_poly
+    pip
+    cython
+    cysignals
+  ];
+
+  buildPhase = ''
+    export SAGE_ROOT="$PWD"
+    export SAGE_LOCAL="$SAGE_ROOT"
+    export SAGE_SHARE="$SAGE_LOCAL/share"
+    export JUPYTER_PATH="$SAGE_LOCAL/jupyter"
+
+    export PATH="$SAGE_ROOT/build/bin:$SAGE_ROOT/src/bin:$PATH"
+
+    export SAGE_NUM_THREADS="$NIX_BUILD_CORES"
+
+    mkdir -p "$SAGE_SHARE/sage/ext/notebook-ipython"
+    mkdir -p "var/lib/sage/installed"
+
+    cd src
+    source bin/sage-dist-helpers
+
+    ${python.interpreter} -u setup.py --no-user-cfg build
+  '';
+
+  installPhase = ''
+    ${python.interpreter} -u setup.py --no-user-cfg install --prefix=$out
+
+    rm -r "$out/${python.sitePackages}/sage/cython_debug"
+  '';
+}
diff --git a/pkgs/applications/science/math/sage/sagenb.nix b/pkgs/applications/science/math/sage/sagenb.nix
new file mode 100644
index 00000000000..5ab387ebc5e
--- /dev/null
+++ b/pkgs/applications/science/math/sage/sagenb.nix
@@ -0,0 +1,49 @@
+# Has a cyclic dependency with sage (not expressed here) and is not useful outside of sage
+{ stdenv
+, fetchpatch
+, python
+, buildPythonPackage
+, fetchFromGitHub
+, mathjax
+, twisted
+, flask
+, flask-oldsessions
+, flask-openid
+, flask-autoindex
+, flask-babel
+}:
+
+buildPythonPackage rec {
+  pname = "sagenb";
+  version = "2018-06-26"; # not 1.0.1 because of new flask syntax
+
+  src = fetchFromGitHub {
+    owner = "sagemath";
+    repo = "sagenb";
+    rev = "b360a0172e15501fb0163d02dce713a561fee2af";
+    sha256 = "12anydw0v9w23rbc0a94bqmjhjdir9h820c5zdhipw9ccdcc2jlf";
+  };
+
+  propagatedBuildInputs = [
+    twisted
+    flask
+    flask-oldsessions
+    flask-openid
+    flask-autoindex
+    flask-babel
+  ];
+
+  # tests depend on sage
+  doCheck = false;
+
+  meta = with stdenv.lib; {
+    description = "Sage Notebook";
+    license = licenses.gpl3Plus;
+    maintainers = with maintainers; [ timokau ];
+  };
+
+  # let sagenb use mathjax
+  postInstall = ''
+    ln -s ${mathjax}/lib/node_modules/mathjax "$out/${python.sitePackages}/mathjax"
+  '';
+}
diff --git a/pkgs/applications/science/math/sage/shebangs.patch b/pkgs/applications/science/math/sage/shebangs.patch
deleted file mode 100644
index 96ed5a4bc6c..00000000000
--- a/pkgs/applications/science/math/sage/shebangs.patch
+++ /dev/null
@@ -1,36 +0,0 @@
-diff --git a/build/bin/sage-spkg b/build/bin/sage-spkg
-index 83e61a7e0d..942ba206c7 100755
---- a/build/bin/sage-spkg
-+++ b/build/bin/sage-spkg
-@@ -648,8 +648,12 @@ if ! sage-apply-patches; then
-     error_msg "Error applying patches"
-     exit 1
- fi
-+
-+@bash@/bin/bash @patchSageShebangs@ .
-+
- cd ..
- 
-+
- ##################################################################
- # The package has been extracted, prepare for installation
- ##################################################################
-@@ -671,7 +675,7 @@ write_script_wrapper() {
-     local tmpscript="$(dirname "$script")/.tmp-${script##*/}"
- 
-     cat > "$tmpscript" <<__EOF__
--#!/usr/bin/env bash
-+#! @bash@/bin/bash
- 
- export SAGE_ROOT="$SAGE_ROOT"
- export SAGE_SRC="$SAGE_SRC"
-@@ -833,6 +837,9 @@ if [ "$UNAME" = "CYGWIN" ]; then
-     sage-rebase.sh "$SAGE_LOCAL" 2>/dev/null
- fi
- 
-+@bash@/bin/bash @patchSageShebangs@ .
-+@bash@/bin/bash @patchSageShebangs@ "$out/bin"
-+
- echo "Successfully installed $PKG_NAME"
- 
- if [ "$SAGE_CHECK" = "yes" ]; then
diff --git a/pkgs/applications/science/math/sage/spkg-giac.patch b/pkgs/applications/science/math/sage/spkg-giac.patch
deleted file mode 100644
index c79d4422133..00000000000
--- a/pkgs/applications/science/math/sage/spkg-giac.patch
+++ /dev/null
@@ -1,20 +0,0 @@
-diff --git a/build/pkgs/giac/spkg-install b/build/pkgs/giac/spkg-install
-index bdd8df6cb8..3fd7a3ef8a 100644
---- a/build/pkgs/giac/spkg-install
-+++ b/build/pkgs/giac/spkg-install
-@@ -2,6 +2,15 @@
- ## Giac
- ###########################################
- 
-+# Fix hardcoded paths, while making sure to only update timestamps of actually
-+# changed files (otherwise confuses make)
-+grep -rlF '/bin/cp' . | while read file
-+do
-+	sed -e 's@/bin/cp@cp@g' -i "$file"
-+done
-+
-+# Fix input parser syntax
-+sed -e 's@yylex (&yylval)@yylex (\&yyval, scanner)@gp' -i 'src/src/input_parser.cc'
- 
- if [ "$SAGE_LOCAL" = "" ]; then
-    echo "SAGE_LOCAL undefined ... exiting";
diff --git a/pkgs/applications/science/math/sage/spkg-git.patch b/pkgs/applications/science/math/sage/spkg-git.patch
deleted file mode 100644
index 74f552dd3c3..00000000000
--- a/pkgs/applications/science/math/sage/spkg-git.patch
+++ /dev/null
@@ -1,18 +0,0 @@
-diff --git a/build/pkgs/git/spkg-install b/build/pkgs/git/spkg-install
-index 87874de3d8..b0906245fa 100644
---- a/build/pkgs/git/spkg-install
-+++ b/build/pkgs/git/spkg-install
-@@ -33,6 +33,13 @@ fi
- 
- cd src
- 
-+# Fix hardcoded paths, while making sure to only update timestamps of actually
-+# changed files (otherwise confuses make)
-+grep -rlF '/usr/bin/perl' . | while read file
-+do
-+	sed -e 's@/usr/bin/perl@perl@g' -i "$file"
-+done
-+
- # We don't want to think about Fink or Macports
- export NO_FINK=1
- export NO_DARWIN_PORTS=1
diff --git a/pkgs/applications/science/math/sage/spkg-python.patch b/pkgs/applications/science/math/sage/spkg-python.patch
deleted file mode 100644
index e39981b6552..00000000000
--- a/pkgs/applications/science/math/sage/spkg-python.patch
+++ /dev/null
@@ -1,13 +0,0 @@
-diff --git a/build/pkgs/python3/spkg-build b/build/pkgs/python3/spkg-build
-index 56db087ae5..b450703c5f 100644
---- a/build/pkgs/python3/spkg-build
-+++ b/build/pkgs/python3/spkg-build
-@@ -27,6 +27,8 @@ fi
- export EXTRA_CFLAGS="`testcflags.sh -Wno-unused` $CFLAGS"
- unset CFLAGS
- 
-+export LDFLAGS="$LDFLAGS -lcrypt"
-+
- if [ "$UNAME" = Darwin ]; then
-     PYTHON_CONFIGURE="--disable-toolbox-glue $PYTHON_CONFIGURE"
- 
diff --git a/pkgs/applications/science/math/sage/spkg-singular.patch b/pkgs/applications/science/math/sage/spkg-singular.patch
deleted file mode 100644
index 606ffcd3ad4..00000000000
--- a/pkgs/applications/science/math/sage/spkg-singular.patch
+++ /dev/null
@@ -1,18 +0,0 @@
-diff --git a/build/pkgs/singular/spkg-install b/build/pkgs/singular/spkg-install
-index 8caafb1699..3c34e6608a 100644
---- a/build/pkgs/singular/spkg-install
-+++ b/build/pkgs/singular/spkg-install
-@@ -2,6 +2,13 @@
- ## Singular
- ###########################################
- 
-+# Fix hardcoded paths, while making sure to only update timestamps of actually
-+# changed files (otherwise confuses make)
-+grep -rlF '/bin/rm' . | while read file
-+do
-+	sed -e 's@/bin/rm@rm@g' -i "$file"
-+done
-+
- if [ -z "$SAGE_LOCAL" ]; then
-     echo >&2 "Error: SAGE_LOCAL undefined -- exiting..."
-     echo >&2 "Maybe run 'sage -sh'?"