···11+diff --git a/src/sage/repl/image.py b/src/sage/repl/image.py
22+index d7d00b0..cd1607a 100644
33+--- a/src/sage/repl/image.py
44++++ b/src/sage/repl/image.py
55+@@ -77,7 +77,7 @@ class Image(SageObject):
66+77+ - ``size`` -- 2-tuple, containing (width, height) in pixels.
88+99+- - ``color`` -- string or tuple of numeric. What colour to use
1010++ - ``color`` -- string, numeric or tuple of numeric. What colour to use
1111+ for the image. Default is black. If given, this should be a
1212+ a tuple with one value per band. When creating RGB images,
1313+ you can also use colour strings as supported by the
1414+@@ -91,9 +91,15 @@ class Image(SageObject):
1515+ EXAMPLES::
1616+1717+ sage: from sage.repl.image import Image
1818+- sage: Image('P', (16, 16), (13,))
1919++ sage: Image('P', (16, 16), 13)
2020+ 16x16px 8-bit Color image
2121+ """
2222++ # pillow does not support Sage integers as color
2323++ from sage.rings.integer import Integer
2424++ if isinstance(color, Integer):
2525++ color = int(color)
2626++ elif isinstance(color, tuple):
2727++ color = tuple(int(i) if isinstance(i, Integer) else i for i in color)
2828+ self._pil = PIL.Image.new(mode, size, color)
2929+3030+ @property
3131+@@ -233,7 +239,7 @@ class Image(SageObject):
3232+ EXAMPLES::
3333+3434+ sage: from sage.repl.image import Image
3535+- sage: img = Image('P', (12, 34), (13,))
3636++ sage: img = Image('P', (12, 34), 13)
3737+ sage: filename = tmp_filename(ext='.png')
3838+ sage: img.save(filename)
3939+ sage: with open(filename, 'rb') as f:
···11+diff --git a/src/sage/doctest/forker.py b/src/sage/doctest/forker.py
22+index cb3667659e..867f547d71 100644
33+--- a/src/sage/doctest/forker.py
44++++ b/src/sage/doctest/forker.py
55+@@ -200,6 +200,15 @@ def init_sage(controller=None):
66+ from sage.cpython._py2_random import Random
77+ sage.misc.randstate.DEFAULT_PYTHON_RANDOM = Random
88+99++ # IPython's pretty printer sorts the repr of dicts by their keys by default
1010++ # (or their keys' str() if they are not otherwise orderable). However, it
1111++ # disables this for CPython 3.6+ opting to instead display dicts' "natural"
1212++ # insertion order, which is preserved in those versions).
1313++ # However, this order is random in some instances.
1414++ # Also modifications of code may affect the order.
1515++ # So here we fore sorted dict printing.
1616++ IPython.lib.pretty.for_type(dict, _sorted_dict_pprinter_factory('{', '}'))
1717++
1818+ if controller is None:
1919+ import sage.repl.ipython_kernel.all_jupyter
2020+ else:
2121+@@ -222,15 +231,6 @@ def init_sage(controller=None):
2222+ from sage.repl.rich_output.backend_doctest import BackendDoctest
2323+ dm.switch_backend(BackendDoctest())
2424+2525+- # IPython's pretty printer sorts the repr of dicts by their keys by default
2626+- # (or their keys' str() if they are not otherwise orderable). However, it
2727+- # disables this for CPython 3.6+ opting to instead display dicts' "natural"
2828+- # insertion order, which is preserved in those versions).
2929+- # However, this order is random in some instances.
3030+- # Also modifications of code may affect the order.
3131+- # So here we fore sorted dict printing.
3232+- IPython.lib.pretty.for_type(dict, _sorted_dict_pprinter_factory('{', '}'))
3333+-
3434+ # Switch on extra debugging
3535+ from sage.structure.debug_options import debug
3636+ debug.refine_category_hash_check = True
···11{ stdenv
22, lib
33, writeTextFile
44-, python
54, sagelib
65, env-locations
76, gfortran
···6766 "@sage-local@"
6867 "@sage-local@/build"
6968 pythonEnv
7070- # empty python env to add python wrapper that clears PYTHONHOME (see
7171- # wrapper.nix). This is necessary because sage will call the python3 binary
7272- # (from python2 code). The python2 PYTHONHOME (again set in wrapper.nix)
7373- # will then confuse python3, if it is not overwritten.
7474- python3.buildEnv
7569 gfortran # for inline fortran
7670 stdenv.cc # for cython
7771 bash
···129123 ]
130124 }'
131125 export SAGE_ROOT='${sagelib.src}'
132132- export SAGE_LOCAL='@sage-local@'
126126+ '' +
127127+ # TODO: is using pythonEnv instead of @sage-local@ here a good
128128+ # idea? there is a test in src/sage/env.py that checks if the values
129129+ # SAGE_ROOT and SAGE_LOCAL set here match the ones set in env.py.
130130+ # we fix up env.py's SAGE_ROOT in sage-src.nix (which does not
131131+ # have access to sage-with-env), but env.py autodetects
132132+ # SAGE_LOCAL to be pythonEnv.
133133+ # setting SAGE_LOCAL to pythonEnv also avoids having to create
134134+ # python3, ipython, ipython3 and jupyter symlinks in
135135+ # sage-with-env.nix.
136136+ ''
137137+ export SAGE_LOCAL='${pythonEnv}'
138138+133139 export SAGE_SHARE='${sagelib}/share'
140140+ export SAGE_ENV_CONFIG_SOURCED=1 # sage-env complains if sage-env-config is not sourced beforehand
134141 orig_path="$PATH"
135142 export PATH='${runtimepath}'
136143···177184 ])
178185 }'
179186180180- export SAGE_LIB='${sagelib}/${python.sitePackages}'
187187+ export SAGE_LIB='${sagelib}/${python3.sitePackages}'
181188182182- export SAGE_EXTCODE='${sagelib.src}/src/ext'
189189+ export SAGE_EXTCODE='${sagelib.src}/src/sage/ext_data'
183190184191 # for find_library
185192 export DYLD_LIBRARY_PATH="${lib.makeLibraryPath [stdenv.cc.libc singular]}''${DYLD_LIBRARY_PATH:+:}$DYLD_LIBRARY_PATH"
+62-4
pkgs/applications/science/math/sage/sage-src.nix
···3939 # Parallelize docubuild using subprocesses, fixing an isolation issue. See
4040 # https://groups.google.com/forum/#!topic/sage-packaging/YGOm8tkADrE
4141 ./patches/sphinx-docbuild-subprocesses.patch
4242+4343+ # Sage's workaround to pretty print dicts (in
4444+ # src/sage/doctest/forker.py:init_sage) runs too late (after
4545+ # controller.load_environment(), which imports sage.all.*) to to
4646+ # affect sage.sandpiles.Sandpile{Config,Divisor}'s pretty printer.
4747+ # Due to the sandpiles module being lazily loaded, this only
4848+ # affects the first run (subsequent runs read from an import cache
4949+ # at ~/.sage/cache and are not affected), which is probably why
5050+ # other distributions don't hit this bug. This breaks two sandpile
5151+ # tests, so do the workaround a little bit earlier.
5252+ # https://trac.sagemath.org/ticket/31053
5353+ ./patches/register-pretty-printer-earlier.patch
4254 ];
43554456 # Since sage unfortunately does not release bugfix releases, packagers must
···4860 # To help debug the transient error in
4961 # https://trac.sagemath.org/ticket/23087 when it next occurs.
5062 ./patches/configurationpy-error-verbose.patch
6363+6464+ # fix intermittent errors in Sage 9.2's psage.py (this patch is
6565+ # already included in Sage 9.3): https://trac.sagemath.org/ticket/30730
6666+ (fetchpatch {
6767+ name = "fix-psage-is-locked.patch";
6868+ url = "https://git.sagemath.org/sage.git/patch/?id=75df605f216ddc7b6ca719be942d666b241520e9";
6969+ sha256 = "0g9pl1wbb3sgs26d3bvv70cpa77sfskylv4kd255y1794f1fgk4q";
7070+ })
7171+7272+ # fix intermittent errors in sagespawn.pyx: https://trac.sagemath.org/ticket/31052
7373+ ./patches/sagespawn-implicit-casting.patch
5174 ];
52755376 # Patches needed because of package updates. We could just pin the versions of
···7710078101 # ignore a deprecation warning for usage of `cmp` in the attrs library in the doctests
79102 ./patches/ignore-cmp-deprecation.patch
103103+104104+ # adapt sage's Image class to pillow 8.0.1 (https://trac.sagemath.org/ticket/30971)
105105+ ./patches/pillow-update.patch
80106 ];
8110782108 patches = nixPatches ++ bugfixPatches ++ packageUpgradePatches;
···84110 postPatch = ''
85111 # make sure shebangs etc are fixed, but sage-python23 still works
86112 find . -type f -exec sed \
8787- -e 's/sage-python23/python/g' \
113113+ -e 's/sage-python23/python3/g' \
88114 -i {} \;
8911590116 echo '#!${runtimeShell}
9191- python "$@"' > build/bin/sage-python23
117117+ python3 "$@"' > build/bin/sage-python23
9211893119 # Make sure sage can at least be imported without setting any environment
94120 # variables. It won't be close to feature complete though.
95121 sed -i \
9696- "s|var('SAGE_LOCAL',.*|var('SAGE_LOCAL', '$out/src')|" \
122122+ "s|var('SAGE_ROOT'.*|var('SAGE_ROOT', '$out')|" \
97123 src/sage/env.py
9812499125 # Do not use sage-env-config (generated by ./configure).
···101127 echo '# do nothing' > src/bin/sage-env-config
102128 '';
103129104104- configurePhase = "# do nothing";
130130+ # Test src/doc/en/reference/spkg/conf.py will fail if
131131+ # src/doc/en/reference/spkg/index.rst is not generated. It is
132132+ # generated by src/doc/bootstrap, so I've copied the relevant part
133133+ # here. An alternative would be to create an empty
134134+ # src/doc/en/reference/spkg/index.rst file.
135135+ configurePhase = ''
136136+ OUTPUT_DIR="src/doc/en/reference/spkg"
137137+ mkdir -p "$OUTPUT_DIR"
138138+ OUTPUT_INDEX="$OUTPUT_DIR"/index.rst
139139+ cat > "$OUTPUT_INDEX" <<EOF
140140+141141+ External Packages
142142+ =================
143143+144144+ .. toctree::
145145+ :maxdepth: 1
146146+147147+ EOF
148148+ for PKG_SCRIPTS in build/pkgs/*; do
149149+ if [ -d "$PKG_SCRIPTS" ]; then
150150+ PKG_BASE=$(basename "$PKG_SCRIPTS")
151151+ if [ -f "$PKG_SCRIPTS"/SPKG.rst ]; then
152152+ # Instead of just copying, we may want to call
153153+ # a version of sage-spkg-info to format extra information.
154154+ cp "$PKG_SCRIPTS"/SPKG.rst "$OUTPUT_DIR"/$PKG_BASE.rst
155155+ echo >> "$OUTPUT_INDEX" " $PKG_BASE"
156156+ fi
157157+ fi
158158+ done
159159+ cat >> "$OUTPUT_INDEX" <<EOF
160160+ .. include:: ../footer.txt
161161+ EOF
162162+ '';
105163106164 buildPhase = "# do nothing";
107165