# HG changeset patch
# User William Stein <wstein@gmail.com>
# Date 1227497767 28800
# Node ID 334d17e4247e08c16e57b02c2b0245f4171338ee
# Parent  a0b4c7f7ead9aa49975d5c361d9b9fae1a05054b
trac #4601 -- optional magma interface -- fix all broken optional doctests by introducing _magma_init_(self, magma) signature

diff -r a0b4c7f7ead9 -r 334d17e4247e sage/calculus/calculus.py
--- a/sage/calculus/calculus.py	Sun Nov 23 03:08:12 2008 -0800
+++ b/sage/calculus/calculus.py	Sun Nov 23 19:36:07 2008 -0800
@@ -1187,7 +1187,7 @@
     def _maple_init_(self):
         return self._sys_init_('maple')
 
-    def _magma_init_(self):
+    def _magma_init_(self, magma):
         """
         Return string representation in Magma of this symbolic expression.
 
@@ -1197,7 +1197,7 @@
         EXAMPLES:
             sage: x = var('x')                      
             sage: f = sin(cos(x^2) + log(x))
-            sage: f._magma_init_()
+            sage: f._magma_init_(magma)
             '"sin(cos(x^2) + log(x))"'
             sage: magma(f)                         # optional - magma
             sin(cos(x^2) + log(x))
@@ -4095,10 +4095,7 @@
     try:
         return x.__getattribute__('_%s_init_'%system)()
     except AttributeError:
-        try:
-            return x._system_init_(system)
-        except AttributeError:
-            return repr(x)
+        return repr(x)
 
 class SymbolicConstant(Symbolic_object):
     def __init__(self, x):
diff -r a0b4c7f7ead9 -r 334d17e4247e sage/crypto/mq/mpolynomialsystem.py
--- a/sage/crypto/mq/mpolynomialsystem.py	Sun Nov 23 03:08:12 2008 -0800
+++ b/sage/crypto/mq/mpolynomialsystem.py	Sun Nov 23 19:36:07 2008 -0800
@@ -43,7 +43,6 @@
 from sage.matrix.constructor import Matrix
 
 from sage.interfaces.singular import singular
-from sage.interfaces.magma import magma
 
 
 def is_MPolynomialSystem(F):
@@ -408,7 +407,7 @@
         """
         return singular.ideal(self._gens)
 
-    def _magma_(self):
+    def _magma_(self, magma):
         """
         Return MAGMA ideal representation of self.
 
@@ -416,7 +415,7 @@
             sage: sr = mq.SR(allow_zero_inversions=True,gf2=True)
             sage: F,s = sr.polynomial_system()
             sage: R1 = F.round(1)
-            sage: R1._magma_()                               # optional - magma
+            sage: magma(R1)                               # optional - magma
             Ideal of Polynomial ring of rank 20 over GF(2)
             Graded Reverse Lexicographical Order
             Variables: k100, k101, k102, k103, x100, x101, x102, x103, w100, w101, w102, w103, s000, s001, s002, s003, k000, k001, k002, k003
@@ -826,7 +825,7 @@
 
     def _singular_(self):
         """
-        Return SINGULAR ideal representation of this system.
+        Return Singular ideal representation of this system.
 
 	EXAMPLE:
 	    sage: P.<a,b,c,d> = PolynomialRing(GF(127))
@@ -841,14 +840,21 @@
         """
         return singular.ideal(list(self))
 
-    def _magma_(self):
+    def _magma_(self, magma):
         """
-        Return MAGMA ideal representation of this system as an ideal.
+        Return Magma ideal representation of this system as an ideal.
 
 	EXAMPLE:
             sage: sr = mq.SR(allow_zero_inversions=True,gf2=True)
             sage: F,s = sr.polynomial_system()
-            sage: F._magma_()                                       # optional - magma
+            sage: magma(F)                                       # optional - magma
+            Ideal of Polynomial ring of rank 20 over GF(2)
+            Graded Reverse Lexicographical Order
+            Variables: k100, k101, k102, k103, x100, x101, x102, x103, w100, w101, w102, w103, s000, s001, s002, s003, k000, k001, k002, k003
+            Basis:
+            [
+            ...
+            ]
         """
         return magma.ideal(list(self))
 
diff -r a0b4c7f7ead9 -r 334d17e4247e sage/groups/perm_gps/permgroup.py
--- a/sage/groups/perm_gps/permgroup.py	Sun Nov 23 03:08:12 2008 -0800
+++ b/sage/groups/perm_gps/permgroup.py	Sun Nov 23 19:36:07 2008 -0800
@@ -320,7 +320,7 @@
         """
         return self._gap_string
 
-    def _magma_init_(self):
+    def _magma_init_(self, magma):
         r"""
         Returns a string showing how to declare / intialize self in Magma.
 
@@ -329,7 +329,7 @@
         Magma, one would type the string below to construct the group.
             sage: A4 = PermutationGroup([[(1,2,3)],[(2,3,4)]]); A4
             Permutation Group with generators [(2,3,4), (1,2,3)]
-            sage: A4._magma_init_()
+            sage: A4._magma_init_(magma)
             'PermutationGroup<4 | (2,3,4), (1,2,3)>'
         """
         g = str(self.gens())[1:-1]
diff -r a0b4c7f7ead9 -r 334d17e4247e sage/interfaces/magma.py
--- a/sage/interfaces/magma.py	Sun Nov 23 03:08:12 2008 -0800
+++ b/sage/interfaces/magma.py	Sun Nov 23 19:36:07 2008 -0800
@@ -95,7 +95,7 @@
     ]
     
 In SAGE/Python (and sort of C++) coercion of an element x into a
-structure S is denoted by S(x).  This also works for the MAGMA interface:
+structure S is denoted by S(x).  This also works for the Magma interface:
  
     sage: G = magma.DirichletGroup(20)                                    # optional - magma
     sage: G.AssignNames(['a', 'b'])                                       # optional - magma
@@ -107,7 +107,7 @@
     sage: print e.Modulus()                                               # optional - magma
     40
 
-We coerce some polynomial rings into MAGMA:
+We coerce some polynomial rings into Magma:
 
     sage: R.<y> = PolynomialRing(QQ)
     sage: S = magma(R)                                                    # optional - magma
@@ -185,9 +185,9 @@
     a new Magma object, and \code{magma.eval(...)} to run a string
     using Magma (and get the result back as a string).
 
-    NOTE: If you do not own a local copy of MAGMA, try using the
+    NOTE: If you do not own a local copy of Magma, try using the
     \code{magma\_free} command instead, which uses the free demo web
-    interface to MAGMA.
+    interface to Magma.
 
     EXAMPLES:
 
@@ -209,8 +209,8 @@
             logfile -- output logged to this file
             server -- address of remote server
             user_config -- if True, then local user configuration files
-                           will be read by MAGMA.  If False (the default),
-                           then MAGMA is started with the -n option which
+                           will be read by Magma.  If False (the default),
+                           then Magma is started with the -n option which
                            supresses user configuration files.
 
         EXAMPLES:
@@ -476,8 +476,8 @@
         Coerce x into this Magma interpreter interface.
 
         INPUT:
-            x -- object
-            gens -- string; names of generators of self, separated by commas
+            x     -- object
+            gens  -- string; names of generators of self, separated by commas
 
         OUTPUT:
             MagmaElement
@@ -502,13 +502,63 @@
             True
             sage: a.parent() is m       # optional - magma
             False
+
+        We test caching:
+            sage: R.<x> =  ZZ[]                     # optional - magma
+            sage: magma(R) is magma(R)              # optional - magma
+            True
+            sage: m = Magma()                       # optional - magma
+            sage: m(R)                              # optional - magma
+            Univariate Polynomial Ring in x over Integer Ring
+            sage: m(R) is magma(R)                  # optional - magma
+            False
+            sage: R._magma_cache                    # optional - magma
+            {Magma: Univariate Polynomial Ring in x over Integer Ring,
+             Magma: Univariate Polynomial Ring in x over Integer Ring}
         """
-        if gens is None:
-            if isinstance(x, bool):
-                return Expect.__call__(self, str(x).lower())
-            return Expect.__call__(self, x)
-        return self.objgens(x, gens)
-        
+        if isinstance(x, bool):
+            return Expect.__call__(self, 'true' if x else 'false')
+
+        if gens is not None:  # get rid of this at some point -- it's weird
+            return self.objgens(x, gens)
+
+        # This is mostly about caching the Magma element in the object
+        # itself below.  Note that it is *very* important that caching
+        # happen on the object itself, and not in a dictionary that is
+        # held by the Magma interface, since we want garbage collection
+        # of the objects in the Magma interface to work correctly.
+        has_cache = hasattr(x, '_magma_cache')
+        try:
+            if has_cache and x._magma_cache.has_key(self):
+                A = x._magma_cache[self]
+                if A._session_number == self._session_number:
+                    return A
+        except AttributeError:
+            # This happens when x has _magma_cache as a cdef public object attribute.
+            x._magma_cache = {}
+        A = Expect.__call__(self, x)
+        if has_cache:
+            x._magma_cache[self] = A
+        else:
+            try:  # use try/except here, because if x is cdef'd we won't be able to set this.
+                x._magma_cache = {self:A}
+            except AttributeError, msg: 
+                pass
+        return A
+
+
+    def _coerce_from_special_method(self, x):
+        """
+        Tries to coerce to self by calling a special underscore method.
+
+        If no such method is defined, raises an AttributeError
+        instead of a TypeError. 
+        """
+        try:
+            return x._magma_(self)
+        except AttributeError:
+            return self(x._magma_init_(self))
+
     def clear(self, var):
         """
         Clear the variable named var and make it available
@@ -593,9 +643,9 @@
         
     def attach(self, filename):
         r"""
-        Attach the given file to the running instance of MAGMA.
+        Attach the given file to the running instance of Magma.
 
-        Attaching a file in MAGMA makes all intrinsics defined in the
+        Attaching a file in Magma makes all intrinsics defined in the
         file available to the shell.  Moreover, if the file doesn't
         start with the \code{freeze;} command, then the file is
         reloaded whenever it is changed.  Note that functions and
@@ -645,9 +695,9 @@
     def load(self, filename):
         """
         Load the file with given filename using the 'load' command
-        in the MAGMA shell.
+        in the Magma shell.
 
-        Loading a file in MAGMA makes all the functions and procedures
+        Loading a file in Magma makes all the functions and procedures
         in the file available. The file should not contain any
         intrinsics (or you'll get errors).  It also runs code in the
         file, which can produce output.
@@ -693,7 +743,7 @@
             try:
                 self.eval('Append(~_sage_, 0);')
             except:
-                # this exception could happen if the MAGMA process
+                # this exception could happen if the Magma process
                 # was interrupted during startup / initialization.
                 self.eval('_sage_ := [* 0 : i in [1..%s] *];'%self.__seq)
         if len(self.__available_var) > 0:
@@ -861,7 +911,7 @@
         """
         return MagmaElement
 
-    # Usually "Sequences" are what you want in MAGMA, not "lists".
+    # Usually "Sequences" are what you want in Magma, not "lists".
     # It's very painful using the interface without this.
     def _left_list_delim(self):
         """
@@ -1037,12 +1087,12 @@
                 except IOError:
                     pass
             if verbose:
-                print "\nCreating list of all MAGMA intrinsics for use in tab completion."
+                print "\nCreating list of all Magma intrinsics for use in tab completion."
                 print "This takes a few minutes the first time, but is saved to the"
                 print "file '%s' for future instant use."%INTRINSIC_CACHE
-                print "MAGMA may produce errors during this process, which are safe to ignore."
+                print "Magma may produce errors during this process, which are safe to ignore."
                 print "Delete that file to force recreation of this cache."
-                print "Scanning MAGMA types ..."
+                print "Scanning Magma types ..."
                 tm = sage.misc.misc.cputime()
             T = self.eval('ListTypes()').split()
             N = []
@@ -1055,7 +1105,7 @@
                     for x in s.split('\n'):
                         i = x.find('(')
                         N.append(x[:i])
-                except RuntimeError, msg:  # weird internal problems in MAGMA type system
+                except RuntimeError, msg:  # weird internal problems in Magma type system
                     print 'Error -- %s'%msg
                     pass
             if verbose:
@@ -1070,7 +1120,7 @@
 
     def ideal(self, L):
         """
-        Return the MAGMA ideal defined by L.
+        Return the Magma ideal defined by L.
 
         INPUT:
             L -- a list of elements of a SAGE multivariate polynomial ring.
@@ -1091,7 +1141,7 @@
             ]
         """
         P = iter(L).next().parent()
-        Pn = P._magma_().name()
+        Pn = self(P).name()
         k = P.base_ring() 
         if k.degree() > 1:
             i = str(k.gen())
@@ -1477,7 +1527,7 @@
             [$.1]
         """
         try:
-            return self.__gens
+            return self._magma_gens
         except AttributeError:
             pass
         G = []
@@ -1490,8 +1540,30 @@
             except (RuntimeError, TypeError):
                 break
             i += 1
-        self.__gens = G
+        self._magma_gens = G
         return G
+
+    def gen_names(self):
+        """
+        Return list of Magma variable names of the generators of self.
+
+        NOTE: As illustrated below, these are not the print names of
+        the the generators of the Magma object, but special variable
+        names in the Magma session that reference the generators.
+
+        EXAMPLES:
+            sage: R.<x,zw> = QQ[]
+            sage: S = magma(R)         # optional - magma
+            sage: S.gen_names()        # optional - magma
+            ('_sage_[...]', '_sage_[...]')
+            sage: magma(S.gen_names()[1])
+            zw
+        """
+        try:
+            return self.__gen_names
+        except AttributeError:
+            self.__gen_names = tuple([x.name() for x in self.gens()])
+        return self.__gen_names
 
     def evaluate(self, *args):
         """
@@ -1818,12 +1890,12 @@
         Quotient of division of self by other.  This is denoted // ("div" in magma).
 
         EXAMPLE:
-            sage: R.<x,y,z>=QQ[]
-            sage: magma(5)//magma(2) # optional - magma
+            sage: R.<x,y,z> = QQ[]
+            sage: magma(5)//magma(2)     # optional - magma
             2
-            sage: m=magma(x*z+x*y)   # optional - magma
-            sage: n=magma(x)         # optional - magma 
-            sage: m//n               # optional - magma
+            sage: m = magma(x*z + x*y)   # optional - magma
+            sage: n = magma(x)           # optional - magma 
+            sage: m//n                   # optional - magma
             y + z
         """
         return self.parent()('%s div %s'%(self.name(), x.name()))
diff -r a0b4c7f7ead9 -r 334d17e4247e sage/matrix/matrix1.pyx
--- a/sage/matrix/matrix1.pyx	Sun Nov 23 03:08:12 2008 -0800
+++ b/sage/matrix/matrix1.pyx	Sun Nov 23 19:36:07 2008 -0800
@@ -220,9 +220,9 @@
             [             zeta9            zeta9^4          zeta9 - 1]
             [-zeta9^5 - zeta9^2                  1                  0]
             sage: magma(M)                             # optional - magma
-            [                   0                    1                    3]
-            [              zeta_9             zeta_9^4           zeta_9 - 1]
-            [-zeta_9^5 - zeta_9^2                    1                    0]
+            [                 0                  1                  3]
+            [             zeta9            zeta9^4          zeta9 - 1]
+            [-zeta9^5 - zeta9^2                  1                  0]
             sage: magma(M**2) == magma(M)**2           # optional - magma
             True
         """
@@ -233,7 +233,7 @@
            s = 'RMatrixSpace(%s, %s, %s)'%(K.name(), self.nrows(), self.ncols())
         v = []
         for x in self.list():
-             v.append(x._magma_init_())
+             v.append(x._magma_init_(magma))
         return magma(s + '![%s]'%(','.join(v)))
 
     def _maple_init_(self):
diff -r a0b4c7f7ead9 -r 334d17e4247e sage/matrix/matrix_mod2_dense.pyx
--- a/sage/matrix/matrix_mod2_dense.pyx	Sun Nov 23 03:08:12 2008 -0800
+++ b/sage/matrix/matrix_mod2_dense.pyx	Sun Nov 23 19:36:07 2008 -0800
@@ -1128,14 +1128,14 @@
     
 
 
-    def _magma_init_(self):
+    def _magma_init_(self, magma):
         r"""
         Returns a string of self in \Magma form. Does not return \Magma
         object but string.
 
         EXAMPLE:
             sage: A = random_matrix(GF(2),3,3)
-            sage: A._magma_init_()                             # optional - magma
+            sage: A._magma_init_(magma)                             # optional - magma
             'MatrixAlgebra(GF(2), 3)![0,1,0,0,1,1,0,0,0]'
             sage: A = random_matrix(GF(2),100,100)
             sage: B = random_matrix(GF(2),100,100)
@@ -1148,7 +1148,7 @@
             Matrix with 0 rows and 3 columns
         """
         cdef int i,j
-        K = self._base_ring._magma_init_()
+        K = self._base_ring._magma_init_(magma)
         if self._nrows == self._ncols: 
             s = 'MatrixAlgebra(%s, %s)'%(K, self.nrows())
         else:
diff -r a0b4c7f7ead9 -r 334d17e4247e sage/matrix/matrix_modn_dense.pyx
--- a/sage/matrix/matrix_modn_dense.pyx	Sun Nov 23 03:08:12 2008 -0800
+++ b/sage/matrix/matrix_modn_dense.pyx	Sun Nov 23 19:36:07 2008 -0800
@@ -1537,14 +1537,17 @@
             raise IndexError, "matrix window index out of range"
         return matrix_window_modn_dense.MatrixWindow_modn_dense(self, row, col, nrows, ncols)
 
-    def _magma_init_(self):
+    def _magma_init_(self, magma):
         """
-        Returns a string of self in MAGMA form.
+        Returns a string representation of self in Magma form.
 
-        NOTE: Does not return MAGMA object but string.
+        INPUT:
+            magma -- a Magma session
+        OUTPUT:
+            string
         """
         cdef int i,j
-        K = self._base_ring._magma_init_()
+        K = self._base_ring._magma_init_(magma)
         if self._nrows == self._ncols: 
             s = 'MatrixAlgebra(%s, %s)'%(K, self.nrows())
         else:
diff -r a0b4c7f7ead9 -r 334d17e4247e sage/matrix/matrix_space.py
--- a/sage/matrix/matrix_space.py	Sun Nov 23 03:08:12 2008 -0800
+++ b/sage/matrix/matrix_space.py	Sun Nov 23 19:36:07 2008 -0800
@@ -1086,7 +1086,7 @@
         Z.randomize(density, *args, **kwds)
         return Z
 
-    def _magma_init_(self):
+    def _magma_init_(self, magma):
         r"""
         EXAMPLES:
         We first coerce a square matrix.
@@ -1096,7 +1096,7 @@
             sage: magma(MatrixSpace(Integers(8),2,3))           # optional - magma
             Full RMatrixSpace of 2 by 3 matrices over IntegerRing(8)
         """
-        K = self.base_ring()._magma_init_()
+        K = self.base_ring()._magma_init_(magma)
         if self.__nrows == self.__ncols:
             s = 'MatrixAlgebra(%s, %s)'%(K, self.__nrows)
         else:
diff -r a0b4c7f7ead9 -r 334d17e4247e sage/rings/finite_field_element.py
--- a/sage/rings/finite_field_element.py	Sun Nov 23 03:08:12 2008 -0800
+++ b/sage/rings/finite_field_element.py	Sun Nov 23 19:36:07 2008 -0800
@@ -414,15 +414,15 @@
     def _pari_init_(self):
         return str(self.__value)
 
-    def _magma_init_(self):
+    def _magma_init_(self, magma):
         """
         Return a string representation of self that Magma can understand.
 
         EXAMPLES:
-            sage: GF(7)(3)._magma_init_()                 # optional - magma
+            sage: GF(7)(3)._magma_init_(magma)                 # optional - magma
             'GF(7)!3'
         """
-        km = self.parent()._magma_()
+        km = magma(self.parent())
         vn = km.gen(1).name()
         return ("%s"%(self.__value.lift().lift())).replace('a',vn)
 
diff -r a0b4c7f7ead9 -r 334d17e4247e sage/rings/finite_field_givaro.pyx
--- a/sage/rings/finite_field_givaro.pyx	Sun Nov 23 03:08:12 2008 -0800
+++ b/sage/rings/finite_field_givaro.pyx	Sun Nov 23 19:36:07 2008 -0800
@@ -1884,19 +1884,19 @@
         """
         return pari(self._pari_init_(var))
 
-    def _magma_init_(self):
+    def _magma_init_(self, magma):
         """
         Return a string representation of self that MAGMA can
         understand.
 
         EXAMPLE:
             sage: k.<a> = GF(3^5)
-            sage: k._magma_init_()        # optional - magma
+            sage: k._magma_init_(magma)        # optional - magma
             'ext< GF(3) | Polynomial(GF(3), [GF(3)!1,GF(3)!2,GF(3)!0,GF(3)!0,GF(3)!0,GF(3)!1]) >'
         """
-        km = self.parent()._magma_()
+        km = magma(self.parent())
         vn = km.gen(1).name()
-        return self.parent()._element_poly_repr(self,vn)
+        return self.parent()._element_poly_repr(self, vn)
 
     def multiplicative_order(FiniteField_givaroElement self):
         """
diff -r a0b4c7f7ead9 -r 334d17e4247e sage/rings/finite_field_ntl_gf2e.pyx
--- a/sage/rings/finite_field_ntl_gf2e.pyx	Sun Nov 23 03:08:12 2008 -0800
+++ b/sage/rings/finite_field_ntl_gf2e.pyx	Sun Nov 23 19:36:07 2008 -0800
@@ -1245,19 +1245,19 @@
             o *= g
         return ret
             
-    def _magma_init_(self):
+    def _magma_init_(self, magma):
         r"""
         Return a string representation of self that \MAGMA can
         understand.
 
         EXAMPLE:
             sage: k.<a> = GF(2^16)
-            sage: a._magma_init_()      # random; optional - magma
+            sage: a._magma_init_(magma)      # random; optional - magma
             '_sage_[2]'
             
         NOTE: This method calls \MAGMA to setup the parent.
         """
-        km = self.parent()._magma_()
+        km = magma(self.parent())
         vn_m = km.gen(1).name()
         vn_s = str(self.parent().polynomial_ring().gen())
         return str(self.polynomial()).replace(vn_s,vn_m)
diff -r a0b4c7f7ead9 -r 334d17e4247e sage/rings/fraction_field.py
--- a/sage/rings/fraction_field.py	Sun Nov 23 03:08:12 2008 -0800
+++ b/sage/rings/fraction_field.py	Sun Nov 23 19:36:07 2008 -0800
@@ -195,17 +195,17 @@
         return "\\mbox{\\rm Frac}(%s)"%latex.latex(self.ring())
 
     __magma = None
-    def _magma_init_(self):
+    def _magma_init_(self, magma):
         """
         Return a string representation of self Magma can understand.
 
         EXAMPLES:
-            sage: QQ['x'].fraction_field()._magma_init_()            # optional - magma
+            sage: QQ['x'].fraction_field()._magma_init_(magma)            # optional - magma
             'FieldOfFractions(PolynomialRing(RationalField()))'
         """
         if self.__magma:
             return self.__magma
-        B = self.ring()._magma_init_()
+        B = self.ring()._magma_init_(magma)
         return "FieldOfFractions(%s)"%B
 
     def _magma_(self, magma = None):
@@ -223,7 +223,7 @@
             import sage.interfaces.magma
             magma = sage.interfaces.magma.magma
         if self.__magma is None:
-            s = self._magma_init_()
+            s = self._magma_init_(magma)
             F = magma(s)
             F.assign_names(self.variable_names())
             self.__magma = F
diff -r a0b4c7f7ead9 -r 334d17e4247e sage/rings/fraction_field_element.py
--- a/sage/rings/fraction_field_element.py	Sun Nov 23 03:08:12 2008 -0800
+++ b/sage/rings/fraction_field_element.py	Sun Nov 23 19:36:07 2008 -0800
@@ -349,7 +349,7 @@
         return "\\frac{%s}{%s}"%(latex.latex(self.__numerator),
                                  latex.latex(self.__denominator))
 
-    def _magma_init_(self):
+    def _magma_init_(self, magma):
         """
         Return a string representation of self Magma can understand.
 
@@ -362,7 +362,7 @@
             sage: magma((x+y)/x)                        # optional - magma
             (x + y)/x
         """
-        pgens = self.parent()._magma_().gens()
+        pgens = magma(self.parent()).gens()
 
         s = self._repr_()
         for i, j in zip(self.parent().variable_names(), pgens):
diff -r a0b4c7f7ead9 -r 334d17e4247e sage/rings/integer_mod.pyx
--- a/sage/rings/integer_mod.pyx	Sun Nov 23 03:08:12 2008 -0800
+++ b/sage/rings/integer_mod.pyx	Sun Nov 23 19:36:07 2008 -0800
@@ -350,7 +350,7 @@
         n = self.log(R(g))
         return 'Z(%s)^%s'%(m, n)
 
-    def _magma_init_(self):
+    def _magma_init_(self, magma):
         """
         Coercion to Magma.
         
@@ -362,7 +362,7 @@
             sage: b^2                         # optional - magma
             1
         """
-        return '%s!%s'%(self.parent()._magma_init_(), self)
+        return '%s!%s'%(self.parent()._magma_init_(magma), self)
 
     def _sage_input_(self, sib, coerced):
         r"""
diff -r a0b4c7f7ead9 -r 334d17e4247e sage/rings/integer_mod_ring.py
--- a/sage/rings/integer_mod_ring.py	Sun Nov 23 03:08:12 2008 -0800
+++ b/sage/rings/integer_mod_ring.py	Sun Nov 23 19:36:07 2008 -0800
@@ -898,7 +898,7 @@
         """
         return 'ZmodnZ(%s)'%self.order()
 
-    def _magma_init_(self):
+    def _magma_init_(self, magma):
         """
         EXAMPLES:
             sage: R = Integers(12345678900)
diff -r a0b4c7f7ead9 -r 334d17e4247e sage/rings/integer_ring.pyx
--- a/sage/rings/integer_ring.pyx	Sun Nov 23 03:08:12 2008 -0800
+++ b/sage/rings/integer_ring.pyx	Sun Nov 23 19:36:07 2008 -0800
@@ -840,7 +840,7 @@
         """
         return 'Integers'
     
-    def _magma_init_(self):
+    def _magma_init_(self, magma):
         """
         EXAMPLES:
             sage: magma(ZZ)           # optional - magma
diff -r a0b4c7f7ead9 -r 334d17e4247e sage/rings/number_field/number_field.py
--- a/sage/rings/number_field/number_field.py	Sun Nov 23 03:08:12 2008 -0800
+++ b/sage/rings/number_field/number_field.py	Sun Nov 23 19:36:07 2008 -0800
@@ -5472,7 +5472,7 @@
         """
         return NumberField_cyclotomic_v1, (self.__n, self.variable_name())
 
-    def _magma_init_(self):
+    def _magma_init_(self, magma):
         # TODO: I really don't like this on multiple levels.
         # (1) it kills a global symbol self.gen()
         # (2) it abuses how conversion works and throws in an extra define.
@@ -5489,10 +5489,10 @@
 
         EXAMPLES:
             sage: K=CyclotomicField(7,'z') 
-            sage: K._magma_init_()                                # optional - magma
+            sage: K._magma_init_(magma)                                # optional - magma
             'CyclotomicField(7); z:=CyclotomicField(7).1;'
             sage: K=CyclotomicField(7,'zeta')               
-            sage: K._magma_init_()                                # optional - magma
+            sage: K._magma_init_(magma)                                # optional - magma
             'CyclotomicField(7); zeta:=CyclotomicField(7).1;'        
         """
         return 'CyclotomicField(%s); %s:=CyclotomicField(%s).1;'%(self.__n, self.gen(), self.__n)
diff -r a0b4c7f7ead9 -r 334d17e4247e sage/rings/number_field/number_field_element.pyx
--- a/sage/rings/number_field/number_field_element.pyx	Sun Nov 23 03:08:12 2008 -0800
+++ b/sage/rings/number_field/number_field_element.pyx	Sun Nov 23 19:36:07 2008 -0800
@@ -1820,7 +1820,7 @@
         self.__pari[var] = h
         return h
 
-    def _magma_(self, magma):
+    def _magma_init_(self, magma):
         """
         Return Magma version of this number field element.
 
@@ -1832,11 +1832,22 @@
 
         EXAMPLES:
             sage: K.<a> = NumberField(x^3 + 2)
-            sage: magma((2/3)*a^2 - 17/3) # optional -- requires magma
+            sage: a._magma_init_(magma)            # optional - magma
+            '(_sage_[...]![0, 1, 0])'            
+            sage: magma((2/3)*a^2 - 17/3)          # optional - magma
             1/3*(2*a^2 - 17)
+
+        An element of a cyclotomic field.
+            sage: K = CyclotomicField(9)
+            sage: K.gen()
+            zeta9
+            sage: K.gen()._magma_init_(magma)
+            '(_sage_[...]![0, 1, 0, 0, 0, 0])'
+            sage: magma(K.gen())
+            zeta9
         """
         K = magma(self.parent())
-        return K(self.list())
+        return '(%s!%s)'%(K.name(), self.list())
         
     cdef void _parent_poly_c_(self, ZZX_c *num, ZZ_c *den):
         """
diff -r a0b4c7f7ead9 -r 334d17e4247e sage/rings/polynomial/multi_polynomial.pyx
--- a/sage/rings/polynomial/multi_polynomial.pyx	Sun Nov 23 03:08:12 2008 -0800
+++ b/sage/rings/polynomial/multi_polynomial.pyx	Sun Nov 23 19:36:07 2008 -0800
@@ -662,17 +662,31 @@
         P = P.change_ring(R)
         return P(self)
 
-    def _magma_init_(self):
+    def _magma_init_(self, magma):
         """
-        Returns the MAGMA representation of self.
+        Returns a Magma string representation of self valid in the
+        given magma session.
         
         EXAMPLES:
             sage: R.<x,y> = GF(2)[]
             sage: f = y*x^2 + x +1
-            sage: f._magma_init_()                    # optional - magma
-            '_sage_[3]^2*_sage_[4] + _sage_[3] + 1'
+            sage: f._magma_init_(magma)                    # optional - magma
+            '(GF(2)!1)*_sage_[...]^2*_sage_[...]+(GF(2)!1)*_sage_[...]+(GF(2)!1)*1'
+
+        A more complicated nested example:
+            sage: R.<x,y> = QQ[]; S.<z,w> = R[]; f = (2/3)*x^3*z + w^2 + 5
+            sage: f._magma_init_(magma)               # optional - magma
+            '((1/1)*1)*_sage_[...]^2+((2/3)*_sage_[...]^3)*_sage_[...]+((5/1)*1)*1'
+            sage: magma(f)                            # optional - magma
+            w^2 + 2/3*x^3*z + 5
         """
-        return self._repr_with_changed_varnames(self.parent()._magma_gens())
+        g = magma(self.parent()).gen_names()
+        v = []
+        for m, c in zip(self.monomials(), self.coefficients()):
+            v.append('(%s)*%s'%( c._magma_init_(magma),
+                                 m._repr_with_changed_varnames(g)))
+        return '+'.join(v)
+
         
     def gradient(self):
         r"""
diff -r a0b4c7f7ead9 -r 334d17e4247e sage/rings/polynomial/multi_polynomial_ideal.py
--- a/sage/rings/polynomial/multi_polynomial_ideal.py	Sun Nov 23 03:08:12 2008 -0800
+++ b/sage/rings/polynomial/multi_polynomial_ideal.py	Sun Nov 23 19:36:07 2008 -0800
@@ -359,7 +359,7 @@
         EXAMPLES:
             sage: R.<a,b,c,d,e,f,g,h,i,j> = PolynomialRing(GF(127),10)
             sage: I = sage.rings.ideal.Cyclic(R,4)
-            sage: I._magma_()                                          # optional - magma
+            sage: magma(I)                                          # optional - magma
             Ideal of Polynomial ring of rank 10 over GF(127)
             Graded Reverse Lexicographical Order
             Variables: a, b, c, d, e, f, g, h, i, j
diff -r a0b4c7f7ead9 -r 334d17e4247e sage/rings/polynomial/multi_polynomial_ring_generic.pxd
--- a/sage/rings/polynomial/multi_polynomial_ring_generic.pxd	Sun Nov 23 03:08:12 2008 -0800
+++ b/sage/rings/polynomial/multi_polynomial_ring_generic.pxd	Sun Nov 23 19:36:07 2008 -0800
@@ -7,8 +7,7 @@
     cdef object __ngens
     cdef object __term_order
     cdef object _has_singular
-    cdef object __magma
-    cdef object __magma_gens
+    cdef public object _magma_gens, _magma_cache
 
     cdef _coerce_c_impl(self, x)
     cdef int _cmp_c_impl(left, Parent right) except -2
diff -r a0b4c7f7ead9 -r 334d17e4247e sage/rings/polynomial/multi_polynomial_ring_generic.pyx
--- a/sage/rings/polynomial/multi_polynomial_ring_generic.pyx	Sun Nov 23 03:08:12 2008 -0800
+++ b/sage/rings/polynomial/multi_polynomial_ring_generic.pyx	Sun Nov 23 19:36:07 2008 -0800
@@ -250,7 +250,7 @@
             return False
         return True
 
-    def _magma_(self, magma=None):
+    def _magma_convert_(self, magma=None):
         """
         Used in converting this ring to the corresponding ring in MAGMA.
 
@@ -276,52 +276,20 @@
             Graded Reverse Lexicographical Order
             Variables: x0, x1, x2
         """
-        if magma == None:
-            import sage.interfaces.magma
-            magma = sage.interfaces.magma.magma
-        
-        try:
-            if self.__magma is None:
-                raise AttributeError
-            m = self.__magma
-            m._check_valid()
-            if not m.parent() is magma:
-                raise ValueError
-            return m
-        except (AttributeError,ValueError):
-            B = magma(self.base_ring())
-            R = magma('PolynomialRing(%s, %s, %s)'%(B.name(), self.ngens(),self.term_order().magma_str()))
-            R.assign_names(self.variable_names())
-            self.__magma = R
-            self.__magma_gens = [e.name() for e in R.gens()]
-            return R
+        B = magma(self.base_ring())
+        R = magma('PolynomialRing(%s, %s, %s)'%(B.name(), self.ngens(), self.term_order().magma_str()))
+        R.assign_names(self.variable_names())
+        return R
 
-    def _magma_gens(self):
+    def _magma_init_(self, magma):
         """
-        Returns a list with names of Magma representations of the generators 
-        of this ring.
-
-        If a Magma object for this ring has not already been initialized,
-        Magma is called first, otherwise cached names are returned.
-
-        EXAMPLES:
-            sage: R = ZZ['x,y']
-            sage: R._magma_gens()                    # optional - magma
-            ['_sage_[3]', '_sage_[4]']
-
-        """
-        if self.__magma_gens is None or not self.__magma._check_valid():
-            self._magma_()
-        return self.__magma_gens
-
-    def _magma_init_(self):
-        """
-        Return a string representation of self MAGMA can understand.
+        Return a string representation of self Magma can understand.
+        Used in conversion of self to Magma.
         """
         try: # we need that for GF(q) arithmetic
-            B = self.base_ring()._magma_().name()
+            B = magma(self.base_ring()).name()
         except (RuntimeError,TypeError):
-            B = self.base_ring()._magma_init_()
+            B = self.base_ring()._magma_init_(magma)
         R = 'PolynomialRing(%s, %s, %s)'%(B, self.ngens(),self.term_order().magma_str())
         return R
     
diff -r a0b4c7f7ead9 -r 334d17e4247e sage/rings/polynomial/pbori.pxd
--- a/sage/rings/polynomial/pbori.pxd	Sun Nov 23 03:08:12 2008 -0800
+++ b/sage/rings/polynomial/pbori.pxd	Sun Nov 23 19:36:07 2008 -0800
@@ -12,6 +12,9 @@
     cdef Py_ssize_t* pbind
     cdef public _monom_monoid
     cdef public object __interface
+
+    # it is very important to keep this cached, since otherwise the magma interface will break
+    cdef public object __cover_ring
 
 cdef class BooleanPolynomial(MPolynomial):
     cdef PBPoly _pbpoly
diff -r a0b4c7f7ead9 -r 334d17e4247e sage/rings/polynomial/pbori.pyx
--- a/sage/rings/polynomial/pbori.pyx	Sun Nov 23 03:08:12 2008 -0800
+++ b/sage/rings/polynomial/pbori.pyx	Sun Nov 23 19:36:07 2008 -0800
@@ -935,8 +935,18 @@
 
             sage: B.term_order() == R.term_order()
             True
-        """
-        return PolynomialRing(GF(2),self.ngens(),self.variable_names(),order=self.term_order())
+
+        The cover ring is cached:
+            sage: B.cover_ring() is B.cover_ring()
+            True
+        """
+        if self.__cover_ring is not None:
+            return self.__cover_ring
+        R = PolynomialRing(GF(2), self.ngens(),
+                           self.variable_names(), order=self.term_order())
+        self.__cover_ring = R
+        return R
+        
 
     def defining_ideal(self):
         r"""
@@ -976,16 +986,17 @@
         """
         return self.cover_ring().quo( self.defining_ideal() )._singular_init_()
 
-    def _magma_(self, magma=None):
-        r"""
-        Return a \Magma representation of this boolean polynomial ring.
-
-        INPUT:
-            magma -- a magma instance (default: default instance)
-
-        EXAMPLE:
-            sage: B.<x,y,z> = BooleanPolynomialRing(3)
-            sage: B._magma_()                              # optional - magma
+    def _magma_init_(self, magma):
+        r"""
+        Return a a string which when evaluated with Magma returns a
+        Magma representaion of this boolean polynomial ring.
+
+        INPUT:
+            magma -- a magma instance
+
+        EXAMPLE:
+            sage: B.<x,y,z> = BooleanPolynomialRing(3)
+            sage: magma(B)                               # indirect doctest; optional - magma
             Affine Algebra of rank 3 over GF(2)
             Lexicographical Order
             Variables: x, y, z
@@ -996,52 +1007,17 @@
             z^2 + z
             ]
         """
-
-        if magma is None:
-            import sage.interfaces.magma
-            magma = sage.interfaces.magma.magma
-
-        try:
-            m = self.__interface['magma']
-            m._check_valid()
-            if not m.parent() is magma:
-                raise ValueError
-            return m
-        except (KeyError, ValueError):
-            self.__interface['magma'] = magma(self._magma_init_(magma=magma))
-            return self.__interface['magma']
-
-    def _magma_init_(self, magma=None):
-        r"""
-        Return a a string which when evaluated with \Magma returns a
-        \Magma representaion of this boolean polynomial ring.
-
-        INPUT:
-            magma -- a magma instance (default: default instance)
-
-        EXAMPLE:
-            sage: B.<x,y,z> = BooleanPolynomialRing(3)
-            sage: B._magma_()                               # indirect doctest; optional - magma
-            Affine Algebra of rank 3 over GF(2)
-            Lexicographical Order
-            Variables: x, y, z
-            Quotient relations:
-            [
-            x^2 + x,
-            y^2 + y,
-            z^2 + z
-            ]
-            
-        NOTE: This method actually calls \Magma.
-        """
-        if magma is None:
-            import sage.interfaces.magma
-            magma = sage.interfaces.magma.magma
-
-        R = self.cover_ring()._magma_(magma=magma)
-        vn = [x._magma_().name() for x in self.cover_ring().gens()]
-        return "quo<%s | %s>"%(R.name(), ",".join([f._repr_with_changed_varnames(vn) for f in self.defining_ideal().gens()]))
-
+        R = magma(self.cover_ring())
+        v = [z.name() for z in R.gens()]  # important to use this because it caches the generators
+        w = [f._repr_with_changed_varnames(v) for f in self.defining_ideal().gens()]
+        return "quo<%s | %s>"%(R.name(), ",".join(w))
+
+    def _magma_convert_(self, magma):
+        return magma(self._magma_init_(magma))
+
+    def _magma_(self, magma):
+        return magma(self._magma_init_(magma))
+    
     def interpolation_polynomial(self, zeros, ones):
         r"""
         Return the lexicographically minimal boolean polynomial for
@@ -2786,21 +2762,17 @@
         """ 
         return unpickle_BooleanPolynomial, (self._parent, PBPoly_to_str(&self._pbpoly)) 
 
-    def _magma_(self, magma=None):
+    def _magma_(self, magma):
         r"""
         Returns the \MAGMA representation of self.
         
         EXAMPLES:
             sage: R.<x,y> = BooleanPolynomialRing()
             sage: f = y*x + x +1
-            sage: f._magma_() # optional - magma
+            sage: magma(f) # optional - magma
             x*y + x + 1
         """
-        if magma is None:
-            import sage.interfaces.magma
-            magma = sage.interfaces.magma.magma
-        
-        magma_gens = [e.name() for e in self.parent()._magma_().gens()]
+        magma_gens = [e.name() for e in magma(self.parent()).gens()]
         f = self._repr_with_changed_varnames(magma_gens)
         return magma(f)
 
diff -r a0b4c7f7ead9 -r 334d17e4247e sage/rings/polynomial/polynomial_element.pyx
--- a/sage/rings/polynomial/polynomial_element.pyx	Sun Nov 23 03:08:12 2008 -0800
+++ b/sage/rings/polynomial/polynomial_element.pyx	Sun Nov 23 19:36:07 2008 -0800
@@ -2831,17 +2831,18 @@
     def _pari_init_(self):
         return repr(self._pari_())
 
-    def _magma_init_(self):
+    def _magma_init_(self, magma):
         """
         Return a string that evaluates in Magma to this polynomial.
 
         EXAMPLES:
             sage: R.<y> = ZZ[]
             sage: f = y^3 - 17*y + 5
-            sage: f._magma_init_()             # optional - magma
+            sage: f._magma_init_(magma)             # optional - magma
             'Polynomial(IntegerRing(), [5,-17,0,1])'        
         """
-        return 'Polynomial(%s, [%s])'%(self.base_ring()._magma_init_(), ','.join([a._magma_init_() for a in self.list()]))
+        return 'Polynomial(%s, [%s])'%(self.base_ring()._magma_init_(magma),
+                                       ','.join([a._magma_init_(magma) for a in self.list()]))
 
     def _magma_convert_(self, G):
         """
@@ -2867,7 +2868,7 @@
             y^3 - 17*y + 5        
         """
         z = G(self.parent())   # makes sure the indeterminate var name is defined
-        return G(self._magma_init_())
+        return G(self._magma_init_(G))
 
     def _gap_init_(self):
         return repr(self)
diff -r a0b4c7f7ead9 -r 334d17e4247e sage/rings/polynomial/polynomial_element_generic.py
--- a/sage/rings/polynomial/polynomial_element_generic.py	Sun Nov 23 03:08:12 2008 -0800
+++ b/sage/rings/polynomial/polynomial_element_generic.py	Sun Nov 23 19:36:07 2008 -0800
@@ -715,7 +715,7 @@
             sage: G = f.galois_group(); G            # optional - database_gap
             Transitive group number 5 of degree 4
             sage: G.gens()                           # optional - database_gap
-            ((1,2,3,4), (1,2))
+            [(1,2,3,4), (1,2)]
             sage: G.order()                          # optional - database_gap
             24
 
@@ -739,7 +739,7 @@
             Transitive group number 5 of degree 4
         
             sage: f = x^4 - 17*x^3 - 2*x + 1
-            sage: f.galois_group(algorithm='magma')      # optional - magma
+            sage: f.galois_group(algorithm='magma')     # optional - magma
             Transitive group number 5 of degree 4
         """
         from sage.groups.all import PariGroup, PermutationGroup, TransitiveGroup
diff -r a0b4c7f7ead9 -r 334d17e4247e sage/rings/polynomial/polynomial_ring.py
--- a/sage/rings/polynomial/polynomial_ring.py	Sun Nov 23 03:08:12 2008 -0800
+++ b/sage/rings/polynomial/polynomial_ring.py	Sun Nov 23 19:36:07 2008 -0800
@@ -346,7 +346,7 @@
             pass
         raise TypeError
 
-    def _magma_(self, G=None):
+    def _magma_convert_(self, magma):
         """
         Used in converting this ring to the corresponding ring in MAGMA.
         
@@ -367,15 +367,12 @@
             sage: magma(PolynomialRing(PolynomialRing(ZZ,'w'), 'x')) # optional - magma
             Univariate Polynomial Ring in x over Univariate Polynomial Ring over Integer Ring
         """
-        if G is None:
-            import sage.interfaces.magma
-            G = sage.interfaces.magma.magma
-        R = G(self._magma_init_())
+        R = magma(self._magma_init_(magma))
         R.assign_names(self.variable_names())
         return R
 
-    def _magma_init_(self):
-        return 'PolynomialRing(%s)'%(self.base_ring()._magma_init_())
+    def _magma_init_(self, magma):
+        return 'PolynomialRing(%s)'%(self.base_ring()._magma_init_(magma))
 
     def _gap_(self, G=None):
         """
diff -r a0b4c7f7ead9 -r 334d17e4247e sage/rings/polynomial/term_order.py
--- a/sage/rings/polynomial/term_order.py	Sun Nov 23 03:08:12 2008 -0800
+++ b/sage/rings/polynomial/term_order.py	Sun Nov 23 19:36:07 2008 -0800
@@ -902,7 +902,7 @@
 
         EXAMPLE:
             sage: P = PolynomialRing(GF(127), 10,names='x',order='degrevlex')
-            sage: P._magma_() # optional - magma
+            sage: magma(P)                                                        # optional - magma
             Polynomial ring of rank 10 over GF(127)
             Graded Reverse Lexicographical Order
             Variables: x0, x1, x2, x3, x4, x5, x6, x7, x8, x9
diff -r a0b4c7f7ead9 -r 334d17e4247e sage/rings/quotient_ring.py
--- a/sage/rings/quotient_ring.py	Sun Nov 23 03:08:12 2008 -0800
+++ b/sage/rings/quotient_ring.py	Sun Nov 23 19:36:07 2008 -0800
@@ -644,7 +644,7 @@
         EXAMPLE:
             sage: P.<x,y> = PolynomialRing(GF(2))
             sage: Q = P.quotient(sage.rings.ideal.FieldIdeal(P))
-            sage: Q._magma_()                                         # optional - magma
+            sage: magma(Q)                                         # optional - magma
             Affine Algebra of rank 2 over GF(2)
             Graded Reverse Lexicographical Order
             Variables: x, y
diff -r a0b4c7f7ead9 -r 334d17e4247e sage/rings/quotient_ring_element.py
--- a/sage/rings/quotient_ring_element.py	Sun Nov 23 03:08:12 2008 -0800
+++ b/sage/rings/quotient_ring_element.py	Sun Nov 23 19:36:07 2008 -0800
@@ -240,14 +240,14 @@
             sage: P.<x,y> = PolynomialRing(GF(2))
             sage: Q = P.quotient(sage.rings.ideal.FieldIdeal(P))
             sage: xbar, ybar = Q.gens()
-            sage: xbar._magma_() # optional requires magma
+            sage: magma(xbar)             # optional -- magma
             x
         """
         if magma is None:
             import sage.interfaces.magma
             magma = sage.interfaces.magma.magma
         
-        magma_gens = [e.name() for e in self.parent()._magma_().gens()]
+        magma_gens = [e.name() for e in magma(self.parent()).gens()]
         f = self.__rep._repr_with_changed_varnames(magma_gens)
         return magma(f)
 
diff -r a0b4c7f7ead9 -r 334d17e4247e sage/rings/rational_field.py
--- a/sage/rings/rational_field.py	Sun Nov 23 03:08:12 2008 -0800
+++ b/sage/rings/rational_field.py	Sun Nov 23 19:36:07 2008 -0800
@@ -731,7 +731,7 @@
         """
         return 'Rationals'
     
-    def _magma_init_(self):
+    def _magma_init_(self, magma):
         """
         EXAMPLES:
             sage: magma(QQ)                       # optional - magma
diff -r a0b4c7f7ead9 -r 334d17e4247e sage/rings/ring.pyx
--- a/sage/rings/ring.pyx	Sun Nov 23 03:08:12 2008 -0800
+++ b/sage/rings/ring.pyx	Sun Nov 23 19:36:07 2008 -0800
@@ -1545,22 +1545,22 @@
         """
         return 'GF(%s)'%self.order()
 
-    def _magma_init_(self):
+    def _magma_init_(self, magma):
         """
         Return string representation of self that Magma can
         understand.
 
         EXAMPLES:
-            sage: GF(97,'a')._magma_init_()              # optional - magma
+            sage: GF(97,'a')._magma_init_(magma)              # optional - magma
             'GF(97)'
-            sage: GF(9,'a')._magma_init_()               # optional - magma
+            sage: GF(9,'a')._magma_init_(magma)               # optional - magma
             'ext< GF(3) | Polynomial(GF(3), [GF(3)!2,GF(3)!2,GF(3)!1]) >'
         """
         if self.degree() == 1:
             return 'GF(%s)'%self.order()
         B = self.base_ring()
         p = self.polynomial()
-        return "ext< %s | %s >"%(B._magma_init_(),p._magma_init_())
+        return "ext< %s | %s >"%(B._magma_init_(magma),p._magma_init_(magma))
 
     def _magma_convert_(self, magma):
         """
@@ -1572,7 +1572,7 @@
             sage: magma(GF(9,'a')).1         # optional - magma
             a
         """
-        K = magma(self._magma_init_())
+        K = magma(self._magma_init_(magma))
         K.assign_names([self.variable_name()])
         return K
     
diff -r a0b4c7f7ead9 -r 334d17e4247e sage/schemes/elliptic_curves/ell_finite_field.py
--- a/sage/schemes/elliptic_curves/ell_finite_field.py	Sun Nov 23 03:08:12 2008 -0800
+++ b/sage/schemes/elliptic_curves/ell_finite_field.py	Sun Nov 23 19:36:07 2008 -0800
@@ -92,18 +92,18 @@
         self.__pari = pari('ellinit(Mod(1,%s)*%s)'%(F.characteristic(), [b._pari_() for b in self.ainvs()]))
         return self.__pari
 
-    def _magma_init_(self):
+    def _magma_init_(self, magma):
         """
         Return a Magma command that creates this curve.
 
         EXAMPLES:
             sage: E =  EllipticCurve(GF(41),[2,5]) # optional - magma
-            sage: E._magma_init_()                 # optional - magma
+            sage: E._magma_init_(magma)                 # optional - magma
             'EllipticCurve([GF(41)|GF(41)!0,GF(41)!0,GF(41)!0,GF(41)!2,GF(41)!5])'
        """
         k = self.base_ring()
-        kmn = k._magma_init_()
-        return 'EllipticCurve([%s|%s])'%(kmn,','.join([x._magma_init_() for x in self.ainvs()]))
+        kmn = k._magma_init_(magma)
+        return 'EllipticCurve([%s|%s])'%(kmn,','.join([x._magma_init_(magma) for x in self.ainvs()]))
 
     def _gp(self):
         """
diff -r a0b4c7f7ead9 -r 334d17e4247e sage/schemes/elliptic_curves/ell_generic.py
--- a/sage/schemes/elliptic_curves/ell_generic.py	Sun Nov 23 03:08:12 2008 -0800
+++ b/sage/schemes/elliptic_curves/ell_generic.py	Sun Nov 23 19:36:07 2008 -0800
@@ -290,17 +290,17 @@
         """
         return 'ellinit([%s])'%(','.join([x._pari_init_() for x in self.ainvs()]))
 
-    def _magma_init_(self):
+    def _magma_init_(self, magma):
         """
         Internal function.  Returns a string to initialize this
         elliptic curve in the Magma subsystem.
 
         EXAMPLES:
             sage: E = EllipticCurve(QQ,[1,1])
-            sage: E._magma_init_()                          # optional - magma
+            sage: E._magma_init_(magma)                          # optional - magma
             'EllipticCurve([0/1,0/1,0/1,1/1,1/1])'
         """
-        return 'EllipticCurve([%s])'%(','.join([x._magma_init_() for x in self.ainvs()]))
+        return 'EllipticCurve([%s])'%(','.join([x._magma_init_(magma) for x in self.ainvs()]))
 
     def _symbolic_(self, SR):
         r"""
diff -r a0b4c7f7ead9 -r 334d17e4247e sage/schemes/elliptic_curves/ell_point.py
--- a/sage/schemes/elliptic_curves/ell_point.py	Sun Nov 23 03:08:12 2008 -0800
+++ b/sage/schemes/elliptic_curves/ell_point.py	Sun Nov 23 19:36:07 2008 -0800
@@ -1321,7 +1321,7 @@
 
 class EllipticCurvePoint_finite_field(EllipticCurvePoint_field):
 
-    def _magma_init_(self):
+    def _magma_init_(self, magma):
         """
         Return a string representation of self that MAGMA can
         understand.
@@ -1329,10 +1329,10 @@
         EXAMPLE:
         sage: E = EllipticCurve(GF(17), [1,-1])
         sage: P = E([13, 4])
-        sage: P._magma_init_()
+        sage: P._magma_init_(magma)
         'EllipticCurve([GF(17)|GF(17)!0,GF(17)!0,GF(17)!0,GF(17)!1,GF(17)!16])![13,4]'
         """
-        E = self.curve()._magma_init_()
+        E = self.curve()._magma_init_(magma)
         x,y = self.xy()
         return "%s![%s,%s]"%(E,x,y) 
 
diff -r a0b4c7f7ead9 -r 334d17e4247e sage/schemes/elliptic_curves/ell_rational_field.py
--- a/sage/schemes/elliptic_curves/ell_rational_field.py	Sun Nov 23 03:08:12 2008 -0800
+++ b/sage/schemes/elliptic_curves/ell_rational_field.py	Sun Nov 23 19:36:07 2008 -0800
@@ -1011,7 +1011,8 @@
             from sage.lfunctions.sympow import sympow
             return sympow.analytic_rank(self)[0]
         elif algorithm == 'magma':
-            return rings.Integer(self._magma_().AnalyticRank())
+            from sage.interfaces.all import magma
+            return rings.Integer(magma(self).AnalyticRank())
         elif algorithm == 'all':
             S = list(set([self.analytic_rank('cremona'), 
                      self.analytic_rank('rubinstein'), self.analytic_rank('sympow')]))
@@ -2379,7 +2380,8 @@
                 from sage.lfunctions.all import sympow
                 m = sympow.modular_degree(self)
             elif algorithm == 'magma':
-                m = rings.Integer(self._magma_().ModularDegree())
+                from sage.interfaces.all import magma
+                m = rings.Integer(magma(self).ModularDegree())
             else:
                 raise ValueError, "unknown algorithm %s"%algorithm
             self.__modular_degree = m
diff -r a0b4c7f7ead9 -r 334d17e4247e sage/structure/element.pyx
--- a/sage/structure/element.pyx	Sun Nov 23 03:08:12 2008 -0800
+++ b/sage/structure/element.pyx	Sun Nov 23 19:36:07 2008 -0800
@@ -1591,7 +1591,7 @@
         V = magma(self._parent)
         v = []
         for x in self.list():
-            v.append(x._magma_init_())
+            v.append(x._magma_init_(magma))
         s = '%s![%s]'%(V.name(), ','.join(v))
         return magma(s)
 
diff -r a0b4c7f7ead9 -r 334d17e4247e sage/structure/sage_object.pyx
--- a/sage/structure/sage_object.pyx	Sun Nov 23 03:08:12 2008 -0800
+++ b/sage/structure/sage_object.pyx	Sun Nov 23 19:36:07 2008 -0800
@@ -233,10 +233,11 @@
                     pass
             except (KeyError, ValueError):
                 pass
-        if hasattr(self, '_%s_init_'%I.name()):
-            s = self.__getattribute__('_%s_init_'%I.name())()
-        elif hasattr(self, '_system_init_'):
-            s = self._system_init_(I.name())
+        nm = I.name()
+        if nm == 'magma':
+            s = self._magma_init_(I)
+        elif hasattr(self, '_%s_init_'%nm):
+            s = self.__getattribute__('_%s_init_'%nm)()
         else:
             try:
               s = self._interface_init_()
@@ -309,7 +310,7 @@
         return self._interface_init_()
 
 
-    def _magma_(self, M=None):
+    def _magma_(self, magma):
         """
         Given a Magma interpreter M (or None for the default global
         interpreter), return MagmaElement corresponding to self in M.
@@ -328,13 +329,13 @@
         EXAMPLES:
             sage: n = -3/7
             sage: m2 = Magma()                  
-            sage: n._magma_()                        # optional - magma
+            sage: n._magma_(magma)                        # optional - magma
             -3/7
-            sage: n._magma_().parent()               # optional - magma
+            sage: n._magma_(magma).parent()               # optional - magma
             Magma
-            sage: n._magma_().parent() is m2         # optional - magma
+            sage: n._magma_(magma).parent() is m2         # optional - magma
             False
-            sage: n._magma_().parent() is magma      # optional - magma
+            sage: n._magma_(magma).parent() is magma      # optional - magma
             True
             sage: n._magma_(m2).parent() is m2       # optional - magma
             True
@@ -342,19 +343,16 @@
         This example illustrates caching, which happens automatically
         since K is a Python object:
             sage: K.<a> = NumberField(x^3 + 2)
-            sage: K._magma_() is K._magma_()        # optional - magma
+            sage: magma(K) is magma(K)        # optional - magma
             True
             sage: magma2 = Magma()                  
-            sage: K._magma_() is K._magma_(magma2)  # optional - magma
+            sage: magma(K) is magma2(K)       # optional - magma
             False
         """
-        if M is None:
-            import sage.interfaces.magma
-            M = sage.interfaces.magma.magma
         c = self._interface_is_cached_()
         if c:
             try:
-                X = self.__interface[M]
+                X = self.__interface[magma]
                 X._check_valid()
                 return X
             except (AttributeError, TypeError):
@@ -367,28 +365,24 @@
                     pass
             except (KeyError, ValueError):
                 pass
-        A = self._magma_convert_(M)
+        A = self._magma_convert_(magma)
         if c:
-            self.__interface[M] = A
+            self.__interface[magma] = A
         return A
 
-    def _magma_init_(self):
+    def _magma_init_(self, magma):
         """
-        Return an ascii string that evaluates to something equal to
-        self in Magma.  Use this for converting very simple things
-        (e.g., integers) from Sage to Magma.  For anything much more
-        complicated, use _magma_convert_.
+        Return an ascii string that evaluates to the Magma version of
+        self in the given magma interface.  
 
-        The default coercion for elements from Sage to Magma is to
-        call _magma_init_, which just calls the repr method of the
-        object.
-
+        INPUT:
+            magma -- a Magma interface
         OUTPUT:
             string
 
         EXAMPLES:
             sage: n = -3/7
-            sage: n._magma_init_()
+            sage: n._magma_init_(magma)
             '-3/7'
         """
         return self._interface_init_()
