diff options
-rw-r--r-- | .SRCINFO | 26 | ||||
-rw-r--r-- | PKGBUILD | 38 | ||||
-rw-r--r-- | sagemath-cremona.patch | 4 | ||||
-rw-r--r-- | sagemath-ecl-sigfpe.patch | 23 | ||||
-rw-r--r-- | sagemath-env.patch | 9 | ||||
-rw-r--r-- | sagemath-gap-4.10.patch | 4342 | ||||
-rw-r--r-- | sagemath-gap-4.8.patch | 26 | ||||
-rw-r--r-- | sagemath-networkx-2.2.patch | 18 | ||||
-rw-r--r-- | sagemath-python3-notebook.patch | 2 | ||||
-rw-r--r-- | sagemath-singular-4.1.1.p4.patch | 78 | ||||
-rw-r--r-- | sagemath-sphinx-1.8.patch | 6 | ||||
-rw-r--r-- | test-optional.patch | 2 |
12 files changed, 4496 insertions, 78 deletions
@@ -1,6 +1,6 @@ pkgbase = sagemath-git pkgdesc = Open Source Mathematics Software, free alternative to Magma, Maple, Mathematica, and Matlab - pkgver = 8.5.beta6.r0.gd45ef02048 + pkgver = 8.5.r0.g934b744f65 pkgrel = 1 url = http://www.sagemath.org arch = x86_64 @@ -40,7 +40,7 @@ pkgbase = sagemath-git depends = python2-networkx depends = python2-pillow depends = python2-future - depends = libgap + depends = gap depends = flintqs depends = lcalc depends = lrcalc @@ -83,7 +83,6 @@ pkgbase = sagemath-git optdepends = ffmpeg: to export animations to video optdepends = imagemagick: to show animations optdepends = coxeter: Coxeter groups implementation - optdepends = gap-4.8-data: for computing Galois groups optdepends = lrs: Algorithms for linear reverse search used in game theory and for computing volume of polytopes optdepends = libfes: exhaustive search of solutions for boolean equations optdepends = python2-pynormaliz: Normaliz backend for polyhedral computations @@ -105,23 +104,27 @@ pkgbase = sagemath-git source = fes02.patch source = sagemath-threejs.patch source = sagemath-cremona.patch - source = sagemath-gap-4.8.patch + source = sagemath-gap-4.10.patch source = sagemath-sphinx-1.8.patch source = sagemath-networkx-2.2.patch source = sagemath-cypari2.patch + source = sagemath-singular-4.1.1.p4.patch + source = sagemath-ecl-sigfpe.patch sha256sums = SKIP - sha256sums = a5473aeb082a9c5d5ecb02a81f10ea3a9efd014a77c1c609e0cedbca8cdf2b91 + sha256sums = f26ab0f22d7d916a621f02b9d9fc806eb6825f8d34cdf45accb0e2601c82f049 sha256sums = 960afe4fcbffe2762b66119b8f14355386ced0d8ee52b535d0dac1dba90d365b sha256sums = ef265f88ceb6caf4aac2d86ea74850861d99a63d11c94fc52b2ce88053c26d1e - sha256sums = 769fd5a9c377be61de41e1e30004dadb23818da901cceb6e1bece7712ba7cb83 - sha256sums = 3a0ebda1df708f263be830751cc5ddb430ca1f685b25b08d4b6592b65b123ebe + sha256sums = bd2744c6564bbf71bd6ea3cd7b9031e2126cc1423bcdc1fcc258d90d750a129d + sha256sums = f12bd2a53ad51549015093aacc89978f4d796d9ab5bcd3d737aa0d57a5815b54 sha256sums = 7fcb52e96935dccb0f958d37c2f4e3918392480b9af53e08562f6cba6c68cb94 sha256sums = f6b48abf34f64ea3fc092b0f0179e89633f7d3ecc0d62c2acacbfa1217751d63 - sha256sums = 7efb38ba511037feb3abbd88576323320555ba50235ddc7e3d423ca294dd42ed - sha256sums = 79bce829e2ba3050e14cf66f8d4346852cd02febf937575eec53b885163d5a10 - sha256sums = 7dd2ab94fddda8e7c2cdd5250642c4cdd00b7702815d88762fbcd68416bacaee - sha256sums = a011fac2db31c3076fb8fc59e959fd9a9dc785ad3897f4fe3b3bd00b466cde83 + sha256sums = 4c6df9e4e5a7b29ecf6189eda3e5a79f69b6e1b4d29c1b9559663149b8c0af96 + sha256sums = 224f8d1db783d7ae25408912c4891687d6a8a1dacc8c5b3a00b725a28d951b6c + sha256sums = 22f5e44a42c8276025b8512f45cac1c36d576c29c7fd9d36fde8b19ff87867d8 + sha256sums = c19afd209d1f0caf072a43e0f6447c61cae8cf1583f3f89e27c48c8302542c26 sha256sums = 1677bcaa3fe19bf978b6ffaae7b64b7ec32df63fa3d0e28b179cfa831fcfa896 + sha256sums = 482887fe43d89cef3270e89300ab9e2238fa74cd5b7c875688b68fb1b10c4fdf + sha256sums = 87bf055de0a233e9599c59a86f64b4502be31fda53ba0a426f94f25f17ca76df pkgname = sagemath-git optdepends = cython2: to compile cython code @@ -138,7 +141,6 @@ pkgname = sagemath-git optdepends = ffmpeg: to export animations to video optdepends = imagemagick: to show animations optdepends = coxeter: Coxeter groups implementation - optdepends = gap-4.8-data: for computing Galois groups optdepends = lrs: Algorithms for linear reverse search used in game theory and for computing volume of polytopes optdepends = libfes: exhaustive search of solutions for boolean equations optdepends = python2-pynormaliz: Normaliz backend for polyhedral computations @@ -7,14 +7,14 @@ pkgbase=sagemath-git pkgname=(sagemath-git sagemath-jupyter-git) -pkgver=8.5.beta6.r0.gd45ef02048 +pkgver=8.5.r0.g934b744f65 pkgrel=1 pkgdesc="Open Source Mathematics Software, free alternative to Magma, Maple, Mathematica, and Matlab" arch=(x86_64) url="http://www.sagemath.org" license=(GPL) depends=(ipython2 ppl palp brial cliquer maxima-ecl gfan sympow nauty python2-rpy2 python2-fpylll python2-psutil python2-cypari2 - python2-matplotlib python2-scipy python2-sympy python2-networkx python2-pillow python2-future libgap flintqs lcalc lrcalc arb + python2-matplotlib python2-scipy python2-sympy python2-networkx python2-pillow python2-future gap flintqs lcalc lrcalc arb eclib gmp-ecm zn_poly gd python2-cvxopt pynac linbox m4rie rubiks pari-galdata pari-seadata-small planarity rankwidth tachyon sage-data-combinatorial_designs sage-data-elliptic_curves sage-data-graphs sage-data-polytopes_db sage-data-conway_polynomials libgiac libhomfly libbraiding three.js openblas) @@ -24,7 +24,7 @@ optdepends=('cython2: to compile cython code' 'python2-pkgconfig: to compile cyt 'coin-or-cbc: COIN backend for numerical computations' 'coin-or-csdp: for computing Lovász theta-function of graphs' 'buckygen: for generating fullerene graphs' 'plantri: for generating some classes of graphs' 'benzene: for generating fusenes and benzenoids' 'ffmpeg: to export animations to video' 'imagemagick: to show animations' - 'coxeter: Coxeter groups implementation' 'gap-4.8-data: for computing Galois groups' + 'coxeter: Coxeter groups implementation' 'lrs: Algorithms for linear reverse search used in game theory and for computing volume of polytopes' 'libfes: exhaustive search of solutions for boolean equations' 'python2-pynormaliz: Normaliz backend for polyhedral computations' 'latte-integrale: integral point count in polyhedra' 'polymake: polymake backend for polyhedral computations' @@ -43,23 +43,27 @@ source=(git://git.sagemath.org/sage.git#branch=develop fes02.patch sagemath-threejs.patch sagemath-cremona.patch - sagemath-gap-4.8.patch + sagemath-gap-4.10.patch sagemath-sphinx-1.8.patch sagemath-networkx-2.2.patch - sagemath-cypari2.patch) + sagemath-cypari2.patch + sagemath-singular-4.1.1.p4.patch + sagemath-ecl-sigfpe.patch) sha256sums=('SKIP' - 'a5473aeb082a9c5d5ecb02a81f10ea3a9efd014a77c1c609e0cedbca8cdf2b91' + 'f26ab0f22d7d916a621f02b9d9fc806eb6825f8d34cdf45accb0e2601c82f049' '960afe4fcbffe2762b66119b8f14355386ced0d8ee52b535d0dac1dba90d365b' 'ef265f88ceb6caf4aac2d86ea74850861d99a63d11c94fc52b2ce88053c26d1e' - '769fd5a9c377be61de41e1e30004dadb23818da901cceb6e1bece7712ba7cb83' - '3a0ebda1df708f263be830751cc5ddb430ca1f685b25b08d4b6592b65b123ebe' + 'bd2744c6564bbf71bd6ea3cd7b9031e2126cc1423bcdc1fcc258d90d750a129d' + 'f12bd2a53ad51549015093aacc89978f4d796d9ab5bcd3d737aa0d57a5815b54' '7fcb52e96935dccb0f958d37c2f4e3918392480b9af53e08562f6cba6c68cb94' 'f6b48abf34f64ea3fc092b0f0179e89633f7d3ecc0d62c2acacbfa1217751d63' - '7efb38ba511037feb3abbd88576323320555ba50235ddc7e3d423ca294dd42ed' - '79bce829e2ba3050e14cf66f8d4346852cd02febf937575eec53b885163d5a10' - '7dd2ab94fddda8e7c2cdd5250642c4cdd00b7702815d88762fbcd68416bacaee' - 'a011fac2db31c3076fb8fc59e959fd9a9dc785ad3897f4fe3b3bd00b466cde83' - '1677bcaa3fe19bf978b6ffaae7b64b7ec32df63fa3d0e28b179cfa831fcfa896') + '4c6df9e4e5a7b29ecf6189eda3e5a79f69b6e1b4d29c1b9559663149b8c0af96' + '224f8d1db783d7ae25408912c4891687d6a8a1dacc8c5b3a00b725a28d951b6c' + '22f5e44a42c8276025b8512f45cac1c36d576c29c7fd9d36fde8b19ff87867d8' + 'c19afd209d1f0caf072a43e0f6447c61cae8cf1583f3f89e27c48c8302542c26' + '1677bcaa3fe19bf978b6ffaae7b64b7ec32df63fa3d0e28b179cfa831fcfa896' + '482887fe43d89cef3270e89300ab9e2238fa74cd5b7c875688b68fb1b10c4fdf' + '87bf055de0a233e9599c59a86f64b4502be31fda53ba0a426f94f25f17ca76df') pkgver() { cd sage @@ -82,8 +86,6 @@ prepare(){ patch -p1 -i ../sagemath-python3-notebook.patch # fix three.js plotting backend patch -p1 -i ../sagemath-threejs.patch -# Adjust paths for gap-4.8 - patch -p1 -i ../sagemath-gap-4.8.patch # fix introspection with sphinx 1.8 patch -p1 -i ../sagemath-sphinx-1.8.patch @@ -96,6 +98,12 @@ prepare(){ patch -p1 -i ../sagemath-networkx-2.2.patch # Fix build with cypari 2.0 https://trac.sagemath.org/ticket/26442 patch -p1 -i ../sagemath-cypari2.patch +# Build with GAP 4.10 https://trac.sagemath.org/ticket/22626 + patch -p1 -i ../sagemath-gap-4.10.patch +# Fixes for singular 4.1.1p4 https://trac.sagemath.org/ticket/25993 + patch -p1 -i ../sagemath-singular-4.1.1.p4.patch +# Fix SIGFPE crashes with ecl 16.1.3 https://trac.sagemath.org/ticket/22191 + patch -p1 -i ../sagemath-ecl-sigfpe.patch # use python2 sed -e 's|sage-python23|python2|' -e 's|#!/usr/bin/env python\b|#!/usr/bin/env python2|' -i src/bin/* diff --git a/sagemath-cremona.patch b/sagemath-cremona.patch index 4daa387c16bf..b7ad86ffabd5 100644 --- a/sagemath-cremona.patch +++ b/sagemath-cremona.patch @@ -11,7 +11,7 @@ index 3f8dd62..ed5726a 100644 from sage.env import CREMONA_MINI_DATA_DIR, CREMONA_LARGE_DATA_DIR from sage.misc.all import walltime -@@ -825,7 +825,7 @@ class MiniCremonaDatabase(SQLDatabase): +@@ -835,7 +835,7 @@ class MiniCremonaDatabase(SQLDatabase): if N < self.largest_conductor(): message = "There is no elliptic curve with label " + label \ + " in the database" @@ -20,7 +20,7 @@ index 3f8dd62..ed5726a 100644 message = "There is no elliptic curve with label " + label \ + " in the currently available databases" else: -@@ -1673,7 +1673,7 @@ def CremonaDatabase(name=None,mini=None,set_global=None): +@@ -1683,7 +1683,7 @@ def CremonaDatabase(name=None,mini=None,set_global=None): if name is None and not set_global: return _db if set_global and name is None: diff --git a/sagemath-ecl-sigfpe.patch b/sagemath-ecl-sigfpe.patch new file mode 100644 index 000000000000..f3d06fdd972e --- /dev/null +++ b/sagemath-ecl-sigfpe.patch @@ -0,0 +1,23 @@ +diff --git a/src/sage/libs/ecl.pyx b/src/sage/libs/ecl.pyx +index 1fafb6c..4f730ad 100644 +--- a/src/sage/libs/ecl.pyx ++++ b/src/sage/libs/ecl.pyx +@@ -321,6 +321,7 @@ def init_ecl(): + """)) + safe_funcall_clobj=cl_eval(string_to_object(b"(symbol-function 'sage-safe-funcall)")) + ++ cl_eval(string_to_object("(si::trap-fpe T NIL)")) + ecl_has_booted = 1 + + cdef cl_object ecl_safe_eval(cl_object form) except NULL: +--- sage-8.5/src/sage/interfaces/maxima_lib.py.orig 2018-12-23 21:59:46.431420340 +0000 ++++ sage-8.5/src/sage/interfaces/maxima_lib.py 2018-12-23 22:00:05.494568891 +0000 +@@ -107,6 +107,7 @@ + else: + ecl_eval("(require 'maxima)") + ecl_eval("(in-package :maxima)") ++ecl_eval("(si::trap-fpe 'floating-point-overflow nil)") + ecl_eval("(setq $nolabels t))") + ecl_eval("(defvar *MAXIMA-LANG-SUBDIR* NIL)") + ecl_eval("(set-locale-subdir)") + diff --git a/sagemath-env.patch b/sagemath-env.patch index 12665735492d..787775214379 100644 --- a/sagemath-env.patch +++ b/sagemath-env.patch @@ -160,12 +160,3 @@ try: sitepackages_dirs = site.getsitepackages() -@@ -164,7 +164,7 @@ - _add_variable_or_fallback('GRAPHS_DATA_DIR', opj('$SAGE_SHARE','graphs')) - _add_variable_or_fallback('ELLCURVE_DATA_DIR',opj('$SAGE_SHARE','ellcurves')) - _add_variable_or_fallback('POLYTOPE_DATA_DIR',opj('$SAGE_SHARE','reflexive_polytopes')) --_add_variable_or_fallback('GAP_ROOT_DIR', opj('$SAGE_LOCAL','gap','latest')) -+_add_variable_or_fallback('GAP_ROOT_DIR', opj('$SAGE_LOCAL','lib','gap-4.8')) - _add_variable_or_fallback('THEBE_DIR', opj('$SAGE_SHARE','thebe')) - _add_variable_or_fallback('COMBINATORIAL_DESIGN_DATA_DIR', opj('$SAGE_SHARE', 'combinatorial_designs')) - _add_variable_or_fallback('CREMONA_MINI_DATA_DIR', opj('$SAGE_SHARE', 'cremona')) diff --git a/sagemath-gap-4.10.patch b/sagemath-gap-4.10.patch new file mode 100644 index 000000000000..8adbbc683b63 --- /dev/null +++ b/sagemath-gap-4.10.patch @@ -0,0 +1,4342 @@ +diff --git a/src/doc/en/constructions/groups.rst b/src/doc/en/constructions/groups.rst +index e769171..c771783 100644 +--- a/src/doc/en/constructions/groups.rst ++++ b/src/doc/en/constructions/groups.rst +@@ -163,7 +163,7 @@ If you want to find all the normal subgroups of a permutation group + + sage: G = AlternatingGroup( 5 ) + sage: gap(G).NormalSubgroups() +- [ Group( () ), AlternatingGroup( [ 1 .. 5 ] ) ] ++ [ AlternatingGroup( [ 1 .. 5 ] ), Group( () ) ] + + or + +@@ -171,22 +171,22 @@ or + + sage: G = gap("AlternatingGroup( 5 )") + sage: G.NormalSubgroups() +- [ Group( () ), AlternatingGroup( [ 1 .. 5 ] ) ] ++ [ AlternatingGroup( [ 1 .. 5 ] ), Group( () ) ] + + Here's another way, working more directly with GAP:: + + sage: print(gap.eval("G := AlternatingGroup( 5 )")) + Alt( [ 1 .. 5 ] ) + sage: print(gap.eval("normal := NormalSubgroups( G )")) +- [ Group(()), Alt( [ 1 .. 5 ] ) ] ++ [ Alt( [ 1 .. 5 ] ), Group(()) ] + sage: G = gap.new("DihedralGroup( 10 )") + sage: G.NormalSubgroups() +- [ Group( <identity> of ... ), Group( [ f2 ] ), Group( [ f1, f2 ] ) ] ++ [ Group( [ f1, f2 ] ), Group( [ f2 ] ), Group( <identity> of ... ) ] + sage: print(gap.eval("G := SymmetricGroup( 4 )")) + Sym( [ 1 .. 4 ] ) + sage: print(gap.eval("normal := NormalSubgroups( G );")) +- [ Group(()), Group([ (1,4)(2,3), (1,3)(2,4) ]), Group([ (2,4,3), (1,4) +- (2,3), (1,3)(2,4) ]), Sym( [ 1 .. 4 ] ) ] ++ [ Sym( [ 1 .. 4 ] ), Alt( [ 1 .. 4 ] ), Group([ (1,4)(2,3), (1,3)(2,4) ]), ++ Group(()) ] + + .. index:: + pair: groups; center +diff --git a/src/doc/en/prep/Quickstarts/Abstract-Algebra.rst b/src/doc/en/prep/Quickstarts/Abstract-Algebra.rst +index 042b786..041d6f9 100644 +--- a/src/doc/en/prep/Quickstarts/Abstract-Algebra.rst ++++ b/src/doc/en/prep/Quickstarts/Abstract-Algebra.rst +@@ -85,13 +85,13 @@ rather than just a list of numbers. This can be very powerful. + + sage: for K in D.normal_subgroups(): + ....: print(K) +- Subgroup of (Dihedral group of order 16 as a permutation group) generated by [()] +- Subgroup of (Dihedral group of order 16 as a permutation group) generated by [(1,5)(2,6)(3,7)(4,8)] +- Subgroup of (Dihedral group of order 16 as a permutation group) generated by [(1,3,5,7)(2,4,6,8), (1,5)(2,6)(3,7)(4,8)] +- Subgroup of (Dihedral group of order 16 as a permutation group) generated by [(1,2)(3,8)(4,7)(5,6), (1,3,5,7)(2,4,6,8), (1,5)(2,6)(3,7)(4,8)] +- Subgroup of (Dihedral group of order 16 as a permutation group) generated by [(2,8)(3,7)(4,6), (1,3,5,7)(2,4,6,8), (1,5)(2,6)(3,7)(4,8)] +- Subgroup of (Dihedral group of order 16 as a permutation group) generated by [(1,2,3,4,5,6,7,8), (1,3,5,7)(2,4,6,8), (1,5)(2,6)(3,7)(4,8)] + Subgroup of (Dihedral group of order 16 as a permutation group) generated by [(1,2,3,4,5,6,7,8), (1,8)(2,7)(3,6)(4,5)] ++ Subgroup of (Dihedral group of order 16 as a permutation group) generated by [(1,2,3,4,5,6,7,8), (1,3,5,7)(2,4,6,8), (1,5)(2,6)(3,7)(4,8)] ++ Subgroup of (Dihedral group of order 16 as a permutation group) generated by [(1,3,5,7)(2,4,6,8), (1,5)(2,6)(3,7)(4,8), (1,8)(2,7)(3,6)(4,5)] ++ Subgroup of (Dihedral group of order 16 as a permutation group) generated by [(2,8)(3,7)(4,6), (1,3,5,7)(2,4,6,8), (1,5)(2,6)(3,7)(4,8)] ++ Subgroup of (Dihedral group of order 16 as a permutation group) generated by [(1,3,5,7)(2,4,6,8), (1,5)(2,6)(3,7)(4,8)] ++ Subgroup of (Dihedral group of order 16 as a permutation group) generated by [(1,5)(2,6)(3,7)(4,8)] ++ Subgroup of (Dihedral group of order 16 as a permutation group) generated by [()] + + We can access specific subgroups if we know the generators as a + permutation group. +diff --git a/src/doc/en/thematic_tutorials/group_theory.rst b/src/doc/en/thematic_tutorials/group_theory.rst +index 5d2fba0..868aefa 100644 +--- a/src/doc/en/thematic_tutorials/group_theory.rst ++++ b/src/doc/en/thematic_tutorials/group_theory.rst +@@ -586,7 +586,12 @@ subgroups. :: + + sage: C20 = CyclicPermutationGroup(20) + sage: C20.conjugacy_classes_subgroups() +- [Subgroup of (Cyclic group of order 20 as a permutation group) generated by [()], Subgroup of (Cyclic group of order 20 as a permutation group) generated by [(1,11)(2,12)(3,13)(4,14)(5,15)(6,16)(7,17)(8,18)(9,19)(10,20)], Subgroup of (Cyclic group of order 20 as a permutation group) generated by [(1,6,11,16)(2,7,12,17)(3,8,13,18)(4,9,14,19)(5,10,15,20)], Subgroup of (Cyclic group of order 20 as a permutation group) generated by [(1,5,9,13,17)(2,6,10,14,18)(3,7,11,15,19)(4,8,12,16,20)], Subgroup of (Cyclic group of order 20 as a permutation group) generated by [(1,3,5,7,9,11,13,15,17,19)(2,4,6,8,10,12,14,16,18,20)], Subgroup of (Cyclic group of order 20 as a permutation group) generated by [(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20)]] ++ [Subgroup of (Cyclic group of order 20 as a permutation group) generated by [()], ++ Subgroup of (Cyclic group of order 20 as a permutation group) generated by [(1,11)(2,12)(3,13)(4,14)(5,15)(6,16)(7,17)(8,18)(9,19)(10,20)], ++ Subgroup of (Cyclic group of order 20 as a permutation group) generated by [(1,6,11,16)(2,7,12,17)(3,8,13,18)(4,9,14,19)(5,10,15,20), (1,11)(2,12)(3,13)(4,14)(5,15)(6,16)(7,17)(8,18)(9,19)(10,20)], ++ Subgroup of (Cyclic group of order 20 as a permutation group) generated by [(1,5,9,13,17)(2,6,10,14,18)(3,7,11,15,19)(4,8,12,16,20)], ++ Subgroup of (Cyclic group of order 20 as a permutation group) generated by [(1,3,5,7,9,11,13,15,17,19)(2,4,6,8,10,12,14,16,18,20), (1,5,9,13,17)(2,6,10,14,18)(3,7,11,15,19)(4,8,12,16,20)], ++ Subgroup of (Cyclic group of order 20 as a permutation group) generated by [(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20), (1,3,5,7,9,11,13,15,17,19)(2,4,6,8,10,12,14,16,18,20), (1,5,9,13,17)(2,6,10,14,18)(3,7,11,15,19)(4,8,12,16,20)]] + + Be careful, this command uses some more advanced ideas and will not + usually list *all* of the subgroups of a group. Here we are relying on +@@ -639,10 +644,26 @@ suitable `g`. As an illustration, the code below: + sage: K = DihedralGroup(12) + sage: sg = K.conjugacy_classes_subgroups() + sage: sg +- [Subgroup of (Dihedral group of order 24 as a permutation group) generated by [()], Subgroup of (Dihedral group of order 24 as a permutation group) generated by [(1,2)(3,12)(4,11)(5,10)(6,9)(7,8)], Subgroup of (Dihedral group of order 24 as a permutation group) generated by [(1,7)(2,8)(3,9)(4,10)(5,11)(6,12)], Subgroup of (Dihedral group of order 24 as a permutation group) generated by [(2,12)(3,11)(4,10)(5,9)(6,8)], Subgroup of (Dihedral group of order 24 as a permutation group) generated by [(1,5,9)(2,6,10)(3,7,11)(4,8,12)], Subgroup of (Dihedral group of order 24 as a permutation group) generated by [(2,12)(3,11)(4,10)(5,9)(6,8), (1,7)(2,8)(3,9)(4,10)(5,11)(6,12)], Subgroup of (Dihedral group of order 24 as a permutation group) generated by [(1,2)(3,12)(4,11)(5,10)(6,9)(7,8), (1,7)(2,8)(3,9)(4,10)(5,11)(6,12)], Subgroup of (Dihedral group of order 24 as a permutation group) generated by [(1,7)(2,8)(3,9)(4,10)(5,11)(6,12), (1,10,7,4)(2,11,8,5)(3,12,9,6)], Subgroup of (Dihedral group of order 24 as a permutation group) generated by [(1,3,5,7,9,11)(2,4,6,8,10,12), (1,5,9)(2,6,10)(3,7,11)(4,8,12)], Subgroup of (Dihedral group of order 24 as a permutation group) generated by [(1,2)(3,12)(4,11)(5,10)(6,9)(7,8), (1,5,9)(2,6,10)(3,7,11)(4,8,12)], Subgroup of (Dihedral group of order 24 as a permutation group) generated by [(2,12)(3,11)(4,10)(5,9)(6,8), (1,5,9)(2,6,10)(3,7,11)(4,8,12)], Subgroup of (Dihedral group of order 24 as a permutation group) generated by [(2,12)(3,11)(4,10)(5,9)(6,8), (1,7)(2,8)(3,9)(4,10)(5,11)(6,12), (1,10,7,4)(2,11,8,5)(3,12,9,6)], Subgroup of (Dihedral group of order 24 as a permutation group) generated by [(2,12)(3,11)(4,10)(5,9)(6,8), (1,3,5,7,9,11)(2,4,6,8,10,12), (1,5,9)(2,6,10)(3,7,11)(4,8,12)], Subgroup of (Dihedral group of order 24 as a permutation group) generated by [(1,2)(3,12)(4,11)(5,10)(6,9)(7,8), (1,3,5,7,9,11)(2,4,6,8,10,12), (1,5,9)(2,6,10)(3,7,11)(4,8,12)], Subgroup of (Dihedral group of order 24 as a permutation group) generated by [(1,2,3,4,5,6,7,8,9,10,11,12), (1,3,5,7,9,11)(2,4,6,8,10,12), (1,5,9)(2,6,10)(3,7,11)(4,8,12)], Subgroup of (Dihedral group of order 24 as a permutation group) generated by [(2,12)(3,11)(4,10)(5,9)(6,8), (1,2,3,4,5,6,7,8,9,10,11,12), (1,3,5,7,9,11)(2,4,6,8,10,12), (1,5,9)(2,6,10)(3,7,11)(4,8,12)]] ++ [Subgroup of (Dihedral group of order 24 as a permutation group) generated by [()], ++ Subgroup of (Dihedral group of order 24 as a permutation group) generated by [(1,7)(2,8)(3,9)(4,10)(5,11)(6,12)], ++ Subgroup of (Dihedral group of order 24 as a permutation group) generated by [(2,12)(3,11)(4,10)(5,9)(6,8)], ++ Subgroup of (Dihedral group of order 24 as a permutation group) generated by [(1,2)(3,12)(4,11)(5,10)(6,9)(7,8)], ++ Subgroup of (Dihedral group of order 24 as a permutation group) generated by [(1,5,9)(2,6,10)(3,7,11)(4,8,12)], ++ Subgroup of (Dihedral group of order 24 as a permutation group) generated by [(2,12)(3,11)(4,10)(5,9)(6,8), (1,7)(2,8)(3,9)(4,10)(5,11)(6,12)], ++ Subgroup of (Dihedral group of order 24 as a permutation group) generated by [(1,7)(2,8)(3,9)(4,10)(5,11)(6,12), (1,10,7,4)(2,11,8,5)(3,12,9,6)], ++ Subgroup of (Dihedral group of order 24 as a permutation group) generated by [(1,2)(3,12)(4,11)(5,10)(6,9)(7,8), (1,7)(2,8)(3,9)(4,10)(5,11)(6,12)], ++ Subgroup of (Dihedral group of order 24 as a permutation group) generated by [(1,3,5,7,9,11)(2,4,6,8,10,12), (1,5,9)(2,6,10)(3,7,11)(4,8,12)], ++ Subgroup of (Dihedral group of order 24 as a permutation group) generated by [(2,12)(3,11)(4,10)(5,9)(6,8), (1,5,9)(2,6,10)(3,7,11)(4,8,12)], ++ Subgroup of (Dihedral group of order 24 as a permutation group) generated by [(1,2)(3,12)(4,11)(5,10)(6,9)(7,8), (1,5,9)(2,6,10)(3,7,11)(4,8,12)], ++ Subgroup of (Dihedral group of order 24 as a permutation group) generated by [(2,12)(3,11)(4,10)(5,9)(6,8), (1,7)(2,8)(3,9)(4,10)(5,11)(6,12), (1,10,7,4)(2,11,8,5)(3,12,9,6)], ++ Subgroup of (Dihedral group of order 24 as a permutation group) generated by [(2,12)(3,11)(4,10)(5,9)(6,8), (1,3,5,7,9,11)(2,4,6,8,10,12), (1,5,9)(2,6,10)(3,7,11)(4,8,12)], ++ Subgroup of (Dihedral group of order 24 as a permutation group) generated by [(1,2,3,4,5,6,7,8,9,10,11,12), (1,3,5,7,9,11)(2,4,6,8,10,12), (1,5,9)(2,6,10)(3,7,11)(4,8,12)], ++ Subgroup of (Dihedral group of order 24 as a permutation group) generated by [(1,2)(3,12)(4,11)(5,10)(6,9)(7,8), (1,3,5,7,9,11)(2,4,6,8,10,12), (1,5,9)(2,6,10)(3,7,11)(4,8,12)], ++ Subgroup of (Dihedral group of order 24 as a permutation group) generated by [(2,12)(3,11)(4,10)(5,9)(6,8), (1,2,3,4,5,6,7,8,9,10,11,12), (1,3,5,7,9,11)(2,4,6,8,10,12), (1,5,9)(2,6,10)(3,7,11)(4,8,12)]] ++ + sage: print("An order two subgroup:\n{}".format(sg[1].list())) + An order two subgroup: +- [(), (1,2)(3,12)(4,11)(5,10)(6,9)(7,8)] ++ [(), (1,7)(2,8)(3,9)(4,10)(5,11)(6,12)] + + It is important to note that this is a nice long list of subgroups, + but will rarely create *every* such subgroup. For example, the +diff --git a/src/doc/en/thematic_tutorials/lie/weyl_groups.rst b/src/doc/en/thematic_tutorials/lie/weyl_groups.rst +index c32cd12..64f5436 100644 +--- a/src/doc/en/thematic_tutorials/lie/weyl_groups.rst ++++ b/src/doc/en/thematic_tutorials/lie/weyl_groups.rst +@@ -219,7 +219,7 @@ this as follows:: + sage: def bi(u,v) : return [t for t in W if u.bruhat_le(t) and t.bruhat_le(v)] + ... + sage: bi(s1,s1*s2*s1) +- [s1*s2*s1, s1*s2, s1, s2*s1] ++ [s1*s2, s2*s1, s1, s1*s2*s1] + + This would not be a good definition since it would fail if `W` is + affine and be inefficient of `W` is large. Sage has a Bruhat interval +diff --git a/src/doc/ja/tutorial/tour_groups.rst b/src/doc/ja/tutorial/tour_groups.rst +index d62d8ed..059313a 100644 +--- a/src/doc/ja/tutorial/tour_groups.rst ++++ b/src/doc/ja/tutorial/tour_groups.rst +@@ -21,7 +21,7 @@ Sageでは,置換群,有限古典群(例えば :math:`SU(n,q)`),有限行� + False + sage: G.derived_series() # 結果は変化しがち + [Subgroup of (Permutation Group with generators [(3,4), (1,2,3)(4,5)]) generated by [(3,4), (1,2,3)(4,5)], +- Subgroup of (Permutation Group with generators [(3,4), (1,2,3)(4,5)]) generated by [(1,5,3), (1,5)(3,4), (1,5)(2,4)]] ++ Subgroup of (Permutation Group with generators [(3,4), (1,2,3)(4,5)]) generated by [(1,3,5), (1,5)(3,4), (1,5)(2,4)]] + sage: G.center() + Subgroup of (Permutation Group with generators [(3,4), (1,2,3)(4,5)]) generated by [()] + sage: G.random_element() # random 出力は変化する +diff --git a/src/ext/gap/sage.g b/src/ext/gap/sage.g +index 54fa74f..12402a7 100644 +--- a/src/ext/gap/sage.g ++++ b/src/ext/gap/sage.g +@@ -1,7 +1,22 @@ +- + # + # SAGE support utilities to read into the GAP session. + # ++ ++# Prevent loading the xgap package; we use the -p flag to GAP in order to ++# communicate with it via the pexpect interface; this is normally used by ++# for an xgap window to communicate with GAP, so unfortunatelly setting this ++# flag also allows the xgap package to be loaded and for some packages to ++# attempt to communicate with a "window handler" that doesn't exist. ++# Therefore we must explicitly disable loading of the xgap package. ++# ++# Don't use SetUserPreference since that leads to reloading the workspace, ++# which is confusing to the pexpect interface ++if IsBound(GAPInfo.ExcludeFromAutoload) then ++ Append(GAPInfo.ExcludeFromAutoload, "xgap"); ++else ++ GAPInfo.ExcludeFromAutoload := [ "xgap" ]; ++fi; ++ + \$SAGE := rec(); + + \$SAGE.OldPager := Pager; +@@ -62,19 +77,15 @@ end; + SetAllInfoLevels(0); + + \$SAGE.OperationsAdmittingFirstArgument := function(obj) +- local hits, myflags, i, flagss, flags; +- hits := []; +- myflags := FlagsType(TypeObj(obj)); +- for i in [1,3..Length(OPERATIONS)-1] do +- flagss := OPERATIONS[i+1]; +- for flags in flagss do +- if Length(flags) >= 1 and IS_SUBSET_FLAGS(myflags, flags[1]) then +- Add(hits, OPERATIONS[i]); +- break; +- fi; +- od; +- od; +- return hits; ++ local myflags, mfi; ++ myflags := FlagsObj(obj); ++ mfi := function(o) ++ local f; ++ f := GET_OPER_FLAGS(o); ++ return f<>[] and f[1]<>[] and ++ IS_SUBSET_FLAGS(myflags, f[1][1]); ++ end; ++ return Filtered(OPERATIONS, mfi); + end; + + +diff --git a/src/sage/categories/modules_with_basis.py b/src/sage/categories/modules_with_basis.py +index 3619868..0e56128 100644 +--- a/src/sage/categories/modules_with_basis.py ++++ b/src/sage/categories/modules_with_basis.py +@@ -1201,8 +1201,8 @@ class ModulesWithBasis(CategoryWithAxiom_over_base_ring): + sage: DihedralGroup(6).algebra(QQ).random_element() + -1/95*() - 1/2*(1,4)(2,5)(3,6) + sage: SU(2, 13).algebra(QQ).random_element(1) +- 1/2*[ 3 0] +- [11*a + 1 9] ++ 1/2*[ 5 2*a + 12] ++ [ a + 6 6] + sage: CombinatorialFreeModule(ZZ, Partitions(4)).random_element() # random + 2*B[[2, 1, 1]] + B[[2, 2]] + """ +diff --git a/src/sage/coding/codecan/autgroup_can_label.pyx b/src/sage/coding/codecan/autgroup_can_label.pyx +index 569ce32..fa0eb65 100644 +--- a/src/sage/coding/codecan/autgroup_can_label.pyx ++++ b/src/sage/coding/codecan/autgroup_can_label.pyx +@@ -76,7 +76,7 @@ columns do share the same coloring:: + [[1], + [2], + [3, 5, 4], +- [6, 16, 8, 21, 12, 9, 13, 18, 11, 19, 15, 7, 20, 14, 17, 10]] ++ [6, 19, 9, 21, 16, 14, 11, 20, 15, 8, 10, 12, 7, 13, 18, 17]] + + We can also restrict the group action to linear isometries:: + +diff --git a/src/sage/coding/linear_code.py b/src/sage/coding/linear_code.py +index 18f53b4..b31b869 100644 +--- a/src/sage/coding/linear_code.py ++++ b/src/sage/coding/linear_code.py +@@ -801,27 +801,31 @@ class AbstractLinearCode(Module): + + sage: C = codes.HammingCode(GF(4, 'z'), 3) + sage: C.automorphism_group_gens() +- ([((z, 1, z, z, z, z + 1, 1, z + 1, 1, 1, 1, z + 1, 1, z + 1, z + 1, z + 1, 1, z, 1, z + 1, z); (1,9,5,15,20,13,4)(2,8,12,7,10,14,16,3,21,18,19,6,11,17), Ring endomorphism of Finite Field in z of size 2^2 ++ ([((z, 1, z + 1, z + 1, 1, 1, z + 1, z, z, 1, z + 1, z + 1, z + 1, 1, z, z + 1, 1, z, z + 1, z + 1, z); (1,5,4,2)(6,17,10,20,19,18,12,8)(7,14,15,21,16,9,11,13), Ring endomorphism of Finite Field in z of size 2^2 + Defn: z |--> z + 1), +- ((z, z, z, z, z, 1, z + 1, 1, z + 1, z + 1, z + 1, 1, z, z + 1, z, z, 1, z + 1, 1, 1, 1); (1,10,20,16,6,3,11,19,15,8,5,9,17,12,13)(4,7,21,14,18), Ring endomorphism of Finite Field in z of size 2^2 ++ ((z + 1, 1, z + 1, z + 1, z + 1, z, 1, z, 1, 1, 1, z + 1, z + 1, z, 1, z, z, 1, z, z, z); (1,5,20,19,16,6,4,12,2,18,21,10,11,15,8,14,13,7,3,9,17), Ring endomorphism of Finite Field in z of size 2^2 + Defn: z |--> z), +- ((z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z); (), Ring endomorphism of Finite Field in z of size 2^2 ++ ((z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z); (), Ring endomorphism of Finite Field in z of size 2^2 + Defn: z |--> z)], + 362880) + sage: C.automorphism_group_gens(equivalence="linear") +- ([((z + 1, z + 1, z + 1, z + 1, z + 1, z + 1, z + 1, 1, z + 1, z + 1, z + 1, z + 1, z, z + 1, z + 1, z + 1, z + 1, 1, z + 1, z + 1, z + 1); (1,3,17,20,12,16)(2,18)(4,11,21,9,14,10)(5,15,19)(6,8), Ring endomorphism of Finite Field in z of size 2^2 ++ ([((1, 1, 1, z, z + 1, z, z + 1, 1, 1, z, z + 1, z, 1, 1, z, z + 1, z, 1, 1, z, z + 1); (1,8,3,4,12,13,17,6,18,15,20,5,19,21,16)(2,11,10,9,7), Ring endomorphism of Finite Field in z of size 2^2 + Defn: z |--> z), +- ((z + 1, z, 1, z + 1, z, z + 1, z + 1, z, 1, z + 1, z, z + 1, z, 1, z, z, z + 1, z, 1, 1, z); (1,15,18,20,13,7,21,17,9,11,5,14,19,4,2,16,10,6,8,3,12), Ring endomorphism of Finite Field in z of size 2^2 ++ ((1, z + 1, z, z + 1, z + 1, 1, 1, z + 1, z, z, z + 1, 1, z + 1, z, 1, z + 1, 1, z + 1, z, 1, z + 1); (1,21,12,14,11,5,9,3,15,13,16,20,6,18,19,17,7,4,8,10,2), Ring endomorphism of Finite Field in z of size 2^2 + Defn: z |--> z), +- ((z + 1, z + 1, z + 1, z + 1, z + 1, z + 1, z + 1, z + 1, z + 1, z + 1, z + 1, z + 1, z + 1, z + 1, z + 1, z + 1, z + 1, z + 1, z + 1, z + 1, z + 1); (), Ring endomorphism of Finite Field in z of size 2^2 ++ ((z + 1, z + 1, z + 1, z + 1, z + 1, z + 1, z + 1, z + 1, z + 1, z + 1, z + 1, z + 1, z + 1, z + 1, z + 1, z + 1, z + 1, z + 1, z + 1, z + 1, z + 1); (), Ring endomorphism of Finite Field in z of size 2^2 + Defn: z |--> z)], + 181440) + sage: C.automorphism_group_gens(equivalence="permutational") +- ([((1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); (1,11)(3,10)(4,9)(5,7)(12,21)(14,20)(15,19)(16,17), Ring endomorphism of Finite Field in z of size 2^2 +- Defn: z |--> z), ((1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); (2,18)(3,19)(4,10)(5,16)(8,13)(9,14)(11,21)(15,20), Ring endomorphism of Finite Field in z of size 2^2 +- Defn: z |--> z), ((1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); (1,19)(3,17)(4,21)(5,20)(7,14)(9,12)(10,16)(11,15), Ring endomorphism of Finite Field in z of size 2^2 +- Defn: z |--> z), ((1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); (2,13)(3,14)(4,20)(5,11)(8,18)(9,19)(10,15)(16,21), Ring endomorphism of Finite Field in z of size 2^2 +- Defn: z |--> z)], 64) ++ ([((1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); (1,19)(3,17)(4,21)(5,20)(7,14)(9,12)(10,16)(11,15), Ring endomorphism of Finite Field in z of size 2^2 ++ Defn: z |--> z), ++ ((1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); (1,11)(3,10)(4,9)(5,7)(12,21)(14,20)(15,19)(16,17), Ring endomorphism of Finite Field in z of size 2^2 ++ Defn: z |--> z), ++ ((1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); (1,17)(2,8)(3,14)(4,10)(7,12)(9,19)(13,18)(15,20), Ring endomorphism of Finite Field in z of size 2^2 ++ Defn: z |--> z), ++ ((1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); (2,13)(3,14)(4,20)(5,11)(8,18)(9,19)(10,15)(16,21), Ring endomorphism of Finite Field in z of size 2^2 ++ Defn: z |--> z)], ++ 64) + """ + aut_group_can_label = self._canonize(equivalence) + return aut_group_can_label.get_autom_gens(), \ +@@ -1069,12 +1073,12 @@ class AbstractLinearCode(Module): + sage: C_iso == aut_group_can_label.get_canonical_form() + True + sage: aut_group_can_label.get_autom_gens() +- [((z, 1, z + 1, z, 1, 1, z, 1, z + 1, 1, 1, z, 1, z + 1, z, 1, z, 1, z + 1, z + 1, 1); (1,10,8,21,3,20,2,4,6,18,14,9,12,16,17)(5,15,13,7,19), Ring endomorphism of Finite Field in z of size 2^2 +- Defn: z |--> z), +- ((z + 1, z, z, z + 1, 1, 1, 1, z + 1, z + 1, z, 1, z, z + 1, 1, 1, z + 1, z + 1, 1, 1, z, z); (1,18,17,5,16,3,10,11,8,21,7,12,9,4)(2,19,15,14,6,20,13), Ring endomorphism of Finite Field in z of size 2^2 +- Defn: z |--> z + 1), +- ((z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z); (), Ring endomorphism of Finite Field in z of size 2^2 +- Defn: z |--> z)] ++ [((z + 1, z + 1, z, z, 1, z, z, z, z, z, z, z + 1, z + 1, z + 1, z + 1, z + 1, 1, 1, 1, 1, 1); (1,2,13,11,7,19,4,18)(3,6,20,9,15,12,21,16)(5,8,14,10), Ring endomorphism of Finite Field in z of size 2^2 ++ Defn: z |--> z + 1), ++ ((z, 1, z + 1, 1, 1, 1, z + 1, z + 1, z, 1, 1, 1, z + 1, 1, z, z + 1, 1, z, 1, z + 1, z); (1,17,5,21,12,8,6,10,11,13,4,2,20,9)(3,19,18,15,7,14,16), Ring endomorphism of Finite Field in z of size 2^2 ++ Defn: z |--> z + 1), ++ ((z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z, z); (), Ring endomorphism of Finite Field in z of size 2^2 ++ Defn: z |--> z)] + """ + from sage.coding.codecan.autgroup_can_label import LinearCodeAutGroupCanLabel + return LinearCodeAutGroupCanLabel(self, algorithm_type=equivalence) +diff --git a/src/sage/combinat/root_system/hecke_algebra_representation.py b/src/sage/combinat/root_system/hecke_algebra_representation.py +index 32112c3..6498afb 100644 +--- a/src/sage/combinat/root_system/hecke_algebra_representation.py ++++ b/src/sage/combinat/root_system/hecke_algebra_representation.py +@@ -358,7 +358,7 @@ class HeckeAlgebraRepresentation(WithEqualityById, SageObject): + sage: q1, q2 = K.gens() + sage: KW = W.algebra(K) + sage: x = KW.an_element(); x +- 2*12321 + 3*1231 + 123 + e ++ 123 + 3*32 + 2*3 + e + + sage: T = KW.demazure_lusztig_operators(q1,q2) + sage: T12 = T.Tw( (1,2) ) +diff --git a/src/sage/combinat/root_system/root_system.py b/src/sage/combinat/root_system/root_system.py +index efddfa05..6fb83f1 100644 +--- a/src/sage/combinat/root_system/root_system.py ++++ b/src/sage/combinat/root_system/root_system.py +@@ -207,13 +207,13 @@ class RootSystem(UniqueRepresentation, SageObject): + sage: W = L.weyl_group() + sage: S3 = [ w.action(id) for w in W.classical() ] + sage: [L.classical()(x) for x in S3] +- [(1, 2, 3), (3, 2, 1), (3, 1, 2), (2, 1, 3), (2, 3, 1), (1, 3, 2)] ++ [(1, 2, 3), (3, 1, 2), (2, 3, 1), (2, 1, 3), (1, 3, 2), (3, 2, 1)] + + And the action of `s_0` on these yields:: + + sage: s = W.simple_reflections() + sage: [L.classical()(s[0].action(x)) for x in S3] +- [(0, 2, 4), (-2, 2, 6), (-1, 1, 6), (0, 1, 5), (-2, 3, 5), (-1, 3, 4)] ++ [(0, 2, 4), (-1, 1, 6), (-2, 3, 5), (0, 1, 5), (-1, 3, 4), (-2, 2, 6)] + + We can also plot various components of the ambient spaces:: + +diff --git a/src/sage/combinat/symmetric_group_algebra.py b/src/sage/combinat/symmetric_group_algebra.py +index d5f8637..d89cfca 100644 +--- a/src/sage/combinat/symmetric_group_algebra.py ++++ b/src/sage/combinat/symmetric_group_algebra.py +@@ -103,7 +103,7 @@ def SymmetricGroupAlgebra(R, W, category=None): + sage: SGA.group() + Weyl Group of type ['A', 3] (as a matrix group acting on the ambient space) + sage: SGA.an_element() +- 2*s1*s2*s3*s2*s1 + 3*s1*s2*s3*s1 + s1*s2*s3 + 1 ++ s1*s2*s3 + 3*s3*s2 + 2*s3 + 1 + + The preferred way to construct the symmetric group algebra is to + go through the usual ``algebra`` method:: +diff --git a/src/sage/combinat/tiling.py b/src/sage/combinat/tiling.py +index 580e01a..2f8713a 100644 +--- a/src/sage/combinat/tiling.py ++++ b/src/sage/combinat/tiling.py +@@ -325,21 +325,21 @@ def ncube_isometry_group(n, orientation_preserving=True): + + sage: ncube_isometry_group(3) + [ +- [1 0 0] [ 1 0 0] [-1 0 0] [-1 0 0] [0 0 1] [ 0 0 -1] +- [0 1 0] [ 0 -1 0] [ 0 1 0] [ 0 -1 0] [1 0 0] [ 1 0 0] +- [0 0 1], [ 0 0 -1], [ 0 0 -1], [ 0 0 1], [0 1 0], [ 0 -1 0], ++ [1 0 0] [ 1 0 0] [ 0 1 0] [ 0 0 -1] [ 1 0 0] [ 0 1 0] ++ [0 1 0] [ 0 0 1] [ 0 0 -1] [ 0 -1 0] [ 0 0 -1] [-1 0 0] ++ [0 0 1], [ 0 -1 0], [-1 0 0], [-1 0 0], [ 0 1 0], [ 0 0 1], + <BLANKLINE> +- [ 0 0 -1] [ 0 0 1] [0 1 0] [ 0 -1 0] [ 0 1 0] [ 0 -1 0] +- [-1 0 0] [-1 0 0] [0 0 1] [ 0 0 -1] [ 0 0 -1] [ 0 0 1] +- [ 0 1 0], [ 0 -1 0], [1 0 0], [ 1 0 0], [-1 0 0], [-1 0 0], ++ [ 1 0 0] [ 0 0 1] [0 1 0] [ 0 0 1] [ 0 0 -1] [ 0 -1 0] ++ [ 0 -1 0] [-1 0 0] [0 0 1] [ 0 -1 0] [-1 0 0] [-1 0 0] ++ [ 0 0 -1], [ 0 -1 0], [1 0 0], [ 1 0 0], [ 0 1 0], [ 0 0 -1], + <BLANKLINE> +- [ 0 1 0] [ 0 -1 0] [ 0 1 0] [ 0 -1 0] [ 1 0 0] [ 1 0 0] +- [ 1 0 0] [ 1 0 0] [-1 0 0] [-1 0 0] [ 0 0 -1] [ 0 0 1] +- [ 0 0 -1], [ 0 0 1], [ 0 0 1], [ 0 0 -1], [ 0 1 0], [ 0 -1 0], ++ [ 0 1 0] [ 0 0 1] [ 0 0 -1] [ 0 -1 0] [0 0 1] [ 0 -1 0] ++ [ 1 0 0] [ 0 1 0] [ 1 0 0] [ 0 0 1] [1 0 0] [ 1 0 0] ++ [ 0 0 -1], [-1 0 0], [ 0 -1 0], [-1 0 0], [0 1 0], [ 0 0 1], + <BLANKLINE> +- [-1 0 0] [-1 0 0] [ 0 0 -1] [ 0 0 1] [ 0 0 1] [ 0 0 -1] +- [ 0 0 1] [ 0 0 -1] [ 0 1 0] [ 0 -1 0] [ 0 1 0] [ 0 -1 0] +- [ 0 1 0], [ 0 -1 0], [ 1 0 0], [ 1 0 0], [-1 0 0], [-1 0 0] ++ [-1 0 0] [-1 0 0] [ 0 0 -1] [-1 0 0] [ 0 -1 0] [-1 0 0] ++ [ 0 1 0] [ 0 0 -1] [ 0 1 0] [ 0 0 1] [ 0 0 -1] [ 0 -1 0] ++ [ 0 0 -1], [ 0 -1 0], [ 1 0 0], [ 0 1 0], [ 1 0 0], [ 0 0 1] + ] + + TESTS:: +diff --git a/src/sage/env.py b/src/sage/env.py +index 77e0596..3a64c2d 100644 +--- a/src/sage/env.py ++++ b/src/sage/env.py +@@ -164,7 +164,7 @@ _add_variable_or_fallback('CONWAY_POLYNOMIALS_DATA_DIR', opj('$SAGE_SHARE','con + _add_variable_or_fallback('GRAPHS_DATA_DIR', opj('$SAGE_SHARE','graphs')) + _add_variable_or_fallback('ELLCURVE_DATA_DIR',opj('$SAGE_SHARE','ellcurves')) + _add_variable_or_fallback('POLYTOPE_DATA_DIR',opj('$SAGE_SHARE','reflexive_polytopes')) +-_add_variable_or_fallback('GAP_ROOT_DIR', opj('$SAGE_LOCAL','gap','latest')) ++_add_variable_or_fallback('GAP_ROOT_DIR', opj('$SAGE_SHARE','gap')) + _add_variable_or_fallback('THEBE_DIR', opj('$SAGE_SHARE','thebe')) + _add_variable_or_fallback('COMBINATORIAL_DESIGN_DATA_DIR', opj('$SAGE_SHARE', 'combinatorial_designs')) + _add_variable_or_fallback('CREMONA_MINI_DATA_DIR', opj('$SAGE_SHARE', 'cremona')) +diff --git a/src/sage/graphs/generators/families.py b/src/sage/graphs/generators/families.py +index 8e24817..ac7ea93 100644 +--- a/src/sage/graphs/generators/families.py ++++ b/src/sage/graphs/generators/families.py +@@ -3177,15 +3177,16 @@ def MathonPseudocyclicStronglyRegularGraph(t, G=None, L=None): + sage: ff = list(map(lambda y: (y[0]-1,y[1]-1), + ....: Permutation(map(lambda x: 1+r.index(x^-1), r)).cycle_tuples()[1:])) + sage: L = sum(i*(r[a]-r[b]) for i,(a,b) in zip(range(1,len(ff)+1), ff)); L +- [ 0 -1 1 -2 -3 -4 2 4 3] +- [ 1 0 -1 -4 -2 -3 3 2 4] +- [-1 1 0 -3 -4 -2 4 3 2] +- [ 2 4 3 0 -1 1 -2 -3 -4] +- [ 3 2 4 1 0 -1 -4 -2 -3] +- [ 4 3 2 -1 1 0 -3 -4 -2] +- [-2 -3 -4 2 4 3 0 -1 1] +- [-4 -2 -3 3 2 4 1 0 -1] +- [-3 -4 -2 4 3 2 -1 1 0] ++ [ 0 1 -1 -3 -2 -4 3 4 2] ++ [-1 0 1 -4 -3 -2 2 3 4] ++ [ 1 -1 0 -2 -4 -3 4 2 3] ++ [ 3 4 2 0 1 -1 -3 -2 -4] ++ [ 2 3 4 -1 0 1 -4 -3 -2] ++ [ 4 2 3 1 -1 0 -2 -4 -3] ++ [-3 -2 -4 3 4 2 0 1 -1] ++ [-4 -3 -2 2 3 4 -1 0 1] ++ [-2 -4 -3 4 2 3 1 -1 0] ++ + sage: G.relabel() + sage: G3x3=graphs.MathonPseudocyclicStronglyRegularGraph(2,G=G,L=L) + sage: G3x3.is_strongly_regular(parameters=True) +diff --git a/src/sage/groups/abelian_gps/abelian_group_gap.py b/src/sage/groups/abelian_gps/abelian_group_gap.py +index cebcd39..55a20ed 100644 +--- a/src/sage/groups/abelian_gps/abelian_group_gap.py ++++ b/src/sage/groups/abelian_gps/abelian_group_gap.py +@@ -363,10 +363,10 @@ class AbelianGroup_gap(UniqueRepresentation, GroupMixinLibGAP, ParentLibGAP, Abe + sage: from sage.groups.abelian_gps.abelian_group_gap import AbelianGroupGap + sage: G = AbelianGroupGap([2, 3]) + sage: G.all_subgroups() +- [Subgroup of Abelian group with gap, generator orders (2, 3) generated by (1,), ++ [Subgroup of Abelian group with gap, generator orders (2, 3) generated by (), + Subgroup of Abelian group with gap, generator orders (2, 3) generated by (f1,), + Subgroup of Abelian group with gap, generator orders (2, 3) generated by (f2,), +- Subgroup of Abelian group with gap, generator orders (2, 3) generated by (f1, f2)] ++ Subgroup of Abelian group with gap, generator orders (2, 3) generated by (f2, f1)] + """ + subgroups_gap = self.gap().AllSubgroups() + subgroups_sage = [] +diff --git a/src/sage/groups/braid.py b/src/sage/groups/braid.py +index 4eda6e8..07a765c 100644 +--- a/src/sage/groups/braid.py ++++ b/src/sage/groups/braid.py +@@ -2163,7 +2163,8 @@ class BraidGroup_class(FiniteTypeArtinGroup): + + sage: B = BraidGroup(5) + sage: B._element_from_libbraiding([[-2], [2, 1], [1, 2], [2, 1]]) +- (s0^-1*s1^-1*s2^-1*s3^-1*s0^-1*s1^-1*s2^-1*s0^-1*s1^-1*s0^-1)^2*s1*s0^2*s1^2*s0 ++ (s0^-1*s1^-1*s2^-1*s3^-1*s0^-1*s1^-1*s2^-1*s0^-1*s1^-1*s0^-1)^2*s1*s0^2*s1^2*s\ ++ 0 + sage: B._element_from_libbraiding([[0]]) + 1 + """ +diff --git a/src/sage/groups/finitely_presented.py b/src/sage/groups/finitely_presented.py +index 8f9c192..f27f334 100644 +--- a/src/sage/groups/finitely_presented.py ++++ b/src/sage/groups/finitely_presented.py +@@ -231,7 +231,6 @@ class FinitelyPresentedGroupElement(FreeGroupElement): + + sage: TestSuite(G).run() + sage: TestSuite(H).run() +- + sage: G.<a,b> = FreeGroup() + sage: H = G / (G([1]), G([2, 2, 2])) + sage: x = H([1, 2, -1, -2]) +@@ -1096,6 +1095,7 @@ class FinitelyPresentedGroup(GroupMixinLibGAP, UniqueRepresentation, + sage: C7 = G / [G.0**7]; C6 = G / [G.0**6] + sage: C14 = G / [G.0**14]; C3 = G / [G.0**3] + sage: C7.direct_product(C6).is_isomorphic(C14.direct_product(C3)) ++ #I Forcing finiteness test + True + sage: F = FreeGroup(2); D = F / [F([1,1,1,1,1]),F([2,2]),F([1,2])**2] + sage: D.direct_product(D).as_permutation_group().is_isomorphic( +@@ -1189,6 +1189,7 @@ class FinitelyPresentedGroup(GroupMixinLibGAP, UniqueRepresentation, + sage: alpha = (Q.gens(), [a,b]) + sage: S2 = C2.semidirect_product(Q, ([C2.0],[alpha])) + sage: S1.is_isomorphic(S2) ++ #I Forcing finiteness test + True + + Dihedral groups can be constructed as semidirect products +@@ -1247,6 +1248,8 @@ class FinitelyPresentedGroup(GroupMixinLibGAP, UniqueRepresentation, + sage: Se2 = D.semidirect_product(C ,id2) + sage: Dp1 = C.direct_product(D) + sage: Dp1.is_isomorphic(Se1), Dp1.is_isomorphic(Se2) ++ #I Forcing finiteness test ++ #I Forcing finiteness test + (True, True) + + Most checks for validity of input are left to GAP to handle:: +@@ -1445,27 +1448,27 @@ class FinitelyPresentedGroup(GroupMixinLibGAP, UniqueRepresentation, + sage: H = AlternatingGroup(3) + sage: G.epimorphisms(H) + [Generic morphism: +- From: Finitely presented group < x0, x1, x2 | (x0*x1*x2)^2, x0^3 > +- To: Alternating group of order 3!/2 as a permutation group +- Defn: x0 |--> () +- x1 |--> (1,2,3) +- x2 |--> (1,3,2), Generic morphism: +- From: Finitely presented group < x0, x1, x2 | (x0*x1*x2)^2, x0^3 > +- To: Alternating group of order 3!/2 as a permutation group +- Defn: x0 |--> (1,2,3) +- x1 |--> () +- x2 |--> (1,3,2), Generic morphism: +- From: Finitely presented group < x0, x1, x2 | (x0*x1*x2)^2, x0^3 > +- To: Alternating group of order 3!/2 as a permutation group +- Defn: x0 |--> (1,2,3) +- x1 |--> (1,2,3) +- x2 |--> (1,2,3), Generic morphism: +- From: Finitely presented group < x0, x1, x2 | (x0*x1*x2)^2, x0^3 > +- To: Alternating group of order 3!/2 as a permutation group +- Defn: x0 |--> (1,2,3) +- x1 |--> (1,3,2) +- x2 |--> ()] +- ++ From: Finitely presented group < x0, x1, x2 | (x0*x1*x2)^2, x0^3 > ++ To: Alternating group of order 3!/2 as a permutation group ++ Defn: x0 |--> () ++ x1 |--> (1,3,2) ++ x2 |--> (1,2,3), Generic morphism: ++ From: Finitely presented group < x0, x1, x2 | (x0*x1*x2)^2, x0^3 > ++ To: Alternating group of order 3!/2 as a permutation group ++ Defn: x0 |--> (1,3,2) ++ x1 |--> () ++ x2 |--> (1,2,3), Generic morphism: ++ From: Finitely presented group < x0, x1, x2 | (x0*x1*x2)^2, x0^3 > ++ To: Alternating group of order 3!/2 as a permutation group ++ Defn: x0 |--> (1,3,2) ++ x1 |--> (1,2,3) ++ x2 |--> (), Generic morphism: ++ From: Finitely presented group < x0, x1, x2 | (x0*x1*x2)^2, x0^3 > ++ To: Alternating group of order 3!/2 as a permutation group ++ Defn: x0 |--> (1,2,3) ++ x1 |--> (1,2,3) ++ x2 |--> (1,2,3)] ++ + ALGORITHM: + + Uses libgap's GQuotients function. +diff --git a/src/sage/groups/finitely_presented_named.py b/src/sage/groups/finitely_presented_named.py +index cfd8953..c8075f9 100644 +--- a/src/sage/groups/finitely_presented_named.py ++++ b/src/sage/groups/finitely_presented_named.py +@@ -447,6 +447,7 @@ def QuaternionPresentation(): + sage: Q.order(), Q.is_abelian() + (8, False) + sage: Q.is_isomorphic(groups.presentation.DiCyclic(2)) ++ #I Forcing finiteness test + True + """ + F = FreeGroup(['a','b']) +@@ -546,6 +547,12 @@ def BinaryDihedralPresentation(n): + ....: P = groups.presentation.BinaryDihedral(n) + ....: M = groups.matrix.BinaryDihedral(n) + ....: assert P.is_isomorphic(M) ++ #I Forcing finiteness test ++ #I Forcing finiteness test ++ #I Forcing finiteness test ++ #I Forcing finiteness test ++ #I Forcing finiteness test ++ #I Forcing finiteness test + """ + F = FreeGroup('x,y,z') + x,y,z = F.gens() +diff --git a/src/sage/groups/matrix_gps/finitely_generated.py b/src/sage/groups/matrix_gps/finitely_generated.py +index 78391d5..1946000 100644 +--- a/src/sage/groups/matrix_gps/finitely_generated.py ++++ b/src/sage/groups/matrix_gps/finitely_generated.py +@@ -543,7 +543,7 @@ class FinitelyGeneratedMatrixGroup_gap(MatrixGroup_gap): + smallest one. + + EXAMPLES:: +- ++ + sage: MS = MatrixSpace(GF(2), 5, 5) + sage: A = MS([[0,0,0,0,1],[0,0,0,1,0],[0,0,1,0,0],[0,1,0,0,0],[1,0,0,0,0]]) + sage: G = MatrixGroup([A]) +@@ -711,8 +711,8 @@ class FinitelyGeneratedMatrixGroup_gap(MatrixGroup_gap): + sage: gens = [MS([[0,1],[-1,0]]),MS([[1,1],[2,3]])] + sage: G = MatrixGroup(gens) + sage: G.invariant_generators() +- [x1^7*x2 - x1*x2^7, +- x1^12 - 2*x1^9*x2^3 - x1^6*x2^6 + 2*x1^3*x2^9 + x2^12, ++ [x1^7*x2 - x1*x2^7, ++ x1^12 - 2*x1^9*x2^3 - x1^6*x2^6 + 2*x1^3*x2^9 + x2^12, + x1^18 + 2*x1^15*x2^3 + 3*x1^12*x2^6 + 3*x1^6*x2^12 - 2*x1^3*x2^15 + x2^18] + + sage: q = 4; a = 2 +@@ -1069,10 +1069,10 @@ class FinitelyGeneratedMatrixGroup_gap(MatrixGroup_gap): + sage: chi = G.character(G.character_table()[1]) + sage: R.<x,y,z> = K[] + sage: G.reynolds_operator(x*y^5, chi) +- 1/3*x*y^5 + (-2/3*izeta3^3 - izeta3^2 - 8/3*izeta3 - 4/3)*x^5*z + (2/3*izeta3^3 + izeta3^2 + 8/3*izeta3 + 1)*y*z^5 ++ 1/3*x*y^5 + (2/3*izeta3^3 + izeta3^2 + 8/3*izeta3 + 1)*x^5*z + (-2/3*izeta3^3 - izeta3^2 - 8/3*izeta3 - 4/3)*y*z^5 + sage: R.<x,y,z> = QQbar[] + sage: G.reynolds_operator(x*y^5, chi) +- 1/3*x*y^5 + (-0.1666666666666667? + 0.2886751345948129?*I)*x^5*z + (-0.1666666666666667? - 0.2886751345948129?*I)*y*z^5 ++ 1/3*x*y^5 + (-0.1666666666666667? - 0.2886751345948129?*I)*x^5*z + (-0.1666666666666667? + 0.2886751345948129?*I)*y*z^5 + + :: + +@@ -1288,8 +1288,8 @@ class FinitelyGeneratedMatrixGroup_gap(MatrixGroup_gap): + sage: chi = G.character(G.character_table()[1]) + sage: R.<x,y,z> = K[] + sage: sorted(G.invariants_of_degree(2, R=R, chi=chi)) +- [x*y + (-2*izeta3^3 - 3*izeta3^2 - 8*izeta3 - 4)*x*z + (2*izeta3^3 + 3*izeta3^2 + 8*izeta3 + 3)*y*z, +- x^2 + (2*izeta3^3 + 3*izeta3^2 + 8*izeta3 + 3)*y^2 + (-2*izeta3^3 - 3*izeta3^2 - 8*izeta3 - 4)*z^2] ++ [x*y + (2*izeta3^3 + 3*izeta3^2 + 8*izeta3 + 3)*x*z + (-2*izeta3^3 - 3*izeta3^2 - 8*izeta3 - 4)*y*z, ++ x^2 + (-2*izeta3^3 - 3*izeta3^2 - 8*izeta3 - 4)*y^2 + (2*izeta3^3 + 3*izeta3^2 + 8*izeta3 + 3)*z^2] + + :: + +diff --git a/src/sage/groups/perm_gps/permgroup.py b/src/sage/groups/perm_gps/permgroup.py +index 2ae3a51..8b24ee6 100644 +--- a/src/sage/groups/perm_gps/permgroup.py ++++ b/src/sage/groups/perm_gps/permgroup.py +@@ -325,7 +325,7 @@ def PermutationGroup(gens=None, gap_group=None, domain=None, canonicalize=True, + sage: G = PermutationGroup([[(1,2,3),(4,5)],[(3,4)]]) + sage: current_randstate().set_seed_gap() + sage: G._gap_().DerivedSeries() +- [ Group( [ (3,4), (1,2,3)(4,5) ] ), Group( [ (1,5)(3,4), (1,5)(2,4), (1,5,3) ] ) ] ++ [ Group( [ (3,4), (1,2,3)(4,5) ] ), Group( [ (1,5)(3,4), (1,5)(2,4), (1,3,5) ] ) ] + + TESTS:: + +@@ -3256,7 +3256,7 @@ class PermutationGroup_generic(FiniteGroup): + [Subgroup of (Cyclic group of order 14 as a permutation group) generated by [()], + Subgroup of (Cyclic group of order 14 as a permutation group) generated by [(1,8)(2,9)(3,10)(4,11)(5,12)(6,13)(7,14)], + Subgroup of (Cyclic group of order 14 as a permutation group) generated by [(1,3,5,7,9,11,13)(2,4,6,8,10,12,14)], +- Subgroup of (Cyclic group of order 14 as a permutation group) generated by [(1,2,3,4,5,6,7,8,9,10,11,12,13,14)]] ++ Subgroup of (Cyclic group of order 14 as a permutation group) generated by [(1,2,3,4,5,6,7,8,9,10,11,12,13,14), (1,3,5,7,9,11,13)(2,4,6,8,10,12,14)]] + + AUTHOR: + +@@ -3658,7 +3658,8 @@ class PermutationGroup_generic(FiniteGroup): + rec( + name := "Z(5)", + parameter := 5, +- series := "Z" ) ++ series := "Z", ++ shortname := "C5" ) + + TESTS: + +diff --git a/src/sage/groups/perm_gps/permgroup_element.pyx b/src/sage/groups/perm_gps/permgroup_element.pyx +index 03944d9..d459c0e 100644 +--- a/src/sage/groups/perm_gps/permgroup_element.pyx ++++ b/src/sage/groups/perm_gps/permgroup_element.pyx +@@ -116,7 +116,7 @@ import sage.structure.coerce as coerce + from sage.structure.richcmp cimport richcmp_not_equal, rich_to_bool + + from sage.libs.gap.element cimport GapElement_List +-from sage.libs.gap.gap_includes cimport libGAP_Obj, libGAP_INT_INTOBJ, libGAP_ELM_LIST ++from sage.libs.gap.gap_includes cimport Obj, INT_INTOBJ, ELM_LIST + + import operator + +@@ -951,7 +951,7 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): + (1,4)(2,3) + """ + cdef GapElement_List lst = <GapElement_List?> lst_in +- cdef libGAP_Obj obj = lst.value ++ cdef Obj obj = lst.value + + cdef PermutationGroupElement new = self._new_c() + cdef Py_ssize_t i, j, vn = len(lst) +@@ -959,7 +959,7 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): + assert vn <= self.n + + for i in range(vn): +- j = libGAP_INT_INTOBJ(libGAP_ELM_LIST(obj, i+1)) ++ j = INT_INTOBJ(ELM_LIST(obj, i+1)) + new.perm[i] = j - 1 + for i in range(vn, self.n): + new.perm[i] = i +diff --git a/src/sage/interfaces/gap.py b/src/sage/interfaces/gap.py +index 55d41aa..8db06a9 100644 +--- a/src/sage/interfaces/gap.py ++++ b/src/sage/interfaces/gap.py +@@ -1,3 +1,4 @@ ++# -*- coding: UTF-8 -*- + r""" + Interface to GAP + +@@ -187,6 +188,7 @@ from sage.misc.cachefunc import cached_method + from sage.docs.instancedoc import instancedoc + from sage.interfaces.tab_completion import ExtraTabCompletion + from sage.structure.element import ModuleElement ++ + import re + import os + import io +@@ -194,12 +196,10 @@ import pexpect + import time + import platform + import string ++import warnings + + WORKSPACE = gap_workspace_file() + +-from sage.env import GAP_ROOT_DIR +-GAP_BINARY = os.path.join(GAP_ROOT_DIR, 'bin', 'gap.sh') +- + first_try = True + + gap_cmd = "gap -r" +@@ -514,7 +514,7 @@ class Gap_generic(ExtraTabCompletion, Expect): + RuntimeError: Error loading Gap package chevie. You may want to install the gap_packages and/or database_gap SPKGs. + """ + if verbose: +- print("Loading GAP package %s" % pkg) ++ print("Loading GAP package {}" % pkg) + x = self.eval('LoadPackage("%s")'%pkg) + if x == 'fail': + raise RuntimeError("Error loading Gap package "+str(pkg)+". "+ +@@ -610,8 +610,9 @@ class Gap_generic(ExtraTabCompletion, Expect): + current_outputs.append(E.before) + if x == 0: # @p + if E.after != b'@p1.': +- print("Warning: possibly wrong version of GAP package interface\n") +- print("Crossing fingers and continuing\n") ++ warnings.warn( ++ "possibly wrong version of GAP package " ++ "interface. Crossing fingers and continuing.") + elif x == 1: #@@ + current_outputs.append(b'@') + elif x == 2: #special char +@@ -626,11 +627,11 @@ class Gap_generic(ExtraTabCompletion, Expect): + elif x == 4: # @e -- break loop + E.sendline("quit;") + elif x == 5: # @c completion, doesn't seem to happen when -p is in use +- print("I didn't think GAP could do this\n") ++ warnings.warn("I didn't think GAP could do this") + elif x == 6: # @f GAP error message + current_outputs = error_outputs; + elif x == 7: # @h help text, but this stopped happening with new help +- print("I didn't think GAP could do this") ++ warnings.warn("I didn't think GAP could do this") + elif x == 8: # @i awaiting normal input + break; + elif x == 9: # @m finished running a child +@@ -640,9 +641,9 @@ class Gap_generic(ExtraTabCompletion, Expect): + elif x==11: #@r echoing input + current_outputs = terminal_echo + elif x==12: #@sN shouldn't happen +- print("Warning: this should never happen") ++ warnings.warn("this should never happen") + elif x==13: #@w GAP is trying to send a Window command +- print("Warning: this should never happen") ++ warnings.warn("this should never happen") + elif x ==14: #@x seems to be safely ignorable + pass + elif x == 15:#@z GAP starting a subprocess +@@ -908,17 +909,16 @@ class Gap_generic(ExtraTabCompletion, Expect): + + sage: g = Gap() + sage: g.function_call("ConjugacyClassesSubgroups", sage.interfaces.gap.GapElement(g, 'SymmetricGroup(2)', name = 'a_variable_with_a_very_very_very_long_name')) +- [ ConjugacyClassSubgroups(SymmetricGroup( [ 1 .. 2 ] ),Group( [ () ] )), +- ConjugacyClassSubgroups(SymmetricGroup( [ 1 .. 2 ] ),SymmetricGroup( [ 1 .. 2 ] )) ] ++ [ ConjugacyClassSubgroups(SymmetricGroup( [ 1 .. 2 ] ),Group( () )), ++ ConjugacyClassSubgroups(SymmetricGroup( [ 1 .. 2 ] ),Group( [ (1,2) ] )) ] + + When the command itself is so long that it warrants use of a temporary + file to be communicated to GAP, this does not cause problems since + the file will contain a single command:: + + sage: g.function_call("ConjugacyClassesSubgroups", sage.interfaces.gap.GapElement(g, 'SymmetricGroup(2)', name = 'a_variable_with_a_name_so_very_very_very_long_that_even_by_itself_will_make_expect_use_a_file')) +- [ ConjugacyClassSubgroups(SymmetricGroup( [ 1 .. 2 ] ),Group( [ () ] )), +- ConjugacyClassSubgroups(SymmetricGroup( [ 1 .. 2 ] ),SymmetricGroup( [ 1 .. 2 ] )) ] +- ++ [ ConjugacyClassSubgroups(SymmetricGroup( [ 1 .. 2 ] ),Group( () )), ++ ConjugacyClassSubgroups(SymmetricGroup( [ 1 .. 2 ] ),Group( [ (1,2) ] )) ] + """ + args, kwds = self._convert_args_kwds(args, kwds) + self._check_valid_function_name(function) +@@ -1129,13 +1129,20 @@ class Gap(Gap_generic): + """ + self.__use_workspace_cache = use_workspace_cache + cmd, self.__make_workspace = gap_command(use_workspace_cache, server is None) +- cmd += " -b -p -T" ++ # -b: suppress banner ++ # -p: enable "package output mode"; this confusingly named option ++ # causes GAP to output special control characters that are normally ++ # intended for communication with a window manager (i.e. for xgap) ++ # but that we also use to control GAP with pexepect ++ # -T: disable interactive break loop when encountering errors ++ # -E: disable readline support ++ cmd += " -b -p -T -E" + if max_workspace_size is None: + max_workspace_size = _get_gap_memory_pool_size_MB() + cmd += ' -o ' + str(max_workspace_size) + cmd += ' -s ' + str(max_workspace_size) + cmd += ' -m 64m ' # attempt at a workaround for http://tracker.gap-system.org/issues/224 +- cmd += ' ' + os.path.join(SAGE_EXTCODE,'gap','sage.g') ++ cmd += ' ' + os.path.join(SAGE_EXTCODE, 'gap', 'sage.g') + Expect.__init__(self, + name='gap', + prompt='gap> ', +@@ -1343,11 +1350,11 @@ class Gap(Gap_generic): + + sage: print(gap.help('SymmetricGroup', pager=False)) + <BLANKLINE> +- 50 Group Libraries ++ 50.1-... SymmetricGroup + <BLANKLINE> +- When you start GAP, it already knows several groups. Currently GAP initially +- knows the following groups: ++ ‣ SymmetricGroup( [filt, ]deg ) ─────────────────────────────────── function + ... ++ <BLANKLINE> + """ + tmp_to_use = self._local_tmpfile() + if self.is_remote(): +@@ -1364,6 +1371,7 @@ class Gap(Gap_generic): + print(line) + else: + (sline,) = match.groups() ++ sline = int(sline) - 1 + if self.is_remote(): + self._get_tmpfile() + with io.open(self._local_tmpfile(), "r", +@@ -1371,9 +1379,20 @@ class Gap(Gap_generic): + help = fobj.read() + if pager: + from IPython.core.page import page +- page(help, start=int(sline) - 1) ++ page(help, start=sline) + else: +- return help ++ # Find the n-th line and return from there ++ idx = -1 ++ while sline: ++ try: ++ idx = help.find('\n', idx + 1) ++ sline -= 1 ++ except ValueError: ++ # We ran out of lines early somehow; this shouldn't ++ # happen though ++ break ++ ++ return help[idx:] + + def set(self, var, value): + """ +@@ -1552,8 +1571,8 @@ def gap_reset_workspace(max_workspace_size=None, verbose=False): + # Create new workspace with filename WORKSPACE + g = Gap(use_workspace_cache=False, max_workspace_size=None) + g.eval('SetUserPreference("HistoryMaxLines", 30)') +- for pkg in ['GAPDoc', 'ctbllib', 'sonata', 'guava', 'factint', \ +- 'gapdoc', 'grape', 'design', \ ++ for pkg in ['GAPDoc', 'ctbllib', 'sonata', 'guava', 'factint', ++ 'gapdoc', 'grape', 'design', + 'toric', 'laguna', 'braid', 'polycyclic', 'nq']: + # NOTE: Do *not* autoload hap - it screws up PolynomialRing(Rationals,2) + try: +@@ -1647,10 +1666,9 @@ class GapFunctionElement(FunctionElement): + + sage: print(gap(4).SymmetricGroup.__doc__) + <BLANKLINE> +- 50 Group Libraries ++ 50.1-... SymmetricGroup + <BLANKLINE> +- When you start GAP, it already knows several groups. Currently GAP initially +- knows the following groups: ++ ‣ SymmetricGroup( [filt, ]deg ) ─────────────────────────────────── function + ... + """ + M = self._obj.parent() +@@ -1660,16 +1678,15 @@ class GapFunctionElement(FunctionElement): + + @instancedoc + class GapFunction(ExpectFunction): +- def _instancedoc(self): ++ def _instancedoc_(self): + """ + EXAMPLES:: + + sage: print(gap.SymmetricGroup.__doc__) + <BLANKLINE> +- 50 Group Libraries ++ 50.1-... SymmetricGroup + <BLANKLINE> +- When you start GAP, it already knows several groups. Currently GAP initially +- knows the following groups: ++ ‣ SymmetricGroup( [filt, ]deg ) ─────────────────────────────────── function + ... + """ + M = self._parent +diff --git a/src/sage/knots/link.py b/src/sage/knots/link.py +index fe11d9c..7e305c4 100644 +--- a/src/sage/knots/link.py ++++ b/src/sage/knots/link.py +@@ -479,9 +479,8 @@ class Link(object): + x1*x3^-1*x2^-1*x3, x3*x1^-1*x0^-1*x1 > + sage: GB = K8.fundamental_group(presentation='braid') + sage: GB +- Finitely presented group < x0, x1, x2 | +- x1*x2^-1*x1^-1*x0*x1*x2*x1*x2^-1*x1^-1*x0^-1*x1*x2*x1^-1*x0^-1, +- x1*x2^-1*x1^-1*x0*x1*x2*x1^-1*x2^-1*x1^-1*x0^-1*x1*x2*x1^-1*x0*x1*x2*x1*x2^-1*x1^-1*x0^-1*x1*x2*x1^-2, x1*x2^-1*x1^-1*x0*x1*x2*x1^-1*x2^-1 > ++ Finitely presented group < x0, x1, x2 | x1*x2^-1*x1^-1*x0*x1*x2*x1*x2^-1*x1^-1*x0^-1*x1*x2*x1^-1*x0^-1, x1*x2^-1*x1^-1*x0*x1*x2*x1^-1*x2^-1*x1^-1*x0^-1*x1*x2*x1^-1*x0*x1*x2*x1*x2^-1*\ ++ x1^-1*x0^-1*x1*x2*x1^-2, x1*x2^-1*x1^-1*x0*x1*x2*x1^-1*x2^-1 > + sage: GA.simplified() + Finitely presented group < x0, x1 | + x1^-1*x0*x1*x0^-1*x1*x0*x1^-1*x0^-1*x1*x0^-1 > +diff --git a/src/sage/libs/gap/assigned_names.py b/src/sage/libs/gap/assigned_names.py +index a3633a4..ab5d973 100644 +--- a/src/sage/libs/gap/assigned_names.py ++++ b/src/sage/libs/gap/assigned_names.py +@@ -27,7 +27,7 @@ from sage.libs.gap.saved_workspace import workspace + + + NamesGVars = libgap.function_factory('NamesGVars') +-Filtered =libgap.function_factory('Filtered') ++Filtered = libgap.function_factory('Filtered') + ValueGlobal = libgap.function_factory('ValueGlobal') + IsBoundGlobal = libgap.function_factory('IsBoundGlobal') + IsFunction = libgap.function_factory('IsFunction') +diff --git a/src/sage/libs/gap/element.pxd b/src/sage/libs/gap/element.pxd +index c803ade..74e7d6c 100644 +--- a/src/sage/libs/gap/element.pxd ++++ b/src/sage/libs/gap/element.pxd +@@ -8,31 +8,31 @@ + # http://www.gnu.org/licenses/ + #***************************************************************************** + +-from .types cimport libGAP_Obj, libGAP_UInt ++from .gap_includes cimport Obj, UInt + from sage.structure.sage_object cimport SageObject + from sage.structure.element cimport Element, ModuleElement, RingElement + +-cdef libGAP_Obj make_gap_list(sage_list) except NULL +-cdef libGAP_Obj make_gap_record(sage_dict) except NULL +-cdef libGAP_Obj make_gap_integer(sage_dict) except NULL +-cdef libGAP_Obj make_gap_string(sage_string) except NULL +- +-cdef GapElement make_any_gap_element(parent, libGAP_Obj obj) +-cdef GapElement make_GapElement(parent, libGAP_Obj obj) +-cdef GapElement_List make_GapElement_List(parent, libGAP_Obj obj) +-cdef GapElement_Record make_GapElement_Record(parent, libGAP_Obj obj) +-cdef GapElement_Integer make_GapElement_Integer(parent, libGAP_Obj obj) +-cdef GapElement_Rational make_GapElement_Rational(parent, libGAP_Obj obj) +-cdef GapElement_String make_GapElement_String(parent, libGAP_Obj obj) +-cdef GapElement_Boolean make_GapElement_Boolean(parent, libGAP_Obj obj) +-cdef GapElement_Function make_GapElement_Function(parent, libGAP_Obj obj) ++cdef Obj make_gap_list(sage_list) except NULL ++cdef Obj make_gap_record(sage_dict) except NULL ++cdef Obj make_gap_integer(sage_dict) except NULL ++cdef Obj make_gap_string(sage_string) except NULL + ++cdef GapElement make_any_gap_element(parent, Obj obj) ++cdef GapElement make_GapElement(parent, Obj obj) ++cdef GapElement_List make_GapElement_List(parent, Obj obj) ++cdef GapElement_Record make_GapElement_Record(parent, Obj obj) ++cdef GapElement_Integer make_GapElement_Integer(parent, Obj obj) ++cdef GapElement_Rational make_GapElement_Rational(parent, Obj obj) ++cdef GapElement_String make_GapElement_String(parent, Obj obj) ++cdef GapElement_Boolean make_GapElement_Boolean(parent, Obj obj) ++cdef GapElement_Function make_GapElement_Function(parent, Obj obj) ++cdef char *crepr(Obj) + + + cdef class GapElement(RingElement): + + # the pointer to the GAP object (memory managed by GASMAN) +- cdef libGAP_Obj value ++ cdef Obj value + + # comparison + cdef bint _compare_by_id +@@ -41,7 +41,7 @@ cdef class GapElement(RingElement): + cpdef _set_compare_by_id(self) + cpdef _assert_compare_by_id(self) + +- cdef _initialize(self, parent, libGAP_Obj obj) ++ cdef _initialize(self, parent, Obj obj) + cpdef _type_number(self) + cpdef is_bool(self) + cpdef _add_(self, other) +@@ -81,11 +81,11 @@ cdef class GapElement_MethodProxy(GapElement_Function): + cdef GapElement first_argument + + cdef class GapElement_Record(GapElement): +- cpdef libGAP_UInt record_name_to_index(self, name) ++ cpdef UInt record_name_to_index(self, name) + + cdef class GapElement_RecordIterator(object): + cdef GapElement_Record rec +- cdef libGAP_UInt i ++ cdef UInt i + + cdef class GapElement_List(GapElement): + pass +diff --git a/src/sage/libs/gap/element.pyx b/src/sage/libs/gap/element.pyx +index 446c393..0aa9c32 100644 +--- a/src/sage/libs/gap/element.pyx ++++ b/src/sage/libs/gap/element.pyx +@@ -23,7 +23,7 @@ from cysignals.signals cimport sig_on, sig_off + + from .gap_includes cimport * + from .util cimport * +-from sage.cpython.string cimport char_to_str, str_to_bytes ++from sage.cpython.string cimport str_to_bytes, char_to_str + from sage.misc.cachefunc import cached_method + from sage.structure.sage_object cimport SageObject + from sage.structure.parent import Parent +@@ -33,33 +33,33 @@ from sage.groups.perm_gps.permgroup_element cimport PermutationGroupElement + from sage.combinat.permutation import Permutation + + decode_type_number = { +- libGAP_T_INT: 'T_INT (integer)', +- libGAP_T_INTPOS: 'T_INTPOS (positive integer)', +- libGAP_T_INTNEG: 'T_INTNEG (negative integer)', +- libGAP_T_RAT: 'T_RAT (rational number)', +- libGAP_T_CYC: 'T_CYC (universal cylotomic)', +- libGAP_T_FFE: 'T_FFE (finite field element)', +- libGAP_T_PERM2: 'T_PERM2', +- libGAP_T_PERM4: 'T_PERM4', +- libGAP_T_BOOL: 'T_BOOL', +- libGAP_T_CHAR: 'T_CHAR', +- libGAP_T_FUNCTION: 'T_FUNCTION', +- libGAP_T_PLIST: 'T_PLIST', +- libGAP_T_PLIST_CYC: 'T_PLIST_CYC', +- libGAP_T_BLIST: 'T_BLIST', +- libGAP_T_STRING: 'T_STRING', +- libGAP_T_MACFLOAT: 'T_MACFLOAT (hardware floating point number)', +- libGAP_T_COMOBJ: 'T_COMOBJ (component object)', +- libGAP_T_POSOBJ: 'T_POSOBJ (positional object)', +- libGAP_T_DATOBJ: 'T_DATOBJ (data object)', +- libGAP_T_WPOBJ: 'T_WPOBJ (weak pointer object)', ++ 0: 'T_INT (integer)', ++ T_INTPOS: 'T_INTPOS (positive integer)', ++ T_INTNEG: 'T_INTNEG (negative integer)', ++ T_RAT: 'T_RAT (rational number)', ++ T_CYC: 'T_CYC (universal cylotomic)', ++ T_FFE: 'T_FFE (finite field element)', ++ T_PERM2: 'T_PERM2', ++ T_PERM4: 'T_PERM4', ++ T_BOOL: 'T_BOOL', ++ T_CHAR: 'T_CHAR', ++ T_FUNCTION: 'T_FUNCTION', ++ T_PLIST: 'T_PLIST', ++ T_PLIST_CYC: 'T_PLIST_CYC', ++ T_BLIST: 'T_BLIST', ++ T_STRING: 'T_STRING', ++ T_MACFLOAT: 'T_MACFLOAT (hardware floating point number)', ++ T_COMOBJ: 'T_COMOBJ (component object)', ++ T_POSOBJ: 'T_POSOBJ (positional object)', ++ T_DATOBJ: 'T_DATOBJ (data object)', ++ T_WPOBJ: 'T_WPOBJ (weak pointer object)', + } + + ############################################################################ + ### helper functions to construct lists and records ######################## + ############################################################################ + +-cdef libGAP_Obj make_gap_list(sage_list) except NULL: ++cdef Obj make_gap_list(sage_list) except NULL: + """ + Convert Sage lists into Gap lists + +@@ -71,15 +71,50 @@ cdef libGAP_Obj make_gap_list(sage_list) except NULL: + + The list of the elements in ``a`` as a Gap ``Obj``. + """ +- # FIXME slow -- to make fast directly use ADD_LIST in Gap's C code. + from sage.libs.gap.libgap import libgap + cdef GapElement l = libgap.eval('[]') ++ cdef GapElement elem + for x in sage_list: +- l.Add(x) ++ if not isinstance(x, GapElement): ++ elem = <GapElement>libgap(x) ++ else: ++ elem = <GapElement>x ++ ++ AddList(l.value, elem.value) + return l.value + + +-cdef libGAP_Obj make_gap_record(sage_dict) except NULL: ++cdef char *crepr(Obj obj): ++ cdef Obj s, stream, output_text_string, view_obj ++ cdef UInt res ++ # The only way to get a string representation of an object that is truly ++ # consistent with how it would be represented at the GAP REPL is to call ++ # ViewObj on it. Unfortunately, ViewObj *prints* to the output stream, ++ # and there is no equivalent that simply returns the string that would be ++ # printed. The closest approximation would be DisplayString, but this ++ # bypasses any type-specific overrides for ViewObj so for many objects ++ # that does not give consistent results. ++ # TODO: This is probably needlessly slow, but we might need better ++ # support from GAP to improve this... ++ try: ++ GAP_Enter() ++ s = NEW_STRING(0) ++ output_text_string = GAP_ValueGlobalVariable("OutputTextString") ++ stream = CALL_2ARGS(output_text_string, s, GAP_True) ++ ++ if not OpenOutputStream(stream): ++ raise RuntimeError("failed to open output capture stream for " ++ "representing GAP object") ++ ++ viewobj = GAP_ValueGlobalVariable("ViewObj") ++ CALL_1ARGS(viewobj, obj) ++ CloseOutput() ++ return CSTR_STRING(s) ++ finally: ++ GAP_Leave() ++ ++ ++cdef Obj make_gap_record(sage_dict) except NULL: + """ + Convert Sage lists into Gap lists + +@@ -99,19 +134,23 @@ cdef libGAP_Obj make_gap_record(sage_dict) except NULL: + from sage.libs.gap.libgap import libgap + data = [ (str(key), libgap(value)) for key, value in sage_dict.iteritems() ] + +- libgap_enter() +- cdef libGAP_Obj rec = libGAP_NEW_PREC(len(data)) ++ cdef Obj rec + cdef GapElement val +- cdef libGAP_UInt rnam +- for d in data: +- key, val = d +- rnam = libGAP_RNamName(str_to_bytes(key)) +- libGAP_AssPRec(rec, rnam, val.value) +- libgap_exit() +- return rec ++ cdef UInt rnam + ++ try: ++ GAP_Enter() ++ rec = NEW_PREC(len(data)) ++ for d in data: ++ key, val = d ++ rnam = RNamName(str_to_bytes(key)) ++ AssPRec(rec, rnam, val.value) ++ return rec ++ finally: ++ GAP_Leave() + +-cdef libGAP_Obj make_gap_integer(sage_int) except NULL: ++ ++cdef Obj make_gap_integer(sage_int) except NULL: + """ + Convert Sage integer into Gap integer + +@@ -128,19 +167,22 @@ cdef libGAP_Obj make_gap_integer(sage_int) except NULL: + sage: libgap(1) # indirect doctest + 1 + """ +- libgap_enter() +- cdef libGAP_Obj result = libGAP_INTOBJ_INT(<int>sage_int) +- libgap_exit() +- return result ++ cdef Obj result ++ try: ++ GAP_Enter() ++ result = INTOBJ_INT(<int>sage_int) ++ return result ++ finally: ++ GAP_Leave() + + +-cdef libGAP_Obj make_gap_string(sage_string) except NULL: ++cdef Obj make_gap_string(sage_string) except NULL: + """ +- Convert a Sage string to a Gap string ++ Convert a Python string to a Gap string + + INPUT: + +- - ``sage_string`` -- a Sage integer. ++ - ``sage_string`` -- a Python str. + + OUTPUT: + +@@ -151,19 +193,21 @@ cdef libGAP_Obj make_gap_string(sage_string) except NULL: + sage: libgap('string') # indirect doctest + "string" + """ +- libgap_enter() +- cdef libGAP_Obj result +- sage_string = str_to_bytes(sage_string) +- libGAP_C_NEW_STRING(result, len(sage_string), sage_string) +- libgap_exit() +- return result ++ cdef Obj result ++ try: ++ GAP_Enter() ++ b = str_to_bytes(sage_string) ++ C_NEW_STRING(result, len(b), b) ++ return result ++ finally: ++ GAP_Leave() + + + ############################################################################ + ### generic construction of GapElements #################################### + ############################################################################ + +-cdef GapElement make_any_gap_element(parent, libGAP_Obj obj): ++cdef GapElement make_any_gap_element(parent, Obj obj): + """ + Return the libGAP element wrapper of ``obj`` + +@@ -199,55 +243,59 @@ cdef GapElement make_any_gap_element(parent, libGAP_Obj obj): + sage: irr[1] + 0 + """ +- if obj is NULL: +- return make_GapElement(parent, obj) +- cdef int num = libGAP_TNUM_OBJ(obj) +- if num == libGAP_T_INT or num == libGAP_T_INTPOS or num == libGAP_T_INTNEG: +- return make_GapElement_Integer(parent, obj) +- elif num == libGAP_T_MACFLOAT: +- return make_GapElement_Float(parent, obj) +- elif num == libGAP_T_CYC: +- return make_GapElement_Cyclotomic(parent, obj) +- elif num == libGAP_T_FFE: +- return make_GapElement_FiniteField(parent, obj) +- elif num == libGAP_T_RAT: +- return make_GapElement_Rational(parent, obj) +- elif num == libGAP_T_BOOL: +- return make_GapElement_Boolean(parent, obj) +- elif num == libGAP_T_FUNCTION: +- return make_GapElement_Function(parent, obj) +- elif num == libGAP_T_PERM2 or num == libGAP_T_PERM4: +- return make_GapElement_Permutation(parent, obj) +- elif libGAP_FIRST_RECORD_TNUM <= num <= libGAP_LAST_RECORD_TNUM: +- return make_GapElement_Record(parent, obj) +- elif libGAP_FIRST_LIST_TNUM <= num <= libGAP_LAST_LIST_TNUM and libGAP_LEN_PLIST(obj) == 0: +- # Empty lists are lists and not strings in Python +- return make_GapElement_List(parent, obj) +- elif libGAP_IsStringConv(obj): +- # GAP strings are lists, too. Make sure this comes before non-empty make_GapElement_List +- return make_GapElement_String(parent, obj) +- elif libGAP_IS_LIST(obj): +- return make_GapElement_List(parent, obj) +- elif num == libGAP_T_CHAR: +- ch = make_GapElement(parent, obj).IntChar().sage() +- return make_GapElement_String(parent, make_gap_string(chr(ch))) +- result = make_GapElement(parent, obj) +- if num == libGAP_T_POSOBJ: +- if result.IsZmodnZObj(): +- return make_GapElement_IntegerMod(parent, obj) +- if num == libGAP_T_COMOBJ: +- if result.IsRing(): +- return make_GapElement_Ring(parent, obj) +- return result +- ++ cdef int num + ++ try: ++ GAP_Enter() ++ if obj is NULL: ++ return make_GapElement(parent, obj) ++ num = TNUM_OBJ(obj) ++ if IS_INT(obj): ++ return make_GapElement_Integer(parent, obj) ++ elif num == T_MACFLOAT: ++ return make_GapElement_Float(parent, obj) ++ elif num == T_CYC: ++ return make_GapElement_Cyclotomic(parent, obj) ++ elif num == T_FFE: ++ return make_GapElement_FiniteField(parent, obj) ++ elif num == T_RAT: ++ return make_GapElement_Rational(parent, obj) ++ elif num == T_BOOL: ++ return make_GapElement_Boolean(parent, obj) ++ elif num == T_FUNCTION: ++ return make_GapElement_Function(parent, obj) ++ elif num == T_PERM2 or num == T_PERM4: ++ return make_GapElement_Permutation(parent, obj) ++ elif IS_REC(obj): ++ return make_GapElement_Record(parent, obj) ++ elif IS_LIST(obj) and LEN_LIST(obj) == 0: ++ # Empty lists are lists and not strings in Python ++ return make_GapElement_List(parent, obj) ++ elif IsStringConv(obj): ++ # GAP strings are lists, too. Make sure this comes before non-empty make_GapElement_List ++ return make_GapElement_String(parent, obj) ++ elif IS_LIST(obj): ++ return make_GapElement_List(parent, obj) ++ elif num == T_CHAR: ++ ch = make_GapElement(parent, obj).IntChar().sage() ++ return make_GapElement_String(parent, make_gap_string(chr(ch))) ++ result = make_GapElement(parent, obj) ++ if num == T_POSOBJ: ++ if result.IsZmodnZObj(): ++ return make_GapElement_IntegerMod(parent, obj) ++ if num == T_COMOBJ: ++ if result.IsRing(): ++ return make_GapElement_Ring(parent, obj) ++ return result ++ finally: ++ GAP_Leave() + + + ############################################################################ + ### GapElement ############################################################# + ############################################################################ + +-cdef GapElement make_GapElement(parent, libGAP_Obj obj): ++cdef GapElement make_GapElement(parent, Obj obj): + r""" + Turn a Gap C object (of type ``Obj``) into a Cython ``GapElement``. + +@@ -270,8 +318,6 @@ cdef GapElement make_GapElement(parent, libGAP_Obj obj): + <type 'sage.libs.gap.element.GapElement_Integer'> + + sage: libgap.eval('') +- NULL +- + sage: libgap(None) + Traceback (most recent call last): + ... +@@ -344,7 +390,7 @@ cdef class GapElement(RingElement): + """ + raise TypeError('this class cannot be instantiated from Python') + +- cdef _initialize(self, parent, libGAP_Obj obj): ++ cdef _initialize(self, parent, Obj obj): + r""" + Initialize the GapElement. + +@@ -424,8 +470,8 @@ cdef class GapElement(RingElement): + sage: a + [ [ 0, -2 ], [ 2, 3, 4 ] ] + """ +- if libGAP_IS_MUTABLE_OBJ(self.value): +- return make_any_gap_element(self.parent(), libGAP_SHALLOW_COPY_OBJ(self.value)) ++ if IS_MUTABLE_OBJ(self.value): ++ return make_any_gap_element(self.parent(), SHALLOW_COPY_OBJ(self.value)) + else: + return self + +@@ -456,8 +502,8 @@ cdef class GapElement(RingElement): + sage: l.deepcopy(1).IsMutable() + true + """ +- if libGAP_IS_MUTABLE_OBJ(self.value): +- return make_any_gap_element(self.parent(), libGAP_CopyObj(self.value, mut)) ++ if IS_MUTABLE_OBJ(self.value): ++ return make_any_gap_element(self.parent(), CopyObj(self.value, mut)) + else: + return self + +@@ -514,7 +560,7 @@ cdef class GapElement(RingElement): + sage: x._type_number() + (0L, 'T_INT (integer)') + """ +- n = libGAP_TNUM_OBJ(self.value) ++ n = TNUM_OBJ(self.value) + global decode_type_number + name = decode_type_number.get(n, 'unknown') + return (n, name) +@@ -592,7 +638,6 @@ cdef class GapElement(RingElement): + sage: libgap(0) + 0 + sage: libgap.eval('') +- NULL + sage: libgap(0) + 0 + sage: libgap(0)._repr_() +@@ -600,15 +645,9 @@ cdef class GapElement(RingElement): + """ + if self.value == NULL: + return 'NULL' +- try: +- libgap_enter() +- libgap_start_interaction('') +- libGAP_ViewObjHandler(self.value) +- s = char_to_str(libgap_get_output()) +- return s.strip() +- finally: +- libgap_finish_interaction() +- libgap_exit() ++ ++ s = char_to_str(crepr(self.value)) ++ return s.strip() + + cpdef _set_compare_by_id(self): + """ +@@ -777,17 +816,15 @@ cdef class GapElement(RingElement): + if self._compare_by_id: + return id(self) == id(other) + cdef GapElement c_other = <GapElement>other +- cdef bint result +- libgap_enter() ++ sig_on() + try: +- sig_on() +- result = libGAP_EQ(self.value, c_other.value) +- sig_off() ++ GAP_Enter() ++ return EQ(self.value, c_other.value) + except RuntimeError as msg: + raise ValueError('libGAP: cannot compare equality: '+str(msg)) + finally: +- libgap_exit() +- return result ++ GAP_Leave() ++ sig_off() + + cdef bint _compare_less(self, Element other) except -2: + """ +@@ -802,18 +839,16 @@ cdef class GapElement(RingElement): + """ + if self._compare_by_id: + return id(self) < id(other) +- cdef bint result + cdef GapElement c_other = <GapElement>other +- libgap_enter() ++ sig_on() + try: +- sig_on() +- result = libGAP_LT(self.value, c_other.value) +- sig_off() ++ GAP_Enter() ++ return LT(self.value, c_other.value) + except RuntimeError as msg: + raise ValueError('libGAP: cannot compare less than: '+str(msg)) + finally: +- libgap_exit() +- return result ++ GAP_Leave() ++ sig_off() + + cpdef _add_(self, right): + r""" +@@ -834,18 +869,17 @@ cdef class GapElement(RingElement): + ValueError: libGAP: Error, no method found! + Error, no 1st choice method found for `+' on 2 arguments + """ +- cdef libGAP_Obj result ++ cdef Obj result ++ sig_on() + try: +- libgap_enter() +- sig_on() +- result = libGAP_SUM(self.value, (<GapElement>right).value) +- sig_off() ++ GAP_Enter() ++ result = SUM(self.value, (<GapElement>right).value) ++ return make_any_gap_element(self.parent(), result) + except RuntimeError as msg: +- libGAP_ClearError() + raise ValueError('libGAP: '+str(msg)) + finally: +- libgap_exit() +- return make_any_gap_element(self.parent(), result) ++ GAP_Leave() ++ sig_off() + + + cpdef _sub_(self, right): +@@ -867,18 +901,17 @@ cdef class GapElement(RingElement): + ValueError: libGAP: Error, no method found! + Error, no 1st choice method found for `-' on 2 arguments + """ +- cdef libGAP_Obj result ++ cdef Obj result ++ sig_on() + try: +- libgap_enter() +- sig_on() +- result = libGAP_DIFF(self.value, (<GapElement>right).value) +- sig_off() ++ GAP_Enter() ++ result = DIFF(self.value, (<GapElement>right).value) ++ return make_any_gap_element(self.parent(), result) + except RuntimeError as msg: +- libGAP_ClearError() + raise ValueError('libGAP: {}'.format(msg)) + finally: +- libgap_exit() +- return make_any_gap_element(self.parent(), result) ++ GAP_Leave() ++ sig_off() + + + cpdef _mul_(self, right): +@@ -900,18 +933,17 @@ cdef class GapElement(RingElement): + ValueError: libGAP: Error, no method found! + Error, no 1st choice method found for `*' on 2 arguments + """ +- cdef libGAP_Obj result ++ cdef Obj result ++ sig_on() + try: +- libgap_enter() +- sig_on() +- result = libGAP_PROD(self.value, (<GapElement>right).value) +- sig_off() ++ GAP_Enter() ++ result = PROD(self.value, (<GapElement>right).value) ++ return make_any_gap_element(self.parent(), result) + except RuntimeError as msg: +- libGAP_ClearError() + raise ValueError('libGAP: {}'.format(msg)) + finally: +- libgap_exit() +- return make_any_gap_element(self.parent(), result) ++ GAP_Leave() ++ sig_off() + + + cpdef _div_(self, right): +@@ -938,18 +970,17 @@ cdef class GapElement(RingElement): + ... + ValueError: libGAP: Error, Rational operations: <divisor> must not be zero + """ +- cdef libGAP_Obj result ++ cdef Obj result ++ sig_on() + try: +- libgap_enter() +- sig_on() +- result = libGAP_QUO(self.value, (<GapElement>right).value) +- sig_off() ++ GAP_Enter() ++ result = QUO(self.value, (<GapElement>right).value) ++ return make_any_gap_element(self.parent(), result) + except RuntimeError as msg: +- libGAP_ClearError() + raise ValueError('libGAP: '+str(msg)) + finally: +- libgap_exit() +- return make_any_gap_element(self.parent(), result) ++ GAP_Leave() ++ sig_off() + + cpdef _mod_(self, right): + r""" +@@ -968,18 +999,17 @@ cdef class GapElement(RingElement): + ValueError: libGAP: Error, no method found! + Error, no 1st choice method found for `mod' on 2 arguments + """ +- cdef libGAP_Obj result ++ cdef Obj result ++ sig_on() + try: +- libgap_enter() +- sig_on() +- result = libGAP_MOD(self.value, (<GapElement>right).value) +- sig_off() ++ GAP_Enter() ++ result = MOD(self.value, (<GapElement>right).value) ++ return make_any_gap_element(self.parent(), result) + except RuntimeError as msg: +- libGAP_ClearError() + raise ValueError('libGAP: '+str(msg)) + finally: +- libgap_exit() +- return make_any_gap_element(self.parent(), result) ++ GAP_Leave() ++ sig_off() + + + def __pow__(GapElement self, right, dummy): +@@ -1008,18 +1038,17 @@ cdef class GapElement(RingElement): + if not isinstance(right, GapElement): + libgap = self.parent() + right = libgap(right) +- cdef libGAP_Obj result ++ cdef Obj result ++ sig_on() + try: +- libgap_enter() +- sig_on() +- result = libGAP_POW(self.value, (<GapElement>right).value) +- sig_off() ++ GAP_Enter() ++ result = POW(self.value, (<GapElement>right).value) ++ return make_any_gap_element(self.parent(), result) + except RuntimeError as msg: +- libGAP_ClearError() + raise ValueError('libGAP: ' + str(msg)) + finally: +- libgap_exit() +- return make_any_gap_element(self.parent(), result) ++ GAP_Leave() ++ sig_off() + + + def is_function(self): +@@ -1039,7 +1068,7 @@ cdef class GapElement(RingElement): + sage: a.is_function() + False + """ +- return libGAP_IS_FUNC(self.value) ++ return IS_FUNC(self.value) + + + def is_list(self): +@@ -1057,7 +1086,7 @@ cdef class GapElement(RingElement): + sage: libgap.eval('3/2').is_list() + False + """ +- return libGAP_IS_LIST(self.value) ++ return IS_LIST(self.value) + + + def is_record(self): +@@ -1075,7 +1104,7 @@ cdef class GapElement(RingElement): + sage: libgap.eval('rec(a:=1, b:=3)').is_record() + True + """ +- return libGAP_IS_REC(self.value) ++ return IS_REC(self.value) + + + cpdef is_bool(self): +@@ -1093,9 +1122,8 @@ cdef class GapElement(RingElement): + """ + libgap = self.parent() + cdef GapElement r_sage = libgap.IsBool(self) +- cdef libGAP_Obj r_gap = r_sage.value +- return r_gap == libGAP_True +- ++ cdef Obj r_gap = r_sage.value ++ return r_gap == GAP_True + + def is_string(self): + r""" +@@ -1110,7 +1138,7 @@ cdef class GapElement(RingElement): + sage: libgap('this is a string').is_string() + True + """ +- return libGAP_IS_STRING(self.value) ++ return IS_STRING(self.value) + + + def is_permutation(self): +@@ -1130,8 +1158,8 @@ cdef class GapElement(RingElement): + sage: libgap('this is a string').is_permutation() + False + """ +- return (libGAP_TNUM_OBJ(self.value) == libGAP_T_PERM2 or +- libGAP_TNUM_OBJ(self.value) == libGAP_T_PERM4) ++ return (TNUM_OBJ(self.value) == T_PERM2 or ++ TNUM_OBJ(self.value) == T_PERM4) + + + def sage(self): +@@ -1191,7 +1219,7 @@ cdef class GapElement(RingElement): + ### GapElement_Integer ##################################################### + ############################################################################ + +-cdef GapElement_Integer make_GapElement_Integer(parent, libGAP_Obj obj): ++cdef GapElement_Integer make_GapElement_Integer(parent, Obj obj): + r""" + Turn a Gap integer object into a GapElement_Integer Sage object + +@@ -1250,7 +1278,7 @@ cdef class GapElement_Integer(GapElement): + sage: N.IsInt() + true + """ +- return libGAP_IS_INTOBJ(self.value) ++ return IS_INTOBJ(self.value) + + def _rational_(self): + r""" +@@ -1301,7 +1329,7 @@ cdef class GapElement_Integer(GapElement): + if ring is None: + ring = ZZ + if self.is_C_int(): +- return ring(libGAP_INT_INTOBJ(self.value)) ++ return ring(INT_INTOBJ(self.value)) + else: + # TODO: waste of time! + # gap integers are stored as a mp_limb_t and we have a much more direct +@@ -1318,13 +1346,13 @@ cdef class GapElement_Integer(GapElement): + + sage: int(libgap(3)) + 3 +- sage: type(_) is int +- True ++ sage: type(_) ++ <... 'int'> + + sage: int(libgap(2)**128) + 340282366920938463463374607431768211456L +- sage: type(_) is long +- True ++ sage: type(_) ++ <type 'long'> + """ + return self.sage(ring=int) + +@@ -1345,7 +1373,7 @@ cdef class GapElement_Integer(GapElement): + ### GapElement_Float ##################################################### + ########################################################################## + +-cdef GapElement_Float make_GapElement_Float(parent, libGAP_Obj obj): ++cdef GapElement_Float make_GapElement_Float(parent, Obj obj): + r""" + Turn a Gap macfloat object into a GapElement_Float Sage object + +@@ -1401,7 +1429,7 @@ cdef class GapElement_Float(GapElement): + """ + if ring is None: + ring = RDF +- return ring(libGAP_VAL_MACFLOAT(self.value)) ++ return ring(VAL_MACFLOAT(self.value)) + + def __float__(self): + r""" +@@ -1410,7 +1438,7 @@ cdef class GapElement_Float(GapElement): + sage: float(libgap.eval("Float(3.5)")) + 3.5 + """ +- return libGAP_VAL_MACFLOAT(self.value) ++ return VAL_MACFLOAT(self.value) + + + +@@ -1418,7 +1446,7 @@ cdef class GapElement_Float(GapElement): + ### GapElement_IntegerMod ##################################################### + ############################################################################ + +-cdef GapElement_IntegerMod make_GapElement_IntegerMod(parent, libGAP_Obj obj): ++cdef GapElement_IntegerMod make_GapElement_IntegerMod(parent, Obj obj): + r""" + Turn a Gap integer object into a :class:`GapElement_IntegerMod` Sage object + +@@ -1499,7 +1527,7 @@ cdef class GapElement_IntegerMod(GapElement): + ### GapElement_FiniteField ##################################################### + ############################################################################ + +-cdef GapElement_FiniteField make_GapElement_FiniteField(parent, libGAP_Obj obj): ++cdef GapElement_FiniteField make_GapElement_FiniteField(parent, Obj obj): + r""" + Turn a GAP finite field object into a :class:`GapElement_FiniteField` Sage object + +@@ -1666,7 +1694,7 @@ cdef class GapElement_FiniteField(GapElement): + ### GapElement_Cyclotomic ##################################################### + ############################################################################ + +-cdef GapElement_Cyclotomic make_GapElement_Cyclotomic(parent, libGAP_Obj obj): ++cdef GapElement_Cyclotomic make_GapElement_Cyclotomic(parent, Obj obj): + r""" + Turn a Gap cyclotomic object into a :class:`GapElement_Cyclotomic` Sage + object. +@@ -1754,7 +1782,7 @@ cdef class GapElement_Cyclotomic(GapElement): + ### GapElement_Rational #################################################### + ############################################################################ + +-cdef GapElement_Rational make_GapElement_Rational(parent, libGAP_Obj obj): ++cdef GapElement_Rational make_GapElement_Rational(parent, Obj obj): + r""" + Turn a Gap Rational number (of type ``Obj``) into a Cython ``GapElement_Rational``. + +@@ -1826,7 +1854,7 @@ cdef class GapElement_Rational(GapElement): + ### GapElement_Ring ##################################################### + ############################################################################ + +-cdef GapElement_Ring make_GapElement_Ring(parent, libGAP_Obj obj): ++cdef GapElement_Ring make_GapElement_Ring(parent, Obj obj): + r""" + Turn a Gap integer object into a :class:`GapElement_Ring` Sage + object. +@@ -1968,7 +1996,7 @@ cdef class GapElement_Ring(GapElement): + ### GapElement_Boolean ##################################################### + ############################################################################ + +-cdef GapElement_Boolean make_GapElement_Boolean(parent, libGAP_Obj obj): ++cdef GapElement_Boolean make_GapElement_Boolean(parent, Obj obj): + r""" + Turn a Gap Boolean number (of type ``Obj``) into a Cython ``GapElement_Boolean``. + +@@ -2023,11 +2051,12 @@ cdef class GapElement_Boolean(GapElement): + ... + ValueError: the GAP boolean value "fail" cannot be represented in Sage + """ +- if self.value == libGAP_True: return True +- if self.value == libGAP_False: return False ++ if self.value == GAP_True: ++ return True ++ if self.value == GAP_False: ++ return False + raise ValueError('the GAP boolean value "fail" cannot be represented in Sage') + +- + def __nonzero__(self): + """ + Check that the boolean is "true". +@@ -2051,15 +2080,15 @@ cdef class GapElement_Boolean(GapElement): + ....: print("{} {}".format( x, type(x))) + false <type 'sage.libs.gap.element.GapElement_Boolean'> + fail <type 'sage.libs.gap.element.GapElement_Boolean'> +- """ +- return self.value == libGAP_True ++ """ ++ return self.value == GAP_True + + + ############################################################################ + ### GapElement_String #################################################### + ############################################################################ + +-cdef GapElement_String make_GapElement_String(parent, libGAP_Obj obj): ++cdef GapElement_String make_GapElement_String(parent, Obj obj): + r""" + Turn a Gap String (of type ``Obj``) into a Cython ``GapElement_String``. + +@@ -2108,11 +2137,9 @@ cdef class GapElement_String(GapElement): + sage: s.sage() + 'string' + sage: type(_) +- <... 'str'> ++ <type 'str'> + """ +- libgap_enter() +- s = char_to_str(libGAP_CSTR_STRING(self.value)) +- libgap_exit() ++ s = char_to_str(CSTR_STRING(self.value)) + return s + + sage = __str__ +@@ -2121,7 +2148,7 @@ cdef class GapElement_String(GapElement): + ### GapElement_Function #################################################### + ############################################################################ + +-cdef GapElement_Function make_GapElement_Function(parent, libGAP_Obj obj): ++cdef GapElement_Function make_GapElement_Function(parent, Obj obj): + r""" + Turn a Gap C function object (of type ``Obj``) into a Cython ``GapElement_Function``. + +@@ -2201,30 +2228,31 @@ cdef class GapElement_Function(GapElement): + <Gap function "NormalSubgroups"> + sage: b + Sym( [ 1 .. 4 ] ) +- sage: a(b) +- [ Group(()), +- Group([ (1,4)(2,3), (1,3)(2,4) ]), +- Group([ (2,4,3), (1,4)(2,3), (1,3)(2,4) ]), +- Sym( [ 1 .. 4 ] ) ] ++ sage: sorted(a(b)) ++ [Group(()), ++ Sym( [ 1 .. 4 ] ), ++ Alt( [ 1 .. 4 ] ), ++ Group([ (1,4)(2,3), (1,2)(3,4) ])] + + sage: libgap.eval("a := NormalSubgroups") + <Gap function "NormalSubgroups"> + sage: libgap.eval("b := SymmetricGroup(4)") + Sym( [ 1 .. 4 ] ) + sage: libgap.collect() +- sage: libgap.eval('a') (libgap.eval('b')) +- [ Group(()), +- Group([ (1,4)(2,3), (1,3)(2,4) ]), +- Group([ (2,4,3), (1,4)(2,3), (1,3)(2,4) ]), +- Sym( [ 1 .. 4 ] ) ] ++ sage: sorted(libgap.eval('a') (libgap.eval('b'))) ++ [Group(()), ++ Sym( [ 1 .. 4 ] ), ++ Alt( [ 1 .. 4 ] ), ++ Group([ (1,4)(2,3), (1,2)(3,4) ])] ++ + sage: a = libgap.eval('a') + sage: b = libgap.eval('b') + sage: libgap.collect() +- sage: a(b) +- [ Group(()), +- Group([ (1,4)(2,3), (1,3)(2,4) ]), +- Group([ (2,4,3), (1,4)(2,3), (1,3)(2,4) ]), +- Sym( [ 1 .. 4 ] ) ] ++ sage: sorted(a(b)) ++ [Group(()), ++ Sym( [ 1 .. 4 ] ), ++ Alt( [ 1 .. 4 ] ), ++ Group([ (1,4)(2,3), (1,2)(3,4) ])] + + Not every ``GapElement`` is callable:: + +@@ -2269,46 +2297,46 @@ cdef class GapElement_Function(GapElement): + sage: libgap_exec('echo hello from the shell') + hello from the shell + """ +- cdef libGAP_Obj result = NULL +- cdef libGAP_Obj arg_list ++ cdef Obj result = NULL ++ cdef Obj arg_list + cdef int i, n = len(args) + + if n > 0: + libgap = self.parent() +- a = [x if isinstance(x,GapElement) else libgap(x) for x in args] ++ a = [x if isinstance(x, GapElement) else libgap(x) for x in args] + ++ sig_on() + try: +- libgap_enter() +- sig_on() ++ GAP_Enter() + if n == 0: +- result = libGAP_CALL_0ARGS(self.value) ++ result = CALL_0ARGS(self.value) + elif n == 1: +- result = libGAP_CALL_1ARGS(self.value, ++ result = CALL_1ARGS(self.value, + (<GapElement>a[0]).value) + elif n == 2: +- result = libGAP_CALL_2ARGS(self.value, ++ result = CALL_2ARGS(self.value, + (<GapElement>a[0]).value, + (<GapElement>a[1]).value) + elif n == 3: +- result = libGAP_CALL_3ARGS(self.value, ++ result = CALL_3ARGS(self.value, + (<GapElement>a[0]).value, + (<GapElement>a[1]).value, + (<GapElement>a[2]).value) + elif n == 4: +- result = libGAP_CALL_4ARGS(self.value, ++ result = CALL_4ARGS(self.value, + (<GapElement>a[0]).value, + (<GapElement>a[1]).value, + (<GapElement>a[2]).value, + (<GapElement>a[3]).value) + elif n == 5: +- result = libGAP_CALL_5ARGS(self.value, ++ result = CALL_5ARGS(self.value, + (<GapElement>a[0]).value, + (<GapElement>a[1]).value, + (<GapElement>a[2]).value, + (<GapElement>a[3]).value, + (<GapElement>a[4]).value) + elif n == 6: +- result = libGAP_CALL_6ARGS(self.value, ++ result = CALL_6ARGS(self.value, + (<GapElement>a[0]).value, + (<GapElement>a[1]).value, + (<GapElement>a[2]).value, +@@ -2316,21 +2344,20 @@ cdef class GapElement_Function(GapElement): + (<GapElement>a[4]).value, + (<GapElement>a[5]).value) + elif n >= 7: +- libgap_exit() + arg_list = make_gap_list(args) +- libgap_enter() +- result = libGAP_CALL_XARGS(self.value, arg_list) +- sig_off() ++ result = CALL_XARGS(self.value, arg_list) ++ ++ if result == NULL: ++ # We called a procedure that does not return anything ++ return None ++ ++ return make_any_gap_element(self.parent(), result) + except RuntimeError as msg: + raise ValueError('libGAP: ' + str(msg)) + finally: +- libgap_exit() +- +- if result == NULL: +- # We called a procedure that does not return anything +- return None ++ GAP_Leave() ++ sig_off() + +- return make_any_gap_element(self.parent(), result) + + + def _instancedoc_(self): +@@ -2356,7 +2383,7 @@ cdef class GapElement_Function(GapElement): + ### GapElement_MethodProxy ################################################# + ############################################################################ + +-cdef GapElement_MethodProxy make_GapElement_MethodProxy(parent, libGAP_Obj function, GapElement base_object): ++cdef GapElement_MethodProxy make_GapElement_MethodProxy(parent, Obj function, GapElement base_object): + r""" + Turn a Gap C rec object (of type ``Obj``) into a Cython ``GapElement_Record``. + +@@ -2435,7 +2462,7 @@ cdef class GapElement_MethodProxy(GapElement_Function): + sage: lst + [ 1,, 3, 4, 5 ] + """ +- if args: ++ if len(args) > 0: + return GapElement_Function.__call__(self, * ([self.first_argument] + list(args))) + else: + return GapElement_Function.__call__(self, self.first_argument) +@@ -2446,7 +2473,7 @@ cdef class GapElement_MethodProxy(GapElement_Function): + ### GapElement_List ######################################################## + ############################################################################ + +-cdef GapElement_List make_GapElement_List(parent, libGAP_Obj obj): ++cdef GapElement_List make_GapElement_List(parent, Obj obj): + r""" + Turn a Gap C List object (of type ``Obj``) into a Cython ``GapElement_List``. + +@@ -2498,6 +2525,21 @@ cdef class GapElement_List(GapElement): + IndexError: index out of range. + """ + ++ def __bool__(self): ++ r""" ++ Return True if the list is non-empty, as with Python ``list``s. ++ ++ EXAMPLES:: ++ ++ sage: lst = libgap.eval('[1,,,4]') ++ sage: bool(lst) ++ True ++ sage: lst = libgap.eval('[]') ++ sage: bool(lst) ++ False ++ """ ++ return bool(len(self)) ++ + def __len__(self): + r""" + Return the length of the list. +@@ -2512,7 +2554,7 @@ cdef class GapElement_List(GapElement): + sage: len(lst) + 4 + """ +- return libGAP_LEN_LIST(self.value) ++ return LEN_LIST(self.value) + + def __getitem__(self, i): + r""" +@@ -2556,21 +2598,21 @@ cdef class GapElement_List(GapElement): + ValueError: too many indices + """ + cdef int j +- cdef libGAP_Obj obj = self.value ++ cdef Obj obj = self.value + + if isinstance(i, tuple): + for j in i: +- if not libGAP_IS_LIST(obj): ++ if not IS_LIST(obj): + raise ValueError('too many indices') +- if j < 0 or j >= libGAP_LEN_LIST(obj): ++ if j < 0 or j >= LEN_LIST(obj): + raise IndexError('index out of range') +- obj = libGAP_ELM_LIST(obj, j+1) ++ obj = ELM_LIST(obj, j+1) + + else: + j = i +- if j < 0 or j >= libGAP_LEN_LIST(obj): ++ if j < 0 or j >= LEN_LIST(obj): + raise IndexError('index out of range.') +- obj = libGAP_ELM_LIST(obj, j+1) ++ obj = ELM_LIST(obj, j+1) + + return make_any_gap_element(self.parent(), obj) + +@@ -2623,20 +2665,20 @@ cdef class GapElement_List(GapElement): + sage: m + [ [ 1, 2 ], [ 3, 4 ] ] + """ +- if not libGAP_IS_MUTABLE_OBJ(self.value): ++ if not IS_MUTABLE_OBJ(self.value): + raise TypeError('immutable Gap object does not support item assignment') + + cdef int j +- cdef libGAP_Obj obj = self.value ++ cdef Obj obj = self.value + + if isinstance(i, tuple): + for j in i[:-1]: +- if not libGAP_IS_LIST(obj): ++ if not IS_LIST(obj): + raise ValueError('too many indices') +- if j < 0 or j >= libGAP_LEN_LIST(obj): ++ if j < 0 or j >= LEN_LIST(obj): + raise IndexError('index out of range') +- obj = libGAP_ELM_LIST(obj, j+1) +- if not libGAP_IS_LIST(obj): ++ obj = ELM_LIST(obj, j+1) ++ if not IS_LIST(obj): + raise ValueError('too many indices') + j = i[-1] + else: +@@ -2651,7 +2693,7 @@ cdef class GapElement_List(GapElement): + else: + celt= self.parent()(elt) + +- libGAP_ASS_LIST(obj, j+1, celt.value) ++ ASS_LIST(obj, j+1, celt.value) + + def sage(self, **kwds): + r""" +@@ -2769,7 +2811,7 @@ cdef class GapElement_List(GapElement): + ############################################################################ + + +-cdef GapElement_Permutation make_GapElement_Permutation(parent, libGAP_Obj obj): ++cdef GapElement_Permutation make_GapElement_Permutation(parent, Obj obj): + r""" + Turn a Gap C permutation object (of type ``Obj``) into a Cython ``GapElement_Permutation``. + +@@ -2834,7 +2876,7 @@ cdef class GapElement_Permutation(GapElement): + ### GapElement_Record ###################################################### + ############################################################################ + +-cdef GapElement_Record make_GapElement_Record(parent, libGAP_Obj obj): ++cdef GapElement_Record make_GapElement_Record(parent, Obj obj): + r""" + Turn a Gap C rec object (of type ``Obj``) into a Cython ``GapElement_Record``. + +@@ -2876,7 +2918,8 @@ cdef class GapElement_Record(GapElement): + sage: rec['no_such_element'] + Traceback (most recent call last): + ... +- IndexError: libGAP: Error, Record: '<rec>.no_such_element' must have an assigned value ++ IndexError: libGAP: Error, Record Element: '<rec>.no_such_element' must ++ have an assigned value + """ + + def __len__(self): +@@ -2893,7 +2936,7 @@ cdef class GapElement_Record(GapElement): + sage: len(rec) + 3 + """ +- return libGAP_LEN_PREC(self.value) ++ return LEN_PREC(self.value) + + + def __iter__(self): +@@ -2910,19 +2953,19 @@ cdef class GapElement_Record(GapElement): + sage: iter = rec.__iter__() + sage: type(iter) + <type 'sage.libs.gap.element.GapElement_RecordIterator'> +- sage: list(rec) ++ sage: sorted(rec) + [('a', 123), ('b', 456)] + """ + return GapElement_RecordIterator(self) + + +- cpdef libGAP_UInt record_name_to_index(self, name): ++ cpdef UInt record_name_to_index(self, name): + r""" + Convert string to GAP record index. + + INPUT: + +- - ``name`` -- a python string. ++ - ``py_name`` -- a python string. + + OUTPUT: + +@@ -2939,12 +2982,7 @@ cdef class GapElement_Record(GapElement): + 3776L + """ + name = str_to_bytes(name) +- +- try: +- libgap_enter() +- return libGAP_RNamName(name) +- finally: +- libgap_exit() ++ return RNamName(name) + + def __getitem__(self, name): + r""" +@@ -2964,15 +3002,18 @@ cdef class GapElement_Record(GapElement): + sage: rec['first'] + 123 + """ +- cdef libGAP_UInt i = self.record_name_to_index(name) +- cdef libGAP_Obj result ++ cdef UInt i = self.record_name_to_index(name) ++ cdef Obj result ++ sig_on() + try: +- sig_on() +- result = libGAP_ELM_REC(self.value, i) +- sig_off() ++ GAP_Enter() ++ result = ELM_REC(self.value, i) ++ return make_any_gap_element(self.parent(), result) + except RuntimeError as msg: + raise IndexError('libGAP: ' + str(msg)) +- return make_any_gap_element(self.parent(), result) ++ finally: ++ GAP_Leave() ++ sig_off() + + + def sage(self): +@@ -3016,7 +3057,7 @@ cdef class GapElement_RecordIterator(object): + EXAMPLES:: + + sage: rec = libgap.eval('rec(a:=123, b:=456)') +- sage: list(rec) ++ sage: sorted(rec) + [('a', 123), ('b', 456)] + sage: dict(rec) + {'a': 123, 'b': 456} +@@ -3052,20 +3093,18 @@ cdef class GapElement_RecordIterator(object): + + sage: rec = libgap.eval('rec(a:=123, b:=456)') + sage: iter = rec.__iter__() +- sage: iter.__next__() +- ('a', 123) +- sage: next(iter) +- ('b', 456) ++ sage: a = iter.__next__() ++ sage: b = next(iter) ++ sage: sorted([a, b]) ++ [('a', 123), ('b', 456)] + """ +- cdef libGAP_UInt i = self.i ++ cdef UInt i = self.i + if i>len(self.rec): + raise StopIteration + # note the abs: negative values mean the rec keys are not sorted +- libgap_enter() +- key_index = abs(libGAP_GET_RNAM_PREC(self.rec.value, i)) +- key = char_to_str(libGAP_NAME_RNAM(key_index)) +- cdef libGAP_Obj result = libGAP_GET_ELM_PREC(self.rec.value,i) +- libgap_exit() ++ key_index = abs(GET_RNAM_PREC(self.rec.value, i)) ++ key = char_to_str(CSTR_STRING(NAME_RNAM(key_index))) ++ cdef Obj result = GET_ELM_PREC(self.rec.value,i) + val = make_any_gap_element(self.rec.parent(), result) + self.i += 1 + return (key, val) +diff --git a/src/sage/libs/gap/gap_functions.py b/src/sage/libs/gap/gap_functions.py +index 271a8aa..f7dac14 100644 +--- a/src/sage/libs/gap/gap_functions.py ++++ b/src/sage/libs/gap/gap_functions.py +@@ -1,4 +1,4 @@ +-"Gap functions" ++"""Common global functions defined by GAP.""" + + ############################################################################### + # Copyright (C) 2009, William Stein <wstein@gmail.com> +@@ -11,8 +11,9 @@ + ############################################################################### + + ++ + # selected gap functions to use in tab completion +-common_gap_functions = [ ++common_gap_functions = set([ + 'AbelianGroup', + 'AbelianInvariants', + 'AbelianInvariantsMultiplier', +@@ -37,13 +38,11 @@ common_gap_functions = [ + 'AppendTo', + 'Apply', + 'AsGroup', +- 'Assert', +- 'AtlasGroup', + 'AutomorphismGroup', + 'BaseOfGroup', + 'Basis', + 'BasisVectors', +- 'Bell', ++ 'Bell', + 'Binomial', + 'BlockMatrix', + 'Blocks', +@@ -125,7 +124,6 @@ common_gap_functions = [ + 'CyclicGroup', + 'CyclotomicField', + 'CyclotomicPolynomial', +- 'Cyclotomics', + 'DefiningPolynomial', + 'Degree', + 'DegreeFFE', +@@ -210,8 +208,6 @@ common_gap_functions = [ + 'GaloisGroup', + 'GaloisMat', + 'GaloisStabilizer', +- 'GaussianIntegers', +- 'GaussianRationals', + 'Gcd', + 'GcdInt', + 'GcdOp', +@@ -225,7 +221,6 @@ common_gap_functions = [ + 'GeneratorsOfField', + 'GeneratorsOfGroup', + 'GeneratorsOfIdeal', +- 'GlobalMersenneTwister', + 'GroebnerBasis', + 'Group', + 'GroupHomomorphismByFunction', +@@ -243,23 +238,7 @@ common_gap_functions = [ + 'Image', + 'Images', + 'Index', +- 'InfoAlgebra', +- 'InfoAttributes', +- 'InfoBckt', +- 'InfoCharacterTable', +- 'InfoCoh', +- 'InfoComplement', +- 'InfoCoset', +- 'InfoFpGroup', +- 'InfoGroebner', +- 'InfoGroup', +- 'InfoLattice', + 'InfoLevel', +- 'InfoMatrix', +- 'InfoMonomial', +- 'InfoNumtheor', +- 'InfoOptions', +- 'InfoPcSubgroup', + 'InfoText', + 'InnerAutomorphism', + 'InnerAutomorphismsAutomorphismGroup', +@@ -269,7 +248,6 @@ common_gap_functions = [ + 'IntHexString', + 'IntScalarProducts', + 'IntVecFFE', +- 'Integers', + 'IntersectSet', + 'Intersection', + 'InvariantBilinearForm', +@@ -319,7 +297,6 @@ common_gap_functions = [ + 'IsBinaryRelation', + 'IsBlockMatrixRep', + 'IsBool', +- 'IsBound', + 'IsBoundGlobal', + 'IsBrauerTable', + 'IsBravaisGroup', +@@ -528,7 +505,6 @@ common_gap_functions = [ + 'IsTransitive', + 'IsTransitiveBinaryRelation', + 'IsTrivial', +- 'IsTuple', + 'IsUniqueFactorizationRing', + 'IsUnit', + 'IsUnivariatePolynomial', +@@ -718,7 +694,6 @@ common_gap_functions = [ + 'MonomialGrevlexOrdering', + 'MonomialGrlexOrdering', + 'MonomialLexOrdering', +- 'MonomialTotalDegreeLess', + 'MostFrequentGeneratorFpGroup', + 'MovedPoints', + 'MultRowVector', +@@ -742,7 +717,6 @@ common_gap_functions = [ + 'NextIterator', + 'NextPrimeInt', + 'NiceBasis', +- 'NiceBasisFiltersInfo', + 'NiceFreeLeftModule', + 'NiceFreeLeftModuleInfo', + 'NiceMonomorphism', +@@ -933,7 +907,6 @@ common_gap_functions = [ + 'Position', + 'PositionBound', + 'PositionCanonical', +- 'PositionFirstComponent', + 'PositionNonZero', + 'PositionNot', + 'PositionNthOccurrence', +@@ -976,7 +949,6 @@ common_gap_functions = [ + 'PrimePGroup', + 'PrimePowersInt', + 'PrimeResidues', +- 'Primes', + 'PrimitiveElement', + 'PrimitiveGroup', + 'PrimitiveIdentification', +@@ -1047,7 +1019,6 @@ common_gap_functions = [ + 'RationalClass', + 'RationalClasses', + 'RationalizedMat', +- 'Rationals', + 'Read', + 'ReadAll', + 'ReadAllLine', +@@ -1094,7 +1065,6 @@ common_gap_functions = [ + 'ReesMatrixSemigroupElement', + 'ReesZeroMatrixSemigroup', + 'ReesZeroMatrixSemigroupElement', +- 'ReesZeroMatrixSemigroupElementIsZero', + 'RefinedPcGroup', + 'RegularActionHomomorphism', + 'RegularModule', +@@ -1124,7 +1094,6 @@ common_gap_functions = [ + 'Reread', + 'RereadPackage', + 'Reset', +- 'RestoreStateRandom', + 'RestrictOutputsOfSLP', + 'Restricted', + 'RestrictedClassFunction', +@@ -1157,8 +1126,6 @@ common_gap_functions = [ + 'SSortedList', + 'SU', + 'SameBlock', +- 'SandwichMatrixOfReesMatrixSemigroup', +- 'SandwichMatrixOfReesZeroMatrixSemigroup', + 'SaveWorkspace', + 'ScalarProduct', + 'SchurCover', +@@ -1249,7 +1216,6 @@ common_gap_functions = [ + 'StabilizerOfExternalSet', + 'StabilizerPcgs', + 'StandardAssociate', +- 'StandardGeneratorsInfo', + 'StandardizeTable', + 'StarCyc', + 'Stirling1', +@@ -1296,7 +1262,6 @@ common_gap_functions = [ + 'SumIntersectionMat', + 'SumX', + 'SupersolvableResiduum', +- 'SupportedCharacterTableInfo', + 'SurjectiveActionHomomorphismAttr', + 'SuzukiGroup', + 'SylowComplement', +@@ -1314,7 +1279,6 @@ common_gap_functions = [ + 'TableAutomorphisms', + 'TableOfMarks', + 'TableOfMarksByLattice', +- 'TableOfMarksComponents', + 'TableOfMarksCyclic', + 'TableOfMarksDihedral', + 'TableOfMarksFrobenius', +@@ -1332,9 +1296,6 @@ common_gap_functions = [ + 'TracedCosetFpGroup', + 'TransferDiagram', + 'Transformation', +- 'TransformationData', +- 'TransformationRelation', +- 'TransformationType', + 'TransformingPermutations', + 'TransformingPermutationsCharacterTables', + 'TransitiveClosureBinaryRelation', +@@ -1365,7 +1326,6 @@ common_gap_functions = [ + 'TrivialSubspace', + 'Tuple', + 'Tuples', +- 'Unbind', + 'UnbindElmWPObj', + 'UnbindGlobal', + 'UnderlyingCharacterTable', +@@ -1441,4 +1401,6 @@ common_gap_functions = [ + 'ZeroOp', + 'ZeroSM', + 'ZeroSameMutability', +- ] ++ 'GASMAN_STATS', ++ 'GASMAN', ++ ]) +diff --git a/src/sage/libs/gap/gap_globals.py b/src/sage/libs/gap/gap_globals.py +new file mode 100644 +index 00000000..99b3921 +--- /dev/null ++++ b/src/sage/libs/gap/gap_globals.py +@@ -0,0 +1,46 @@ ++"""Common globals defined by GAP.""" ++ ++############################################################################### ++# Copyright (C) 2009, William Stein <wstein@gmail.com> ++# Copyright (C) 2012, Volker Braun <vbraun.name@gmail.com> ++# ++# Distributed under the terms of the GNU General Public License (GPL) ++# as published by the Free Software Foundation; either version 2 of ++# the License, or (at your option) any later version. ++# http://www.gnu.org/licenses/ ++############################################################################### ++ ++ ++from .gap_functions import common_gap_functions ++ ++ ++# selected gap globals to use in tab completion ++common_gap_globals = set([ ++ 'Assert', ++ 'Cyclotomics', ++ 'GaussianIntegers', ++ 'GaussianRationals', ++ 'GlobalMersenneTwister', ++ 'GlobalRandomSource', ++ 'InfoAlgebra', ++ 'InfoAttributes', ++ 'InfoBckt', ++ 'InfoCharacterTable', ++ 'InfoCoh', ++ 'InfoComplement', ++ 'InfoCoset', ++ 'InfoFpGroup', ++ 'InfoGroebner', ++ 'InfoGroup', ++ 'InfoLattice', ++ 'InfoMatrix', ++ 'InfoMonomial', ++ 'InfoNumtheor', ++ 'InfoOptions', ++ 'InfoPcSubgroup', ++ 'Integers', ++ 'NiceBasisFiltersInfo', ++ 'Primes', ++ 'Rationals', ++ 'TableOfMarksComponents' ++]) | common_gap_functions +diff --git a/src/sage/libs/gap/gap_includes.pxd b/src/sage/libs/gap/gap_includes.pxd +index c3f4dcb..f62b24e 100644 +--- a/src/sage/libs/gap/gap_includes.pxd ++++ b/src/sage/libs/gap/gap_includes.pxd +@@ -10,318 +10,152 @@ + ############################################################################### + + +-from .types cimport * +- +-cdef extern from "<gap/libgap.h>": +- void libgap_initialize(int argc, char** argv) +- ctypedef void(*libgap_gasman_callback_ptr)() +- void libgap_set_gasman_callback(libgap_gasman_callback_ptr callback) +- ctypedef void(*libgap_error_func_ptr)(char* msg) +- void libgap_set_error_handler(libgap_error_func_ptr error_handler) +- void libgap_call_error_handler() +- void libgap_finalize() +- void libgap_start_interaction(char* inputline) +- char* libgap_get_output() +- char* libgap_get_error() +- void libgap_finish_interaction() +- void libgap_mark_stack_bottom() +- void libgap_enter() +- void libgap_exit() +- +-cdef extern from "<gap/gap.h>": +- void libGAP_ViewObjHandler(void*) +- void libGAP_InitializeGap(int*, char** argv) +- void libGAP_set_system_variables(char**, char**) +- cdef libGAP_UInt libGAP_Last +- cdef libGAP_UInt libGAP_Last2 +- cdef libGAP_UInt libGAP_Last3 +- cdef libGAP_ExecStatus libGAP_STATUS_END +- cdef libGAP_ExecStatus libGAP_STATUS_RETURN_VAL +- cdef libGAP_ExecStatus libGAP_STATUS_RETURN_VOID +- cdef libGAP_ExecStatus libGAP_STATUS_TNM +- cdef libGAP_ExecStatus libGAP_STATUS_QUIT +- cdef libGAP_ExecStatus libGAP_STATUS_EOF +- cdef libGAP_ExecStatus libGAP_STATUS_ERROR +- cdef libGAP_ExecStatus libGAP_STATUS_QQUIT ++cdef extern from "<gap/system.h>": ++ ctypedef char Char ++ ctypedef int Int ++ ctypedef unsigned int UInt ++ ctypedef void* Obj + +-cdef extern from "<gap/objects.h>": +- bint libGAP_IS_MUTABLE_OBJ(libGAP_Obj obj) +- bint libGAP_IS_COPYABLE_OBJ(libGAP_Obj obj) +- libGAP_Obj libGAP_SHALLOW_COPY_OBJ(libGAP_Obj obj) +- libGAP_Obj libGAP_CopyObj(libGAP_Obj obj, int mut) +- +- bint libGAP_IS_INTOBJ(libGAP_Obj obj) +- libGAP_Obj libGAP_INTOBJ_INT(libGAP_Int) +- libGAP_Int libGAP_INT_INTOBJ(libGAP_Obj) +- libGAP_UInt libGAP_TNUM_OBJ(libGAP_Obj obj) +- char* libGAP_TNAM_OBJ(libGAP_Obj obj) +- cdef int libGAP_FIRST_REAL_TNUM +- cdef int libGAP_FIRST_CONSTANT_TNUM +- cdef int libGAP_T_INT +- cdef int libGAP_T_INTPOS +- cdef int libGAP_T_INTNEG +- cdef int libGAP_T_RAT +- cdef int libGAP_T_CYC +- cdef int libGAP_T_FFE +- cdef int libGAP_T_PERM2 +- cdef int libGAP_T_PERM4 +- cdef int libGAP_T_BOOL +- cdef int libGAP_T_CHAR +- cdef int libGAP_T_FUNCTION +- cdef int libGAP_T_FLAGS +- cdef int libGAP_T_MACFLOAT +- cdef int libGAP_T_RESERVED_BY_GAP +- cdef int libGAP_LAST_CONSTANT_TNUM +- cdef int libGAP_IMMUTABLE +- cdef int libGAP_FIRST_IMM_MUT_TNUM +- cdef int libGAP_FIRST_RECORD_TNUM +- cdef int libGAP_T_PREC +- cdef int libGAP_LAST_RECORD_TNUM +- cdef int libGAP_FIRST_LIST_TNUM +- cdef int libGAP_FIRST_PLIST_TNUM +- cdef int libGAP_T_PLIST +- cdef int libGAP_T_PLIST_NDENSE +- cdef int libGAP_T_PLIST_DENSE +- cdef int libGAP_T_PLIST_DENSE_NHOM +- cdef int libGAP_T_PLIST_DENSE_NHOM_SSORT +- cdef int libGAP_T_PLIST_DENSE_NHOM_NSORT +- cdef int libGAP_T_PLIST_EMPTY +- cdef int libGAP_T_PLIST_HOM +- cdef int libGAP_T_PLIST_HOM_NSORT +- cdef int libGAP_T_PLIST_HOM_SSORT +- cdef int libGAP_T_PLIST_TAB +- cdef int libGAP_T_PLIST_TAB_NSORT +- cdef int libGAP_T_PLIST_TAB_SSORT +- cdef int libGAP_T_PLIST_TAB_RECT +- cdef int libGAP_T_PLIST_TAB_RECT_NSORT +- cdef int libGAP_T_PLIST_TAB_RECT_SSORT +- cdef int libGAP_T_PLIST_CYC +- cdef int libGAP_T_PLIST_CYC_NSORT +- cdef int libGAP_T_PLIST_CYC_SSORT +- cdef int libGAP_T_PLIST_FFE +- cdef int libGAP_LAST_PLIST_TNUM +- cdef int libGAP_T_RANGE_NSORT +- cdef int libGAP_T_RANGE_SSORT +- cdef int libGAP_T_BLIST +- cdef int libGAP_T_BLIST_NSORT +- cdef int libGAP_T_BLIST_SSORT +- cdef int libGAP_T_STRING +- cdef int libGAP_T_STRING_NSORT +- cdef int libGAP_T_STRING_SSORT +- cdef int libGAP_LAST_LIST_TNUM +- cdef int libGAP_LAST_IMM_MUT_TNUM +- cdef int libGAP_FIRST_EXTERNAL_TNUM +- cdef int libGAP_T_COMOBJ +- cdef int libGAP_T_POSOBJ +- cdef int libGAP_T_DATOBJ +- cdef int libGAP_T_WPOBJ +- cdef int libGAP_LAST_EXTERNAL_TNUM +- cdef int libGAP_LAST_REAL_TNUM +- cdef int libGAP_LAST_VIRTUAL_TNUM +- cdef int libGAP_FIRST_COPYING_TNUM +- cdef int libGAP_COPYING +- cdef int libGAP_LAST_COPYING_TNUM +- cdef int libGAP_FIRST_TESTING_TNUM +- cdef int libGAP_TESTING +- cdef int libGAP_LAST_TESTING_TNUM +- +-cdef extern from "<gap/read.h>": +- void* libGAP_ReadEvalCommand(libGAP_Obj context, libGAP_UInt *dualSemicolon) +- void* libGAP_ReadEvalFile() +- void* libGAP_ReadEvalResult +- bint libGAP_READ_ERROR() +- +-cdef extern from "<gap/scanner.h>": +- void libGAP_ClearError() +- libGAP_UInt libGAP_NrError +- libGAP_UInt libGAP_Symbol +- void libGAP_GetSymbol() +- void libGAP_Match (libGAP_UInt symbol, char* msg, libGAP_UInt skipto) +- int libGAP_S_ILLEGAL +- int libGAP_S_IDENT +- int libGAP_S_UNBIND +- int libGAP_S_ISBOUND +- int libGAP_S_TRYNEXT +- int libGAP_S_INFO +- int libGAP_S_ASSERT +- int libGAP_S_SAVEWS +- int libGAP_S_LOADWS +- int libGAP_S_LBRACK +- int libGAP_S_LBRACE +- int libGAP_S_BLBRACK +- int libGAP_S_BLBRACE +- int libGAP_S_RBRACK +- int libGAP_S_RBRACE +- int libGAP_S_DOT +- int libGAP_S_BDOT +- int libGAP_S_LPAREN +- int libGAP_S_RPAREN +- int libGAP_S_COMMA +- int libGAP_S_DOTDOT +- int libGAP_S_COLON +- int libGAP_S_PARTIALINT +- int libGAP_S_INT +- int libGAP_S_TRUE +- int libGAP_S_FALSE +- int libGAP_S_CHAR +- int libGAP_S_STRING +- int libGAP_S_PARTIALSTRING +- int libGAP_S_REC +- int libGAP_S_FUNCTION +- int libGAP_S_LOCAL +- int libGAP_S_END +- int libGAP_S_MAPTO +- int libGAP_S_MULT +- int libGAP_S_DIV +- int libGAP_S_MOD +- int libGAP_S_POW +- int libGAP_S_PLUS +- int libGAP_S_MINUS +- int libGAP_S_EQ +- int libGAP_S_LT +- int libGAP_S_GT +- int libGAP_S_NE +- int libGAP_S_LE +- int libGAP_S_GE +- int libGAP_S_IN +- int libGAP_S_NOT +- int libGAP_S_AND +- int libGAP_S_OR +- int libGAP_S_ASSIGN +- int libGAP_S_IF +- int libGAP_S_FOR +- int libGAP_S_WHILE +- int libGAP_S_REPEAT +- int libGAP_S_THEN +- int libGAP_S_ELIF +- int libGAP_S_ELSE +- int libGAP_S_FI +- int libGAP_S_DO +- int libGAP_S_OD +- int libGAP_S_UNTIL +- int libGAP_S_BREAK +- int libGAP_S_RETURN +- int libGAP_S_QUIT +- int libGAP_S_QQUIT +- int libGAP_S_CONTINUE +- int libGAP_S_SEMICOLON +- int libGAP_S_EOF + +-cdef extern from "<gap/gvars.h>": +- libGAP_UInt libGAP_GVarName(char* name) +- void libGAP_AssGVar(libGAP_UInt gvar, libGAP_Obj val) +- libGAP_Obj libGAP_VAL_GVAR(libGAP_UInt gvar) +- +-cdef extern from "<gap/string.h>": +- char* libGAP_CSTR_STRING(libGAP_Obj list) +- int libGAP_GET_LEN_STRING(libGAP_Obj list) +- bint libGAP_IS_STRING(libGAP_Obj obj) +- bint libGAP_IsStringConv(libGAP_Obj obj) +- bint libGAP_ConvString(libGAP_Obj obj) +- void libGAP_C_NEW_STRING(libGAP_Obj new_gap_string, int length, char* c_string) ++cdef extern from "<gap/ariths.h>": ++ Obj SUM(Obj, Obj) ++ Obj DIFF(Obj, Obj) ++ Obj PROD(Obj, Obj) ++ Obj QUO(Obj, Obj) ++ Obj POW(Obj, Obj) ++ Obj MOD(Obj, Obj) ++ bint EQ(Obj opL, Obj opR) ++ bint LT(Obj opL, Obj opR) + +-cdef extern from "<gap/gasman.h>": +- void libGAP_InitGlobalBag(libGAP_Obj* addr, char* cookie) +- libGAP_Obj libGAP_NewBag(libGAP_UInt type, libGAP_UInt size) +- void libGAP_CHANGED_BAG(libGAP_Obj bag) +- void libGAP_MARK_BAG(libGAP_Obj bag) +- bint libGAP_IS_MARKED_ALIVE(libGAP_Obj bag) +- bint libGAP_IS_MARKED_DEAD(libGAP_Obj bag) +- bint libGAP_IS_MARKED_HALFDEAD(libGAP_Obj bag) +- cdef libGAP_UInt libGAP_NrAllBags +- cdef libGAP_UInt libGAP_SizeAllBags +- cdef libGAP_UInt libGAP_NrLiveBags +- cdef libGAP_UInt libGAP_SizeLiveBags +- cdef libGAP_UInt libGAP_NrDeadBags +- cdef libGAP_UInt libGAP_SizeDeadBags +- cdef libGAP_UInt libGAP_NrHalfDeadBags +- libGAP_UInt libGAP_CollectBags(libGAP_UInt size, libGAP_UInt full) +- void libGAP_CallbackForAllBags(void (*func)(libGAP_Obj)) +- char* libGAP_TNAM_BAG(libGAP_Obj obj) +- libGAP_UInt libGAP_TNUM_BAG(libGAP_Obj) +- libGAP_UInt libGAP_SIZE_BAG(libGAP_Obj) +- void libGAP_CheckMasterPointers() +- libGAP_Obj* libGAP_MptrBags +- libGAP_Obj* libGAP_YoungBags +- libGAP_Obj* libGAP_OldBags +- libGAP_Obj* libGAP_AllocBags +- libGAP_Obj* libGAP_MarkedBags +- libGAP_Obj* libGAP_ChangedBags +- +-# in gasman.c but not declared in gasman.h +-cdef extern: +- libGAP_Obj* libGAP_StopBags +- libGAP_Obj* libGAP_EndBags + +-cdef extern from "<gap/ariths.h>": +- libGAP_Obj libGAP_SUM (libGAP_Obj, libGAP_Obj) +- libGAP_Obj libGAP_DIFF(libGAP_Obj, libGAP_Obj) +- libGAP_Obj libGAP_PROD(libGAP_Obj, libGAP_Obj) +- libGAP_Obj libGAP_QUO(libGAP_Obj, libGAP_Obj) +- libGAP_Obj libGAP_POW(libGAP_Obj, libGAP_Obj) +- libGAP_Obj libGAP_MOD(libGAP_Obj, libGAP_Obj) +- libGAP_Obj libGAP_CALL_0ARGS(libGAP_Obj f) # 0 arguments +- libGAP_Obj libGAP_CALL_1ARGS(libGAP_Obj f, libGAP_Obj a1) # 1 argument +- libGAP_Obj libGAP_CALL_2ARGS(libGAP_Obj f, libGAP_Obj a1, libGAP_Obj a2) +- libGAP_Obj libGAP_CALL_3ARGS(libGAP_Obj f, libGAP_Obj a1, libGAP_Obj a2, libGAP_Obj a3) +- libGAP_Obj libGAP_CALL_4ARGS(libGAP_Obj f, libGAP_Obj a1, libGAP_Obj a2, libGAP_Obj a3, +- libGAP_Obj a4) +- libGAP_Obj libGAP_CALL_5ARGS(libGAP_Obj f, libGAP_Obj a1, libGAP_Obj a2, libGAP_Obj a3, +- libGAP_Obj a4, libGAP_Obj a5) +- libGAP_Obj libGAP_CALL_6ARGS(libGAP_Obj f, libGAP_Obj a1, libGAP_Obj a2, libGAP_Obj a3, +- libGAP_Obj a4, libGAP_Obj a5, libGAP_Obj a6) +- libGAP_Obj libGAP_CALL_XARGS(libGAP_Obj f, libGAP_Obj args) # more than 6 arguments +- bint libGAP_EQ(libGAP_Obj opL, libGAP_Obj opR) +- bint libGAP_LT(libGAP_Obj opL, libGAP_Obj opR) ++cdef extern from "<gap/bool.h>": ++ cdef Obj GAP_True "True" ++ cdef Obj GAP_False "False" ++ + + cdef extern from "<gap/calls.h>": +- bint libGAP_IS_FUNC(libGAP_Obj) ++ bint IS_FUNC(Obj) ++ Obj CALL_0ARGS(Obj f) # 0 arguments ++ Obj CALL_1ARGS(Obj f, Obj a1) # 1 argument ++ Obj CALL_2ARGS(Obj f, Obj a1, Obj a2) ++ Obj CALL_3ARGS(Obj f, Obj a1, Obj a2, Obj a3) ++ Obj CALL_4ARGS(Obj f, Obj a1, Obj a2, Obj a3, Obj a4) ++ Obj CALL_5ARGS(Obj f, Obj a1, Obj a2, Obj a3, Obj a4, Obj a5) ++ Obj CALL_6ARGS(Obj f, Obj a1, Obj a2, Obj a3, Obj a4, Obj a5, Obj a6) ++ Obj CALL_XARGS(Obj f, Obj args) # more than 6 arguments ++ ++ ++cdef extern from "<gap/gasman.h>": ++ Obj NewBag "NewBag"(UInt type, UInt size) ++ void MarkBag(Obj bag) ++ UInt CollectBags(UInt size, UInt full) ++ ++ ++cdef extern from "<gap/gasman_intern.h>": ++ void CallbackForAllBags(void (*func)(Obj)) ++ ++ ++cdef extern from "<gap/gvars.h>": ++ UInt GVarName "GVarName"(char* name) ++ void AssGVar "AssGVar"(UInt gvar, Obj val) ++ ++ ++cdef extern from "<gap/integer.h>": ++ Int IS_INT(Obj) ++ ++ ++cdef extern from "<gap/intobj.h>": ++ bint IS_INTOBJ(Obj obj) ++ Obj INTOBJ_INT(Int) ++ Int INT_INTOBJ(Obj) ++ ++ ++cdef extern from "<gap/io.h>": ++ UInt OpenOutputStream(Obj stream) ++ UInt CloseOutput() ++ ++ ++cdef extern from "<gap/libgap-api.h>": ++ ctypedef void (*CallbackFunc)() ++ void GAP_Initialize(int argc, char ** argv, char ** env, ++ CallbackFunc, CallbackFunc) ++ Obj GAP_EvalString(const char *) except * ++ Obj GAP_EvalStringNoExcept "GAP_EvalString"(const char *) ++ Obj GAP_ValueGlobalVariable(const char *) ++ ++ ++cdef extern from "<gap/libgap-api.h>" nogil: ++ cdef void GAP_EnterStack() ++ cdef void GAP_LeaveStack() ++ cdef int GAP_Enter() except 0 ++ cdef void GAP_Leave() ++ cdef int GAP_Error_Setjmp() except 0 + +-cdef extern from "<gap/plist.h>": +- libGAP_Obj libGAP_NEW_PLIST(int type, int len) +- bint libGAP_IS_PLIST(libGAP_Obj lst) +- int libGAP_LEN_PLIST(libGAP_Obj lst) +- libGAP_Obj libGAP_ELM_PLIST(libGAP_Obj lst, int pos) + + cdef extern from "<gap/lists.h>": +- void libGAP_UNB_LIST(libGAP_Obj lst, int pos) +- bint libGAP_IS_LIST(libGAP_Obj lst) +- int libGAP_LEN_LIST(libGAP_Obj lst) +- libGAP_Obj libGAP_ELM_LIST(libGAP_Obj lst, int pos) +- void libGAP_ASS_LIST(libGAP_Obj lst, int pos, libGAP_Obj elt) ++ bint IS_LIST(Obj lst) ++ int LEN_LIST(Obj lst) ++ Obj ELM_LIST(Obj lst, int pos) ++ Obj ELM0_LIST(Obj lst, int pos) ++ void ASS_LIST(Obj lst, int pos, Obj elt) ++ + + cdef extern from "<gap/listfunc.h>": +- void libGAP_AddList(libGAP_Obj list, libGAP_Obj obj) +- void libGAP_AddPlist(libGAP_Obj list, libGAP_Obj obj) ++ void AddList(Obj list, Obj obj) ++ + + cdef extern from "<gap/macfloat.h>": +- bint libGAP_IS_MACFLOAT(libGAP_Obj obj) +- double libGAP_VAL_MACFLOAT(libGAP_Obj obj) ++ double VAL_MACFLOAT(Obj obj) ++ ++ ++cdef extern from "<gap/objects.h>": ++ bint IS_MUTABLE_OBJ(Obj obj) ++ Obj SHALLOW_COPY_OBJ(Obj obj) ++ Obj CopyObj(Obj obj, int mut) ++ ++ UInt SIZE_OBJ(Obj obj) ++ UInt TNUM_OBJ(Obj obj) ++ char* TNAM_OBJ(Obj obj) ++ ++ cdef int T_INTPOS ++ cdef int T_INTNEG ++ cdef int T_RAT ++ cdef int T_CYC ++ cdef int T_FFE ++ cdef int T_PERM2 ++ cdef int T_PERM4 ++ cdef int T_BOOL ++ cdef int T_CHAR ++ cdef int T_FUNCTION ++ cdef int T_MACFLOAT ++ cdef int T_PLIST ++ cdef int T_PLIST_CYC ++ cdef int T_BLIST ++ cdef int T_STRING ++ cdef int T_COMOBJ ++ cdef int T_POSOBJ ++ cdef int T_DATOBJ ++ cdef int T_WPOBJ + +-cdef extern from "<gap/records.h>": +- char* libGAP_NAME_RNAM(libGAP_UInt rnam) +- libGAP_UInt libGAP_RNamIntg(int i) +- bint libGAP_IS_REC(libGAP_Obj obj) +- libGAP_Obj libGAP_ELM_REC(libGAP_Obj rec, libGAP_UInt rnam) +- libGAP_UInt libGAP_RNamName(libGAP_Char* name) + + cdef extern from "<gap/precord.h>": +- libGAP_Obj libGAP_NEW_PREC(int len) +- int libGAP_LEN_PREC(libGAP_Obj rec) +- int libGAP_GET_RNAM_PREC(libGAP_Obj rec, int i) +- libGAP_Obj libGAP_GET_ELM_PREC(libGAP_Obj rec, int i) +- void libGAP_AssPRec(libGAP_Obj rec, libGAP_UInt rnam, libGAP_Obj val) +- void libGAP_UnbPRec(libGAP_Obj rec, libGAP_UInt rnam) +- bint libGAP_IsbPRec(libGAP_Obj rec, libGAP_UInt rnam) +- libGAP_Obj libGAP_ElmPRec(libGAP_Obj rec, libGAP_UInt rnam) +- +-cdef extern from "<gap/cyclotom.h>": +- pass ++ Obj NEW_PREC(int len) ++ int LEN_PREC(Obj rec) ++ int GET_RNAM_PREC(Obj rec, int i) ++ Obj GET_ELM_PREC(Obj rec, int i) ++ void AssPRec(Obj rec, UInt rnam, Obj val) + +-cdef extern from "<gap/bool.h>": +- cdef libGAP_Obj libGAP_True +- cdef libGAP_Obj libGAP_False + +-cdef extern from "<gap/vars.h>": +- cdef int libGAP_T_LVARS +- libGAP_Obj libGAP_BottomLVars ++cdef extern from "<gap/records.h>": ++ char* NAME_RNAM(UInt rnam) ++ bint IS_REC(Obj obj) ++ Obj ELM_REC(Obj rec, UInt rnam) ++ UInt RNamName(Char* name) ++ ++ ++cdef extern from "<gap/stringobj.h>": ++ char* CSTR_STRING(Obj list) ++ bint IS_STRING(Obj obj) ++ bint IsStringConv(Obj obj) ++ Obj NEW_STRING(Int) ++ void C_NEW_STRING(Obj new_gap_string, int length, char* c_string) +diff --git a/src/sage/libs/gap/libgap.pyx b/src/sage/libs/gap/libgap.pyx +index 8d2fc46..cb7b2cb 100644 +--- a/src/sage/libs/gap/libgap.pyx ++++ b/src/sage/libs/gap/libgap.pyx +@@ -160,53 +160,10 @@ using the recursive expansion of the + Using the libGAP C library from Cython + ====================================== + +-The lower-case ``libgap_foobar`` functions are ones that we added to +-make the libGAP C shared library. The ``libGAP_foobar`` methods are +-the original GAP methods simply prefixed with the string +-``libGAP_``. The latter were originally not designed to be in a +-library, so some care needs to be taken to call them. +- +-In particular, you must call ``libgap_mark_stack_bottom()`` in every +-function that calls into the libGAP C functions. The reason is that +-the GAP memory manager will automatically keep objects alive that are +-referenced in local (stack-allocated) variables. While convenient, +-this requires to look through the stack to find anything that looks +-like an address to a memory bag. But this requires vigilance against +-the following pattern:: +- +- cdef f() +- libgap_mark_stack_bottom() +- libGAP_function() +- +- cdef g() +- libgap_mark_stack_bottom(); +- f() # f() changed the stack bottom marker +- libGAP_function() # boom +- +-The solution is to re-order ``g()`` to first call ``f()``. In order to +-catch this error, it is recommended that you wrap calls into libGAP in +-``libgap_enter`` / ``libgap_exit`` blocks and not call +-``libgap_mark_stack_bottom`` manually. So instead, always write +- +- cdef f() +- libgap_enter() +- libGAP_function() +- libgap_exit() +- +- cdef g() +- f() +- libgap_enter() +- libGAP_function() +- libgap_exit() +- +-If you accidentally call ``libgap_enter()`` twice then an error +-message is printed to help you debug this:: +- +- sage: from sage.libs.gap.util import error_enter_libgap_block_twice +- sage: error_enter_libgap_block_twice() +- Traceback (most recent call last): +- ... +- RuntimeError: Entered a critical block twice ++.. TODO:: Update the following text ++ ++ We are using libgap API provided by the GAP project since ++ GAP 4.10. + + AUTHORS: + +@@ -215,6 +172,8 @@ AUTHORS: + almost complete rewrite; first usable version. + - Volker Braun (2012-08-28, GAP/Singular workshop): update to + gap-4.5.5, make it ready for public consumption. ++ - Dima Pasechnik (2018-09-18, GAP Days): started the port to native ++ libgap API + """ + + ############################################################################### +@@ -254,6 +213,8 @@ AUTHORS: + + from __future__ import print_function, absolute_import + ++from pprint import pprint ++ + from .gap_includes cimport * + from .util cimport * + from .element cimport * +@@ -263,23 +224,20 @@ from sage.structure.parent cimport Parent + from sage.structure.element cimport ModuleElement, RingElement, Vector + from sage.rings.all import ZZ + from sage.misc.cachefunc import cached_method +-from sage.misc.superseded import deprecated_function_alias ++from sage.misc.superseded import deprecated_function_alias, deprecation + + + ############################################################################ + ### Debugging ############################################################## + ############################################################################ + +-cdef void report(libGAP_Obj bag): +- print(libGAP_TNAM_OBJ(bag), <int>libGAP_TNUM_BAG(bag), <int>libGAP_SIZE_BAG(bag)) + +- +-cdef void print_gasman_objects(): +- libgap_enter() +- libGAP_CallbackForAllBags(report) +- libgap_exit() ++cdef void report(Obj bag): ++ print(TNAM_OBJ(bag), <int>SIZE_OBJ(bag)) + + ++cdef void print_gasman_objects(): ++ CallbackForAllBags(report) + + + from sage.misc.lazy_import import is_during_startup +@@ -370,7 +328,7 @@ class Gap(Parent): + return make_GapElement_Record(self, make_gap_record(x)) + elif isinstance(x, bool): + # attention: must come before int +- return make_GapElement_Boolean(self, libGAP_True if x else libGAP_False) ++ return make_GapElement_Boolean(self, GAP_True if x else GAP_False) + elif isinstance(x, int): + return make_GapElement_Integer(self, make_gap_integer(x)) + elif isinstance(x, basestring): +@@ -443,9 +401,18 @@ class Gap(Parent): + sage: libgap.eval('"string"') + "string" + """ ++ cdef GapElement elem ++ + if not isinstance(gap_command, basestring): + gap_command = str(gap_command._gap_init_()) +- return make_any_gap_element(self, gap_eval(gap_command)) ++ ++ elem = make_any_gap_element(self, gap_eval(gap_command)) ++ ++ # If the element is NULL just return None instead ++ if elem.value == NULL: ++ return None ++ ++ return elem + + @cached_method + def function_factory(self, function_name): +@@ -520,9 +487,11 @@ class Gap(Parent): + ... + ValueError: libGAP: Error, VAL_GVAR: No value bound to FooBar + """ ++ is_readonlyglobal = self.function_factory('IsReadOnlyGlobal') + make_readwrite = self.function_factory('MakeReadWriteGlobal') + unbind_global = self.function_factory('UnbindGlobal') +- make_readwrite(variable) ++ if is_readonlyglobal(variable): ++ make_readwrite(variable) + unbind_global(variable) + + def get_global(self, variable): +@@ -634,7 +603,6 @@ class Gap(Parent): + <class 'sage.libs.gap.libgap.Gap'> + """ + initialize() +- libgap_set_gasman_callback(gasman_callback) + from sage.rings.integer_ring import ZZ + Parent.__init__(self, base=ZZ) + +@@ -663,12 +631,13 @@ class Gap(Parent): + sage: 'OctaveAlgebra' in dir(libgap) + True + """ +- from sage.libs.gap.gap_functions import common_gap_functions +- return dir(self.__class__) + list(common_gap_functions) ++ from sage.libs.gap.gap_globals import common_gap_globals ++ return dir(self.__class__) + sorted(common_gap_globals) + + def __getattr__(self, name): + r""" +- The attributes of the Gap object are the Gap functions. ++ The attributes of the Gap object are the Gap functions, and in some ++ cases other global variables from GAP. + + INPUT: + +@@ -677,32 +646,52 @@ class Gap(Parent): + + OUTPUT: + +- A :class:`GapElement_Function`. A ``AttributeError`` is raised +- if there is no such function. ++ A :class:`GapElement`. A ``AttributeError`` is raised ++ if there is no such function or global variable. + + EXAMPLES:: + + sage: libgap.List + <Gap function "List"> ++ sage: libgap.GlobalRandomSource ++ <RandomSource in IsGlobalRandomSource> + """ + if name in dir(self.__class__): + return getattr(self.__class__, name) ++ + from sage.libs.gap.gap_functions import common_gap_functions ++ from sage.libs.gap.gap_globals import common_gap_globals + if name in common_gap_functions: +- f = make_GapElement_Function(self, gap_eval(str(name))) +- assert f.is_function() +- self.__dict__[name] = f +- return f ++ g = make_GapElement_Function(self, gap_eval(name)) ++ assert g.is_function() ++ elif name in common_gap_globals: ++ g = make_any_gap_element(self, gap_eval(name)) + else: +- raise AttributeError('No such attribute: '+name+'.') ++ raise AttributeError(f'No such attribute: {name}.') ++ ++ self.__dict__[name] = g ++ return g + + def show(self): + """ +- Print statistics about the GAP owned object list ++ Return statistics about the GAP owned object list ++ ++ This includes the total memory allocated by GAP as returned by ++ ``libgap.eval('TotalMemoryAllocated()'), as well as garbage collection ++ / object count statistitics as returned by ++ ``libgap.eval('GasmanStatistics')``, and finally the total number of ++ GAP objects held by Sage as :class:`~sage.libs.gap.element.GapElement` ++ instances. + +- Slight complication is that we want to do it without accessing +- libgap objects, so we don't create new GapElements as a side +- effect. ++ The value ``livekb + deadkb`` will roughly equal the total memory ++ allocated for GAP objects (see ++ ``libgap.eval('TotalMemoryAllocated()')``). ++ ++ .. note:: ++ ++ Slight complication is that we want to do it without accessing ++ libgap objects, so we don't create new GapElements as a side ++ effect. + + EXAMPLES:: + +@@ -710,15 +699,25 @@ class Gap(Parent): + sage: b = libgap(456) + sage: c = libgap(789) + sage: del b +- sage: libgap.show() # random output +- 11 LibGAP elements currently alive +- rec( full := rec( cumulative := 122, deadbags := 9, +- deadkb := 0, freekb := 7785, livebags := 304915, +- livekb := 47367, time := 33, totalkb := 68608 ), +- nfull := 3, npartial := 14 ) +- """ +- print('{} LibGAP elements currently alive'.format(self.count_GAP_objects())) +- print(self.eval('GasmanStatistics()')) ++ sage: libgap.collect() ++ sage: libgap.show() # random output ++ {'gasman_stats': {'full': {'cumulative': 110, ++ 'deadbags': 321400, ++ 'deadkb': 12967, ++ 'freekb': 15492, ++ 'livebags': 396645, ++ 'livekb': 37730, ++ 'time': 110, ++ 'totalkb': 65536}, ++ 'nfull': 1, ++ 'npartial': 1}, ++ 'nelements': 23123, ++ 'total_alloc': 3234234} ++ """ ++ d = {'nelements': self.count_GAP_objects()} ++ d['total_alloc'] = self.eval('TotalMemoryAllocated()').sage() ++ d['gasman_stats'] = self.eval('GasmanStatistics()').sage() ++ return d + + def count_GAP_objects(self): + """ +@@ -734,57 +733,19 @@ class Gap(Parent): + sage: libgap.count_GAP_objects() # random output + 5 + """ +- return sum([1 for obj in get_owned_objects()]) ++ return len(get_owned_objects()) + + def mem(self): + """ +- Return information about libGAP memory usage ++ Return information about GAP memory usage + +- The GAP workspace is partitioned into 5 pieces (see gasman.c +- in the GAP sources for more details): +- +- * The **masterpointer area** contains all the masterpointers of the bags. +- +- * The **old bags area** contains the bodies of all the bags that survived at +- least one garbage collection. This area is only scanned for dead bags +- during a full garbage collection. +- +- * The **young bags area** contains the bodies of all the bags that have been +- allocated since the last garbage collection. This area is scanned for +- dead bags during each garbage collection. +- +- * The **allocation area** is the storage that is available for allocation of +- new bags. When a new bag is allocated the storage for the body is taken +- from the beginning of this area, and this area is correspondingly +- reduced. If the body does not fit in the allocation area a garbage +- collection is performed. +- +- * The **unavailable area** is the free storage that is not available for +- allocation. +- +- OUTPUT: +- +- This function returns a tuple containing 5 integers. Each is +- the size (in bytes) of the five partitions of the +- workspace. This will potentially change after each GAP garbage +- collection. +- +- EXAMPLES:: +- +- sage: libgap.collect() +- sage: libgap.mem() # random output +- (1048576, 6706782, 0, 960930, 0) +- +- sage: libgap.FreeGroup(3) +- <free group on the generators [ f1, f2, f3 ]> +- sage: libgap.mem() # random output +- (1048576, 6706782, 47571, 913359, 0) +- +- sage: libgap.collect() +- sage: libgap.mem() # random output +- (1048576, 6734785, 0, 998463, 0) ++ This method is deprecated and is a no-op. Use :meth:`Gap.show` to ++ display memory-usage and bag count statistics from GASMAN. + """ +- return memory_usage() ++ ++ deprecation(22626, 'this functionality is not supported by GAP; use ' ++ 'libgap.show() for GAP memory usage statistics') ++ return (0, 0, 0, 0, 0) + + def collect(self): + """ +@@ -796,9 +757,7 @@ class Gap(Parent): + sage: del a + sage: libgap.collect() + """ +- libgap_enter() +- rc = libGAP_CollectBags(0, 1) +- libgap_exit() ++ rc = CollectBags(0, 1) + if rc != 1: + raise RuntimeError('Garbage collection failed.') + +diff --git a/src/sage/libs/gap/operations.py b/src/sage/libs/gap/operations.py +index 92ffc3d..f28b4ab 100644 +--- a/src/sage/libs/gap/operations.py ++++ b/src/sage/libs/gap/operations.py +@@ -11,6 +11,7 @@ lists all GAP operations for which ``Operation(x, ...)`` is defined. + + import re + import string ++ + from sage.structure.sage_object import SageObject + from sage.libs.gap.libgap import libgap + +@@ -18,6 +19,7 @@ Length = libgap.function_factory('Length') + FlagsType = libgap.function_factory('FlagsType') + TypeObj = libgap.function_factory('TypeObj') + IS_SUBSET_FLAGS = libgap.function_factory('IS_SUBSET_FLAGS') ++GET_OPER_FLAGS = libgap.function_factory('GET_OPER_FLAGS') + OPERATIONS = libgap.get_global('OPERATIONS') + NameFunction = libgap.function_factory('NameFunction') + +@@ -74,7 +76,7 @@ class OperationInspector(SageObject): + + sage: from sage.libs.gap.operations import OperationInspector + sage: x = OperationInspector(libgap(123)) +- sage: x.obj ++ sage: print(x.obj) + 123 + """ + return self._obj +@@ -95,20 +97,12 @@ class OperationInspector(SageObject): + sage: Unknown in x.operations() + True + """ +- result = [] +- for i in range(len(OPERATIONS) // 2): +- match = False +- for flag_list in OPERATIONS[2*i + 1]: +- if Length(flag_list) == 0: +- continue +- first_flag = flag_list[0] +- if IS_SUBSET_FLAGS(self.flags, first_flag): +- match = True +- break +- if match: +- op = OPERATIONS[2*i] +- result.append(op) +- return result ++ def mfi(o): ++ filts = GET_OPER_FLAGS(o) ++ return any(all(IS_SUBSET_FLAGS(self.flags, fl) for fl in fls) ++ for fls in filts) ++ ++ return filter(mfi, OPERATIONS) + + def op_names(self): + """ +diff --git a/src/sage/libs/gap/sage.gaprc b/src/sage/libs/gap/sage.gaprc +new file mode 100644 +index 00000000..17613fa +--- /dev/null ++++ b/src/sage/libs/gap/sage.gaprc +@@ -0,0 +1,12 @@ ++# This file is run by Sage when initializing libgap via GAP_Initialize, and may ++# contain bug fixes/workarounds and/or any Sage-specific patches necessary for ++# Sage's libgap interface. ++ ++if GAPInfo.CommandLineOptions.norepl then ++ # GAP 4.10.0 has a bug that an interactive session will be started ++ # even if --norepl was set; see https://github.com/gap-system/gap/pull/2840 ++ # To work around this we redefine the SESSION function to a no-op ++ MAKE_READ_WRITE_GLOBAL("SESSION"); ++ UNBIND_GLOBAL("SESSION"); ++ BIND_GLOBAL("SESSION", function() end); ++fi; +diff --git a/src/sage/libs/gap/saved_workspace.py b/src/sage/libs/gap/saved_workspace.py +index 3cb8fd3..ad5adec 100644 +--- a/src/sage/libs/gap/saved_workspace.py ++++ b/src/sage/libs/gap/saved_workspace.py +@@ -9,7 +9,6 @@ workspaces. + import os + import glob + from sage.env import GAP_ROOT_DIR +-from sage.interfaces.gap import GAP_BINARY + from sage.interfaces.gap_workspace import gap_workspace_file + + +@@ -33,7 +32,7 @@ def timestamp(): + libgap_dir = os.path.dirname(__file__) + libgap_files = glob.glob(os.path.join(libgap_dir, '*')) + gap_packages = glob.glob(os.path.join(GAP_ROOT_DIR, 'pkg', '*')) +- files = libgap_files + [GAP_BINARY] + gap_packages ++ files = libgap_files + gap_packages + if len(files) == 0: + print('Unable to find LibGAP files.') + return float('inf') +diff --git a/src/sage/libs/gap/types.pxd b/src/sage/libs/gap/types.pxd +deleted file mode 100644 +index dcf5003..00000000 +--- a/src/sage/libs/gap/types.pxd ++++ /dev/null +@@ -1,26 +0,0 @@ +-############################################################################### +-# Copyright (C) 2009, William Stein <wstein@gmail.com> +-# Copyright (C) 2012, Volker Braun <vbraun.name@gmail.com> +-# +-# Distributed under the terms of the GNU General Public License (GPL) +-# as published by the Free Software Foundation; either version 2 of +-# the License, or (at your option) any later version. +-# http://www.gnu.org/licenses/ +-############################################################################### +- +- +-cdef extern from "<gap/system.h>": +- ctypedef char libGAP_Char +- ctypedef int libGAP_Int +- ctypedef unsigned char libGAP_UChar +- +-cdef extern from "<gap/code.h>": +- ctypedef unsigned int libGAP_Stat +- ctypedef libGAP_Stat* libGAP_PtrBody +- +-cdef extern from "<gap/gap.h>": +- ctypedef unsigned int libGAP_UInt +- ctypedef void* libGAP_ExecStatus +- +-cdef extern from "<gap/objects.h>": +- ctypedef void* libGAP_Obj +diff --git a/src/sage/libs/gap/util.pxd b/src/sage/libs/gap/util.pxd +index 2a82834..d2ce2d0 100644 +--- a/src/sage/libs/gap/util.pxd ++++ b/src/sage/libs/gap/util.pxd +@@ -8,25 +8,24 @@ + # http://www.gnu.org/licenses/ + #***************************************************************************** + +-from .types cimport libGAP_Obj +- ++from .gap_includes cimport Obj + + ############################################################################ + ### Hooking into the GAP memory management ################################# + ############################################################################ + + cdef class ObjWrapper(object): +- cdef libGAP_Obj value ++ cdef Obj value + +-cdef ObjWrapper wrap_obj(libGAP_Obj obj) ++cdef ObjWrapper wrap_obj(Obj obj) + + # returns the refcount dictionary for debugging purposes + cpdef get_owned_objects() + + # Reference count GAP objects that you want to prevent from being + # garbage collected +-cdef void reference_obj(libGAP_Obj obj) +-cdef void dereference_obj(libGAP_Obj obj) ++cdef void reference_obj(Obj obj) ++cdef void dereference_obj(Obj obj) + + # callback from the GAP memory manager so we can mark all_gap_elements.values() + cdef void gasman_callback() +@@ -44,12 +43,4 @@ cdef initialize() + ############################################################################ + + # Evaluate a string +-cdef libGAP_Obj gap_eval(str gap_string) except? NULL +- +- +-############################################################################ +-### Debug functions ######################################################## +-############################################################################ +- +-# Return details of the GAP memory pool +-cpdef memory_usage() ++cdef Obj gap_eval(str gap_string) except? NULL +diff --git a/src/sage/libs/gap/util.pyx b/src/sage/libs/gap/util.pyx +index 5ff6710..5e2805d 100644 +--- a/src/sage/libs/gap/util.pyx ++++ b/src/sage/libs/gap/util.pyx +@@ -14,24 +14,33 @@ Utility functions for libGAP + + from __future__ import print_function, absolute_import + +-import os.path ++import os ++import signal ++import warnings + +-from cpython.exc cimport PyErr_SetObject ++from libc.string cimport strcpy, strlen ++ ++from cpython.exc cimport PyErr_SetObject, PyErr_Occurred, PyErr_Fetch + from cpython.object cimport Py_LT, Py_LE, Py_EQ, Py_NE, Py_GT, Py_GE ++from cpython.ref cimport PyObject ++from cysignals.memory cimport sig_malloc ++from cysignals.pysignals import changesignal + from cysignals.signals cimport sig_on, sig_off, sig_error + ++import sage.env ++ + from .gap_includes cimport * + from .element cimport * + from sage.cpython.string import FS_ENCODING + from sage.cpython.string cimport str_to_bytes, char_to_str + from sage.interfaces.gap_workspace import prepare_workspace_dir +-from sage.env import SAGE_LOCAL, GAP_ROOT_DIR + + + ############################################################################ + ### Hooking into the GAP memory management ################################# + ############################################################################ + ++ + cdef class ObjWrapper(object): + """ + Wrapper for GAP master pointers +@@ -47,7 +56,7 @@ cdef class ObjWrapper(object): + + def __richcmp__(ObjWrapper self, ObjWrapper other, int op): + r""" +- Comparison wrapped libGAP_Obj. ++ Comparison wrapped Obj. + + INPUT: + +@@ -68,8 +77,8 @@ cdef class ObjWrapper(object): + True + """ + cdef result +- cdef libGAP_Obj self_value = self.value +- cdef libGAP_Obj other_value = other.value ++ cdef Obj self_value = self.value ++ cdef Obj other_value = other.value + if op == Py_LT: + return self_value < other_value + elif op == Py_LE: +@@ -99,7 +108,7 @@ cdef class ObjWrapper(object): + return <int>(self.value) + + +-cdef ObjWrapper wrap_obj(libGAP_Obj obj): ++cdef ObjWrapper wrap_obj(Obj obj): + """ + Constructor function for :class:`ObjWrapper` + """ +@@ -109,8 +118,13 @@ cdef ObjWrapper wrap_obj(libGAP_Obj obj): + + + # a dictionary to keep all GAP elements ++# needed for GASMAN callbacks ++# + cdef dict owned_objects_refcount = dict() + ++# ++# used in Sage's libgap.Gap.count_GAP_objects ++# + cpdef get_owned_objects(): + """ + Helper to access the refcount dictionary from Python code +@@ -118,19 +132,20 @@ cpdef get_owned_objects(): + return owned_objects_refcount + + +-cdef void reference_obj(libGAP_Obj obj): ++cdef void reference_obj(Obj obj): + """ + Reference ``obj`` + """ + cdef ObjWrapper wrapped = wrap_obj(obj) + global owned_objects_refcount ++# print("reference_obj called "+ crepr(obj) +"\n") + if wrapped in owned_objects_refcount: + owned_objects_refcount[wrapped] += 1 + else: + owned_objects_refcount[wrapped] = 1 + + +-cdef void dereference_obj(libGAP_Obj obj): ++cdef void dereference_obj(Obj obj): + """ + Reference ``obj`` + """ +@@ -147,7 +162,7 @@ cdef void gasman_callback(): + """ + global owned_objects_refcount + for obj in owned_objects_refcount: +- libGAP_MARK_BAG((<ObjWrapper>obj).value) ++ MarkBag((<ObjWrapper>obj).value) + + + +@@ -157,25 +172,6 @@ cdef void gasman_callback(): + ### Initialization of libGAP ############################################### + ############################################################################ + +-def _guess_gap_root(): +- """ +- Used as a fallback to determine gapdir if if GAP_ROOT_DIR is undefined or +- pointing to the wrong location. +- +- EXAMPLES:: +- +- sage: from sage.libs.gap.util import _guess_gap_root +- sage: _guess_gap_root() +- The gap-4.5.5.spkg (or later) seems to be not installed! +- ... +- """ +- print('The gap-4.5.5.spkg (or later) seems to be not installed!') +- gap_sh = open(os.path.join(SAGE_LOCAL, 'bin', 'gap')).read().splitlines() +- gapdir = next(dir for dir in gap_sh if dir.strip().startswith('GAP_DIR')) +- gapdir = gapdir.split('"')[1] +- gapdir = gapdir.replace('$SAGE_LOCAL', SAGE_LOCAL) +- return gapdir +- + def gap_root(): + """ + Find the location of the GAP root install which is stored in the gap +@@ -187,17 +183,68 @@ def gap_root(): + sage: gap_root() # random output + '/home/vbraun/opt/sage-5.3.rc0/local/gap/latest' + """ +- try: +- if os.path.exists(GAP_ROOT_DIR): +- return GAP_ROOT_DIR +- except TypeError: +- raise RuntimeError('The GAP_ROOT_DIR environment variable is set to an invalid path: "{}"'.format(GAP_ROOT_DIR)) ++ if os.path.exists(sage.env.GAP_ROOT_DIR): ++ return sage.env.GAP_ROOT_DIR + +- return _guess_gap_root() ++ # Attempt to figure out the appropriate GAP_ROOT by reading the ++ # local/bin/gap shell script; this is an ugly hack that exists for ++ # historical reasons; the best approach to setting where Sage looks for ++ # the appropriate GAP_ROOT is to set the GAP_ROOT_DIR variable ++ SAGE_LOCAL = sage.env.SAGE_LOCAL ++ gap_sh = open(os.path.join(SAGE_LOCAL, 'bin', 'gap')).read().splitlines() ++ gapdir = filter(lambda dir:dir.strip().startswith('GAP_ROOT'), gap_sh)[0] ++ gapdir = gapdir.split('"')[1] ++ gapdir = gapdir.replace('$SAGE_LOCAL', SAGE_LOCAL) ++ return gapdir + + + # To ensure that we call initialize_libgap only once. + cdef bint _gap_is_initialized = False ++cdef extern char **environ ++ ++ ++cdef char* _reset_error_output_cmd = """\ ++libgap_errout := ""; ++MakeReadWriteGlobal("ERROR_OUTPUT"); ++ERROR_OUTPUT := OutputTextString(libgap_errout, false); ++MakeReadOnlyGlobal("ERROR_OUTPUT"); ++""" ++ ++cdef char* _close_error_output_cmd = """\ ++CloseStream(ERROR_OUTPUT); ++MakeReadWriteGlobal("ERROR_OUTPUT"); ++ERROR_OUTPUT := "*errout*"; ++MakeReadOnlyGlobal("ERROR_OUTPUT"); ++MakeImmutable(libgap_errout); ++""" ++ ++ ++cdef char** copy_environ(char** env): ++ """ ++ Make a copy of the environment block given by ``env``. ++ ++ Returns a pointer to the copy, which is the caller's responsibility to ++ free. ++ """ ++ ++ cdef char** env_copy ++ cdef int envc = 0; ++ cdef int idx ++ cdef size_t size ++ ++ while env[envc]: ++ envc += 1 ++ ++ env_copy = <char**>sig_malloc((envc + 1) * sizeof(char*)) ++ ++ for idx in range(envc): ++ size = strlen(env[idx]) + 1 ++ env_copy[idx] = <char*>sig_malloc(size) ++ strcpy(env_copy[idx], env[idx]) ++ ++ env_copy[envc] = NULL ++ return env_copy ++ + + cdef initialize(): + """ +@@ -209,13 +256,14 @@ cdef initialize(): + sage: libgap(123) # indirect doctest + 123 + """ +- global _gap_is_initialized ++ global _gap_is_initialized, environ + if _gap_is_initialized: return + + # Define argv and environ variables, which we will pass in to + # initialize GAP. Note that we must pass define the memory pool + # size! +- cdef char* argv[14] ++ cdef char** env ++ cdef char* argv[16] + argv[0] = "sage" + argv[1] = "-l" + s = str_to_bytes(gap_root(), FS_ENCODING, "surrogateescape") +@@ -232,36 +280,56 @@ cdef initialize(): + argv[8] = "64m" + + argv[9] = "-q" # no prompt! +- argv[10] = "-T" # no debug loop +- argv[11] = NULL +- cdef int argc = 11 # argv[argc] must be NULL ++ argv[10] = "-E" # don't use readline as this will interfere with Python ++ argv[11] = "--nointeract" # Implies -T ++ ++ cdef int argc = 12 # argv[argc] must be NULL + + from .saved_workspace import workspace + workspace, workspace_is_up_to_date = workspace() + ws = str_to_bytes(workspace, FS_ENCODING, "surrogateescape") + if workspace_is_up_to_date: +- argv[11] = "-L" +- argv[12] = ws +- argv[13] = NULL +- argc = 13 ++ argv[argc] = "-L" ++ argv[argc + 1] = ws ++ argc += 2 ++ ++ # Get the path to the sage.gaprc file and check that it exists ++ sage_gaprc = os.path.join(os.path.dirname(__file__), 'sage.gaprc') ++ if not os.path.exists(sage_gaprc): ++ warnings.warn(f"Sage's GAP initialization file {sage_gaprc} is " ++ "is missing; some functionality may be limited") ++ else: ++ sage_gaprc = str_to_bytes(sage_gaprc, FS_ENCODING, "surrogateescape") ++ argv[argc] = sage_gaprc ++ argc += 1 ++ ++ argv[argc] = NULL ++ ++ env = copy_environ(environ) + + # Initialize GAP and capture any error messages + # The initialization just prints error and does not use the error handler +- libgap_start_interaction('') +- libgap_initialize(argc, argv) +- gap_error_msg = char_to_str(libgap_get_output()) +- libgap_finish_interaction() +- if gap_error_msg: +- raise RuntimeError('libGAP initialization failed\n' + gap_error_msg) ++ sig_on() ++ try: ++ with changesignal(signal.SIGCHLD, signal.SIG_DFL), \ ++ changesignal(signal.SIGINT, signal.SIG_DFL): ++ # Need to save/restore current SIGINT handling since GAP_Initialize ++ # currently clobbers it; it doesn't matter what we set SIGINT to ++ # temporarily. ++ GAP_Initialize(argc, argv, env, &gasman_callback, ++ &error_handler) ++ except RuntimeError as msg: ++ raise RuntimeError('libGAP initialization failed\n' + msg) ++ finally: ++ sig_off() + +- # The error handler is called if a GAP evaluation fails, e.g. 1/0 +- libgap_set_error_handler(&error_handler) ++ # Set the ERROR_OUTPUT global in GAP to an output stream in which to ++ # receive error output ++ GAP_EvalString(_reset_error_output_cmd) + + # Prepare global GAP variable to hold temporary GAP objects + global reference_holder +- libgap_enter() +- reference_holder = libGAP_GVarName("$SAGE_libgap_reference_holder") +- libgap_exit() ++ reference_holder = GVarName("$SAGE_libgap_reference_holder") + + # Finished! + _gap_is_initialized = True +@@ -279,7 +347,7 @@ cdef initialize(): + ### Evaluate string in GAP ################################################# + ############################################################################ + +-cdef libGAP_Obj gap_eval(str gap_string) except? NULL: ++cdef Obj gap_eval(str gap_string) except? NULL: + r""" + Evaluate a string in GAP. + +@@ -290,79 +358,109 @@ cdef libGAP_Obj gap_eval(str gap_string) except? NULL: + OUTPUT: + + The resulting GAP object or NULL+Python Exception in case of error. ++ The result object may also be NULL without a Python exception set for ++ statements that do not return a value. + + EXAMPLES:: + + sage: libgap.eval('if 4>3 then\nPrint("hi");\nfi') +- NULL + sage: libgap.eval('1+1') # testing that we have successfully recovered + 2 + + sage: libgap.eval('if 4>3 thenPrint("hi");\nfi') + Traceback (most recent call last): + ... +- ValueError: libGAP: Syntax error: then expected ++ ValueError: libGAP: Syntax error: then expected in stream:1 + if 4>3 thenPrint("hi"); +- fi; +- ^ ++ ^^^^^^^^^ + sage: libgap.eval('1+1') # testing that we have successfully recovered + 2 + + TESTS: + +- Check that we fail gracefully if this is called within +- ``libgap_enter()``:: ++ A bad eval string that results in multiple statement evaluations by GAP ++ and hence multiple errors should still result in a single exception ++ with a message capturing all errors that occurrer:: + +- sage: cython(''' +- ....: # distutils: libraries = gap +- ....: from sage.libs.gap.gap_includes cimport libgap_enter +- ....: libgap_enter() +- ....: ''') +- sage: libgap.eval('1+1') ++ sage: libgap.eval('Complex Field with 53 bits of precision;') + Traceback (most recent call last): + ... +- ValueError: libGAP: Entered a critical block twice ++ ValueError: libGAP: Error, Variable: 'Complex' must have a value ++ Syntax error: ; expected in stream:1 ++ Complex Field with 53 bits of precision;; ++ ^^^^^^^^^^^^ ++ Error, Variable: 'with' must have a value ++ Syntax error: ; expected in stream:1 ++ Complex Field with 53 bits of precision;; ++ ^^^^^^^^^^^^^^^^^^^^ ++ Error, Variable: 'bits' must have a value ++ Syntax error: ; expected in stream:1 ++ Complex Field with 53 bits of precision;; ++ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ++ Error, Variable: 'precision' must have a value ++ ++ ++ Test that on a subsequent attemt we get the same message (no garbage was ++ left in the error stream):: ++ ++ sage: libgap.eval('Complex Field with 53 bits of precision;') ++ Traceback (most recent call last): ++ ... ++ ValueError: libGAP: Error, Variable: 'Complex' must have a value ++ ... ++ Error, Variable: 'precision' must have a value ++ ++ sage: libgap.eval('1+1') # test that we successfully recover ++ 2 + """ + initialize() +- cdef libGAP_ExecStatus status ++ cdef Obj result ++ cdef int i, j, nresults + + # Careful: We need to keep a reference to the bytes object here + # so that Cython doesn't dereference it before libGAP is done with + # its contents. + cmd = str_to_bytes(gap_string + ';\n') ++ sig_on() + try: +- try: +- sig_on() +- libgap_enter() +- libgap_start_interaction(cmd) +- status = libGAP_ReadEvalCommand(libGAP_BottomLVars, NULL) +- if status != libGAP_STATUS_END: +- libgap_call_error_handler() +- sig_off() +- except RuntimeError as msg: +- raise ValueError('libGAP: '+str(msg).strip()) +- +- if libGAP_Symbol != libGAP_S_SEMICOLON: +- raise ValueError('did not end with semicolon') +- libGAP_GetSymbol() +- if libGAP_Symbol != libGAP_S_EOF: ++ GAP_Enter() ++ result = GAP_EvalString(cmd) ++ # We can assume that the result object is a GAP PList (plain list) ++ # and we should use functions for PLists directly for now; see ++ # https://github.com/gap-system/gap/pull/2988/files#r233021437 ++ ++ # If an error occurred in GAP_EvalString we won't even get ++ # here if the error handler was set; but in case it wasn't ++ # let's still check the result... ++ nresults = LEN_LIST(result) ++ if nresults > 1: # to mimick the old libGAP ++ # TODO: Get rid of this restriction eventually? + raise ValueError('can only evaluate a single statement') + +- finally: +- libgap_finish_interaction() +- libgap_exit() ++ # Get the result of the first statement ++ result = ELM0_LIST(result, 1) # 1-indexed! + +- if libGAP_ReadEvalResult != NULL: +- libgap_enter() +- libGAP_AssGVar(libGAP_Last3, libGAP_VAL_GVAR(libGAP_Last2)) +- libGAP_AssGVar(libGAP_Last2, libGAP_VAL_GVAR(libGAP_Last)) +- libGAP_AssGVar(libGAP_Last, libGAP_ReadEvalResult) +- libgap_exit() ++ if ELM0_LIST(result, 1) != GAP_True: ++ # An otherwise unhandled error occurred in GAP (such as a ++ # syntax error). Try running the error handler manually ++ # to capture the error output, if any. ++ # This should result in a RuntimeError being set. ++ error_handler_check_exception() + +- return libGAP_ReadEvalResult # may be NULL, thats ok ++ # The actual resultant object, if any, is in the second entry ++ # (which may be unassigned--see previous github comment; in this case ++ # 0 is returned without setting a a Python exception, so we should treat ++ # this like returning None) + ++ return ELM0_LIST(result, 2) ++ except RuntimeError as msg: ++ raise ValueError(f'libGAP: {msg}') ++ finally: ++ GAP_Leave() ++ sig_off() + +-############################################################################ ++ ++########################################################################### + ### Helper to protect temporary objects from deletion ###################### + ############################################################################ + +@@ -370,9 +468,9 @@ cdef libGAP_Obj gap_eval(str gap_string) except? NULL: + # get deleted this works by assigning it to a global variable. This is + # very simple, but you can't use it to keep two objects alive. Be + # careful. +-cdef libGAP_UInt reference_holder ++cdef UInt reference_holder + +-cdef void hold_reference(libGAP_Obj obj): ++cdef void hold_reference(Obj obj): + """ + Hold a reference (inside the GAP kernel) to obj + +@@ -381,177 +479,79 @@ cdef void hold_reference(libGAP_Obj obj): + very simple, but you can't use it to keep two objects alive. Be + careful. + """ +- libgap_enter() + global reference_holder +- libGAP_AssGVar(reference_holder, obj) +- libgap_exit() ++ AssGVar(reference_holder, obj) + + + ############################################################################ + ### Error handler ########################################################## + ############################################################################ + +-cdef void error_handler(char* msg): +- """ +- The libgap error handler +- +- We call ``sig_error()`` which causes us to jump back to the Sage +- signal handler. Since we wrap libGAP C calls in ``sig_on`` / +- ``sig_off`` blocks, this then jumps back to the ``sig_on`` where +- the ``RuntimeError`` we raise here will be seen. +- """ +- msg_py = char_to_str(msg) +- msg_py = msg_py.replace('For debugging hints type ?Recovery from NoMethodFound\n', '') +- PyErr_SetObject(RuntimeError, msg_py) +- sig_error() +- +- +-############################################################################ +-### Debug functions ######################################################## +-############################################################################ + +-cdef inline void DEBUG_CHECK(libGAP_Obj obj): ++cdef object extract_libgap_errout(): + """ +- Check that ``obj`` is valid. +- +- This function is only useful for debugging. ++ Reads the global variable libgap_errout and returns a Python string ++ containing the error message (with some boilerplate removed). + """ +- libgap_enter() +- libGAP_CheckMasterPointers() +- libgap_exit() +- if obj == NULL: +- print('DEBUG_CHECK: Null pointer!') +- +- ++ cdef Obj r ++ cdef char *msg + ++ r = GAP_ValueGlobalVariable("libgap_errout") + +-cpdef memory_usage(): +- """ +- Return information about the memory usage. +- +- See :meth:`~sage.libs.gap.libgap.Gap.mem` for details. +- """ +- cdef size_t SizeMptrsArea = libGAP_OldBags - libGAP_MptrBags +- cdef size_t SizeOldBagsArea = libGAP_YoungBags - libGAP_OldBags +- cdef size_t SizeYoungBagsArea = libGAP_AllocBags - libGAP_YoungBags +- cdef size_t SizeAllocationArea = libGAP_StopBags - libGAP_AllocBags +- cdef size_t SizeUnavailableArea = libGAP_EndBags - libGAP_StopBags +- return (SizeMptrsArea, SizeOldBagsArea, SizeYoungBagsArea, SizeAllocationArea, SizeUnavailableArea) +- +- +-cpdef error_enter_libgap_block_twice(): +- """ +- Demonstrate that we catch errors from entering a block twice. +- +- EXAMPLES:: +- +- sage: from sage.libs.gap.util import error_enter_libgap_block_twice +- sage: error_enter_libgap_block_twice() +- Traceback (most recent call last): +- ... +- RuntimeError: Entered a critical block twice +- """ +- from sage.libs.gap.libgap import libgap +- try: +- # The exception will be seen by this sig_on() after being +- # raised by the second libgap_enter(). +- sig_on() +- libgap_enter() +- libgap_enter() +- sig_off() +- finally: +- libgap_exit() +- +- +-cpdef error_exit_libgap_block_without_enter(): +- """ +- Demonstrate that we catch errors from omitting libgap_enter. +- +- EXAMPLES:: +- +- sage: from sage.libs.gap.util import error_exit_libgap_block_without_enter +- sage: error_exit_libgap_block_without_enter() +- Traceback (most recent call last): +- ... +- RuntimeError: Called libgap_exit without previous libgap_enter +- """ +- from sage.libs.gap.libgap import libgap +- sig_on() +- libgap_exit() +- sig_off() ++ # Grab a pointer to the C string underlying the GAP string libgap_errout ++ # then copy it to a Python str (char_to_str contains an implicit strcpy) ++ msg = CSTR_STRING(r) ++ if msg != NULL: ++ msg_py = char_to_str(msg) ++ msg_py = msg_py.replace('For debugging hints type ?Recovery from ' ++ 'NoMethodFound\n', '').strip() ++ else: ++ # Shouldn't happen but just in case... ++ msg_py = "" + +-############################################################################ +-### Auxilliary functions ################################################### +-############################################################################ ++ return msg_py + + +-def command(command_string): ++cdef void error_handler(): + """ +- Playground for accessing Gap via libGap. ++ The libgap error handler. + +- You should not use this function in your own programs. This is +- just here for convenience if you want to play with the libgap +- libray code. +- +- EXAMPLES:: ++ If an error occurred we set a RuntimeError; when the original ++ GAP_EvalString returns this exception will be raised. + +- sage: from sage.libs.gap.util import command +- sage: command('1') +- Output follows... +- 1 +- +- sage: command('1/0') +- Traceback (most recent call last): +- ... +- ValueError: libGAP: Error, Rational operations: <divisor> must not be zero +- +- sage: command('NormalSubgroups') +- Output follows... +- <Attribute "NormalSubgroups"> +- +- sage: command('rec(a:=1, b:=2)') +- Output follows... +- rec( a := 1, b := 2 ) ++ TODO: We should probably prevent re-entering this function if we ++ are already handling an error; if there is an error in our stream ++ handling code below it could result in a stack overflow. + """ +- initialize() +- cdef libGAP_ExecStatus status ++ cdef PyObject* exc_type ++ cdef PyObject* exc_val ++ cdef PyObject* exc_tb + +- cmd = str_to_bytes(command_string + ';\n') ++ # Close the error stream: This flushes any remaining output and closes ++ # the stream for further writing; reset ERROR_OUTPUT to something sane ++ # just in case (trying to print to a closed stream segfaults GAP) + try: +- libgap_enter() +- libgap_start_interaction(cmd) +- try: +- sig_on() +- status = libGAP_ReadEvalCommand(libGAP_BottomLVars, NULL) +- if status != libGAP_STATUS_END: +- libgap_call_error_handler() +- sig_off() +- except RuntimeError as msg: +- raise ValueError('libGAP: '+str(msg).strip()) +- +- assert libGAP_Symbol == libGAP_S_SEMICOLON, 'Did not end with semicolon?' +- libGAP_GetSymbol() +- if libGAP_Symbol != libGAP_S_EOF: +- raise ValueError('command() expects a single statement.') +- +- if libGAP_ReadEvalResult: +- libGAP_ViewObjHandler(libGAP_ReadEvalResult) +- s = char_to_str(libgap_get_output()) +- print('Output follows...') +- print(s.strip()) +- else: +- print('No output.') +- ++ GAP_EnterStack() ++ GAP_EvalStringNoExcept(_close_error_output_cmd) ++ msg = extract_libgap_errout() ++ ++ if PyErr_Occurred() != NULL and msg: ++ # Sometimes error_handler() can be called multiple times from a ++ # single GAP_EvalString call before it returns; in this case we ++ # just update the exception by appending to the existing exception ++ # message ++ PyErr_Fetch(&exc_type, &exc_val, &exc_tb) ++ if exc_val != NULL: ++ msg = str(<object>exc_val) + '\n' + msg ++ elif not msg: ++ msg = "An unknown error occurred in libGAP" ++ ++ PyErr_SetObject(RuntimeError, msg) + finally: +- libgap_exit() +- libgap_finish_interaction() +- +- DEBUG_CHECK(libGAP_ReadEvalResult) ++ # Reset ERROR_OUTPUT with a new text string stream ++ GAP_EvalStringNoExcept(_reset_error_output_cmd) ++ GAP_LeaveStack() + +- if libGAP_ReadEvalResult != NULL: +- libgap_enter() +- libGAP_AssGVar(libGAP_Last3, libGAP_VAL_GVAR(libGAP_Last2)) +- libGAP_AssGVar(libGAP_Last2, libGAP_VAL_GVAR(libGAP_Last)) +- libGAP_AssGVar(libGAP_Last, libGAP_ReadEvalResult) +- libgap_exit() + ++cdef void error_handler_check_exception() except *: ++ error_handler() +diff --git a/src/sage/misc/randstate.pyx b/src/sage/misc/randstate.pyx +index d2f173c..0e13d60 100644 +--- a/src/sage/misc/randstate.pyx ++++ b/src/sage/misc/randstate.pyx +@@ -54,23 +54,23 @@ Here we see that setting the random number seed really does make the + results of these random number generators reproducible. :: + + sage: set_random_seed(0) +- sage: rtest() +- (303, -0.266166246380421, 1/6, (1,2), [ 1, 1, 1, 1, 0 ], 265625921, 79302, 0.2450652680687958) ++ sage: print(rtest()) ++ (303, -0.266166246380421, 1/6, (1,2), [ 0, 1, 1, 0, 0 ], 265625921, 79302, 0.2450652680687958) + sage: set_random_seed(1) +- sage: rtest() ++ sage: print(rtest()) + (978, 0.0557699430711638, -1/8*x^2 - 1/2*x + 1/2, (1,2,3), [ 1, 0, 0, 0, 1 ], 807447831, 23865, 0.6170498912488264) + sage: set_random_seed(2) +- sage: rtest() +- (207, -0.0141049486533456, 0, (1,3)(4,5), [ 1, 1, 1, 1, 1 ], 1642898426, 16190, 0.9343331114872127) ++ sage: print(rtest()) ++ (207, -0.0141049486533456, 0, (1,3)(4,5), [ 1, 0, 1, 1, 1 ], 1642898426, 16190, 0.9343331114872127) + sage: set_random_seed(0) +- sage: rtest() +- (303, -0.266166246380421, 1/6, (1,2), [ 1, 1, 1, 1, 0 ], 265625921, 79302, 0.2450652680687958) ++ sage: print(rtest()) ++ (303, -0.266166246380421, 1/6, (1,2), [ 0, 1, 1, 0, 0 ], 265625921, 79302, 0.2450652680687958) + sage: set_random_seed(1) +- sage: rtest() ++ sage: print(rtest()) + (978, 0.0557699430711638, -1/8*x^2 - 1/2*x + 1/2, (1,2,3), [ 1, 0, 0, 0, 1 ], 807447831, 23865, 0.6170498912488264) + sage: set_random_seed(2) +- sage: rtest() +- (207, -0.0141049486533456, 0, (1,3)(4,5), [ 1, 1, 1, 1, 1 ], 1642898426, 16190, 0.9343331114872127) ++ sage: print(rtest()) ++ (207, -0.0141049486533456, 0, (1,3)(4,5), [ 1, 0, 1, 1, 1 ], 1642898426, 16190, 0.9343331114872127) + + Once we've set the random number seed, we can check what seed was used. + (This is not the current random number state; it does not change when +@@ -79,8 +79,8 @@ random numbers are generated.) :: + sage: set_random_seed(12345) + sage: initial_seed() + 12345L +- sage: rtest() +- (720, -0.612180244315804, 0, (1,3), [ 1, 0, 1, 1, 1 ], 1911581957, 65175, 0.8043027951758298) ++ sage: print(rtest()) ++ (720, -0.612180244315804, 0, (1,3), [ 1, 0, 1, 1, 0 ], 1911581957, 65175, 0.8043027951758298) + sage: initial_seed() + 12345L + +@@ -214,9 +214,9 @@ We'll demonstrate isolation. First, we show the sequence of random numbers + that you get without intervening ``with seed``. :: + + sage: set_random_seed(0) +- sage: r1 = rtest(); r1 +- (303, -0.266166246380421, 1/6, (1,2), [ 1, 1, 1, 1, 0 ], 265625921, 79302, 0.2450652680687958) +- sage: r2 = rtest(); r2 ++ sage: r1 = rtest(); print(r1) ++ (303, -0.266166246380421, 1/6, (1,2), [ 0, 1, 1, 0, 0 ], 265625921, 79302, 0.2450652680687958) ++ sage: r2 = rtest(); print(r2) + (443, 0.185001351421963, -2, (1,3), [ 0, 0, 1, 1, 0 ], 53231108, 8171, 0.28363811590618193) + + We get slightly different results with an intervening ``with seed``. :: +@@ -242,10 +242,10 @@ case, as we see in this example:: + sage: r1 == rtest() + True + sage: with seed(1): +- ....: rtest() +- ....: rtest() ++ ....: print(rtest()) ++ ....: print(rtest()) + (978, 0.0557699430711638, -1/8*x^2 - 1/2*x + 1/2, (1,2,3), [ 1, 0, 0, 0, 1 ], 807447831, 23865, 0.6170498912488264) +- (181, 0.607995392046754, -x + 1/2, (2,3)(4,5), [ 0, 1, 1, 0, 0 ], 1010791326, 9693, 0.5691716786307407) ++ (181, 0.607995392046754, -x + 1/2, (2,3)(4,5), [ 1, 0, 0, 1, 1 ], 1010791326, 9693, 0.5691716786307407) + sage: r2m == rtest() + True + +@@ -702,8 +702,8 @@ cdef class randstate: + sage: gap.Random(1, 10^50) + 1496738263332555434474532297768680634540939580077 + sage: gap(35).SCRRandomString() +- [ 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, +- 0, 0, 1, 0, 0, 1, 1, 0, 0, 1 ] ++ [ 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, ++ 1, 0, 0, 1, 1, 1, 1, 1, 0, 1 ] + """ + global _gap_seed_randstate + if _gap_seed_randstate is not self: +diff --git a/src/sage/tests/books/judson-abstract-algebra/homomorph-sage-exercises.py b/src/sage/tests/books/judson-abstract-algebra/homomorph-sage-exercises.py +index d5ebaa6..84ed100 100644 +--- a/src/sage/tests/books/judson-abstract-algebra/homomorph-sage-exercises.py ++++ b/src/sage/tests/books/judson-abstract-algebra/homomorph-sage-exercises.py +@@ -60,7 +60,6 @@ r""" + ~~~~~~~~~~~~~~~~~~~~~~ :: + + sage: G = DihedralGroup(20) +- sage: [H.order() for H in G.normal_subgroups()] ++ sage: l=[H.order() for H in G.normal_subgroups()]; l.sort(); l + [1, 2, 4, 5, 10, 20, 20, 20, 40] +- + """ +diff --git a/src/sage/tests/books/judson-abstract-algebra/normal-sage.py b/src/sage/tests/books/judson-abstract-algebra/normal-sage.py +index 16119fd..3db475d 100644 +--- a/src/sage/tests/books/judson-abstract-algebra/normal-sage.py ++++ b/src/sage/tests/books/judson-abstract-algebra/normal-sage.py +@@ -128,7 +128,7 @@ r""" + + sage: G = DihedralGroup(8) + sage: N = G.normal_subgroups() +- sage: [H.order() for H in N] ++ sage: l=[H.order() for H in N]; l.sort(); l + [1, 2, 4, 8, 8, 8, 16] + + """ +diff --git a/src/sage/tests/books/judson-abstract-algebra/sylow-sage.py b/src/sage/tests/books/judson-abstract-algebra/sylow-sage.py +index d6cf39c..8b32726 100644 +--- a/src/sage/tests/books/judson-abstract-algebra/sylow-sage.py ++++ b/src/sage/tests/books/judson-abstract-algebra/sylow-sage.py +@@ -226,7 +226,7 @@ r""" + ~~~~~~~~~~~~~~~~~~~~~~ :: + + sage: gap.version() +- '4.8.6' ++ '4.10.0' + + ~~~~~~~~~~~~~~~~~~~~~~ :: + +diff --git a/src/sage/tests/gap_packages.py b/src/sage/tests/gap_packages.py +index ca961ed..4a3479b 100644 +--- a/src/sage/tests/gap_packages.py ++++ b/src/sage/tests/gap_packages.py +@@ -124,7 +124,7 @@ def all_installed_packages(ignore_dot_gap=False): + (...'GAPDoc'...) + """ + packages = [] +- for path in libgap.eval('GAP_ROOT_PATHS').sage(): ++ for path in libgap.eval('GAPInfo.RootPaths').sage(): + if ignore_dot_gap and path.endswith('/.gap/'): + continue + pkg_dir = os.path.join(path, 'pkg') +diff --git a/src/setup.py b/src/setup.py +index bc8fe12..9d31c9d 100755 +--- a/src/setup.py ++++ b/src/setup.py +@@ -948,6 +948,9 @@ code = setup(name = 'sage', + author_email= 'http://groups.google.com/group/sage-support', + url = 'http://www.sagemath.org', + packages = python_packages, ++ package_data = { ++ 'sage.libs.gap': ['sage.gaprc'], ++ }, + cmdclass = dict(build=sage_build, + build_cython=sage_build_cython, + build_ext=sage_build_ext, diff --git a/sagemath-gap-4.8.patch b/sagemath-gap-4.8.patch deleted file mode 100644 index 64d6b28ea38b..000000000000 --- a/sagemath-gap-4.8.patch +++ /dev/null @@ -1,26 +0,0 @@ -diff --git a/src/sage/interfaces/gap.py b/src/sage/interfaces/gap.py -index 177fc1b6eb..51c67bdd09 100644 ---- a/src/sage/interfaces/gap.py -+++ b/src/sage/interfaces/gap.py -@@ -202,7 +202,7 @@ import string - - first_try = True - --gap_cmd = "gap -r" -+gap_cmd = "gap-4.8 -r" - if platform.processor() == 'ia64' and os.path.exists('/usr/bin/prctl'): - # suppress unaligned access to 0x..., ip=0x... warnings - gap_cmd = 'prctl --unaligned=silent ' + gap_cmd -diff --git a/src/sage/libs/gap/util.pyx b/src/sage/libs/gap/util.pyx -index 7bffcfc00d..51dad178d5 100644 ---- a/src/sage/libs/gap/util.pyx -+++ b/src/sage/libs/gap/util.pyx -@@ -170,7 +170,7 @@ def gap_root(): - if os.path.exists(GAP_ROOT_DIR): - return GAP_ROOT_DIR - print('The gap-4.5.5.spkg (or later) seems to be not installed!') -- gap_sh = open(os.path.join(SAGE_LOCAL, 'bin', 'gap')).read().splitlines() -+ gap_sh = open(os.path.join(SAGE_LOCAL, 'bin', 'gap-4.8')).read().splitlines() - gapdir = next(dir for dir in gap_sh if dir.strip().startswith('GAP_DIR')) - gapdir = gapdir.split('"')[1] - gapdir = gapdir.replace('$SAGE_LOCAL', SAGE_LOCAL) diff --git a/sagemath-networkx-2.2.patch b/sagemath-networkx-2.2.patch index 2bfe2c699837..1e4bef4bd60f 100644 --- a/sagemath-networkx-2.2.patch +++ b/sagemath-networkx-2.2.patch @@ -320,7 +320,7 @@ index 06a5203..5cbf5e9 100644 import networkx return Graph(networkx.powerlaw_cluster_graph(n, m, p, seed=seed)) -@@ -838,13 +847,15 @@ def RandomLobster(n, p, q, seed=None): +@@ -1239,13 +1248,15 @@ def RandomLobster(n, p, q, seed=None): - ``q`` - probability of adding an edge (claw) to the arms @@ -338,7 +338,7 @@ index 06a5203..5cbf5e9 100644 :: -@@ -852,7 +863,7 @@ def RandomLobster(n, p, q, seed=None): +@@ -1253,7 +1264,7 @@ def RandomLobster(n, p, q, seed=None): sage: G.show() # long time """ if seed is None: @@ -347,7 +347,7 @@ index 06a5203..5cbf5e9 100644 import networkx return Graph(networkx.random_lobster(n, p, q, seed=seed)) -@@ -924,7 +935,7 @@ def RandomTree(n): +@@ -1325,7 +1336,7 @@ def RandomTree(n): return g @@ -356,7 +356,7 @@ index 06a5203..5cbf5e9 100644 """ Returns a tree with a power law degree distribution. Returns False on failure. -@@ -943,15 +954,17 @@ def RandomTreePowerlaw(n, gamma=3, tries=100, seed=None): +@@ -1344,15 +1355,17 @@ def RandomTreePowerlaw(n, gamma=3, tries=100, seed=None): - ``tries`` - number of attempts to adjust sequence to make a tree @@ -377,7 +377,7 @@ index 06a5203..5cbf5e9 100644 :: -@@ -960,7 +973,7 @@ def RandomTreePowerlaw(n, gamma=3, tries=100, seed=None): +@@ -1361,7 +1374,7 @@ def RandomTreePowerlaw(n, gamma=3, tries=100, seed=None): ....: G.show() # random output, long time """ if seed is None: @@ -386,7 +386,7 @@ index 06a5203..5cbf5e9 100644 import networkx try: return Graph(networkx.random_powerlaw_tree(n, gamma, seed=seed, tries=tries)) -@@ -981,7 +994,8 @@ def RandomRegular(d, n, seed=None): +@@ -1382,7 +1395,8 @@ def RandomRegular(d, n, seed=None): - ``d`` - degree @@ -396,7 +396,7 @@ index 06a5203..5cbf5e9 100644 EXAMPLES: We show the edge list of a random graph with 8 nodes each -@@ -990,7 +1004,7 @@ def RandomRegular(d, n, seed=None): +@@ -1391,7 +1405,7 @@ def RandomRegular(d, n, seed=None): :: sage: graphs.RandomRegular(3, 8).edges(labels=False) @@ -405,7 +405,7 @@ index 06a5203..5cbf5e9 100644 :: -@@ -1009,7 +1023,7 @@ def RandomRegular(d, n, seed=None): +@@ -1410,7 +1424,7 @@ def RandomRegular(d, n, seed=None): regular graphs quickly. Prob. and Comp. 8 (1999), pp 377-396. """ if seed is None: @@ -414,7 +414,7 @@ index 06a5203..5cbf5e9 100644 import networkx try: N = networkx.random_regular_graph(d, n, seed=seed) -@@ -1034,17 +1048,19 @@ def RandomShell(constructor, seed=None): +@@ -1435,17 +1449,19 @@ def RandomShell(constructor, seed=None): - ``d`` - the ratio of inter (next) shell edges to intra shell edges diff --git a/sagemath-python3-notebook.patch b/sagemath-python3-notebook.patch index cef38c4fde47..b3133c1e7334 100644 --- a/sagemath-python3-notebook.patch +++ b/sagemath-python3-notebook.patch @@ -16,7 +16,7 @@ diff --git a/src/sage/repl/ipython_kernel/install.py b/src/sage/repl/ipython_ker index 3912b8cdf5..bd40cdadda 100644 --- a/src/sage/repl/ipython_kernel/install.py +++ b/src/sage/repl/ipython_kernel/install.py -@@ -292,7 +292,6 @@ def have_prerequisites(debug=True): +@@ -303,7 +303,6 @@ def have_prerequisites(debug=True): True """ try: diff --git a/sagemath-singular-4.1.1.p4.patch b/sagemath-singular-4.1.1.p4.patch new file mode 100644 index 000000000000..2bc025c46897 --- /dev/null +++ b/sagemath-singular-4.1.1.p4.patch @@ -0,0 +1,78 @@ +diff --git a/src/sage/libs/singular/function.pyx b/src/sage/libs/singular/function.pyx +index 87342e8..9a0d37d 100644 +--- a/src/sage/libs/singular/function.pyx ++++ b/src/sage/libs/singular/function.pyx +@@ -1258,7 +1258,7 @@ cdef class SingularFunction(SageObject): + Traceback (most recent call last): + ... + RuntimeError: error in Singular function call 'size': +- Wrong number of arguments (got 2 arguments, arity code is 300) ++ Wrong number of arguments (got 2 arguments, arity code is 302) + sage: size('foobar', ring=P) + 6 + +@@ -1667,17 +1667,17 @@ def singular_function(name): + Traceback (most recent call last): + ... + RuntimeError: error in Singular function call 'factorize': +- Wrong number of arguments (got 0 arguments, arity code is 303) ++ Wrong number of arguments (got 0 arguments, arity code is 305) + sage: factorize(f, 1, 2) + Traceback (most recent call last): + ... + RuntimeError: error in Singular function call 'factorize': +- Wrong number of arguments (got 3 arguments, arity code is 303) ++ Wrong number of arguments (got 3 arguments, arity code is 305) + sage: factorize(f, 1, 2, 3) + Traceback (most recent call last): + ... + RuntimeError: error in Singular function call 'factorize': +- Wrong number of arguments (got 4 arguments, arity code is 303) ++ Wrong number of arguments (got 4 arguments, arity code is 305) + + The Singular function ``list`` can be called with any number of + arguments:: +diff --git a/src/sage/algebras/letterplace/free_algebra_element_letterplace.pyx b/src/sage/algebras/letterplace/free_algebra_element_letterplace.pyx +index 8f6576b477..deaf0f5769 100644 +--- a/src/sage/algebras/letterplace/free_algebra_element_letterplace.pyx ++++ b/src/sage/algebras/letterplace/free_algebra_element_letterplace.pyx +@@ -447,7 +447,7 @@ cdef class FreeAlgebraElement_letterplace(AlgebraElement): + return True + for i from 0 <= i < p_d-s_d: + s_poly = singular_system("stest",s_poly,1, +- A._degbound,A.__ngens,ring=P) ++ ring=P) + if P.monomial_divides(s_poly,p_poly): + return True + return False +@@ -601,7 +601,7 @@ cdef class FreeAlgebraElement_letterplace(AlgebraElement): + # we must put the polynomials into the same ring + left._poly = A._current_ring(left._poly) + right._poly = A._current_ring(right._poly) +- rshift = singular_system("stest",right._poly,left._poly.degree(),A._degbound,A.__ngens, ring=A._current_ring) ++ rshift = singular_system("stest",right._poly,left._poly.degree(), ring=A._current_ring) + return FreeAlgebraElement_letterplace(A,left._poly*rshift, check=False) + + def __pow__(FreeAlgebraElement_letterplace self, int n, k): +@@ -629,7 +629,7 @@ cdef class FreeAlgebraElement_letterplace(AlgebraElement): + q = p = self._poly + cdef int i + for i from 0<i<n: +- q = singular_system("stest",q,d,A._degbound,A.__ngens, ++ q = singular_system("stest",q,d, + ring=A._current_ring) + p *= q + return FreeAlgebraElement_letterplace(A, p, check=False) +diff --git a/src/sage/algebras/letterplace/free_algebra_letterplace.pyx b/src/sage/algebras/letterplace/free_algebra_letterplace.pyx +index 7a8400052e..b3474fa07c 100644 +--- a/src/sage/algebras/letterplace/free_algebra_letterplace.pyx ++++ b/src/sage/algebras/letterplace/free_algebra_letterplace.pyx +@@ -683,7 +683,7 @@ cdef class FreeAlgebra_letterplace(Algebra): + degbound = self._degbound + cdef list G = [C(x._poly) for x in g] + for y in G: +- out.extend([y]+[singular_system("stest",y,n+1,degbound,ngens,ring=C) for n in xrange(d-y.degree())]) ++ out.extend([y]+[singular_system("stest",y,n+1,ring=C) for n in xrange(d-y.degree())]) + return C.ideal(out) + + ########################### diff --git a/sagemath-sphinx-1.8.patch b/sagemath-sphinx-1.8.patch index f54439334a0d..c153be175f8e 100644 --- a/sagemath-sphinx-1.8.patch +++ b/sagemath-sphinx-1.8.patch @@ -1,6 +1,6 @@ --- a/src/sage/misc/sphinxify.py 2018-09-14 20:13:32.788831484 +0200 +++ b/src/sage/misc/sphinxify.py 2018-09-14 20:14:07.142478667 +0200 -@@ -64,6 +64,7 @@ +@@ -68,6 +68,7 @@ sage: assert n == len(sys.path) """ srcdir = mkdtemp() @@ -8,7 +8,7 @@ base_name = os.path.join(srcdir, 'docstring') rst_name = base_name + '.rst' -@@ -71,7 +72,7 @@ +@@ -75,7 +76,7 @@ suffix = '.html' else: suffix = '.txt' @@ -17,7 +17,7 @@ with open(rst_name, 'w') as filed: filed.write(docstring) -@@ -89,7 +90,7 @@ +@@ -93,7 +94,7 @@ import sys old_sys_path = list(sys.path) # Sphinx modifies sys.path diff --git a/test-optional.patch b/test-optional.patch index b04946e7f608..7ac4ade793a4 100644 --- a/test-optional.patch +++ b/test-optional.patch @@ -1,6 +1,6 @@ --- src/sage/doctest/control.py.orig 2016-10-20 19:39:53.714618246 +0200 +++ src/sage/doctest/control.py 2016-10-20 19:40:15.158049920 +0200 -@@ -346,22 +346,6 @@ +@@ -347,22 +347,6 @@ # Special case to run all optional tests options.optional = True else: |