summarylogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.SRCINFO26
-rw-r--r--PKGBUILD38
-rw-r--r--sagemath-cremona.patch4
-rw-r--r--sagemath-ecl-sigfpe.patch23
-rw-r--r--sagemath-env.patch9
-rw-r--r--sagemath-gap-4.10.patch4342
-rw-r--r--sagemath-gap-4.8.patch26
-rw-r--r--sagemath-networkx-2.2.patch18
-rw-r--r--sagemath-python3-notebook.patch2
-rw-r--r--sagemath-singular-4.1.1.p4.patch78
-rw-r--r--sagemath-sphinx-1.8.patch6
-rw-r--r--test-optional.patch2
12 files changed, 4496 insertions, 78 deletions
diff --git a/.SRCINFO b/.SRCINFO
index eeab2c950bf7..f58c3c6699ff 100644
--- a/.SRCINFO
+++ b/.SRCINFO
@@ -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
diff --git a/PKGBUILD b/PKGBUILD
index 8165ff6f63e3..fa9eee73cc0b 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -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: