summary refs log tree commit diff
path: root/pkgs/applications/science/math/sage
diff options
context:
space:
mode:
authorMasanori Ogino <masanori.ogino@gmail.com>2021-04-02 18:10:36 -0300
committerMasanori Ogino <167209+omasanori@users.noreply.github.com>2021-04-22 14:06:56 +0900
commit090b71f62766f953a0c57409df2789291d47ce18 (patch)
tree6c11e0ef6466526c128e40b934c9d1951c910617 /pkgs/applications/science/math/sage
parent9bcbff30c3b8a6ec7e0c526043f23c58ebc7af54 (diff)
downloadnixpkgs-090b71f62766f953a0c57409df2789291d47ce18.tar
nixpkgs-090b71f62766f953a0c57409df2789291d47ce18.tar.gz
nixpkgs-090b71f62766f953a0c57409df2789291d47ce18.tar.bz2
nixpkgs-090b71f62766f953a0c57409df2789291d47ce18.tar.lz
nixpkgs-090b71f62766f953a0c57409df2789291d47ce18.tar.xz
nixpkgs-090b71f62766f953a0c57409df2789291d47ce18.tar.zst
nixpkgs-090b71f62766f953a0c57409df2789291d47ce18.zip
sage: 9.2 -> 9.3.rc4
Co-authored-by: Mauricio Collares <mauricio@collares.org>
Diffstat (limited to 'pkgs/applications/science/math/sage')
-rw-r--r--pkgs/applications/science/math/sage/default.nix6
-rw-r--r--pkgs/applications/science/math/sage/patches/do-not-test-find-library.patch92
-rw-r--r--pkgs/applications/science/math/sage/patches/sphinx-docbuild-subprocesses.patch34
-rw-r--r--pkgs/applications/science/math/sage/patches/sympy-1.7-update.patch25
-rw-r--r--pkgs/applications/science/math/sage/sage-env.nix6
-rw-r--r--pkgs/applications/science/math/sage/sage-src.nix148
-rw-r--r--pkgs/applications/science/math/sage/sage_docbuild.nix20
-rw-r--r--pkgs/applications/science/math/sage/sagedoc.nix12
-rw-r--r--pkgs/applications/science/math/sage/sagelib.nix16
9 files changed, 116 insertions, 243 deletions
diff --git a/pkgs/applications/science/math/sage/default.nix b/pkgs/applications/science/math/sage/default.nix
index 4a18d1e88a6..e39db4b1ac2 100644
--- a/pkgs/applications/science/math/sage/default.nix
+++ b/pkgs/applications/science/math/sage/default.nix
@@ -19,6 +19,10 @@ let
         linbox = pkgs.linbox.override { withSage = true; };
         pkg-config = pkgs.pkg-config; # not to confuse with pythonPackages.pkg-config
       };
+
+      sage_docbuild = self.callPackage ./sage_docbuild.nix {
+        inherit sage-src;
+      };
     };
   };
 
@@ -55,6 +59,7 @@ let
   # the env-locations file.
   sage-env = callPackage ./sage-env.nix {
     sagelib = python3.pkgs.sagelib;
+    sage_docbuild = python3.pkgs.sage_docbuild;
     inherit env-locations;
     inherit python3 singular palp flint pynac pythonEnv maxima-ecl;
     ecl = maxima-ecl.ecl;
@@ -88,6 +93,7 @@ let
 
   pythonRuntimeDeps = with python3.pkgs; [
     sagelib
+    sage_docbuild
     cvxopt
     networkx
     service-identity
diff --git a/pkgs/applications/science/math/sage/patches/do-not-test-find-library.patch b/pkgs/applications/science/math/sage/patches/do-not-test-find-library.patch
index 98175920238..0dbfba642e8 100644
--- a/pkgs/applications/science/math/sage/patches/do-not-test-find-library.patch
+++ b/pkgs/applications/science/math/sage/patches/do-not-test-find-library.patch
@@ -1,13 +1,13 @@
 diff --git a/src/sage/env.py b/src/sage/env.py
-index 1ddfc7cfb9..45033d6328 100644
+index 2908f5d04f..81dfd75c0d 100644
 --- a/src/sage/env.py
 +++ b/src/sage/env.py
-@@ -203,97 +203,13 @@ var('ARB_LIBRARY',                   'arb')
- var('SAGE_BANNER', '')
- var('SAGE_IMPORTALL', 'yes')
+@@ -218,93 +218,12 @@ NTL_LIBDIR = var("NTL_LIBDIR")
+ SAGE_BANNER = var("SAGE_BANNER", "")
+ SAGE_IMPORTALL = var("SAGE_IMPORTALL", "yes")
  
 -
--def _get_shared_lib_filename(libname, *additional_libnames):
+-def _get_shared_lib_path(*libnames: str) -> Optional[str]:
 -    """
 -    Return the full path to a shared library file installed in
 -    ``$SAGE_LOCAL/lib`` or the directories associated with the
@@ -25,80 +25,76 @@ index 1ddfc7cfb9..45033d6328 100644
 -    For distributions like Debian that use a multiarch layout, we also try the
 -    multiarch lib paths (i.e. ``/usr/lib/<arch>/``).
 -
--    This returns ``None`` if the file does not exist.
+-    This returns ``None`` if no matching library file could be found.
 -
 -    EXAMPLES::
 -
 -        sage: import sys
 -        sage: from fnmatch import fnmatch
--        sage: from sage.env import _get_shared_lib_filename
--        sage: lib_filename = _get_shared_lib_filename("Singular",
--        ....:                                         "singular-Singular")
+-        sage: from sage.env import _get_shared_lib_path
+-        sage: lib_filename = _get_shared_lib_path("Singular", "singular-Singular")
 -        sage: if sys.platform == 'cygwin':
 -        ....:     pattern = "*/cygSingular-*.dll"
 -        ....: elif sys.platform == 'darwin':
--        ....:     pattern = "*/libSingular.dylib"
+-        ....:     pattern = "*/libSingular-*.dylib"
 -        ....: else:
--        ....:     pattern = "*/lib*Singular.so"
--        sage: fnmatch(lib_filename, pattern)
+-        ....:     pattern = "*/lib*Singular-*.so"
+-        sage: fnmatch(str(lib_filename), pattern)
 -        True
--        sage: _get_shared_lib_filename("an_absurd_lib") is None
+-        sage: _get_shared_lib_path("an_absurd_lib") is None
 -        True
 -    """
 -
--    for libname in (libname,) + additional_libnames:
+-    for libname in libnames:
+-        search_directories: List[Path] = []
+-        patterns: List[str] = []
 -        if sys.platform == 'cygwin':
--            # Later down we take the last matching DLL found, so search
--            # SAGE_LOCAL second so that it takes precedence
--            bindirs = [
--                sysconfig.get_config_var('BINDIR'),
--                os.path.join(SAGE_LOCAL, 'bin')
+-            # Later down we take the first matching DLL found, so search
+-            # SAGE_LOCAL first so that it takes precedence
+-            search_directories = [
+-                Path(SAGE_LOCAL) / 'bin',
+-                Path(sysconfig.get_config_var('BINDIR')),
 -            ]
--            pats = ['cyg{}.dll'.format(libname), 'cyg{}-*.dll'.format(libname)]
--            filenames = []
--            for bindir in bindirs:
--                for pat in pats:
--                    filenames += glob.glob(os.path.join(bindir, pat))
--
--            # Note: This is not very robust, since if there are multi DLL
+-            # Note: The following is not very robust, since if there are multible
 -            # versions for the same library this just selects one more or less
--            # at arbitrary.  However, practically speaking, on Cygwin, there
+-            # at arbitrary. However, practically speaking, on Cygwin, there
 -            # will only ever be one version
--            if filenames:
--                return filenames[-1]
+-            patterns = [f'cyg{libname}.dll', f'cyg{libname}-*.dll']
 -        else:
 -            if sys.platform == 'darwin':
 -                ext = 'dylib'
 -            else:
 -                ext = 'so'
 -
--            libdirs = [
--                os.path.join(SAGE_LOCAL, 'lib'),
--                sysconfig.get_config_var('LIBDIR')
--            ]
--            multilib = sysconfig.get_config_var('MULTILIB')
--            if multilib:
--                libdirs.insert(1, os.path.join(libdirs[0], multilib))
+-            search_directories = [Path(SAGE_LOCAL) / 'lib']
+-            libdir = sysconfig.get_config_var('LIBDIR')
+-            if libdir is not None:
+-                libdir = Path(libdir)
+-                search_directories.append(libdir)
+-
+-                multiarchlib = sysconfig.get_config_var('MULTIARCH')
+-                if multiarchlib is not None: 
+-                    search_directories.append(libdir / multiarchlib),
 -
--            for libdir in libdirs:
--                basename = 'lib{}.{}'.format(libname, ext)
--                filename = os.path.join(libdir, basename)
--                if os.path.exists(filename):
--                    return filename
+-            patterns = [f'lib{libname}.{ext}']
+-
+-        for directory in search_directories:
+-            for pattern in patterns:
+-                path = next(directory.glob(pattern), None)
+-                if path is not None:
+-                    return str(path.resolve())
 -
 -    # Just return None if no files were found
 -    return None
 -
--
  # locate singular shared object
  # On Debian it's libsingular-Singular so try that as well
--SINGULAR_SO = _get_shared_lib_filename('Singular', 'singular-Singular')
-+SINGULAR_SO = '/default'
- var('SINGULAR_SO', SINGULAR_SO)
+-SINGULAR_SO = var("SINGULAR_SO", _get_shared_lib_path("Singular", "singular-Singular"))
++SINGULAR_SO = var("SINGULAR_SO", '/default')
  
  # locate libgap shared object
--GAP_SO= _get_shared_lib_filename('gap','')
-+GAP_SO = '/default'
- var('GAP_SO', GAP_SO)
+-GAP_SO = var("GAP_SO", _get_shared_lib_path("gap", ""))
++GAP_SO = var("GAP_SO", '/default')
  
  # post process
+ if ' ' in DOT_SAGE:
diff --git a/pkgs/applications/science/math/sage/patches/sphinx-docbuild-subprocesses.patch b/pkgs/applications/science/math/sage/patches/sphinx-docbuild-subprocesses.patch
index 661077cfa8c..3c64be100d2 100644
--- a/pkgs/applications/science/math/sage/patches/sphinx-docbuild-subprocesses.patch
+++ b/pkgs/applications/science/math/sage/patches/sphinx-docbuild-subprocesses.patch
@@ -1,8 +1,8 @@
-diff --git a/src/sage_setup/docbuild/__init__.py b/src/sage_setup/docbuild/__init__.py
-index 73a078e619..059125c59f 100644
---- a/src/sage_setup/docbuild/__init__.py
-+++ b/src/sage_setup/docbuild/__init__.py
-@@ -86,27 +86,6 @@ def builder_helper(type):
+diff --git a/src/sage_docbuild/__init__.py b/src/sage_docbuild/__init__.py
+index 79005b903a..fbe6fe2595 100644
+--- a/src/sage_docbuild/__init__.py
++++ b/src/sage_docbuild/__init__.py
+@@ -85,27 +85,6 @@ def builder_helper(type):
      """
      Returns a function which builds the documentation for
      output type ``type``.
@@ -11,16 +11,16 @@ index 73a078e619..059125c59f 100644
 -
 -    Check that :trac:`25161` has been resolved::
 -
--        sage: from sage_setup.docbuild import DocBuilder, setup_parser
+-        sage: from sage_docbuild import DocBuilder, setup_parser
 -        sage: DocBuilder._options = setup_parser().parse_args([])[0] # builder_helper needs _options to be set
 -
--        sage: import sage_setup.docbuild.sphinxbuild
+-        sage: import sage_docbuild.sphinxbuild
 -        sage: def raiseBaseException():
 -        ....:     raise BaseException("abort pool operation")
--        sage: original_runsphinx, sage_setup.docbuild.sphinxbuild.runsphinx = sage_setup.docbuild.sphinxbuild.runsphinx, raiseBaseException
+-        sage: original_runsphinx, sage_docbuild.sphinxbuild.runsphinx = sage_docbuild.sphinxbuild.runsphinx, raiseBaseException
 -
--        sage: from sage_setup.docbuild import builder_helper, build_ref_doc
--        sage: from sage_setup.docbuild import _build_many as build_many
+-        sage: from sage_docbuild import builder_helper, build_ref_doc
+-        sage: from sage_docbuild import _build_many as build_many
 -        sage: helper = builder_helper("html")
 -        sage: try:
 -        ....:     build_many(build_ref_doc, [("docname", "en", "html", {})])
@@ -30,24 +30,24 @@ index 73a078e619..059125c59f 100644
      """
      def f(self, *args, **kwds):
          output_dir = self._output_dir(type)
-@@ -128,10 +107,9 @@ def builder_helper(type):
+@@ -127,10 +106,9 @@ def builder_helper(type):
          logger.debug(build_command)
  
          # Run Sphinx with Sage's special logger
 -        sys.argv = ["sphinx-build"] + build_command.split()
 -        from .sphinxbuild import runsphinx
-+        args = "python3 -um sage_setup.docbuild.sphinxbuild -N".split() + build_command.split()
++        args = "python3 -um sage_docbuild.sphinxbuild -N".split() + build_command.split()
          try:
 -            runsphinx()
 +            subprocess.check_call(args)
          except Exception:
              if ABORT_ON_ERROR:
                  raise
-diff --git a/src/sage_setup/docbuild/sphinxbuild.py b/src/sage_setup/docbuild/sphinxbuild.py
-index fe7eba43b2..463790965c 100644
---- a/src/sage_setup/docbuild/sphinxbuild.py
-+++ b/src/sage_setup/docbuild/sphinxbuild.py
-@@ -321,3 +321,8 @@ def runsphinx():
+diff --git a/src/sage_docbuild/sphinxbuild.py b/src/sage_docbuild/sphinxbuild.py
+index f58f6c61d7..ef51a55411 100644
+--- a/src/sage_docbuild/sphinxbuild.py
++++ b/src/sage_docbuild/sphinxbuild.py
+@@ -326,3 +326,8 @@ def runsphinx():
          sys.stderr = saved_stderr
          sys.stdout.flush()
          sys.stderr.flush()
diff --git a/pkgs/applications/science/math/sage/patches/sympy-1.7-update.patch b/pkgs/applications/science/math/sage/patches/sympy-1.7-update.patch
deleted file mode 100644
index 1d21622a235..00000000000
--- a/pkgs/applications/science/math/sage/patches/sympy-1.7-update.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-diff --git a/src/sage/interfaces/sympy.py b/src/sage/interfaces/sympy.py
-index cc35a42a9f..6e577d5d8d 100644
---- a/src/sage/interfaces/sympy.py
-+++ b/src/sage/interfaces/sympy.py
-@@ -397,7 +397,7 @@ def _sympysage_rf(self):
-         sage: from sympy import Symbol, rf
-         sage: _ = var('x, y')
-         sage: rfxy = rf(Symbol('x'), Symbol('y'))
--        sage: assert rising_factorial(x,y)._sympy_() == rfxy.rewrite('gamma')
-+        sage: assert rising_factorial(x,y)._sympy_() == rfxy.rewrite('gamma', piecewise=False)
-         sage: assert rising_factorial(x,y) == rfxy._sage_()
-     """
-     from sage.arith.all import rising_factorial
-diff --git a/src/sage/symbolic/expression.pyx b/src/sage/symbolic/expression.pyx
-index 7c18ec1efa..c2619ac42d 100644
---- a/src/sage/symbolic/expression.pyx
-+++ b/src/sage/symbolic/expression.pyx
-@@ -955,6 +955,6 @@ cdef class Expression(CommutativeRingElement):
-             sage: unicode_art(13 - I)
-             13 - ⅈ
-             sage: unicode_art(1.3 - I)
--            1.3 - 1.0⋅ⅈ
-+            1.3 - ⅈ
-             sage: unicode_art(cos(I))
-             cosh(1)
diff --git a/pkgs/applications/science/math/sage/sage-env.nix b/pkgs/applications/science/math/sage/sage-env.nix
index 568a4a39f39..fd67076c97d 100644
--- a/pkgs/applications/science/math/sage/sage-env.nix
+++ b/pkgs/applications/science/math/sage/sage-env.nix
@@ -2,6 +2,7 @@
 , lib
 , writeTextFile
 , sagelib
+, sage_docbuild
 , env-locations
 , gfortran
 , bash
@@ -191,6 +192,7 @@ writeTextFile rec {
   # for find_library
     export DYLD_LIBRARY_PATH="${lib.makeLibraryPath [stdenv.cc.libc singular]}''${DYLD_LIBRARY_PATH:+:}$DYLD_LIBRARY_PATH"
   '';
-} // {
-  lib = sagelib; # equivalent of `passthru`, which `writeTextFile` doesn't support
+} // { # equivalent of `passthru`, which `writeTextFile` doesn't support
+  lib = sagelib;
+  docbuild = sage_docbuild;
 }
diff --git a/pkgs/applications/science/math/sage/sage-src.nix b/pkgs/applications/science/math/sage/sage-src.nix
index e9069725737..91e855777f0 100644
--- a/pkgs/applications/science/math/sage/sage-src.nix
+++ b/pkgs/applications/science/math/sage/sage-src.nix
@@ -24,14 +24,14 @@ let
   );
 in
 stdenv.mkDerivation rec {
-  version = "9.2";
+  version = "9.3.rc4";
   pname = "sage-src";
 
   src = fetchFromGitHub {
     owner = "sagemath";
     repo = "sage";
     rev = version;
-    sha256 = "103j8d5x6szl9fxaz0dvdi4y47q1af9h9y5hmjh2xayi62qmp5ql";
+    sha256 = "sha256-LDY07By2j6JagkgT9zeDJ93+m2/oXXEnDRTDzmR8ftk=";
   };
 
   # Patches needed because of particularities of nix or the way this is packaged.
@@ -53,14 +53,6 @@ stdenv.mkDerivation rec {
     # Parallelize docubuild using subprocesses, fixing an isolation issue. See
     # https://groups.google.com/forum/#!topic/sage-packaging/YGOm8tkADrE
     ./patches/sphinx-docbuild-subprocesses.patch
-
-    # Register sorted dict pprinter earlier (https://trac.sagemath.org/ticket/31053)
-    (fetchSageDiff {
-      base = "9.3.beta4";
-      name = "register-pretty-printer-earlier.patch";
-      rev = "d658230ce06ca19f4a3b3a4576297ee82f2d2151";
-      sha256 = "sha256-9mPUV7K5PoLDH2vVaYaOfvDLDpmxU0Aj7m/eaXYotDs=";
-    })
   ];
 
   # Since sage unfortunately does not release bugfix releases, packagers must
@@ -70,31 +62,6 @@ stdenv.mkDerivation rec {
     # To help debug the transient error in
     # https://trac.sagemath.org/ticket/23087 when it next occurs.
     ./patches/configurationpy-error-verbose.patch
-
-    # fix intermittent errors in Sage 9.2's psage.py (this patch is
-    # already included in Sage 9.3): https://trac.sagemath.org/ticket/30730
-    (fetchSageDiff {
-      base = "9.2.rc2";
-      name = "fix-psage-is-locked.patch";
-      rev = "75df605f216ddc7b6ca719be942d666b241520e9";
-      sha256 = "0g9pl1wbb3sgs26d3bvv70cpa77sfskylv4kd255y1794f1fgk4q";
-    })
-
-    # fix intermittent errors in sagespawn.pyx: https://trac.sagemath.org/ticket/31052
-    (fetchSageDiff {
-      base = "9.2";
-      name = "sagespawn-implicit-casting.patch";
-      rev = "2959ac792ebd6107fe87c9af1541083de5ba02d6";
-      sha256 = "sha256-bWIpEGir9Kawak5CJegBMNcHm/CqhWmdru+emeSsvO0=";
-    })
-
-    # fix intermittent errors in doctest/test.py: https://trac.sagemath.org/ticket/26912
-    (fetchSageDiff {
-      base = "9.3.beta8";
-      name = "set-cysignals-crash-ndebug.patch";
-      rev = "ca5257a5d0f32efc9f8f07e126020856270b1a18";
-      sha256 = "sha256-KViw63xE3O0eUiOYzoxNrr4NL+csql9GPJLDJCf/EZs=";
-    })
   ];
 
   # Patches needed because of package updates. We could just pin the versions of
@@ -111,114 +78,29 @@ stdenv.mkDerivation rec {
 
     # ignore a deprecation warning for usage of `cmp` in the attrs library in the doctests
     ./patches/ignore-cmp-deprecation.patch
-
-    # adapt sage's Image class to pillow 8.0.1 (https://trac.sagemath.org/ticket/30971)
-    (fetchSageDiff {
-      base = "9.3.beta2";
-      name = "pillow-8.0.1-update.patch";
-      rev = "f05f2d0aac9c4b5abe68105cee2cc7f2c8461847";
-      sha256 = "sha256-uY2UlgSd5hhOUUukB4Xc3Gjy0/e7p/qyq9jdvz10IOs=";
-    })
-
-    # don't use deprecated numpy type aliases (https://trac.sagemath.org/ticket/31364)
-    (fetchSageDiff {
-      base = "9.3.beta7";
-      name = "dont-use-deprecated-numpy-type-aliases.patch";
-      rev = "dfdef60515d4a4269e82d91280f76a7fdf10bf97";
-      sha256 = "sha256-77/3LkT5J7DQN8IPlGJKB6ZcJPaF7xwje06JNns+0AE=";
-    })
-
-    # fix test output with sympy 1.7 (https://trac.sagemath.org/ticket/30985)
-    ./patches/sympy-1.7-update.patch
-
-    # upgrade arb to 2.18.1 (https://trac.sagemath.org/ticket/28623)
-    (fetchSageDiff {
-      base = "9.3.beta3";
-      name = "arb-2.18.1-update.patch";
-      rev = "0c9c4ed35c2eaf34ae0d19387c07b7f460e4abce";
-      sha256 = "sha256-CjOJIsyyVCziAfvE6pWSihPO35IZMcY2/taXAsqhPLY=";
-    })
-
-    # giac 1.6.0-47 update (https://trac.sagemath.org/ticket/30537)
-    (fetchSageDiff {
-      base = "9.3.beta7";
-      name = "giac-1.6.0-47-update.patch";
-      rev = "f05720bf63dfaf33a4e3b6d3ed2c2c0ec46b5d31";
-      sha256 = "sha256-gDUq+84eXd5GxLBWUSI61GMJpBF2KX4LBVOt3mS1NF8=";
-    })
-
-    # Make gcd/lcm interact better with pari and gmpy2 (https://trac.sagemath.org/ticket/30849)
-    # needed for pari 2.13.1 update, which we will do in the future
-    (fetchSageDiff {
-      base = "9.3.beta0";
-      name = "make-gcd-lcm-interact-better-with-pari-and-gmpy2.patch";
-      rev = "75c1516f0abb9e6f8c335e38e4031f6ef674ed30";
-      sha256 = "sha256-RukkieIZcXNrju904H2oyGKdtpdE+9vNzvyjN2IBNg0=";
-    })
-
-    # cypari 2.1.2 update (https://trac.sagemath.org/ticket/31029)
-    (fetchSageDiff {
-      base = "9.3.beta3";
-      name = "cypari-2.1.2-update.patch";
-      rev = "b9aadfd08e81d74ca7c229bb80eb853b592887d0";
-      sha256 = "sha256-eKaMy7kpu+YKdL8bPStgocxBCTfc2Z/10RrGy2LENFw=";
-    })
   ];
 
   patches = nixPatches ++ bugfixPatches ++ packageUpgradePatches;
 
   postPatch = ''
-    # make sure shebangs etc are fixed, but sage-python23 still works
-    find . -type f -exec sed \
-      -e 's/sage-python23/python3/g' \
-      -i {} \;
-
-    echo '#!${runtimeShell}
-    python3 "$@"' > build/bin/sage-python23
-
     # Make sure sage can at least be imported without setting any environment
     # variables. It won't be close to feature complete though.
     sed -i \
-      "s|var('SAGE_ROOT'.*|var('SAGE_ROOT', '$out')|" \
+      "s|var(\"SAGE_ROOT\".*|var(\"SAGE_ROOT\", \"$out\")|" \
       src/sage/env.py
 
-    # Do not use sage-env-config (generated by ./configure).
-    # Instead variables are set manually.
-    echo '# do nothing' >  src/bin/sage-env-config
-  '';
-
-  # Test src/doc/en/reference/spkg/conf.py will fail if
-  # src/doc/en/reference/spkg/index.rst is not generated.  It is
-  # generated by src/doc/bootstrap, so I've copied the relevant part
-  # here. An alternative would be to create an empty
-  # src/doc/en/reference/spkg/index.rst file.
-  configurePhase = ''
-    OUTPUT_DIR="src/doc/en/reference/spkg"
-    mkdir -p "$OUTPUT_DIR"
-    OUTPUT_INDEX="$OUTPUT_DIR"/index.rst
-    cat > "$OUTPUT_INDEX" <<EOF
-
-    External Packages
-    =================
-
-    .. toctree::
-       :maxdepth: 1
-
-    EOF
-    for PKG_SCRIPTS in build/pkgs/*; do
-        if [ -d "$PKG_SCRIPTS" ]; then
-            PKG_BASE=$(basename "$PKG_SCRIPTS")
-            if [ -f "$PKG_SCRIPTS"/SPKG.rst ]; then
-                # Instead of just copying, we may want to call
-                # a version of sage-spkg-info to format extra information.
-                cp "$PKG_SCRIPTS"/SPKG.rst "$OUTPUT_DIR"/$PKG_BASE.rst
-                echo >> "$OUTPUT_INDEX" "   $PKG_BASE"
-            fi
-        fi
-    done
-    cat >> "$OUTPUT_INDEX" <<EOF
-    .. include:: ../footer.txt
-    EOF
+    # src/doc/en/reference/spkg/conf.py expects index.rst in its directory,
+    # a list of external packages in the sage distribution (build/pkgs)
+    # generated by the bootstrap script (which we don't run).  this is not
+    # relevant for other distributions, so remove it.
+    rm src/doc/en/reference/spkg/conf.py
+    sed -i "/spkg/d" src/doc/en/reference/index.rst
+
+    # the bootstrap script also generates installation instructions for
+    # arch, debian, fedora, cygwin and homebrew using data from build/pkgs.
+    # we don't run the bootstrap script, so disable including the generated
+    # files. docbuilding fails otherwise.
+    sed -i "/literalinclude/d" src/doc/en/installation/source.rst
   '';
 
   buildPhase = "# do nothing";
diff --git a/pkgs/applications/science/math/sage/sage_docbuild.nix b/pkgs/applications/science/math/sage/sage_docbuild.nix
new file mode 100644
index 00000000000..ed78d46b445
--- /dev/null
+++ b/pkgs/applications/science/math/sage/sage_docbuild.nix
@@ -0,0 +1,20 @@
+{ buildPythonPackage
+, sage-src
+, sphinx
+}:
+
+buildPythonPackage rec {
+  version = src.version;
+  pname = "sage_docbuild";
+  src = sage-src;
+
+  propagatedBuildInputs = [
+    sphinx
+  ];
+
+  preBuild = ''
+    cd build/pkgs/sage_docbuild/src
+  '';
+
+  doCheck = false; # we will run tests in sagedoc.nix
+}
diff --git a/pkgs/applications/science/math/sage/sagedoc.nix b/pkgs/applications/science/math/sage/sagedoc.nix
index a10672f3a09..603c1a585c7 100644
--- a/pkgs/applications/science/math/sage/sagedoc.nix
+++ b/pkgs/applications/science/math/sage/sagedoc.nix
@@ -23,6 +23,7 @@ stdenv.mkDerivation rec {
     jmol
     cddlib
   ] ++ (with python3.pkgs; [
+    sage_docbuild
     psutil
     future
     sphinx
@@ -44,13 +45,6 @@ stdenv.mkDerivation rec {
     chmod -R 755 "$SAGE_DOC_SRC_OVERRIDE"
   '';
 
-  postPatch = ''
-    # src/doc/bootstrap generates installation instructions for
-    # arch, debian, fedora, cygwin and homebrew. as a hack, disable
-    # including the generated files.
-    sed -i "/literalinclude/d" $SAGE_DOC_SRC_OVERRIDE/en/installation/source.rst
-  '';
-
   buildPhase = ''
     export SAGE_NUM_THREADS="$NIX_BUILD_CORES"
     export HOME="$TMPDIR/sage_home"
@@ -59,13 +53,13 @@ stdenv.mkDerivation rec {
     # needed to link them in the sage docs using intersphinx
     export PPLPY_DOCS=${python3.pkgs.pplpy.doc}/share/doc/pplpy
 
-    # adapted from src/doc/bootstrap
+    # adapted from src/doc/bootstrap (which we don't run)
     OUTPUT_DIR="$SAGE_DOC_SRC_OVERRIDE/en/reference/repl"
     mkdir -p "$OUTPUT_DIR"
     OUTPUT="$OUTPUT_DIR/options.txt"
     ${sage-with-env}/bin/sage -advanced > "$OUTPUT"
 
-    ${sage-with-env}/bin/sage -python -m sage_setup.docbuild \
+    ${sage-with-env}/bin/sage --docbuild \
       --mathjax \
       --no-pdf-links \
       all html
diff --git a/pkgs/applications/science/math/sage/sagelib.nix b/pkgs/applications/science/math/sage/sagelib.nix
index 245ddcedeee..f60cb64d2e8 100644
--- a/pkgs/applications/science/math/sage/sagelib.nix
+++ b/pkgs/applications/science/math/sage/sagelib.nix
@@ -63,7 +63,6 @@ assert (!blas.isILP64) && (!lapack.isILP64);
 # `sage-tests` and will not have html docs without `sagedoc`.
 
 buildPythonPackage rec {
-  format = "other";
   version = src.version;
   pname = "sagelib";
   src = sage-src;
@@ -74,6 +73,7 @@ buildPythonPackage rec {
     jupyter_core
     pkg-config
     pip # needed to query installed packages
+    ecl
   ];
 
   buildInputs = [
@@ -130,7 +130,7 @@ buildPythonPackage rec {
     sqlite
   ];
 
-  buildPhase = ''
+  preBuild = ''
     export SAGE_ROOT="$PWD"
     export SAGE_LOCAL="$SAGE_ROOT"
     export SAGE_SHARE="$SAGE_LOCAL/share"
@@ -146,15 +146,13 @@ buildPythonPackage rec {
     mkdir -p "$SAGE_SHARE/sage/ext/notebook-ipython"
     mkdir -p "var/lib/sage/installed"
 
-    source build/bin/sage-dist-helpers
-    cd src
-
-    ${python.interpreter} -u setup.py --no-user-cfg build
+    # src/setup.py should not be used, see https://trac.sagemath.org/ticket/31377#comment:124
+    cd build/pkgs/sagelib/src
   '';
 
-  installPhase = ''
-    ${python.interpreter} -u setup.py --no-user-cfg install --prefix=$out
-
+  postInstall = ''
     rm -r "$out/${python.sitePackages}/sage/cython_debug"
   '';
+
+  doCheck = false; # we will run tests in sage-tests.nix
 }