sagemath: rebuild for singular update

Also fix doctests for pkg updates:
 - matplotlib 3.7
 - ipython 8.12
 - nauty 2.8.6
 - pythran 0.12.1

And add support for:
 - networkx 3.1

We use patches from upstream sagemath to fix all of these.

We also add pythran and sphinx to checkdepends to make sure doctests
pass when they are installed.
This commit is contained in:
Gonzalo Tornaría 2023-03-15 09:27:58 -03:00 committed by Leah Neukirchen
parent ccfebe0600
commit b34d0bbd28
11 changed files with 426 additions and 15 deletions

View file

@ -1,8 +1,8 @@
diff --git a/src/sage/rings/number_field/number_field_ideal.py b/src/sage/rings/number_field/number_field_ideal.py
index d5f7157217f..1a9d11aec68 100644
index d5f7157217f..8ca1f958039 100644
--- a/src/sage/rings/number_field/number_field_ideal.py
+++ b/src/sage/rings/number_field/number_field_ideal.py
@@ -996,16 +996,36 @@ def is_prime(self):
@@ -996,16 +996,38 @@ def is_prime(self):
False
sage: K.ideal(17).is_prime() # ramified
False
@ -33,13 +33,15 @@ index d5f7157217f..1a9d11aec68 100644
+ K = self.number_field().pari_nf()
+ I = self.pari_hnf()
+
+ self._pari_prime = K.idealismaximal(I) or None
+ candidate = K.idealismaximal(I) or None
+
+ # PARI uses probabilistic primality testing inside idealismaximal().
+ if self._pari_prime \
+ and get_flag(None, 'arithmetic') \
+ and not self._pari_prime[0].isprime():
+ self._pari_prime = None
+ if get_flag(None, 'arithmetic'):
+ # proof required, check using isprime()
+ if candidate and not candidate[0].isprime():
+ candidate = None
+
+ self._pari_prime = candidate
+
+ return self._pari_prime is not None

View file

@ -0,0 +1,95 @@
diff --git a/src/sage/plot/complex_plot.pyx b/src/sage/plot/complex_plot.pyx
index b77c69b2f77..0586a96ae55 100644
--- a/src/sage/plot/complex_plot.pyx
+++ b/src/sage/plot/complex_plot.pyx
@@ -563,7 +563,7 @@ def complex_to_cmap_rgb(z_values, cmap='turbo', contoured=False, tiled=False,
import matplotlib as mpl
if isinstance(cmap, str):
- cmap = mpl.cm.get_cmap(cmap)
+ cmap = mpl.colormaps[cmap]
if contour_base is None:
if contour_type == "linear":
@@ -1206,11 +1206,11 @@ def complex_plot(f, x_range, y_range, contoured=False, tiled=False, cmap=None,
domain = np.linspace(0, 1, 256)
shifted_domain = np.roll(domain, 128)
default_cmap = mpl.colors.LinearSegmentedColormap.from_list(
- "sage_default", mpl.cm.get_cmap('hsv')(shifted_domain)
+ "sage_default", mpl.colormaps['hsv'](shifted_domain)
)
cmap = default_cmap
else:
- cmap = mpl.cm.get_cmap(cmap)
+ cmap = mpl.colormaps[cmap]
rgbs = complex_to_cmap_rgb(
z_values, cmap=cmap, contoured=contoured, tiled=tiled,
contour_type=contour_type, contour_base=contour_base,
diff --git a/src/sage/plot/contour_plot.py b/src/sage/plot/contour_plot.py
index c0cab456686..4accb309580 100644
--- a/src/sage/plot/contour_plot.py
+++ b/src/sage/plot/contour_plot.py
@@ -848,9 +848,7 @@ def f(x,y): return cos(x) + sin(y)
sage: contour_plot(lambda x,y: 0, (-1,1), (-1,1),
....: contours=[0], fill=False, cmap=['blue'])
- ...
- UserWarning: No contour levels were found within the data range.
- Graphics object consisting of 1 graphics primitive
+ ...Graphics object consisting of 1 graphics primitive
.. PLOT::
@@ -874,8 +872,7 @@ def f(x,y): return cos(x) + sin(y)
Check that :trac:`18074` is fixed::
sage: contour_plot(0, (0,1), (0,1))
- ... UserWarning: No contour levels were found within the data range.
- Graphics object consisting of 1 graphics primitive
+ ...Graphics object consisting of 1 graphics primitive
Domain points in :trac:`11648` with complex output are now skipped::
diff --git a/src/sage/plot/graphics.py b/src/sage/plot/graphics.py
index 64ea1a7e10f..cdc99ced263 100644
--- a/src/sage/plot/graphics.py
+++ b/src/sage/plot/graphics.py
@@ -2341,7 +2341,7 @@ def _matplotlib_tick_formatter(self, subplot, base=(10, 10),
sage: subplot = Figure().add_subplot(111)
sage: p._objects[0]._render_on_subplot(subplot)
sage: p._matplotlib_tick_formatter(subplot, **d)
- (<AxesSubplot:...>,
+ (<Axes...>,
<matplotlib.ticker.MaxNLocator object at ...>,
<matplotlib.ticker.MaxNLocator object at ...>,
<matplotlib.ticker.ScalarFormatter object at ...>,
diff --git a/src/sage/plot/multigraphics.py b/src/sage/plot/multigraphics.py
index 99c817f03a6..ae85183dc93 100644
--- a/src/sage/plot/multigraphics.py
+++ b/src/sage/plot/multigraphics.py
@@ -1207,7 +1207,7 @@ def _add_subplot(self, figure, index, **options):
sage: fig = Figure()
sage: ax1 = G._add_subplot(fig, 0)
sage: type(ax1)
- <class 'matplotlib.axes._subplots.AxesSubplot'>
+ <class 'matplotlib.axes...'>
sage: ax2 = G._add_subplot(fig, 1)
sage: fig.get_axes() == [ax1, ax2]
True
diff --git a/src/sage/plot/plot3d/plot_field3d.py b/src/sage/plot/plot3d/plot_field3d.py
index bdf39391d3e..fe10e27f58f 100644
--- a/src/sage/plot/plot3d/plot_field3d.py
+++ b/src/sage/plot/plot3d/plot_field3d.py
@@ -126,9 +126,9 @@ def plot_vector_field3d(functions, xrange, yrange, zrange,
vectors = [vector((ff(*point), gg(*point), hh(*point))) for point in points]
try:
- from matplotlib.cm import get_cmap
- cm = get_cmap(colors)
- except (TypeError, ValueError):
+ import matplotlib as mpl
+ cm = mpl.colormaps[colors]
+ except (TypeError, KeyError):
cm = None
if cm is None:
if isinstance(colors, (list, tuple)):

View file

@ -0,0 +1,56 @@
diff --git a/src/sage/interfaces/maxima_lib.py b/src/sage/interfaces/maxima_lib.py
index c9ca5e30939..9459cb70334 100644
--- a/src/sage/interfaces/maxima_lib.py
+++ b/src/sage/interfaces/maxima_lib.py
@@ -77,6 +77,26 @@
sage: bar == foo
True
+TESTS:
+
+Check our workaround for a race in ecl works, see :trac:`26968`.
+We use a temporary `MAXIMA_USERDIR` so it's empty; we place it
+in `DOT_SAGE` since we expect it to have more latency than `/tmp`.
+
+ sage: import tempfile, subprocess
+ sage: tmpdir = tempfile.TemporaryDirectory(dir=DOT_SAGE)
+ sage: _ = subprocess.run(['sage', '-c', # long time
+ ....: f'''
+ ....: import os
+ ....: os.environ["MAXIMA_USERDIR"] = "{tmpdir.name}"
+ ....: if not os.fork():
+ ....: import sage.interfaces.maxima_lib
+ ....: else:
+ ....: import sage.interfaces.maxima_lib
+ ....: os.wait()
+ ....: '''])
+ sage: tmpdir.cleanup()
+
"""
# ****************************************************************************
@@ -116,7 +136,23 @@
ecl_eval("(setq $nolabels t))")
ecl_eval("(defvar *MAXIMA-LANG-SUBDIR* NIL)")
ecl_eval("(set-locale-subdir)")
-ecl_eval("(set-pathnames)")
+
+try:
+ ecl_eval("(set-pathnames)")
+except RuntimeError:
+ # Recover from :trac:`26968` by creating `*maxima-objdir*` here.
+ # This cannot be done before calling `(set-pathnames)` since
+ # `*maxima-objdir*` is computed there.
+ # We use python `os.makedirs()` which is immune to the race.
+ # Using `(ensure-directories-exist ...)` in lisp would be
+ # subject to the same race condition and since `*maxima-objdir*`
+ # has multiple components this is quite plausible to happen.
+ maxima_objdir = ecl_eval("*maxima-objdir*").python()[1:-1]
+ import os
+ os.makedirs(maxima_objdir, exist_ok=True)
+ # Call `(set-pathnames)` again to complete its job.
+ ecl_eval("(set-pathnames)")
+
ecl_eval("(defun add-lineinfo (x) x)")
ecl_eval('(defun principal nil (cond ($noprincipal (diverg)) ((not pcprntd) (merror "Divergent Integral"))))')
ecl_eval("(remprop 'mfactorial 'grind)") # don't use ! for factorials (#11539)

View file

@ -0,0 +1,28 @@
diff --git a/src/bin/sage-cleaner b/src/bin/sage-cleaner
index e2e578eec60..dc7d8f0482e 100755
--- a/src/bin/sage-cleaner
+++ b/src/bin/sage-cleaner
@@ -99,6 +99,15 @@ def cleanup():
return len(pid_list)
+def cleanup_cruft():
+ """ remove directories leftover from improper shutdown """
+ tmp_dirs = os.listdir(SAGE_TMP_ROOT)
+ for dir_entry in tmp_dirs:
+ baddir = os.path.join(SAGE_TMP_ROOT, dir_entry)
+ if os.path.isdir(baddir):
+ logger.warning('Removing old directory %s from SAGE_TMP_ROOT', baddir)
+ rm_rf(baddir)
+
def kill_spawned_jobs(jobfile, parent_pid):
logger.info("Killing %s's spawned jobs", parent_pid)
killed_them_all = True
@@ -193,6 +202,7 @@ if __name__ == '__main__':
setup_daemon()
fix_old_mistakes()
logger.info("Starting sage-cleaner with PID %s", os.getpid())
+ cleanup_cruft()
if len(sys.argv) > 1:
wait = int(sys.argv[1])

View file

@ -0,0 +1,35 @@
diff --git a/src/sage/graphs/generators/families.py b/src/sage/graphs/generators/families.py
index ec6a5c19e60..9dd7bc1cb1e 100644
--- a/src/sage/graphs/generators/families.py
+++ b/src/sage/graphs/generators/families.py
@@ -3660,7 +3660,7 @@ def nauty_gentreeg(options="", debug=False):
sage: gen = graphs.nauty_gentreeg("4", debug=True)
sage: print(next(gen))
- >A ...gentreeg Z=2:3 D=3 n=4
+ >A ...gentreeg ...
sage: gen = graphs.nauty_gentreeg("4 -q", debug=True)
sage: next(gen)
''
@@ -3687,7 +3687,7 @@ def nauty_gentreeg(options="", debug=False):
sage: list(graphs.nauty_gentreeg("3 -x", debug=True))
['>E Usage: ...gentreeg [-D#] [-Z#:#] [-ulps] [-q] n [res/mod] ...
sage: list(graphs.nauty_gentreeg("3", debug=True))
- ['>A ...gentreeg Z=2:2 D=2 n=3\n', Graph on 3 vertices]
+ ['>A ...gentreeg ...\n', Graph on 3 vertices]
"""
import shlex
from sage.features.nauty import NautyExecutable
diff --git a/src/sage/graphs/graph_generators.py b/src/sage/graphs/graph_generators.py
index df88bbe2713..1a8016976c2 100644
--- a/src/sage/graphs/graph_generators.py
+++ b/src/sage/graphs/graph_generators.py
@@ -966,7 +966,7 @@ def nauty_geng(self, options="", debug=False):
...
ValueError: wrong format of parameter option
sage: list(graphs.nauty_geng("-c3", debug=True))
- ['>E Usage: ...geng [-cCmtfbd#D#] [-uygsnh] [-lvq] ...
+ ['>E Usage: ...geng ...\n']
sage: list(graphs.nauty_geng("-c 3", debug=True))
['>A ...geng -cd1D2 n=3 e=2-3\n', Graph on 3 vertices, Graph on 3 vertices]
"""

View file

@ -0,0 +1,51 @@
diff --git a/src/sage/repl/inputhook.py b/src/sage/repl/inputhook.py
index da5df0268c0..7f7894f6dcf 100644
--- a/src/sage/repl/inputhook.py
+++ b/src/sage/repl/inputhook.py
@@ -17,6 +17,8 @@
import select
import errno
+import contextlib
+import io
from IPython import get_ipython
from IPython.terminal.pt_inputhooks import register
@@ -47,15 +49,27 @@ def install():
"""
Install the Sage input hook
- EXAMPLES::
+ EXAMPLES:
+
+ Make sure ipython is running so we really test this function::
+
+ sage: from sage.repl.interpreter import get_test_shell
+ sage: get_test_shell()
+ <sage.repl.interpreter.SageTestShell object at ...>
+
+ Run the function twice, to check it is idempotent (see :trac:`35235`)::
sage: from sage.repl.inputhook import install
sage: install()
+ sage: install()
"""
ip = get_ipython()
if not ip:
return # Not running in ipython, e.g. doctests
- ip.enable_gui('sage')
+ if ip._inputhook != sage_inputhook:
+ # silence `ip.enable_gui()` useless output
+ with contextlib.redirect_stdout(io.StringIO()):
+ ip.enable_gui('sage')
def uninstall():
@@ -71,4 +85,6 @@ def uninstall():
if not ip:
return
if ip._inputhook == sage_inputhook:
- ip.enable_gui(None)
+ # silence `ip.enable_gui()` useless output
+ with contextlib.redirect_stdout(io.StringIO()):
+ ip.enable_gui(None)

View file

@ -0,0 +1,41 @@
From 532fbbaf71bb41c73920b584108eb2a09d6deeb1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gonzalo=20Tornar=C3=ADa?= <tornaria@cmat.edu.uy>
Date: Tue, 4 Apr 2023 12:56:57 -0300
Subject: [PATCH] Ignore deprecation warnings triggered by pythran 0.12.1
These happen with python 3.11, setuptools 67.6.1, numpy 1.24.2.
When pythran 0.12.1 is installed, I get 24 doctest failures due to
deprecation warnings; they are all gone with this commit.
[backported from 839a6e928c264a9863bd42860c78ae95a6d9f3e0]
---
src/sage/all.py | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/src/sage/all.py b/src/sage/all.py
index 93588df1b93..ee775aad0e9 100644
--- a/src/sage/all.py
+++ b/src/sage/all.py
@@ -96,9 +96,17 @@ warnings.filterwarnings('ignore', category=DeprecationWarning,
warnings.filterwarnings('ignore', category=DeprecationWarning,
module='(.*[.]_vendor[.])?packaging')
-# Ignore numpy warnings triggered by pythran
+# Ignore a few warnings triggered by pythran 0.12.1
warnings.filterwarnings('ignore', category=DeprecationWarning,
- module='pythran')
+ message='\n\n `numpy.distutils` is deprecated since NumPy 1.23.0',
+ module='pythran.dist')
+warnings.filterwarnings('ignore', category=DeprecationWarning,
+ message='pkg_resources is deprecated as an API|'
+ 'Deprecated call to `pkg_resources.declare_namespace(.*)`',
+ module='pkg_resources')
+warnings.filterwarnings('ignore', category=DeprecationWarning,
+ message='msvccompiler is deprecated and slated to be removed',
+ module='distutils.msvccompiler')
warnings.filterwarnings('ignore', category=DeprecationWarning,
message='The distutils(.sysconfig module| package) is deprecated',
--
2.40.0

View file

@ -0,0 +1,81 @@
diff --git a/src/sage/graphs/graph.py b/src/sage/graphs/graph.py
index c2e42bcbd3..b6a10efbf4 100644
--- a/src/sage/graphs/graph.py
+++ b/src/sage/graphs/graph.py
@@ -6786,13 +6786,21 @@ def cliques_number_of(self, vertices=None, cliques=None):
{(0, 0): 2, (0, 1): 3, (0, 2): 2, (1, 0): 2, (1, 1): 3, (1, 2): 2}
sage: F.cliques_number_of(vertices=[(0, 1), (1, 2)])
{(0, 1): 3, (1, 2): 2}
+ sage: F.cliques_number_of(vertices=(0, 1))
+ 3
sage: G = Graph({0:[1,2,3], 1:[2], 3:[0,1]})
sage: G.show(figsize=[2,2])
sage: G.cliques_number_of()
{0: 2, 1: 2, 2: 1, 3: 1}
"""
- import networkx
- return networkx.number_of_cliques(self.networkx_graph(), vertices, cliques)
+ if cliques is None:
+ cliques = self.cliques_maximal()
+
+ if vertices in self: # single vertex
+ return sum(1 for c in cliques if vertices in c)
+ else:
+ return { v : sum(1 for c in cliques if v in c)
+ for v in vertices or self }
@doc_index("Clique-related methods")
def cliques_get_max_clique_graph(self):
@@ -7493,17 +7501,32 @@ def cliques_containing_vertex(self, vertices=None, cliques=None):
sage: C = Graph('DJ{')
sage: C.cliques_containing_vertex()
- {0: [[4, 0]], 1: [[4, 1, 2, 3]], 2: [[4, 1, 2, 3]], 3: [[4, 1, 2, 3]], 4: [[4, 0], [4, 1, 2, 3]]}
+ {0: [[0, 4]],
+ 1: [[1, 2, 3, 4]],
+ 2: [[1, 2, 3, 4]],
+ 3: [[1, 2, 3, 4]],
+ 4: [[0, 4], [1, 2, 3, 4]]}
+ sage: C.cliques_containing_vertex(4)
+ [[0, 4], [1, 2, 3, 4]]
+ sage: C.cliques_containing_vertex([0, 1])
+ {0: [[0, 4]], 1: [[1, 2, 3, 4]]}
sage: E = C.cliques_maximal()
sage: E
[[0, 4], [1, 2, 3, 4]]
sage: C.cliques_containing_vertex(cliques=E)
- {0: [[0, 4]], 1: [[1, 2, 3, 4]], 2: [[1, 2, 3, 4]], 3: [[1, 2, 3, 4]], 4: [[0, 4], [1, 2, 3, 4]]}
+ {0: [[0, 4]],
+ 1: [[1, 2, 3, 4]],
+ 2: [[1, 2, 3, 4]],
+ 3: [[1, 2, 3, 4]],
+ 4: [[0, 4], [1, 2, 3, 4]]}
sage: G = Graph({0:[1,2,3], 1:[2], 3:[0,1]})
sage: G.show(figsize=[2,2])
sage: G.cliques_containing_vertex()
- {0: [[0, 1, 2], [0, 1, 3]], 1: [[0, 1, 2], [0, 1, 3]], 2: [[0, 1, 2]], 3: [[0, 1, 3]]}
+ {0: [[0, 1, 2], [0, 1, 3]],
+ 1: [[0, 1, 2], [0, 1, 3]],
+ 2: [[0, 1, 2]],
+ 3: [[0, 1, 3]]}
Since each clique of a 2 dimensional grid corresponds to an edge, the
number of cliques in which a vertex is involved equals its degree::
@@ -7518,8 +7541,14 @@ def cliques_containing_vertex(self, vertices=None, cliques=None):
sage: sorted(sorted(x for x in L) for L in d[(0, 1)])
[[(0, 0), (0, 1)], [(0, 1), (0, 2)], [(0, 1), (1, 1)]]
"""
- import networkx
- return networkx.cliques_containing_node(self.networkx_graph(), vertices, cliques)
+ if cliques is None:
+ cliques = self.cliques_maximal()
+
+ if vertices in self: # single vertex
+ return [c for c in cliques if vertices in c]
+ else:
+ return { v : [c for c in cliques if v in c]
+ for v in vertices or self }
@doc_index("Clique-related methods")
def clique_complex(self):

View file

@ -19,7 +19,7 @@ get_trac() {
ticket=$1
desc=$(echo "$2" | sed -e 's/ /_/g')
commit=$3
$DO wget "$URL_BASE_COMPARE$commit.diff" -O "trac-$ticket-$desc-$commit.patch"
$DO wget "$URL_BASE_COMPARE$commit.diff" -O "$ticket-$desc-$commit.patch"
}
# run from patches dir
@ -29,13 +29,35 @@ cd $(dirname "$0")
get_trac 34851 "support singular 4.3.1.p3" 5e5737a0c
get_pr 35068 "fix tests giac 1.9.0.35" patch
# positive review
# merged in 10.0.beta1
get_pr 35058 "skip unstable tests klyachko"
# merged in 10.0.beta2
get_pr 34994 "fix tests numpy 1.24"
get_pr 34997 "fix edge case of integer_check"
get_pr 35058 "skip unstable tests klyachko"
# merged in 10.0.beta3
get_pr 34995 "support tachyon 0.99.2"
# merged in 10.0.beta4
get_pr 34980 "avoid factoring in is_prime"
# merged in 10.0.beta5
get_pr 35094 "support gap 4.12" # includes PR 35093
# needs review
get_pr 34995 "support tachyon 0.99.2"
get_pr 34980 "avoid factoring in is_prime"
# merged in 10.0.beta6
get_pr 35127 "fix very slow test stream.py"
get_pr 35177 "matplotlib 3.7"
get_pr 35195 "workaround ecl race"
get_pr 35204 "fix sage-cleaner"
# merged in 10.0.beta7
get_pr 35250 "nauty 2.8.6"
# merged in 10.0.beta8
#get_pr 35337 "ipython 8.11"
get_pr 35423 "ipython 8.12" # includes PR 35337
get_pr 35438 "pythran 0.12.1"
# needs review
get_pr 35584 "networkx 3.1"

View file

@ -1,7 +1,7 @@
# Template file for 'sagemath'
pkgname=sagemath
version=9.8
revision=1
revision=2
build_wrksrc=pkgs/sagemath-standard
build_style=python3-module
_bindir=/usr/lib/sagemath/$version/bin
@ -26,7 +26,7 @@ depends="FlintQS eclib-devel fflas-ffpack flintlib-devel gcc-fortran gd-devel
python3-sympy python3-traitlets sage-data-combinatorial_designs
sage-data-conway_polynomials sage-data-elliptic_curves sage-data-graphs
sage-data-polytopes_db sympow tachyon threejs-sage"
checkdepends="$depends"
checkdepends="$depends pythran python3-Sphinx"
short_desc="Open source mathematics software"
maintainer="Gonzalo Tornaría <tornaria@cmat.edu.uy>"
license="GPL-2.0-or-later"