Commits

Volker Braun committed 846f696

updated to sage-5.4.rc4

  • Participants
  • Parent commits a98e820

Comments (0)

Files changed (5)

File 13681_sagelib.patch

-# HG changeset patch
-# User Jeroen Demeyer <jdemeyer@cage.ugent.be>
-# Date 1351972010 -3600
-# Node ID 12f48e5fe23d178a11d305e33a70917bcceaf93d
-# Parent  ac04c0a5230b1925f81c980d54b69319ba1100b3
-Use os.path.join() to construct temporary filenames
-
-diff --git a/sage/calculus/calculus.py b/sage/calculus/calculus.py
---- a/sage/calculus/calculus.py
-+++ b/sage/calculus/calculus.py
-@@ -1301,7 +1301,7 @@
-         629/8*e^(-4*t) + 91/8*e^(4*t)
-         sage: p1 = plot(xt,0,1/2,rgbcolor=(1,0,0))
-         sage: p2 = plot(yt,0,1/2,rgbcolor=(0,1,0))
--        sage: (p1+p2).save(SAGE_TMP + "de_plot.png")
-+        sage: (p1+p2).save(os.path.join(SAGE_TMP, "de_plot.png"))
- 
-     Another example::
- 
-diff --git a/sage/combinat/words/morphism.py b/sage/combinat/words/morphism.py
---- a/sage/combinat/words/morphism.py
-+++ b/sage/combinat/words/morphism.py
-@@ -563,7 +563,7 @@
-             <class 'sage.combinat.words.word.FiniteWord_iter_with_caching'>
-             sage: w == loads(dumps(w))
-             True
--            sage: save(w, filename=SAGE_TMP + 'test.sobj')
-+            sage: save(w, filename=os.path.join(SAGE_TMP, 'test.sobj'))
- 
-         One may impose the datatype of the resulting word::
- 
-diff --git a/sage/geometry/polytope.py b/sage/geometry/polytope.py
---- a/sage/geometry/polytope.py
-+++ b/sage/geometry/polytope.py
-@@ -50,7 +50,7 @@
- if os.path.exists(path):
-     os.environ['PATH'] = '%s:'%path + os.environ['PATH']
- 
--tmp_file = '%s/tmp.poly'%SAGE_TMP
-+tmp_file = os.path.join(SAGE_TMP, 'tmp.poly')
- 
- class Polytope(SageObject):
-     """
-diff --git a/sage/graphs/bipartite_graph.py b/sage/graphs/bipartite_graph.py
---- a/sage/graphs/bipartite_graph.py
-+++ b/sage/graphs/bipartite_graph.py
-@@ -202,7 +202,7 @@
- 
-     5. From an alist file::
- 
--         sage: file_name = SAGE_TMP + 'deleteme.alist.txt'
-+         sage: file_name = os.path.join(SAGE_TMP, 'deleteme.alist.txt')
-          sage: fi = open(file_name, 'w')
-          sage: fi.write("7 4 \n 3 4 \n 3 3 1 3 1 1 1 \n 3 3 3 4 \n\
-                          1 2 4 \n 1 3 4 \n 1 0 0 \n 2 3 4 \n\
-@@ -903,7 +903,7 @@
- 
-         EXAMPLE::
- 
--            sage: file_name = SAGE_TMP + 'deleteme.alist.txt'
-+            sage: file_name = os.path.join(SAGE_TMP, 'deleteme.alist.txt')
-             sage: fi = open(file_name, 'w')
-             sage: fi.write("7 4 \n 3 4 \n 3 3 1 3 1 1 1 \n 3 3 3 4 \n\
-                             1 2 4 \n 1 3 4 \n 1 0 0 \n 2 3 4 \n\
-@@ -999,7 +999,7 @@
-             [0 1 0 1 0 1 0]
-             [1 1 0 1 0 0 1]
-             sage: b = BipartiteGraph(M)
--            sage: file_name = SAGE_TMP + 'deleteme.alist.txt'
-+            sage: file_name = os.path.join(SAGE_TMP, 'deleteme.alist.txt')
-             sage: b.save_afile(file_name)
-             sage: b2 = BipartiteGraph(file_name)
-             sage: b == b2
-@@ -1007,7 +1007,7 @@
- 
-         TESTS::
- 
--            sage: file_name = SAGE_TMP + 'deleteme.alist.txt'
-+            sage: file_name = os.path.join(SAGE_TMP, 'deleteme.alist.txt')
-             sage: for order in range(3, 13, 3):
-             ...       num_chks = int(order / 3)
-             ...       num_vars = order - num_chks
-diff --git a/sage/gsl/ode.pyx b/sage/gsl/ode.pyx
---- a/sage/gsl/ode.pyx
-+++ b/sage/gsl/ode.pyx
-@@ -226,7 +226,7 @@
-         sage: T.function=f_1
-         sage: T.jacobian=j_1
-         sage: T.ode_solve(y_0=[1,0],t_span=[0,100],params=[10.0],num_points=1000)
--        sage: outfile = SAGE_TMP + 'sage.png'
-+        sage: outfile = os.path.join(SAGE_TMP, 'sage.png')
-         sage: T.plot_solution(filename=outfile)
-         
-     The solver line is equivalent to::
-@@ -316,7 +316,7 @@
-         sage: vander = van_der_pol()               # not tested
-         sage: T.function=vander                    # not tested
-         sage: T.ode_solve(y_0 = [1,0], t_span=[0,2000], num_points=1000)   # not tested
--        sage: T.plot_solution(i=0, filename=SAGE_TMP + '/test.png')        # not tested
-+        sage: T.plot_solution(i=0, filename=os.path.join(SAGE_TMP, 'test.png'))        # not tested
- 
- 
-     """
-diff --git a/sage/interfaces/cleaner.py b/sage/interfaces/cleaner.py
---- a/sage/interfaces/cleaner.py
-+++ b/sage/interfaces/cleaner.py
-@@ -15,16 +15,16 @@
- import os
- 
- import sage.misc.misc as misc
--F = '%s/spawned_processes'%misc.SAGE_TMP
- 
- def cleaner(pid, cmd=''):
-     if cmd != '':
-         cmd = cmd.strip().split()[0]
-     # This is safe, since only this process writes to this file.
-+    F = os.path.join(misc.SAGE_TMP, 'spawned_processes')
-     if os.path.exists(F):
-         o = open(F,'a')
-     else:
--        if not os.path.exists(misc.SAGE_TMP):
-+        if not os.path.exists(str(misc.SAGE_TMP)):
-             return
-         o = open(F,'w')
-     o.write('%s %s\n'%(pid, cmd))
-diff --git a/sage/interfaces/expect.py b/sage/interfaces/expect.py
---- a/sage/interfaces/expect.py
-+++ b/sage/interfaces/expect.py
-@@ -72,21 +72,6 @@
- 
- failed_to_start = []
- 
--#tmp_expect_interface_local='%s/tmp'%SAGE_TMP_INTERFACE
--
--#def tmp_expect_interface_local():
--#    return '%s/tmp'%SAGE_TMP_INTERFACE + str(os.getpid())
--
--## On some platforms, e.g., windows, this can easily take 10 seconds!?!  Terrible.  And
--## it should not be necessary or used anyways. 
--## def _absolute(cmd):
--##     c = cmd.split()
--##     s  = c[0]
--##     t = os.popen('which %s'%s).read().strip()
--##     if len(t) == 0:
--##         raise RuntimeError
--##     return ' '.join([t] + c[1:])
--
- # The subprocess is a shared resource.  In a multi-threaded
- # environment, there would have to be a lock to control access to the
- # subprocess.  Fortunately, Sage does not use Python threads.
-@@ -613,11 +598,10 @@
-         - Simon King (2010-09): Making the tmp-file unique for the interface instance
- 
-         """
--        #return '%s/tmp'%SAGE_TMP_INTERFACE + str(self.pid())
-         try:
-             return self.__local_tmpfile
-         except AttributeError:
--            self.__local_tmpfile = '%s/tmp'%SAGE_TMP_INTERFACE + str(self.pid())
-+            self.__local_tmpfile = os.path.join(SAGE_TMP_INTERFACE, 'tmp' + str(self.pid()))
-             return self.__local_tmpfile
- 
-     def _remote_tmpdir(self):
-diff --git a/sage/interfaces/gap.py b/sage/interfaces/gap.py
---- a/sage/interfaces/gap.py
-+++ b/sage/interfaces/gap.py
-@@ -1026,7 +1026,7 @@
-         workspace file contains more than 82 characters) is fixed::
- 
-             sage: ORIGINAL_WORKSPACE = sage.interfaces.gap.WORKSPACE
--            sage: sage.interfaces.gap.WORKSPACE = SAGE_TMP + "gap" + "0"*(80-len(SAGE_TMP))
-+            sage: sage.interfaces.gap.WORKSPACE = os.path.join(SAGE_TMP, "gap" + "0"*(80-len(SAGE_TMP)))
-             sage: gap = Gap()
-             sage: gap('3+2')
-             5
-diff --git a/sage/interfaces/gnuplot.py b/sage/interfaces/gnuplot.py
---- a/sage/interfaces/gnuplot.py
-+++ b/sage/interfaces/gnuplot.py
-@@ -176,7 +176,7 @@
- 
-     def interact(self, cmd):
-         from sage.misc.all import SAGE_TMP
--        file= '%s/gnuplot'%SAGE_TMP
-+        file = os.path.join(SAGE_TMP, 'gnuplot')
-         open(file, 'w').write(cmd + '\n pause -1 "Press return to continue (no further rotation possible)"')
-         os.system('sage-native-execute gnuplot -persist %s'%file)
- 
-diff --git a/sage/interfaces/magma.py b/sage/interfaces/magma.py
---- a/sage/interfaces/magma.py
-+++ b/sage/interfaces/magma.py
-@@ -1001,9 +1001,10 @@
-         
-         EXAMPLES::
-         
--            sage: open(SAGE_TMP + 'a.m','w').write('function f(n) return n^2; end function;\nprint "hi";')
--            sage: print magma.load(SAGE_TMP + 'a.m')      # optional - magma
--            Loading ".../.sage//temp/.../a.m"
-+            sage: filename = os.path.join(SAGE_TMP, 'a.m')
-+            sage: open(filename, 'w').write('function f(n) return n^2; end function;\nprint "hi";')
-+            sage: print magma.load(filename)      # optional - magma
-+            Loading ".../tmp/.../a.m"
-             hi
-             sage: magma('f(12)')       # optional - magma
-             144
-diff --git a/sage/libs/mwrank/mwrank.pyx b/sage/libs/mwrank/mwrank.pyx
---- a/sage/libs/mwrank/mwrank.pyx
-+++ b/sage/libs/mwrank/mwrank.pyx
-@@ -117,8 +117,7 @@
- 
-         sage: from sage.libs.mwrank.mwrank import get_precision
-         sage: get_precision()
--	50
--
-+        50
-     """
-     return mwrank_get_precision()
- 
-@@ -154,7 +153,7 @@
- 
-     EXAMPLES::
- 
--        sage: file= SAGE_TMP + '/PRIMES'
-+        sage: file = os.path.join(SAGE_TMP, 'PRIMES')
-         sage: open(file,'w').write(' '.join([str(p) for p in prime_range(10^7,10^7+20)]))
-         sage: mwrank_initprimes(file, verb=True)
- 
-diff --git a/sage/matrix/matrix2.pyx b/sage/matrix/matrix2.pyx
---- a/sage/matrix/matrix2.pyx
-+++ b/sage/matrix/matrix2.pyx
-@@ -7333,7 +7333,7 @@
-         EXAMPLE::
-         
-             sage: M = random_matrix(CC, 4)
--            sage: M.visualize_structure(SAGE_TMP + "matrix.png")
-+            sage: M.visualize_structure(os.path.join(SAGE_TMP, "matrix.png"))
-         """
-         import gd
-         import os
-diff --git a/sage/misc/cython.py b/sage/misc/cython.py
---- a/sage/misc/cython.py
-+++ b/sage/misc/cython.py
-@@ -373,7 +373,7 @@
-     # This is the *temporary* directory where we build the pyx file.
-     # This is deleted when sage exits, which means pyx files must be
-     # rebuilt every time Sage is restarted at present.
--    build_dir = '%s/%s'%(SPYX_TMP, base)
-+    build_dir = os.path.join(SPYX_TMP, base)
- 
-     if os.path.exists(build_dir):
-         # There is already a module here. Maybe we do not have to rebuild?
-diff --git a/sage/misc/dist.py b/sage/misc/dist.py
---- a/sage/misc/dist.py
-+++ b/sage/misc/dist.py
-@@ -70,7 +70,7 @@
- 
-     EXAMPLES::
- 
--        sage: install_scripts(SAGE_TMP, ignore_existing=True)
-+        sage: install_scripts(str(SAGE_TMP), ignore_existing=True)
-         Checking that Sage has the command 'gap' installed
-         ...
-     """
-diff --git a/sage/misc/latex.py b/sage/misc/latex.py
---- a/sage/misc/latex.py
-+++ b/sage/misc/latex.py
-@@ -2112,7 +2112,7 @@
-     EXAMPLES::
- 
-         sage: from sage.misc.latex import png
--        sage: png(ZZ[x], SAGE_TMP + "zz.png") # random - error if no latex
-+        sage: png(ZZ[x], os.path.join(SAGE_TMP, "zz.png")) # random - error if no latex
-     """
-     if not pdflatex:
-         engine = "latex"
-diff --git a/sage/misc/misc.py b/sage/misc/misc.py
---- a/sage/misc/misc.py
-+++ b/sage/misc/misc.py
-@@ -135,15 +135,14 @@
- 
- #################################################
- # Next we create the Sage temporary directory.
--# It is called temp instead of tmp mainly for
--# "historical reasons"...
-+#################################################
- 
- SAGE_TMP = os.path.join(DOT_SAGE, 'tmp', HOSTNAME, str(os.getpid()))
- sage_makedirs(SAGE_TMP)
- 
--SPYX_TMP = os.path.join(SAGE_TMP, 'spyx/')
-+SPYX_TMP = os.path.join(SAGE_TMP, 'spyx')
- 
--SAGE_TMP_INTERFACE = os.path.join(SAGE_TMP, 'interface/')
-+SAGE_TMP_INTERFACE = os.path.join(SAGE_TMP, 'interface')
- sage_makedirs(SAGE_TMP_INTERFACE)
- 
- SAGE_DB = os.path.join(DOT_SAGE, 'db')
-diff --git a/sage/misc/sageinspect.py b/sage/misc/sageinspect.py
---- a/sage/misc/sageinspect.py
-+++ b/sage/misc/sageinspect.py
-@@ -1430,9 +1430,9 @@
-         source_lines = open(filename).readlines()
-     except IOError:
-         try:
--            from sage.all import SAGE_TMP
-+            from sage.misc.misc import SPYX_TMP
-             raw_name = filename.split('/')[-1]
--            newname = SAGE_TMP+'/spyx/'+'_'.join(raw_name.split('_')[:-1])+'/'+raw_name
-+            newname = os.path.join(SPYX_TMP, '_'.join(raw_name.split('_')[:-1]), raw_name)
-             source_lines = open(newname).readlines()
-         except IOError:
-             return None
-diff --git a/sage/misc/session.pyx b/sage/misc/session.pyx
---- a/sage/misc/session.pyx
-+++ b/sage/misc/session.pyx
-@@ -17,11 +17,11 @@
- save your session permanently, since SAGE_TMP will be removed when
- leaving Sage!::
- 
--    sage: save_session(SAGE_TMP+'session')
-+    sage: save_session(os.path.join(SAGE_TMP, 'session'))
- 
- This saves a dictionary with $w$ as one of the keys::
- 
--    sage: z = load(SAGE_TMP+'session')
-+    sage: z = load(os.path.join(SAGE_TMP, 'session'))
-     sage: z.keys()
-     ['w']
-     sage: z['w']
-@@ -32,7 +32,7 @@
-     sage: reset()
-     sage: show_identifiers()
-     []
--    sage: load_session(SAGE_TMP+'session')
-+    sage: load_session(os.path.join(SAGE_TMP, 'session'))
- 
- Indeed $w$ is now defined again.::
- 
-diff --git a/sage/numerical/backends/coin_backend.pyx b/sage/numerical/backends/coin_backend.pyx
---- a/sage/numerical/backends/coin_backend.pyx
-+++ b/sage/numerical/backends/coin_backend.pyx
-@@ -1035,7 +1035,7 @@
-             1
-             sage: p.add_linear_constraint([(0, 1), (1, 2)], None, 3)          # optional - Coin
-             sage: p.set_objective([2, 5])                          # optional - Coin
--            sage: p.write_mps(SAGE_TMP+"/lp_problem.mps", 0)       # optional - Coin
-+            sage: p.write_mps(os.path.join(SAGE_TMP, "lp_problem.mps"), 0)       # optional - Coin
-         """
- 
-         cdef char * mps = "mps"
-@@ -1057,7 +1057,7 @@
-             1
-             sage: p.add_linear_constraint([(0, 1), (1, 2)], None, 3)          # optional - Coin
-             sage: p.set_objective([2, 5])                          # optional - Coin
--            sage: p.write_lp(SAGE_TMP+"/lp_problem.lp")       # optional - Coin
-+            sage: p.write_lp(os.path.join(SAGE_TMP, "lp_problem.lp"))       # optional - Coin
-         """
- 
-         cdef char * lp = "lp"
-diff --git a/sage/numerical/backends/cplex_backend.pyx b/sage/numerical/backends/cplex_backend.pyx
---- a/sage/numerical/backends/cplex_backend.pyx
-+++ b/sage/numerical/backends/cplex_backend.pyx
-@@ -1274,7 +1274,7 @@
-             1
-             sage: p.add_linear_constraint([(0, 1), (1, 2)], None, 3)          # optional - CPLEX
-             sage: p.set_objective([2, 5])                          # optional - CPLEX
--            sage: p.write_lp(SAGE_TMP+"/lp_problem.lp")            # optional - CPLEX
-+            sage: p.write_lp(os.path.join(SAGE_TMP, "lp_problem.lp"))            # optional - CPLEX
-         """
- 
-         cdef int status
-@@ -1298,7 +1298,7 @@
-             1
-             sage: p.add_linear_constraint([(0, 1), (1, 2)], None, 3)          # optional - CPLEX
-             sage: p.set_objective([2, 5])                          # optional - CPLEX
--            sage: p.write_lp(SAGE_TMP+"/lp_problem.lp")            # optional - CPLEX
-+            sage: p.write_lp(os.path.join(SAGE_TMP, "lp_problem.lp"))            # optional - CPLEX
-         """
- 
-         cdef int status
-diff --git a/sage/numerical/backends/generic_backend.pyx b/sage/numerical/backends/generic_backend.pyx
---- a/sage/numerical/backends/generic_backend.pyx
-+++ b/sage/numerical/backends/generic_backend.pyx
-@@ -554,7 +554,7 @@
-             2
-             sage: p.add_linear_constraint([(0, 1], (1, 2)], None, 3) # optional - Nonexistent_LP_solver
-             sage: p.set_objective([2, 5])                          # optional - Nonexistent_LP_solver
--            sage: p.write_lp(SAGE_TMP+"/lp_problem.lp")            # optional - Nonexistent_LP_solver
-+            sage: p.write_lp(os.path.join(SAGE_TMP, "lp_problem.lp"))            # optional - Nonexistent_LP_solver
-         """
-         raise NotImplementedError()
- 
-@@ -574,7 +574,7 @@
-             2
-             sage: p.add_linear_constraint([(0, 1), (1, 2)], None, 3) # optional - Nonexistent_LP_solver
-             sage: p.set_objective([2, 5])                          # optional - Nonexistent_LP_solver
--            sage: p.write_lp(SAGE_TMP+"/lp_problem.lp")            # optional - Nonexistent_LP_solver
-+            sage: p.write_lp(os.path.join(SAGE_TMP, "lp_problem.lp"))            # optional - Nonexistent_LP_solver
-         """
-         raise NotImplementedError()
- 
-diff --git a/sage/numerical/backends/glpk_backend.pyx b/sage/numerical/backends/glpk_backend.pyx
---- a/sage/numerical/backends/glpk_backend.pyx
-+++ b/sage/numerical/backends/glpk_backend.pyx
-@@ -1211,7 +1211,7 @@
-             1
-             sage: p.add_linear_constraint([[0, 1], [1, 2]], None, 3)
-             sage: p.set_objective([2, 5])
--            sage: p.write_lp(SAGE_TMP+"/lp_problem.lp")
-+            sage: p.write_lp(os.path.join(SAGE_TMP, "lp_problem.lp"))
-         """
-         glp_write_lp(self.lp, NULL, filename)
- 
-@@ -1231,7 +1231,7 @@
-             1
-             sage: p.add_linear_constraint([[0, 1], [1, 2]], None, 3)
-             sage: p.set_objective([2, 5])
--            sage: p.write_lp(SAGE_TMP+"/lp_problem.lp")
-+            sage: p.write_lp(os.path.join(SAGE_TMP, "lp_problem.lp"))
-         """
-         glp_write_mps(self.lp, modern, NULL,  filename)
- 
-diff --git a/sage/numerical/backends/gurobi_backend.pyx b/sage/numerical/backends/gurobi_backend.pyx
---- a/sage/numerical/backends/gurobi_backend.pyx
-+++ b/sage/numerical/backends/gurobi_backend.pyx
-@@ -1101,7 +1101,7 @@
-             1
-             sage: p.add_linear_constraint([[0, 1], [1, 2]], None, 3)                # optional - Gurobi
-             sage: p.set_objective([2, 5])                                           # optional - Gurobi
--            sage: p.write_lp(SAGE_TMP+"/lp_problem.lp")                             # optional - Gurobi
-+            sage: p.write_lp(os.path.join(SAGE_TMP, "lp_problem.lp"))               # optional - Gurobi
-         """
-         check(self.env, GRBwrite(self.model[0], filename))
- 
-@@ -1121,7 +1121,7 @@
-             1
-             sage: p.add_linear_constraint([[0, 1], [1, 2]], None, 3)                # optional - Gurobi
-             sage: p.set_objective([2, 5])                                           # optional - Gurobi
--            sage: p.write_lp(SAGE_TMP+"/lp_problem.lp")                             # optional - Gurobi
-+            sage: p.write_lp(os.path.join(SAGE_TMP, "lp_problem.lp"))               # optional - Gurobi
-         """
-         check(self.env, GRBwrite(self.model[0], filename))
- 
-diff --git a/sage/numerical/mip.pyx b/sage/numerical/mip.pyx
---- a/sage/numerical/mip.pyx
-+++ b/sage/numerical/mip.pyx
-@@ -724,7 +724,7 @@
-             sage: x = p.new_variable()
-             sage: p.set_objective(x[1] + x[2])
-             sage: p.add_constraint(-3*x[1] + 2*x[2], max=2,name="OneConstraint")
--            sage: p.write_mps(SAGE_TMP+"/lp_problem.mps")
-+            sage: p.write_mps(os.path.join(SAGE_TMP, "lp_problem.mps"))
- 
-         For information about the MPS file format :
-         http://en.wikipedia.org/wiki/MPS_%28format%29
-@@ -749,7 +749,7 @@
-             sage: x = p.new_variable()
-             sage: p.set_objective(x[1] + x[2])
-             sage: p.add_constraint(-3*x[1] + 2*x[2], max=2)
--            sage: p.write_lp(SAGE_TMP+"/lp_problem.lp")
-+            sage: p.write_lp(os.path.join(SAGE_TMP, "lp_problem.lp"))
- 
-         For more information about the LP file format :
-         http://lpsolve.sourceforge.net/5.5/lp-format.htm
-diff --git a/sage/plot/plot3d/base.pyx b/sage/plot/plot3d/base.pyx
---- a/sage/plot/plot3d/base.pyx
-+++ b/sage/plot/plot3d/base.pyx
-@@ -1082,7 +1082,7 @@
-         # Tachyon resolution options
-         if DOCTEST_MODE:
-             opts = '-res 10 10'
--            filename = sage.misc.misc.SAGE_TMP + "/tmp"
-+            filename = os.path.join(sage.misc.misc.SAGE_TMP, "tmp")
-         elif EMBEDDED_MODE:
-             opts = '-res %s %s'%(figsize[0]*100, figsize[1]*100)
-             filename = sage.misc.temporary_file.graphics_filename()[:-4]
-diff --git a/sage/plot/plot3d/tachyon.py b/sage/plot/plot3d/tachyon.py
---- a/sage/plot/plot3d/tachyon.py
-+++ b/sage/plot/plot3d/tachyon.py
-@@ -314,7 +314,7 @@
-         import sage.plot.plot
-         if sage.plot.plot.DOCTEST_MODE:
-             filename = graphics_filename()
--            self.save(SAGE_TMP + '/test.png', verbose=verbose, extra_opts=extra_opts)
-+            self.save(os.path.join(SAGE_TMP, 'test.png'), verbose=verbose, extra_opts=extra_opts)
-             return
-         if sage.plot.plot.EMBEDDED_MODE:
-             filename = graphics_filename()
-diff --git a/sage/plot/text.py b/sage/plot/text.py
---- a/sage/plot/text.py
-+++ b/sage/plot/text.py
-@@ -232,7 +232,7 @@
- 
-     You can save text as part of PDF output::
- 
--        sage: text("sage", (0,0), rgbcolor=(0,0,0)).save(SAGE_TMP + 'a.pdf')
-+        sage: text("sage", (0,0), rgbcolor=(0,0,0)).save(os.path.join(SAGE_TMP, 'a.pdf'))
- 
-     Text must be 2D (use the text3d command for 3D text)::
- 
-diff --git a/sage/server/notebook/notebook.py b/sage/server/notebook/notebook.py
---- a/sage/server/notebook/notebook.py
-+++ b/sage/server/notebook/notebook.py
-@@ -1180,7 +1180,7 @@
-         
-         ::
- 
--            sage: savefile = SAGE_TMP + 'tmp.sws'
-+            sage: savefile = os.path.join(SAGE_TMP, 'tmp.sws')
-         
-             sage: nb.export_worksheet(W.filename(),  savefile, verbose=False)
-         
-diff --git a/sage/structure/sage_object.pyx b/sage/structure/sage_object.pyx
---- a/sage/structure/sage_object.pyx
-+++ b/sage/structure/sage_object.pyx
-@@ -185,8 +185,8 @@
-         EXAMPLES::
-         
-             sage: f = x^3 + 5
--            sage: f.save(SAGE_TMP + '/file')
--            sage: load(SAGE_TMP + '/file.sobj')
-+            sage: f.save(os.path.join(SAGE_TMP, 'file'))
-+            sage: load(os.path.join(SAGE_TMP, 'file.sobj'))
-             x^3 + 5
-         """
-         if filename is None:
-@@ -814,8 +814,8 @@
-     EXAMPLES::
-     
-         sage: a = matrix(2, [1,2,3,-5/2])
--        sage: objfile = SAGE_TMP + 'test.sobj'
--        sage: objfile_short = SAGE_TMP + 'test'
-+        sage: objfile = os.path.join(SAGE_TMP, 'test.sobj')
-+        sage: objfile_short = os.path.join(SAGE_TMP, 'test')
-         sage: save(a, objfile)
-         sage: load(objfile_short)
-         [   1    2]
-@@ -823,14 +823,14 @@
-         sage: E = EllipticCurve([-1,0])
-         sage: P = plot(E)
-         sage: save(P, objfile_short)   # saves the plot to "test.sobj"
--        sage: save(P, filename=SAGE_TMP + "sage.png", xmin=-2)
--        sage: save(P, SAGE_TMP + "filename.with.some.wrong.ext")
-+        sage: save(P, filename=os.path.join(SAGE_TMP, "sage.png"), xmin=-2)
-+        sage: save(P, os.path.join(SAGE_TMP, "filename.with.some.wrong.ext"))
-         Traceback (most recent call last):
-         ...
-         ValueError: allowed file extensions for images are '.eps', '.pdf', '.png', '.ps', '.sobj', '.svg'!
-         sage: print load(objfile)
-         Graphics object consisting of 2 graphics primitives
--        sage: save("A python string", SAGE_TMP + 'test')
-+        sage: save("A python string", os.path.join(SAGE_TMP, 'test'))
-         sage: load(objfile)
-         'A python string'
-         sage: load(objfile_short)
-@@ -840,7 +840,7 @@
- 
-     Check that #11577 is fixed::
- 
--        sage: filename = SAGE_TMP + "foo.bar" # filename containing a dot
-+        sage: filename = os.path.join(SAGE_TMP, "foo.bar")  # filename containing a dot
-         sage: save((1,1),filename)            # saves tuple to "foo.bar.sobj"
-         sage: load(filename)
-         (1, 1)
 trac_13211_pool_size.patch
 trac_13211_itanium_fix.patch
 trac_13211_quit_after_workspace.patch
-13681_sagelib.patch
 trac_6391_libGAP.patch
 trac_13588_improve_libGAP.patch
 trac_13687_Parent_for_groups.patch
+trac_13687_review.patch
 trac_11395_update_gfan.patch
 trac11395-fix_tutorial.patch
 trac_11395_doctest_fix.patch
 trac_9880_revert_marking_random_from_trac_10187.patch #+pynac
 trac_11667_use_groebner_basis_with_degree_bound.patch  #+todo
 trac_11559_fix_Chow_group.patch   #+todo maybe delete
-trac_11763_ZZ_polyhedron.patch          #+todo
 trac_12193_fix_dimension.patch
 trac_12553_ppl_count_points.patch
 trac_12553_ppl_lattice_polytope.patch

File trac_11763_ZZ_polyhedron.patch

-# HG changeset patch
-# Parent c69fd8f38ffcadfec2decc0155b267a6e23498d3
-# HG changeset patch
-# Parent fe5790d3e8b49343e2049d5078055a8ceec9c167
-# HG changeset patch
-# Parent c69fd8f38ffcadfec2decc0155b267a6e23498d3
-# HG changeset patch
-# Parent fe5790d3e8b49343e2049d5078055a8ceec9c167
-
-Trac #11763: Add ZZ as allowed base ring for polyhedra
-
-diff --git a/doc/en/reference/geometry.rst b/doc/en/reference/geometry.rst
---- a/doc/en/reference/geometry.rst
-+++ b/doc/en/reference/geometry.rst
-@@ -25,6 +25,7 @@
-    sage/geometry/polyhedron/plot
-    sage/geometry/polyhedron/base
-    sage/geometry/polyhedron/base_QQ
-+   sage/geometry/polyhedron/base_ZZ
-    sage/geometry/polyhedron/base_RDF
-    sage/geometry/polyhedron/backend_cdd
-    sage/geometry/polyhedron/backend_ppl
-diff --git a/sage/geometry/polyhedron/backend_ppl.py b/sage/geometry/polyhedron/backend_ppl.py
---- a/sage/geometry/polyhedron/backend_ppl.py
-+++ b/sage/geometry/polyhedron/backend_ppl.py
-@@ -11,7 +11,9 @@
-     Variable, Linear_Expression,
-     line, ray, point )
-
-+from base import Polyhedron_base
- from base_QQ import Polyhedron_QQ
-+from base_ZZ import Polyhedron_ZZ
- from representation import (
-     PolyhedronRepresentation,
-     Hrepresentation,
-@@ -22,9 +24,9 @@
-
-
- #########################################################################
--class Polyhedron_QQ_ppl(Polyhedron_QQ):
-+class Polyhedron_ppl(Polyhedron_base):
-     """
--    Polyhedra over `\QQ` with ppl
-+    Polyhedra with ppl
-
-     INPUT:
-
-@@ -63,8 +65,8 @@
-         EXAMPLES::
-
-             sage: p = Polyhedron(backend='ppl')
--            sage: from sage.geometry.polyhedron.backend_ppl import Polyhedron_QQ_ppl
--            sage: Polyhedron_QQ_ppl._init_from_Vrepresentation(p, 2, [], [], [])
-+            sage: from sage.geometry.polyhedron.backend_ppl import Polyhedron_ppl
-+            sage: Polyhedron_ppl._init_from_Vrepresentation(p, 2, [], [], [])
-         """
-         gs = Generator_System()
-         if vertices is None: vertices = []
-@@ -106,8 +108,8 @@
-         EXAMPLES::
-
-             sage: p = Polyhedron(backend='ppl')
--            sage: from sage.geometry.polyhedron.backend_ppl import Polyhedron_QQ_ppl
--            sage: Polyhedron_QQ_ppl._init_from_Hrepresentation(p, 2, [], [])
-+            sage: from sage.geometry.polyhedron.backend_ppl import Polyhedron_ppl
-+            sage: Polyhedron_ppl._init_from_Hrepresentation(p, 2, [], [])
-         """
-         cs = Constraint_System()
-         if ieqs is None: ieqs = []
-@@ -212,7 +214,51 @@
-             The empty polyhedron in QQ^0
-             sage: Polyhedron(backend='ppl')._init_empty_polyhedron(0)
-         """
--        super(Polyhedron_QQ_ppl, self)._init_empty_polyhedron(ambient_dim)
-+        super(Polyhedron_ppl, self)._init_empty_polyhedron(ambient_dim)
-         self._ppl_polyhedron = C_Polyhedron(ambient_dim, 'empty')
-
-
-+
-+
-+#########################################################################
-+class Polyhedron_QQ_ppl(Polyhedron_ppl, Polyhedron_QQ):
-+    """
-+    Polyhedra over `\QQ` with ppl
-+
-+    INPUT:
-+
-+    - ``ambient_dim`` -- integer. The dimension of the ambient space.
-+
-+    - ``Vrep`` -- a list ``[vertices, rays, lines]``.
-+
-+    - ``Hrep`` -- a list ``[ieqs, eqns]``.
-+
-+    EXAMPLES::
-+
-+        sage: p = Polyhedron(vertices=[(0,0),(1,0),(0,1)], rays=[(1,1)], lines=[],
-+        ...                  backend='ppl', base_ring=QQ)
-+        sage: TestSuite(p).run(skip='_test_pickling')
-+    """
-+    pass
-+
-+
-+#########################################################################
-+class Polyhedron_ZZ_ppl(Polyhedron_ppl, Polyhedron_ZZ):
-+    """
-+    Polyhedra over `\ZZ` with ppl
-+
-+    INPUT:
-+
-+    - ``ambient_dim`` -- integer. The dimension of the ambient space.
-+
-+    - ``Vrep`` -- a list ``[vertices, rays, lines]``.
-+
-+    - ``Hrep`` -- a list ``[ieqs, eqns]``.
-+
-+    EXAMPLES::
-+
-+        sage: p = Polyhedron(vertices=[(0,0),(1,0),(0,1)], rays=[(1,1)], lines=[])
-+        ...                  backend='ppl', base_ring=ZZ)
-+        sage: TestSuite(p).run(skip='_test_pickling')
-+    """
-+    pass
-diff --git a/sage/geometry/polyhedron/base.py b/sage/geometry/polyhedron/base.py
---- a/sage/geometry/polyhedron/base.py
-+++ b/sage/geometry/polyhedron/base.py
-@@ -542,9 +542,11 @@
-         else:
-             desc += 'A ' + repr(self.dim()) + '-dimensional polyhedron'
-         desc += ' in '
--        if self.field()==QQ: desc += 'QQ'
--        else:                desc += 'RDF'
--        desc += '^' + repr(self.ambient_dim())
-+        if   self.base_ring() is QQ:  desc += 'QQ'
-+        elif self.base_ring() is ZZ:  desc += 'ZZ'
-+        elif self.base_ring() is RDF: desc += 'RDF'
-+        else: assert False
-+        desc += '^' + repr(self.ambient_dim())
-
-         if self.n_vertices()>0:
-             desc += ' defined as the convex hull of '
-@@ -1356,8 +1358,8 @@
-             sage: poly_test.ambient_space()
-             Vector space of dimension 4 over Rational Field
-         """
--        from sage.modules.free_module import VectorSpace
--        return VectorSpace(self.base_ring(), self.ambient_dim())
-+        from sage.modules.free_module import FreeModule
-+        return FreeModule(self.base_ring(), self.ambient_dim())
-
-     Vrepresentation_space = ambient_space
-
-diff --git a/sage/geometry/polyhedron/base_ZZ.py b/sage/geometry/polyhedron/base_ZZ.py
-new file mode 100644
---- /dev/null
-+++ b/sage/geometry/polyhedron/base_ZZ.py
-@@ -0,0 +1,237 @@
-+"""
-+Base class for polyhedra over `\ZZ`
-+"""
-+
-+########################################################################
-+#       Copyright (C) 2011 Volker Braun <vbraun.name@gmail.com>
-+#
-+#  Distributed under the terms of the GNU General Public License (GPL)
-+#
-+#                  http://www.gnu.org/licenses/
-+########################################################################
-+
-+
-+
-+from sage.rings.all import ZZ, QQ
-+from sage.misc.all import cached_method
-+from sage.matrix.constructor import matrix
-+
-+from constructor import Polyhedron
-+from base import Polyhedron_base
-+
-+
-+
-+#########################################################################
-+class Polyhedron_ZZ(Polyhedron_base):
-+    """
-+    Base class for Polyhedra over `\ZZ`
-+
-+    TESTS::
-+
-+        sage: p = Polyhedron([(0,0)], base_ring=ZZ);  p
-+        A 0-dimensional polyhedron in ZZ^2 defined as the convex hull of 1 vertex
-+        sage: TestSuite(p).run(skip='_test_pickling')
-+    """
-+    def _is_zero(self, x):
-+        """
-+        Test whether ``x`` is zero.
-+
-+        INPUT:
-+
-+        - ``x`` -- a number in the base ring.
-+
-+        OUTPUT:
-+
-+        Boolean.
-+
-+        EXAMPLES::
-+
-+            sage: p = Polyhedron([(0,0)], base_ring=ZZ)
-+            sage: p._is_zero(0)
-+            True
-+            sage: p._is_zero(1/100000)
-+            False
-+        """
-+        return x==0
-+
-+    def _is_nonneg(self, x):
-+        """
-+        Test whether ``x`` is nonnegative.
-+
-+        INPUT:
-+
-+        - ``x`` -- a number in the base ring.
-+
-+        OUTPUT:
-+
-+        Boolean.
-+
-+        EXAMPLES::
-+
-+            sage: p = Polyhedron([(0,0)], base_ring=ZZ)
-+            sage: p._is_nonneg(1)
-+            True
-+            sage: p._is_nonneg(-1/100000)
-+            False
-+        """
-+        return x>=0
-+
-+    def _is_positive(self, x):
-+        """
-+        Test whether ``x`` is positive.
-+
-+        INPUT:
-+
-+        - ``x`` -- a number in the base ring.
-+
-+        OUTPUT:
-+
-+        Boolean.
-+
-+        EXAMPLES::
-+
-+            sage: p = Polyhedron([(0,0)], base_ring=ZZ)
-+            sage: p._is_positive(1)
-+            True
-+            sage: p._is_positive(0)
-+            False
-+        """
-+        return x>0
-+
-+    _base_ring = ZZ
-+
-+    def is_lattice_polytope(self):
-+        r"""
-+        Return whether the polyhedron is a lattice polytope.
-+
-+        OUTPUT:
-+
-+        ``True`` if the polyhedron is compact and has only integral
-+        vertices, ``False`` otherwise.
-+
-+        EXAMPLES::
-+
-+            sage: polytopes.cross_polytope(3).is_lattice_polytope()
-+            True
-+            sage: polytopes.regular_polygon(5).is_lattice_polytope()
-+            False
-+        """
-+        return True
-+
-+    @cached_method
-+    def polar(self):
-+        """
-+        Return the polar (dual) polytope.
-+
-+        The polytope must have the IP-property (see
-+        :meth:`has_IP_property`), that is, the origin must be an
-+        interior point. In particular, it must be full-dimensional.
-+
-+        OUTPUT:
-+
-+        The polytope whose vertices are the coefficient vectors of the
-+        inequalities of ``self`` with inhomogeneous term normalized to
-+        unity.
-+
-+        EXAMPLES::
-+
-+            sage: p = Polyhedron(vertices=[(1,0,0),(0,1,0),(0,0,1),(-1,-1,-1)], base_ring=ZZ)
-+            sage: p.polar()
-+            A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 4 vertices
-+            sage: type(_)
-+            <class 'sage.geometry.polyhedron.backend_ppl.Polyhedron_ZZ_ppl'>
-+            sage: p.polar().base_ring()
-+            Integer Ring
-+        """
-+        if not self.has_IP_property():
-+            raise ValueError('The polytope must have the IP property.')
-+
-+        vertices = [ ieq.A()/ieq.b() for
-+                     ieq in self.inequality_generator() ]
-+        if all( all(v_i in ZZ for v_i in v) for v in vertices):
-+            return Polyhedron(vertices=vertices, base_ring=ZZ)
-+        else:
-+            return Polyhedron(vertices=vertices, base_ring=QQ)
-+
-+    @cached_method
-+    def is_reflexive(self):
-+        """
-+        EXAMPLES::
-+
-+            sage: p = Polyhedron(vertices=[(1,0,0),(0,1,0),(0,0,1),(-1,-1,-1)], base_ring=ZZ)
-+            sage: p.is_reflexive()
-+            True
-+        """
-+        return self.polar().is_lattice_polytope()
-+
-+    @cached_method
-+    def has_IP_property(self):
-+        """
-+        Test whether the polyhedron has the IP property.
-+
-+        The IP (interior point) property means that
-+
-+        * ``self`` is compact (a polytope).
-+
-+        * ``self`` contains the origin.
-+
-+        This implies that
-+
-+        * ``self`` is full-dimensional.
-+
-+        * The dual polyhedron is again a polytope (that is, a compact
-+          polyhedron), though not necessarily a lattice polytope.
-+
-+        REFERENCES::
-+
-+        ..  [PALP]
-+            Maximilian Kreuzer, Harald Skarke:
-+            "PALP: A Package for Analyzing Lattice Polytopes
-+            with Applications to Toric Geometry"
-+            Comput.Phys.Commun. 157 (2004) 87-106
-+            http://arxiv.org/abs/math/0204356
-+        """
-+        return self.is_compact() and self.contains(self.ambient_space().zero())
-+
-+    def fibrations(self):
-+        """
-+        EXAMPLES::
-+
-+            sage: P = Polyhedron(toric_varieties.P4_11169().fan().rays(), base_ring=ZZ)
-+            sage: list( P.fibrations() )
-+            [A 2-dimensional polyhedron in QQ^4 defined as the convex hull of 3 vertices]
-+        """
-+        if not self.has_IP_property():
-+            raise ValueError('The polytope must have the IP property.')
-+        # todo: just go through pairs of points on the same facet
-+        fiber_dimension = 2
-+        points = self.integral_points()
-+        fibers = set()
-+        for i1 in range(0,len(points)):
-+            p1 = points[i1]
-+            if p1.is_zero():
-+                continue
-+            for i2 in range(i1+1,len(points)):
-+                p2 = points[i2]
-+                if p2.is_zero():
-+                    continue
-+                plane_12 = Polyhedron(lines=[p1,p2])
-+                if plane_12.dim() != 2:
-+                    continue
-+                fiber = self.intersection(plane_12)
-+                if not fiber.is_lattice_polytope():
-+                    continue
-+                fiber_matrix = matrix(ZZ,sorted(fiber.integral_points()))
-+                fiber_matrix.set_immutable()
-+                if fiber_matrix not in fibers:
-+                    yield fiber
-+                    fibers.update([fiber_matrix])
-+
-+
-+
-+
-+
-+
-+
-+
-+
-diff --git a/sage/geometry/polyhedron/constructor.py b/sage/geometry/polyhedron/constructor.py
---- a/sage/geometry/polyhedron/constructor.py
-+++ b/sage/geometry/polyhedron/constructor.py
-@@ -159,8 +159,8 @@
-       * ``'cddf'``: cdd with floating-point coefficients
-
-       * ``'ppl'``: use ppl
--        (:mod:`~sage.geometry.polyhedron.backend_ppl`) with `\QQ`
--        coefficients.
-+        (:mod:`~sage.geometry.polyhedron.backend_ppl`) with `\QQ` or
-+        `\ZZ` coefficients depending on ``base_ring``.
-
-     Some backends support further optional arguments:
-
-@@ -272,15 +272,19 @@
-         ambient_dim = 0
-
-     if backend is not None:
--        if backend=='ppl':
-+        if backend=='ppl' and base_ring is QQ:
-             from backend_ppl import Polyhedron_QQ_ppl
-             return Polyhedron_QQ_ppl(ambient_dim, Vrep, Hrep, minimize=minimize)
-+        if backend=='ppl' and base_ring is ZZ:
-+            from backend_ppl import Polyhedron_ZZ_ppl
-+            return Polyhedron_ZZ_ppl(ambient_dim, Vrep, Hrep, minimize=minimize)
-         if backend=='cddr':
-             from backend_cdd import Polyhedron_QQ_cdd
-             return Polyhedron_QQ_cdd(ambient_dim, Vrep, Hrep, verbose=verbose)
-         if backend=='cddf':
-             from backend_cdd import Polyhedron_RDF_cdd
-             return Polyhedron_RDF_cdd(ambient_dim, Vrep, Hrep, verbose=verbose)
-+        raise ValueError('No suitable backend implemented.')
-
-     if base_ring is QQ:
-         from backend_ppl import Polyhedron_QQ_ppl
-@@ -288,6 +292,9 @@
-     elif base_ring is RDF:
-         from backend_cdd import Polyhedron_RDF_cdd
-         return Polyhedron_RDF_cdd(ambient_dim, Vrep, Hrep, verbose=verbose)
-+    elif base_ring is ZZ:
-+        from backend_ppl import Polyhedron_ZZ_ppl
-+        return Polyhedron_ZZ_ppl(ambient_dim, Vrep, Hrep, minimize=minimize)
-     else:
-         raise ValueError('Polyhedron objects can only be constructed over QQ and RDF')
-
-diff --git a/sage/geometry/polyhedron/representation.py b/sage/geometry/polyhedron/representation.py
---- a/sage/geometry/polyhedron/representation.py
-+++ b/sage/geometry/polyhedron/representation.py
-@@ -60,7 +60,8 @@
-             (1, 2, 3)
-             sage: TestSuite(pr).run(skip='_test_pickling')
-         """
--        self._representation_data = tuple(data)
-+        R = polyhedron.base_ring()
-+        self._representation_data = tuple(R(x) for x in data)
-         self._polyhedron = polyhedron
-
-     def __len__(self):

File trac_12091_constraints_parents.patch

 # HG changeset patch
-# Parent 9ec5f8100986ada544f324fb383d0a3024168e12
+# Parent 11be0924d40f1d23ddc48ed1b8e72dbaef1bcc25
 
 Implement parents for constraints, fix chained inequalities
 
      def __call__(self, x):
          """
          Construct a new linear function
-@@ -1141,7 +1169,7 @@
+@@ -695,10 +723,24 @@
+             Variables:
+               x_0 is a continuous variable (min=0.0, max=+oo)
+               x_1 is a continuous variable (min=0.0, max=+oo)
++
++        With `\QQ` coefficients::
++
++            sage: p = MixedIntegerLinearProgram(solver= 'ppl')
++            sage: x = p.new_variable()
++            sage: p.set_objective(x[1] + 1/2*x[2])
++            sage: p.add_constraint(-3/5*x[1] + 2/7*x[2], max=2/5)
++            sage: p.show()
++            Maximization:
++              x_0 + 1/2 x_1
++            Constraints:
++              constraint_0: -3/5 x_0 + 2/7 x_1 <= 2/5
++            Variables:
++              x_0 is a continuous variable (min=0, max=+oo)
++              x_1 is a continuous variable (min=0, max=+oo)
+         """
+ 
+         cdef int i, j
+-        cdef double c
+         cdef GenericBackend b = self._backend
+ 
+         # inv_variables associates a MIPVariable object to an id
+@@ -1141,7 +1183,7 @@
              sage: p.add_constraint(True)
              Traceback (most recent call last):
              ...
          """
          if linear_function is 0:
              return
-@@ -1152,7 +1180,7 @@
+@@ -1152,7 +1194,7 @@
              or (max is not None and max not in RR)):
              raise ValueError("min and max arguments are required to be numerical")
  
              f = linear_function.dict()
              constant_coefficient = f.get(-1,0)
  
-@@ -1188,21 +1216,14 @@
+@@ -1188,21 +1230,14 @@
  
              self._backend.add_linear_constraint(C, min, max, name)
  
  
      def remove_constraint(self, int i):
          r"""
-@@ -1765,13 +1786,13 @@
+@@ -1765,13 +1800,13 @@
      cpdef sum(self, L):
          r"""
          Efficiently computes the sum of a sequence of
          
          .. NOTE::
          
-@@ -1793,7 +1814,7 @@
+@@ -1793,7 +1828,7 @@
          """
          d = {}
          for v in L:
                  d[id] = coeff + d.get(id,0)
          return self.linear_functions_parent()(d)
  
-@@ -2029,621 +2050,6 @@
+@@ -2029,621 +2064,6 @@
  
  
  

File trac_13687_review.patch

+# HG changeset patch
+# Parent 66eb197dff909c76788766021a790bfeb237a618
+
+Addressing the reviewer comments
+
+diff --git a/doc/de/tutorial/tour_groups.rst b/doc/de/tutorial/tour_groups.rst
+--- a/doc/de/tutorial/tour_groups.rst
++++ b/doc/de/tutorial/tour_groups.rst
+@@ -82,10 +82,10 @@
+     sage: d * b**2 * c**3 
+     b^2*c^3*d
+     sage: F = AbelianGroup(3,[2]*3); F
+-    Multiplicative Abelian Group isomorphic to C2 x C2 x C2
++    Multiplicative Abelian group isomorphic to C2 x C2 x C2
+     sage: H = AbelianGroup([2,3], names="xy"); H
+-    Multiplicative Abelian Group isomorphic to C2 x C3
++    Multiplicative Abelian group isomorphic to C2 x C3
+     sage: AbelianGroup(5)
+-    Multiplicative Abelian Group isomorphic to Z x Z x Z x Z x Z
++    Multiplicative Abelian group isomorphic to Z x Z x Z x Z x Z
+     sage: AbelianGroup(5).order()
+     +Infinity
+diff --git a/doc/en/tutorial/tour_groups.rst b/doc/en/tutorial/tour_groups.rst
+--- a/doc/en/tutorial/tour_groups.rst
++++ b/doc/en/tutorial/tour_groups.rst
+@@ -80,10 +80,10 @@
+     sage: d * b**2 * c**3 
+     b^2*c^3*d
+     sage: F = AbelianGroup(3,[2]*3); F
+-    Multiplicative Abelian Group isomorphic to C2 x C2 x C2
++    Multiplicative Abelian group isomorphic to C2 x C2 x C2
+     sage: H = AbelianGroup([2,3], names="xy"); H
+-    Multiplicative Abelian Group isomorphic to C2 x C3
++    Multiplicative Abelian group isomorphic to C2 x C3
+     sage: AbelianGroup(5)
+-    Multiplicative Abelian Group isomorphic to Z x Z x Z x Z x Z
++    Multiplicative Abelian group isomorphic to Z x Z x Z x Z x Z
+     sage: AbelianGroup(5).order()
+     +Infinity
+diff --git a/doc/fr/tutorial/tour_groups.rst b/doc/fr/tutorial/tour_groups.rst
+--- a/doc/fr/tutorial/tour_groups.rst
++++ b/doc/fr/tutorial/tour_groups.rst
+@@ -83,10 +83,10 @@
+     sage: d * b**2 * c**3 
+     b^2*c^3*d
+     sage: F = AbelianGroup(3,[2]*3); F
+-    Multiplicative Abelian Group isomorphic to C2 x C2 x C2
++    Multiplicative Abelian group isomorphic to C2 x C2 x C2
+     sage: H = AbelianGroup([2,3], names="xy"); H
+-    Multiplicative Abelian Group isomorphic to C2 x C3
++    Multiplicative Abelian group isomorphic to C2 x C3
+     sage: AbelianGroup(5)
+-    Multiplicative Abelian Group isomorphic to Z x Z x Z x Z x Z
++    Multiplicative Abelian group isomorphic to Z x Z x Z x Z x Z
+     sage: AbelianGroup(5).order()
+     +Infinity
+diff --git a/doc/ru/tutorial/tour_groups.rst b/doc/ru/tutorial/tour_groups.rst
+--- a/doc/ru/tutorial/tour_groups.rst
++++ b/doc/ru/tutorial/tour_groups.rst
+@@ -80,10 +80,10 @@
+     sage: d * b**2 * c**3 
+     b^2*c^3*d
+     sage: F = AbelianGroup(3,[2]*3); F
+-    Multiplicative Abelian Group isomorphic to C2 x C2 x C2
++    Multiplicative Abelian group isomorphic to C2 x C2 x C2
+     sage: H = AbelianGroup([2,3], names="xy"); H
+-    Multiplicative Abelian Group isomorphic to C2 x C3
++    Multiplicative Abelian group isomorphic to C2 x C3
+     sage: AbelianGroup(5)
+-    Multiplicative Abelian Group isomorphic to Z x Z x Z x Z x Z
++    Multiplicative Abelian group isomorphic to Z x Z x Z x Z x Z
+     sage: AbelianGroup(5).order()
+     +Infinity
+diff --git a/sage/categories/category.py b/sage/categories/category.py
+--- a/sage/categories/category.py
++++ b/sage/categories/category.py
+@@ -23,7 +23,7 @@
+     sage: Sets()
+     Category of sets
+     sage: GSets(AbelianGroup([2,4,9]))
+-    Category of G-sets for Multiplicative Abelian Group isomorphic to C2 x C4 x C9
++    Category of G-sets for Multiplicative Abelian group isomorphic to C2 x C4 x C9
+     sage: Semigroups()
+     Category of semigroups
+     sage: VectorSpaces(FiniteField(11))
+diff --git a/sage/groups/abelian_gps/abelian_group.py b/sage/groups/abelian_gps/abelian_group.py
+--- a/sage/groups/abelian_gps/abelian_group.py
++++ b/sage/groups/abelian_gps/abelian_group.py
+@@ -21,9 +21,9 @@
+ generators::
+ 
+     sage: AbelianGroup([0,0,0,2,3])
+-    Multiplicative Abelian Group isomorphic to Z x Z x Z x C2 x C3
++    Multiplicative Abelian group isomorphic to Z x Z x Z x C2 x C3
+     sage: AbelianGroup(5, [2,3])
+-    Multiplicative Abelian Group isomorphic to Z x Z x Z x C2 x C3
++    Multiplicative Abelian group isomorphic to Z x Z x Z x C2 x C3
+ 
+ It is also legal to specify `1` as the order. The corresponding
+ generator will be the neutral element, but it will still take up an
+@@ -41,7 +41,7 @@
+ :meth:`~AbelianGroup_class.gens_orders` instead::
+ 
+    sage: J = AbelianGroup([2,0,3,2,4]);  J
+-   Multiplicative Abelian Group isomorphic to C2 x Z x C3 x C2 x C4
++   Multiplicative Abelian group isomorphic to C2 x Z x C3 x C2 x C4
+    sage: J.gens_orders()            # use this instead
+    (2, 0, 3, 2, 4)
+    sage: J.invariants()             # deprecated
+@@ -126,7 +126,7 @@
+ 
+     sage: T = AbelianGroup(0,[])
+     sage: T
+-    Trivial Abelian Group
++    Trivial Abelian group
+     sage: T.gens()
+     ()
+     sage: T(1)
+@@ -139,7 +139,7 @@
+ 
+     sage: F = AbelianGroup(5,[3,4,5,5,7],names = list("abcde"))
+     sage: F
+-    Multiplicative Abelian Group isomorphic to C3 x C4 x C5 x C5 x C7
++    Multiplicative Abelian group isomorphic to C3 x C4 x C5 x C5 x C7
+     sage: (a,b,c,d,e) = F.gens()
+     sage: a*b^2*e*d
+     a*b^2*d*e
+@@ -250,7 +250,7 @@
+     EXAMPLE::
+     
+         sage: G.<a,b,c> = AbelianGroup(3,[2,3,4]); G
+-        Multiplicative Abelian Group isomorphic to C2 x C3 x C4
++        Multiplicative Abelian group isomorphic to C2 x C3 x C4
+         sage: w = word_problem([a*b,a*c], b*c); w #random 
+         [[a*b, 1], [a*c, 1]]  
+         sage: prod([x^i for x,i in w]) == b*c
+@@ -330,18 +330,56 @@
+     """
+     Helper function for :func:`AbelianGroup`. Beat some sense into the
+     arguments.
+-    """
++
++    This function is also used by some descendents of
++    :class:`AbelianGroup_class`.
++
++    INPUT:
++
++    See :func:`AbelianGroup`
++
++    OUTPUT:
++
++    Unique data for defining a :class:`AbelianGroup_class`. Raises an
++    exception if the input is invalid.
++
++    EXAMPLES::
++
++        sage: from sage.groups.abelian_gps.abelian_group import _normalize
++        sage: _normalize(5, [2,1,0], names='abc')
++        ((0, 0, 2, 1, 0), 'abc')
++        sage: _normalize(5, (2.0, 1.0, 0/1), names=list('abc'))
++        ((0, 0, 2, 1, 0), ('a', 'b', 'c'))
++        sage: _normalize([0,2,1,0], names='a')
++        ((0, 2, 1, 0), 'a')
++
++    TESTS::
++
++        sage: _normalize(5, (2.0, 1.5, 0/1), names=list('abc'))
++        Traceback (most recent call last):
++        ...
++        TypeError: Attempt to coerce non-integral RealNumber to Integer
++        sage: _normalize('1', '[2]', names='a')
++        Traceback (most recent call last):
++        ...
++        TypeError: unable to convert x (=[) to an integer
++        sage: _normalize(3, 'str', names='a')
++        Traceback (most recent call last):
++        ...
++        TypeError: unable to convert x (=s) to an integer
++   """
+     if gens_orders is None:
+         if isinstance(n, (list, tuple)):
+             gens_orders = n
+             n = len(n)
+         else:
+             gens_orders = []
++    n = ZZ(n)
+     if len(gens_orders) < n:
+-        gens_orders = [0] * (n - len(gens_orders)) + gens_orders
+-    elif len(gens_orders) > n:
++        gens_orders = [0] * (n - len(gens_orders)) + list(gens_orders)
++    gens_orders = tuple(ZZ(i) for i in gens_orders)
++    if len(gens_orders) > n:
+         raise ValueError('gens_orders (='+str(gens_orders)+') must have length n (='+str(n)+')')
+-    gens_orders = tuple(gens_orders)
+     if isinstance(names, list):
+         names = tuple(names)
+     return (gens_orders, names)
+@@ -384,18 +422,18 @@
+         sage: d * b**2 * c**3 
+         b^2*c^3*d
+         sage: F = AbelianGroup(3,[2]*3); F
+-        Multiplicative Abelian Group isomorphic to C2 x C2 x C2
++        Multiplicative Abelian group isomorphic to C2 x C2 x C2
+         sage: H = AbelianGroup([2,3], names="xy"); H
+-        Multiplicative Abelian Group isomorphic to C2 x C3
++        Multiplicative Abelian group isomorphic to C2 x C3
+         sage: AbelianGroup(5)
+-        Multiplicative Abelian Group isomorphic to Z x Z x Z x Z x Z
++        Multiplicative Abelian group isomorphic to Z x Z x Z x Z x Z
+         sage: AbelianGroup(5).order()
+         +Infinity
+     
+     Notice that `0`'s are prepended if necessary::
+     
+         sage: G = AbelianGroup(5, [2,3,4]);  G
+-        Multiplicative Abelian Group isomorphic to Z x Z x C2 x C3 x C4
++        Multiplicative Abelian group isomorphic to Z x Z x C2 x C3 x C4
+         sage: G.gens_orders()
+         (0, 0, 2, 3, 4)
+ 
+@@ -404,7 +442,7 @@
+         sage: AbelianGroup(2, [2,3,4])
+         Traceback (most recent call last):
+         ...
+-        ValueError: gens_orders (=[2, 3, 4]) must have length n (=2)
++        ValueError: gens_orders (=(2, 3, 4)) must have length n (=2)
+     """
+     gens_orders, names = _normalize(n, gens_orders, names)
+     M = AbelianGroup_class(gens_orders, names)
+@@ -418,7 +456,7 @@
+     
+         sage: from sage.groups.abelian_gps.abelian_group import is_AbelianGroup
+         sage: F = AbelianGroup(5,[5,5,7,8,9],names = list("abcde")); F
+-        Multiplicative Abelian Group isomorphic to C5 x C5 x C7 x C8 x C9
++        Multiplicative Abelian group isomorphic to C5 x C5 x C7 x C8 x C9
+         sage: is_AbelianGroup(F)
+         True
+         sage: is_AbelianGroup(AbelianGroup(7, [3]*7))
+@@ -451,19 +489,15 @@
+         True
+ 
+         sage: F = AbelianGroup(5,[5,5,7,8,9],names = list("abcde")); F
+-        Multiplicative Abelian Group isomorphic to C5 x C5 x C7 x C8 x C9
++        Multiplicative Abelian group isomorphic to C5 x C5 x C7 x C8 x C9
+         sage: F = AbelianGroup(5,[2, 4, 12, 24, 120],names = list("abcde")); F
+-        Multiplicative Abelian Group isomorphic to C2 x C4 x C12 x C24 x C120
++        Multiplicative Abelian group isomorphic to C2 x C4 x C12 x C24 x C120
+         sage: F.elementary_divisors()
+         (2, 4, 12, 24, 120)
+ 
+         sage: F.category()
+         Category of groups
+ 
+-        sage: G = AbelianGroup([0,5,0,7],names = list("abcd")); G
+-        Multiplicative Abelian Group isomorphic to Z x C5 x Z x C7
+-        sage: TestSuite(G).run()
+-
+     TESTS::
+ 
+         sage: AbelianGroup([]).gens_orders()
+@@ -478,28 +512,24 @@
+     Element = AbelianGroupElement
+ 
+     def __init__(self, generator_orders, names):
++        """
++        The Python constructor
++
++        TESTS::
++
++            sage: G = AbelianGroup([0,5,0,7],names = list("abcd")); G
++            Multiplicative Abelian group isomorphic to Z x C5 x Z x C7
++            sage: TestSuite(G).run()
++        """
++        assert isinstance(names, (basestring, tuple))
++        assert isinstance(generator_orders, tuple)
++        assert all(isinstance(order,Integer) for order in generator_orders)
++        self._gens_orders = generator_orders
+         n = ZZ(len(generator_orders))
+-        if n < 0:
+-            raise ValueError, "n (=%s) must be nonnegative."%n
+-        self._gens_orders = tuple(ZZ(i) for i in generator_orders)
+-
+-        # *now* define ngens
+         names = self.normalize_names(n, names)
+         self._assign_names(names)
+         AbelianGroupBase.__init__(self) # TODO: category=CommutativeGroups()
+ 
+-    def _an_element_(self):
+-        """
+-        Return a random element
+-
+-        EXAMPLES:
+-
+-            sage: G = AbelianGroup([2,3,4,5])
+-            sage: G.an_element()
+-            f0*f1*f2*f3
+-        """
+-        return prod(self.gens())
+-
+     def is_isomorphic(left, right):
+         """
+         Check whether ``left`` and ``right`` are isomorphic
+@@ -528,6 +558,22 @@
+     __eq__ = is_isomorphic
+ 
+     def __ne__(left, right):
++        """
++        Check whether ``left`` and ``right`` are not isomorphic
++
++        OUTPUT:
++
++        Boolean.
++
++        EXAMPLES::
++
++            sage: G1 = AbelianGroup([2,3,4,5])
++            sage: G2 = AbelianGroup([2,3,4,5,1])
++            sage: G1 != G2
++            False
++            sage: G1.__ne__(G2)
++            False
++        """
+         return not left.is_isomorphic(right)
+ 
+     def is_subgroup(left, right):
+@@ -557,6 +603,16 @@
+     __le__ = is_subgroup
+ 
+     def __ge__(left, right):
++        """
++        Test whether ``right`` is a subgroup of ``left``
++
++        EXAMPLE::
++
++            sage: G.<a, b> = AbelianGroup(2)
++            sage: H.<c> = AbelianGroup(1)
++            sage: G >= H
++            False
++        """
+         return right.__le__(left)
+     
+     def __lt__(left, right):
+@@ -573,6 +629,16 @@
+         return left <= right and left != right
+     
+     def __gt__(left, right):
++        """
++        Test whether ``right`` is a strict subgroup of ``left``
++
++        EXAMPLE::
++
++            sage: G.<a, b> = AbelianGroup(2)
++            sage: H.<c> = AbelianGroup(1)
++            sage: G > H
++            False
++        """
+         return left >= right and left != right
+     
+     def is_trivial(self):
+@@ -689,7 +755,7 @@
+             (6,)
+             sage: G = AbelianGroup(2,[2,6])
+             sage: G
+-            Multiplicative Abelian Group isomorphic to C2 x C6
++            Multiplicative Abelian group isomorphic to C2 x C6
+             sage: G.gens_orders()
+             (2, 6)
+             sage: G.elementary_divisors()
+@@ -715,11 +781,11 @@
+         EXAMPLES::
+         
+             sage: G = AbelianGroup([2,3,7]); G
+-            Multiplicative Abelian Group isomorphic to C2 x C3 x C7
++            Multiplicative Abelian group isomorphic to C2 x C3 x C7
+             sage: G.exponent()
+             42
+             sage: G = AbelianGroup([2,4,6]); G
+-            Multiplicative Abelian Group isomorphic to C2 x C4 x C6
++            Multiplicative Abelian group isomorphic to C2 x C4 x C6
+             sage: G.exponent()
+             12
+         """
+@@ -744,6 +810,23 @@
+         return self(1)
+     
+     def _group_notation(self, eldv):
++        """
++        Return abstract group notation for generator orders ``eldv``
++
++        INPUT:
++
++        - ``eldv`` -- iterable of integers.
++
++        OUTPUT:
++
++        String.
++
++        EXAMPLES::
++
++            sage: G = AbelianGroup([2,2])
++            sage: G._group_notation([0,1,2,3])
++            'Z x C1 x C2 x C3'
++        """
+         v = []
+         for x in eldv:
+             if x:
+@@ -780,7 +863,7 @@
+         Only works for finite groups::
+         
+             sage: G = AbelianGroup(3,[0,3,4],names="abc"); G
+-            Multiplicative Abelian Group isomorphic to Z x C3 x C4
++            Multiplicative Abelian group isomorphic to Z x C3 x C4
+             sage: G._gap_init_()
+             Traceback (most recent call last):
+             ...
+@@ -890,7 +973,7 @@
+         factors of the group. Use :meth:`gens_orders` instead::
+ 
+             sage: J = AbelianGroup([2,0,3,2,4]);  J
+-            Multiplicative Abelian Group isomorphic to C2 x Z x C3 x C2 x C4
++            Multiplicative Abelian group isomorphic to C2 x Z x C3 x C2 x C4
+             sage: J.invariants()    # deprecated
+             (2, 0, 3, 2, 4)
+             sage: J.gens_orders()   # use this instead
+@@ -963,7 +1046,7 @@
+             sage: T.is_cyclic()
+             True            
+             sage: T = AbelianGroup(1,[0]); T
+-            Multiplicative Abelian Group isomorphic to Z
++            Multiplicative Abelian group isomorphic to Z
+             sage: T.is_cyclic()
+             True
+             sage: B = AbelianGroup([3,4,5])
+@@ -1016,7 +1099,7 @@
+         EXAMPLES::
+         
+             sage: G = AbelianGroup(2,[2,3]); G
+-            Multiplicative Abelian Group isomorphic to C2 x C3
++            Multiplicative Abelian group isomorphic to C2 x C3
+             sage: G.permutation_group()
+             Permutation Group with generators [(3,4,5), (1,2)]
+         """
+@@ -1045,8 +1128,8 @@
+         EXAMPLES::
+         
+             sage: G = AbelianGroup([2,3,9])
+-            sage: G.random_element()   # random output
+-            f0*f1^2*f2
++            sage: G.random_element()
++            f1^2
+         """
+         from sage.misc.prandom import randint
+         result = self.one()
+@@ -1060,12 +1143,18 @@
+     def _repr_(self):
+         """
+         Return a string representation of ``self``.
+-        """
++
++        EXAMPLES::
++
++            sage: G = AbelianGroup([2,3,9])
++            sage: G._repr_()
++            'Multiplicative Abelian group isomorphic to C2 x C3 x C9'
++       """
+         eldv = self.gens_orders()
+         if len(eldv) == 0:
+-            return "Trivial Abelian Group"
++            return "Trivial Abelian group"
+         g = self._group_notation(eldv)
+-        return "Multiplicative Abelian Group isomorphic to " + g
++        return "Multiplicative Abelian group isomorphic to " + g
+ 
+     def subgroup(self, gensH, names="f"):
+         """
+@@ -1080,30 +1169,22 @@
+          EXAMPLES::
+          
+              sage: G.<a,b,c> = AbelianGroup(3, [2,3,4]); G
+-             Multiplicative Abelian Group isomorphic to C2 x C3 x C4
++             Multiplicative Abelian group isomorphic to C2 x C3 x C4
+              sage: H = G.subgroup([a*b,a]); H
+-             Multiplicative Abelian Group isomorphic to C2 x C3, which is the subgroup of
+-             Multiplicative Abelian Group isomorphic to C2 x C3 x C4
+-             generated by a*b, a
++             Multiplicative Abelian subgroup isomorphic to C2 x C3 generated by {a*b, a}
+              sage: H < G
+              True
+              sage: F = G.subgroup([a,b^2])
+              sage: F
+-             Multiplicative Abelian Group isomorphic to C2 x C3, which is the subgroup of
+-             Multiplicative Abelian Group isomorphic to C2 x C3 x C4
+-             generated by a, b^2
++             Multiplicative Abelian subgroup isomorphic to C2 x C3 generated by {a, b^2}
+              sage: F.gens()
+              (a, b^2)
+              sage: F = AbelianGroup(5,[30,64,729],names = list("abcde"))
+              sage: a,b,c,d,e = F.gens()
+              sage: F.subgroup([a,b])
+-             Multiplicative Abelian Group isomorphic to Z x Z, which is
+-             the subgroup of Multiplicative Abelian Group isomorphic to
+-             Z x Z x C30 x C64 x C729 generated by a, b
++             Multiplicative Abelian subgroup isomorphic to Z x Z generated by {a, b}
+              sage: F.subgroup([c,e])
+-             Multiplicative Abelian Group isomorphic to C2 x C3 x C5 x
+-             C729, which is the subgroup of Multiplicative Abelian
+-             Group isomorphic to Z x Z x C30 x C64 x C729 generated by c, e
++             Multiplicative Abelian subgroup isomorphic to C2 x C3 x C5 x C729 generated by {c, e}
+          """
+         G = self
+         gensH = tuple(gensH)
+@@ -1114,31 +1195,27 @@
+                 raise TypeError('Subgroup generators must belong to the given group.')
+         return AbelianGroup_subgroup(self, gensH, names)
+ 
++    @cached_method
+     def list(self):
+         """
+-        Return list of all elements of this group.
++        Return tuple of all elements of this group.
+         
+         EXAMPLES::
+         
+             sage: G = AbelianGroup([2,3], names = "ab")
+             sage: G.list()
+-            [1, b, b^2, a, a*b, a*b^2]
++            (1, b, b^2, a, a*b, a*b^2)
+         
+         ::
+         
+             sage: G = AbelianGroup([]); G
+-            Trivial Abelian Group
++            Trivial Abelian group
+             sage: G.list()
+-            [1]
++            (1,)
+         """
+-        try:
+-            return list(self._list)
+-        except AttributeError:
+-            pass
+         if not(self.is_finite()):
+            raise NotImplementedError, "Group must be finite"
+-        self._list = list(self.__iter__())
+-        return list(self._list)
++        return tuple(self.__iter__())
+      
+     def __iter__(self):
+         """
+@@ -1163,7 +1240,7 @@
+             [1]
+             sage: G = AbelianGroup([])
+             sage: G.list()
+-            [1]
++            (1,)
+             sage: list(G)
+             [1]
+         """
+@@ -1199,26 +1276,17 @@
+         EXAMPLES::
+ 
+             sage: AbelianGroup([2,3]).subgroups()
+-            [Multiplicative Abelian Group isomorphic to C2 x C3, which is the subgroup of
+-             Multiplicative Abelian Group isomorphic to C2 x C3
+-             generated by f0*f1^2,
+-             Multiplicative Abelian Group isomorphic to C2, which is the subgroup of
+-             Multiplicative Abelian Group isomorphic to C2 x C3
+-             generated by f0,
+-             Multiplicative Abelian Group isomorphic to C3, which is the subgroup of
+-             Multiplicative Abelian Group isomorphic to C2 x C3
+-             generated by f1,
+-             Trivial Abelian Group, which is the subgroup of
+-             Multiplicative Abelian Group isomorphic to C2 x C3
+-             generated by 1]
+-
++            [Multiplicative Abelian subgroup isomorphic to C2 x C3 generated by {f0*f1^2},
++             Multiplicative Abelian subgroup isomorphic to C2 generated by {f0},
++             Multiplicative Abelian subgroup isomorphic to C3 generated by {f1},
++             Trivial Abelian subgroup]
+             sage: len(AbelianGroup([2,4,8]).subgroups())
+             81
+ 
+         TESTS::
+ 
+             sage: AbelianGroup([]).subgroups()
+-            [Trivial Abelian Group]
++            [Trivial Abelian group]
+         """
+         if not self.is_finite(): raise ValueError, "Group must be finite"
+         from sage.misc.misc import verbose
+@@ -1276,13 +1344,11 @@
+ 
+             sage: G = AbelianGroup([4,4])
+             sage: G.subgroup( [ G([1,0]), G([1,2]) ])
+-            Multiplicative Abelian Group isomorphic to C2 x C4, which is the subgroup of
+-            Multiplicative Abelian Group isomorphic to C4 x C4
+-            generated by f0, f0*f1^2
++            Multiplicative Abelian subgroup isomorphic to C2 x C4
++            generated by {f0, f0*f1^2}
+             sage: AbelianGroup([4,4]).subgroup_reduced( [ [1,0], [1,2] ])
+-            Multiplicative Abelian Group isomorphic to C2 x C4, which is the subgroup of
+-            Multiplicative Abelian Group isomorphic to C4 x C4
+-            generated by f1^2, f0
++            Multiplicative Abelian subgroup isomorphic to C2 x C4
++            generated by {f1^2, f0}
+         """
+         from sage.matrix.constructor import matrix
+         d = self.ngens()
+@@ -1318,47 +1384,21 @@
+             sage: F = AbelianGroup(5,[30,64,729],names = list("abcde"))
+             sage: a,b,c,d,e = F.gens()
+             sage: F.subgroup([a^3,b])
+-            Multiplicative Abelian Group isomorphic to Z x Z, which is the subgroup of
+-            Multiplicative Abelian Group isomorphic to Z x Z x C30 x C64 x C729
+-            generated by a^3, b
+-        
++            Multiplicative Abelian subgroup isomorphic to Z x Z generated by {a^3, b}
+             sage: F.subgroup([c])
+-            Multiplicative Abelian Group isomorphic to C2 x C3 x C5, which is the subgroup of
+-            Multiplicative Abelian Group isomorphic to Z x Z x C30 x C64 x C729
+-            generated by c
+-        
+-            sage: F.subgroup([a,c])
+-            Multiplicative Abelian Group isomorphic to C2 x C3 x C5 x
+-            Z, which is the subgroup of Multiplicative Abelian Group
+-            isomorphic to Z x Z x C30 x C64 x C729 generated by a, c
+-        
+-            sage: F.subgroup([a,b*c])
+-            Multiplicative Abelian Group isomorphic to Z x Z, which is
+-            the subgroup of Multiplicative Abelian Group isomorphic to
+-            Z x Z x C30 x C64 x C729 generated by a, b*c
+-        
+-            sage: F.subgroup([b*c,d])
+-            Multiplicative Abelian Group isomorphic to C64 x Z, which
+-            is the subgroup of Multiplicative Abelian Group isomorphic
+-            to Z x Z x C30 x C64 x C729 generated by b*c, d
+-        
+-            sage: F.subgroup([a*b,c^6,d],names = list("xyz"))
+-            Multiplicative Abelian Group isomorphic to C5 x C64 x Z,
+-            which is the subgroup of Multiplicative Abelian Group
+-            isomorphic to Z x Z x C30 x C64 x C729 generated by a*b,
+-            c^6, d
+-        
++            Multiplicative Abelian subgroup isomorphic to C2 x C3 x C5 generated by {c}
++            sage: F.subgroup([a, c])
++            Multiplicative Abelian subgroup isomorphic to C2 x C3 x C5 x Z generated by {a, c}
++            sage: F.subgroup([a, b*c])
++            Multiplicative Abelian subgroup isomorphic to Z x Z generated by {a, b*c}
++            sage: F.subgroup([b*c, d])
++            Multiplicative Abelian subgroup isomorphic to C64 x Z generated by {b*c, d}
++            sage: F.subgroup([a*b, c^6, d],names=list("xyz"))
++            Multiplicative Abelian subgroup isomorphic to C5 x C64 x Z generated by {a*b, c^6, d}
+             sage: H.<x,y,z> = F.subgroup([a*b, c^6, d]); H
+-            Multiplicative Abelian Group isomorphic to C5 x C64 x Z,
+-            which is the subgroup of Multiplicative Abelian Group
+-            isomorphic to Z x Z x C30 x C64 x C729 generated by a*b,
+-            c^6, d
+-        
+-            sage: G = F.subgroup([a*b,c^6,d],names = list("xyz")); G
+-            Multiplicative Abelian Group isomorphic to C5 x C64 x Z,
+-            which is the subgroup of Multiplicative Abelian Group
+-            isomorphic to Z x Z x C30 x C64 x C729 generated by a*b,
+-            c^6, d
++            Multiplicative Abelian subgroup isomorphic to C5 x C64 x Z generated by {a*b, c^6, d}
++            sage: G = F.subgroup([a*b, c^6, d],names = list("xyz")); G
++            Multiplicative Abelian subgroup isomorphic to C5 x C64 x Z generated by {a*b, c^6, d}
+             sage: x,y,z = G.gens()
+             sage: x.order()
+             +Infinity
+@@ -1369,21 +1409,13 @@
+             sage: A = AbelianGroup(5,[3, 5, 5, 7, 8], names = "abcde")
+             sage: a,b,c,d,e = A.gens()
+             sage: A.subgroup([a,b])
+-            Multiplicative Abelian Group isomorphic to C3 x C5, which is the subgroup of
+-            Multiplicative Abelian Group isomorphic to C3 x C5 x C5 x C7 x C8
+-            generated by a, b
++            Multiplicative Abelian subgroup isomorphic to C3 x C5 generated by {a, b}
+             sage: A.subgroup([a,b,c,d^2,e])
+-            Multiplicative Abelian Group isomorphic to C3 x C5 x C5 x C7 x C8, which is the subgroup of
+-            Multiplicative Abelian Group isomorphic to C3 x C5 x C5 x C7 x C8
+-            generated by a, b, c, d^2, e
+-            sage: A.subgroup([a,b,c,d^2,e^2])
+-            Multiplicative Abelian Group isomorphic to C3 x C4 x C5 x C5 x C7, which is the subgroup of
+-            Multiplicative Abelian Group isomorphic to C3 x C5 x C5 x C7 x C8
+-            generated by a, b, c, d^2, e^2
+-            sage: B = A.subgroup([a^3,b,c,d,e^2]); B
+-            Multiplicative Abelian Group isomorphic to C4 x C5 x C5 x C7, which is the subgroup of
+-            Multiplicative Abelian Group isomorphic to C3 x C5 x C5 x C7 x C8
+-            generated by b, c, d, e^2
++            Multiplicative Abelian subgroup isomorphic to C3 x C5 x C5 x C7 x C8 generated by {a, b, c, d^2, e}
++            sage: A.subgroup([a, b, c, d^2, e^2])
++            Multiplicative Abelian subgroup isomorphic to C3 x C4 x C5 x C5 x C7 generated by {a, b, c, d^2, e^2}
++            sage: B = A.subgroup([a^3, b, c, d, e^2]); B
++            Multiplicative Abelian subgroup isomorphic to C4 x C5 x C5 x C7 generated by {b, c, d, e^2}
+             sage: B.gens_orders()
+             (4, 5, 5, 7)
+             sage: A = AbelianGroup(4,[1009, 2003, 3001, 4001], names = "abcd")
+@@ -1398,19 +1430,15 @@
+             sage: A = AbelianGroup(4,[1008, 2003, 3001, 4001], names = "abcd")
+             sage: a,b,c,d = A.gens()
+             sage: B = A.subgroup([a^3,b,c,d]); B
+-            Multiplicative Abelian Group isomorphic to C3 x C7 x C16 x
+-            C2003 x C3001 x C4001, which is the subgroup of
+-            Multiplicative Abelian Group isomorphic to C1008 x C2003 x
+-            C3001 x C4001 generated by a^3, b, c, d
++            Multiplicative Abelian subgroup isomorphic
++            to C3 x C7 x C16 x C2003 x C3001 x C4001 generated by {a^3, b, c, d}
+         
+         Infinite groups can also be handled::
+         
+             sage: G = AbelianGroup([3,4,0], names = "abc")
+             sage: a,b,c = G.gens()
+-            sage: F = G.subgroup([a,b^2,c]); F
+-            Multiplicative Abelian Group isomorphic to C2 x C3 x Z,
+-            which is the subgroup of Multiplicative Abelian Group
+-            isomorphic to C3 x C4 x Z generated by a, b^2, c
++            sage: F = G.subgroup([a, b^2, c]); F
++            Multiplicative Abelian subgroup isomorphic to C2 x C3 x Z generated by {a, b^2, c}
+         
+             sage: F.gens_orders()
+             (2, 3, 0)
+@@ -1473,7 +1501,7 @@
+         if Hgens0 != []:
+             for x in Hgens0:
+                invs.append(0)
+-        #print Hgensf, invs, invs0
++        invs = tuple(ZZ(i) for i in invs)
+         AbelianGroup_class.__init__(self, invs, names)
+ 
+     def __contains__(self, x):
+@@ -1520,12 +1548,23 @@
+     def ambient_group(self):
+         """
+         Return the ambient group related to self.
++
++        OUTPUT:
++
++        A multiplicative Abelian group.
++
++        EXAMPLES::
++
++            sage: G.<a,b,c> = AbelianGroup([2,3,4])
++            sage: H = G.subgroup([a, b^2])
++            sage: H.ambient_group() is G
++            True
+         """
+         return self._ambient_group
+ 
+     def equals(left, right):
+         """
+-        Check whether ``left`` and ``right`` are the same subgroup.
++        Check whether ``left`` and ``right`` are the same (sub)group.
+ 
+         INPUT:
+ 
+@@ -1533,17 +1572,18 @@
+ 
+         OUTPUT:
+ 
+-        Boolean. Whether ``left`` and ``right`` are isomorphic as abelian groups.
++        Boolean. If ``right`` is a subgroup, test whether ``left`` and
++        ``right`` are the same subset of the ambient group. If
++        ``right`` is not a subgroup, test whether they are isomorphic
++        groups, see :meth:`~AbelianGroup_class.is_isomorphic`.
+ 
+         EXAMPLES::
+         
+             sage: G = AbelianGroup(3, [2,3,4], names="abc"); G
+-            Multiplicative Abelian Group isomorphic to C2 x C3 x C4
++            Multiplicative Abelian group isomorphic to C2 x C3 x C4
+             sage: a,b,c = G.gens()
+-            sage: F=G.subgroup([a,b^2]); F
+-            Multiplicative Abelian Group isomorphic to C2 x C3, which is the subgroup of
+-            Multiplicative Abelian Group isomorphic to C2 x C3 x C4
+-            generated by a, b^2
++            sage: F = G.subgroup([a,b^2]); F
++            Multiplicative Abelian subgroup isomorphic to C2 x C3 generated by {a, b^2}
+             sage: F<G
+             True
+         
+@@ -1565,10 +1605,8 @@
+         try:
+             right_ambient = right.ambient_group()
+         except AttributeError:
+-            try:
+-                return right.__eq__(left)
+-            except AttributeError:
+-                return False
++            # right is not a subgroup
++            return left.is_isomorphic(right)
+         if left_ambient is not right_ambient:
+             return False
+         return left <= right and right <= left
+@@ -1582,32 +1620,37 @@
+         EXAMPLES::
+ 
+             sage: G.<a,b> = AbelianGroup(2)
++            sage: G._repr_()
++            'Multiplicative Abelian group isomorphic to Z x Z'
+             sage: A = G.subgroup([a])
+             sage: A._repr_()
+-            'Multiplicative Abelian Group isomorphic to Z, which is the subgroup of\nMultiplicative Abelian Group isomorphic to Z x Z\ngenerated by a'
++            'Multiplicative Abelian subgroup isomorphic to Z generated by {a}'
+        """
+-        s = AbelianGroup_class._repr_(self)
+-        s += ', which is the subgroup of\n'
+-        s += self.ambient_group()._repr_()
+-        s += '\ngenerated by '
++        eldv = self.gens_orders()
+         if self.is_trivial():
+-            s += '1'
+-        else:
+-            s += ', '.join(map(str, self.gens()))
++            return "Trivial Abelian subgroup"
++        s = 'Multiplicative Abelian subgroup isomorphic to '
++        s += self._group_notation(eldv)
++        s += ' generated by '
++        s += '{' + ', '.join(map(str, self.gens())) + '}'
+         return s
+        
+-    def invs(self):
+-        """
+-        Return the invariants for this subgroup.
+-        """
+-        G = self.ambient_group()
+-        invsG = G.invariants()
+-        Hgap = self._gap_init_()
+-        raise Exception # WTF?
+-        
+     def gens(self):
+         """
+         Return the generators for this subgroup.
++
++        OUTPUT:
++
++        A tuple of group elements generating the subgroup.
++
++        EXAMPLES::
++
++            sage: G.<a,b> = AbelianGroup(2)
++            sage: A = G.subgroup([a])
++            sage: G.gens()
++            (a, b)
++            sage: A.gens()
++            (a,)
+         """
+         return self._gens
+ 
+diff --git a/sage/groups/abelian_gps/abelian_group_element.py b/sage/groups/abelian_gps/abelian_group_element.py
+--- a/sage/groups/abelian_gps/abelian_group_element.py
++++ b/sage/groups/abelian_gps/abelian_group_element.py
+@@ -102,7 +102,7 @@
+         EXAMPLES::
+         
+             sage: G = AbelianGroup(3,[2,3,4],names="abc"); G
+-            Multiplicative Abelian Group isomorphic to C2 x C3 x C4
++            Multiplicative Abelian group isomorphic to C2 x C3 x C4
+             sage: a,b,c=G.gens()
+             sage: Gp = G.permutation_group(); Gp
+             Permutation Group with generators [(6,7,8,9), (3,4,5), (1,2)]
+@@ -132,18 +132,6 @@
+         gp = Gp(pg)
+         return gp
+ 
+-    def random_element(self):
+-        """
+-        Return a random element of this dual group.
+-        """
+-        if not(self.is_finite()):
+-            raise NotImplementedError, "Only implemented for finite groups"
+-        gens = self.gens()
+-        g = gens[0]**0
+-        for i in range(len(gens)):
+-            g = g*gens[i]**(random(gens[i].order()))
+-        return g
+-
+     def word_problem(self, words):
+         """
+         TODO - this needs a rewrite - see stuff in the matrix_grp
+diff --git a/sage/groups/abelian_gps/abelian_group_morphism.py b/sage/groups/abelian_gps/abelian_group_morphism.py
+--- a/sage/groups/abelian_gps/abelian_group_morphism.py
++++ b/sage/groups/abelian_gps/abelian_group_morphism.py
+@@ -35,6 +35,9 @@
+     A set-theoretic map between AbelianGroups.
+     """
+     def __init__(self, parent):
++        """
++        The Python constructor.
++        """
+         Morphism.__init__(self, parent)
+ 
+     def _repr_type(self):
+@@ -52,7 +55,7 @@
+     def _repr_defn(self):
+         return "Identity map of "+str(X)
+ 
+-class AbelianGroupMorphism:
++class AbelianGroupMorphism(Morphism):
+     """
+     Some python code for wrapping GAP's GroupHomomorphismByImages
+     function for abelian groups. Returns "fail" if gens does not
+@@ -62,10 +65,10 @@
+     EXAMPLES::
+     
+         sage: G = AbelianGroup(3,[2,3,4],names="abc"); G
+-        Multiplicative Abelian Group isomorphic to C2 x C3 x C4
++        Multiplicative Abelian group isomorphic to C2 x C3 x C4
+         sage: a,b,c = G.gens()
+         sage: H = AbelianGroup(2,[2,3],names="xy"); H
+-        Multiplicative Abelian Group isomorphic to C2 x C3
++        Multiplicative Abelian group isomorphic to C2 x C3
+         sage: x,y = H.gens()
+     
+     ::
+@@ -97,6 +100,8 @@
+ #TypeError: Sorry, the list [a*b, c^2] must generate G.
+ 
+     def __init__(self, G, H, genss, imgss ):
++        from sage.categories.homset import Hom
++        Morphism.__init__(self, Hom(G, H))
+         if len(genss) != len(imgss):
+             raise TypeError, "Sorry, the lengths of %s, %s must be equal."%(genss,imgss)
+         self._domain = G
+@@ -124,23 +129,23 @@
+         EXAMPLES::
+         
+             sage: G = AbelianGroup(3,[2,3,4],names="abc"); G
+-            Multiplicative Abelian Group isomorphic to C2 x C3 x C4
++            Multiplicative Abelian group isomorphic to C2 x C3 x C4
+             sage: a,b,c = G.gens()
+             sage: H = AbelianGroup(2,[2,3],names="xy"); H
+-            Multiplicative Abelian Group isomorphic to C2 x C3
++            Multiplicative Abelian group isomorphic to C2 x C3
+             sage: x,y = H.gens()
+             sage: phi = AbelianGroupMorphism(H,G,[x,y],[a,b])
+             sage: phi._gap_init_()
+             'phi := GroupHomomorphismByImages(G,H,[x, y],[a, b])'
+         """
+         G  = (self.domain())._gap_init_()
+-        H  = (self.range())._gap_init_()
++        H  = (self.codomain())._gap_init_()
+         # print G,H
+         s3 = 'G:=%s; H:=%s'%(G,H)
+         #print s3,"\n"
+         gap.eval(s3)
+         gensG = self.domain().variable_names()                    ## the Sage group generators
+-        gensH = self.range().variable_names()
++        gensH = self.codomain().variable_names()
+         #print gensG, gensH
+         s1 = "gensG := GeneratorsOfGroup(G)"          ## the GAP group generators
+         gap.eval(s1)
+@@ -163,15 +168,6 @@
+     def _repr_type(self):
+         return "AbelianGroup"
+ 
+-    def domain(self):
+-        return self._domain
+-
+-    def range(self):
+-        return self._codomain
+-
+-    def codomain(self):
+-        return self._codomain
+-
+     def kernel(self):
+         """
+         Only works for finite groups.
+@@ -182,10 +178,10 @@
+         EXAMPLES::
+         
+             sage: H = AbelianGroup(3,[2,3,4],names="abc"); H
+-            Multiplicative Abelian Group isomorphic to C2 x C3 x C4
++            Multiplicative Abelian group isomorphic to C2 x C3 x C4
+             sage: a,b,c = H.gens()