text: "Access to Maxima methods"
  
  ###############################################################################
  #   Sage: Open Source Mathematical Software
  #       Copyright (C) 2010 Burcin Erocal <burcin@erocal.org>
  #  Distributed under the terms of the GNU General Public License (GPL),
  #  version 2 or any later version.  The full text of the GPL is available at:
  #                  http://www.gnu.org/licenses/
  ###############################################################################
  
  from sage.structure.sage_object import SageObject
  from sage.interfaces.maxima import MaximaFunctionElement
  from sage.docs.instancedoc import instancedoc
  
  
  @instancedoc
  class MaximaFunctionElementWrapper(MaximaFunctionElement):
      def __call__(self, *args, **kwds):
          """
          Return a Sage expression instead of a Maxima pexpect interface element.
  
          EXAMPLES::
  
              sage: t = sin(x)^2 + cos(x)^2; t
              cos(x)^2 + sin(x)^2
              sage: res = t.maxima_methods().trigsimp(); res
              1
              sage: parent(res)
              Symbolic Ring
          """
          return super(MaximaFunctionElementWrapper, self).__call__(*args,
                  **kwds).sage()
  
  class MaximaWrapper(SageObject):
      def __init__(self, exp):
          """
          Wrapper around Sage expressions to give access to Maxima methods.
  
          We convert the given expression to Maxima and convert the return value
          back to a Sage expression. Tab completion and help strings of Maxima
          methods also work as expected.
  
          EXAMPLES::
  
              sage: t = log(sqrt(2) - 1) + log(sqrt(2) + 1); t
              log(sqrt(2) + 1) + log(sqrt(2) - 1)
              sage: u = t.maxima_methods(); u
              MaximaWrapper(log(sqrt(2) + 1) + log(sqrt(2) - 1))
              sage: type(u)
              <class 'sage.symbolic.maxima_wrapper.MaximaWrapper'>
              sage: u.logcontract()
              log((sqrt(2) + 1)*(sqrt(2) - 1))
              sage: u.logcontract().parent()
              Symbolic Ring
  
          TESTS:
  
          Test tab completions::
  
              sage: import sage.interfaces.tab_completion as s
              sage: u = t.maxima_methods()
              sage: s.completions('u.elliptic_',globals())
              ['u.elliptic_e', 'u.elliptic_ec', 'u.elliptic_eu', 'u.elliptic_f', 'u.elliptic_kc', 'u.elliptic_pi']
          """
          self._exp = exp
          self._maxima_exp = None
  
      def __getattr__(self, s):
          """
          Direct attempts to get attributes of this wrapper to the corresponding
          Maxima expression. This allows tab completion to work as expected.
  
          We wrap the function calls in order to convert results back to Sage.
  
          EXAMPLES::
  
              sage: t = sin(x)^2 + cos(x)^2; t
              cos(x)^2 + sin(x)^2
              sage: u = t.maxima_methods()
              sage: import sage.interfaces.tab_completion as s
              sage: s.completions('u.airy_',globals())
              ['u.airy_ai', 'u.airy_bi', 'u.airy_dai', 'u.airy_dbi']
              sage: type(u.airy_ai)
              <class 'sage.symbolic.maxima_wrapper.MaximaFunctionElementWrapper'>
              sage: u.airy_ai()
              airy_ai(cos(x)^2 + sin(x)^2)
          """
          if self._maxima_exp is None:
              self._maxima_exp = self._exp._maxima_()
          if s[0] == '_':
              return getattr(self._maxima_exp, s)
          if s == 'trait_names':  # SageNB backward compatibility
              return self._maxima_()._tab_completion
          else:
              # add a wrapper function which converts the result back to
              # a Sage expression
              return MaximaFunctionElementWrapper(self._maxima_exp, s)
  
      def sage(self):
          """
          Return the Sage expression this wrapper corresponds to.
  
          EXAMPLES::
  
              sage: t = log(sqrt(2) - 1) + log(sqrt(2) + 1); t
              log(sqrt(2) + 1) + log(sqrt(2) - 1)
              sage: u = t.maxima_methods().sage()
              sage: u is t
              True
          """
          return self._exp
  
      def _symbolic_(self, parent):
          """
          EXAMPLES::
  
              sage: t = log(sqrt(2) - 1) + log(sqrt(2) + 1); t
              log(sqrt(2) + 1) + log(sqrt(2) - 1)
              sage: u = t.maxima_methods()
              sage: u._symbolic_(SR) is t
              True
              sage: SR(u) is t  # indirect doctest
              True
          """
          return parent(self._exp)
  
      def __reduce__(self):
          """
          EXAMPLES::
  
              sage: t = log(sqrt(2) - 1) + log(sqrt(2) + 1); t
              log(sqrt(2) + 1) + log(sqrt(2) - 1)
              sage: u = t.maxima_methods(); u
              MaximaWrapper(log(sqrt(2) + 1) + log(sqrt(2) - 1))
              sage: loads(dumps(u))
              MaximaWrapper(log(sqrt(2) + 1) + log(sqrt(2) - 1))
          """
          return (MaximaWrapper, (self._exp,))
  
      def _repr_(self):
          """
          EXAMPLES::
  
              sage: t = log(sqrt(2) - 1) + log(sqrt(2) + 1); t
              log(sqrt(2) + 1) + log(sqrt(2) - 1)
              sage: u = t.maxima_methods(); u
              MaximaWrapper(log(sqrt(2) + 1) + log(sqrt(2) - 1))
              sage: u._repr_()
              'MaximaWrapper(log(sqrt(2) + 1) + log(sqrt(2) - 1))'
          """
          return "MaximaWrapper(%s)"%(self._exp)
  