Ticket #12719: trac_12719-rebased-to-13211-vb.patch

File trac_12719-rebased-to-13211-vb.patch, 63.8 KB (added by jdemeyer, 8 years ago)

Rediffed patch

  • doc/en/reference/misc.rst

    # HG changeset patch
    # User Mike Hansen <mhansen@gmail.com>
    # Date 1338254047 25200
    # Node ID b0c5c396f8f1a9b90e4d2d898b70e9b5d604d7c6
    # Parent  a163652b02a9d49fea0ac784aaa935159e12cc00
    #12719: Upgrade to IPython 0.13
    
    diff --git a/doc/en/reference/misc.rst b/doc/en/reference/misc.rst
    a b  
    3030   sage/misc/dist
    3131   sage/misc/hg
    3232   sage/misc/preparser
     33   sage/misc/interpreter
    3334   sage/misc/functional
    3435   sage/misc/html
    3536   sage/misc/log
  • sage/all.py

    diff --git a/sage/all.py b/sage/all.py
    a b  
    255255    from sage.libs.all import symmetrica
    256256    symmetrica.end()
    257257       
    258 def _quit_sage_(self):
    259     import sage.misc.preparser_ipython
    260     if sage.misc.preparser_ipython.interface != None:
    261         sage.misc.preparser_ipython.switch_interface('sage')
    262         self.exit_now = False
    263         return
    264    
    265     from IPython.genutils import ask_yes_no
    266     if self.rc.confirm_exit:
    267         if ask_yes_no('Do you really want to exit ([y]/n)?','y'):
    268             self.exit_now = True
    269     else:
    270         self.exit_now = True
    271     if self.exit_now:
    272         quit_sage()
    273         self.exit_now = True
    274 
    275     return self.exit_now
    276 
    277 from IPython.iplib import InteractiveShell
    278 InteractiveShell.exit = _quit_sage_
    279 
    280 import sage.misc.displayhook
    281 sage.misc.displayhook.install()
    282 
    283258from sage.ext.interactive_constructors_c import inject_on, inject_off
    284259
    285260sage.structure.sage_object.register_unpickle_override('sage.categories.category', 'Sets', Sets)
  • sage/all_cmdline.py

    diff --git a/sage/all_cmdline.py b/sage/all_cmdline.py
    a b  
    2424    raise ValueError(msg)
    2525
    2626
     27sage.misc.session.init()
    2728
    28 def _init_cmdline(globs):
    29     from sage.misc.inline_fortran import InlineFortran
    30     fortran = InlineFortran(globs)
    31     globs['fortran'] = fortran
    32 
    33 
    34 
    35 sage.misc.session.init()
  • sage/interfaces/expect.py

    diff --git a/sage/interfaces/expect.py b/sage/interfaces/expect.py
    a b  
    271271            self._start()
    272272        return self._expect
    273273
    274     def interact(self):
    275         r"""
    276         This allows you to interactively interact with the child
    277         interpreter. Press Ctrl-D or type 'quit' or 'exit' to exit and
    278         return to Sage.
    279        
    280         .. note::
    281 
    282            This is completely different than the console() member
    283            function. The console function opens a new copy of the
    284            child interpreter, whereas the interact function gives you
    285            interactive access to the interpreter that is being used by
    286            Sage. Use sage(xxx) or interpretername(xxx) to pull objects
    287            in from sage to the interpreter.
    288         """
    289         if self._expect is None:
    290             self._start()
    291         import sage.misc.preparser_ipython
    292         sage.misc.preparser_ipython.switch_interface_general(self)
    293 
    294     def _pre_interact(self):
    295         pass
    296 
    297     def _post_interact(self):
    298         pass
    299 
    300274    def pid(self):
    301275        """
    302276        Return the PID of the underlying sub-process.
  • sage/interfaces/gap.py

    diff --git a/sage/interfaces/gap.py b/sage/interfaces/gap.py
    a b  
    178178import expect
    179179from expect import Expect, ExpectElement, FunctionElement, ExpectFunction
    180180from sage.misc.misc import SAGE_LOCAL, SAGE_EXTCODE, DOT_SAGE, is_64_bit, is_in_string
    181 from IPython.genutils import page
    182181import re
    183182import os
    184183import pexpect
     
    12751274            F = open(self._local_tmpfile(),"r")
    12761275            help = F.read()
    12771276            if pager:
     1277                from IPython.core.page import page
    12781278                page(help, start = int(sline)-1)
    12791279            else:
    12801280                return help
  • sage/interfaces/interface.py

    diff --git a/sage/interfaces/interface.py b/sage/interfaces/interface.py
    a b  
    8282           Sage. Use sage(xxx) or interpretername(xxx) to pull objects
    8383           in from sage to the interpreter.
    8484        """
    85         import sage.misc.preparser_ipython
    86         sage.misc.preparser_ipython.switch_interface_general(self)
     85        from sage.misc.interpreter import interface_shell_embed
     86        shell = interface_shell_embed(self)
     87        try:
     88            ipython = get_ipython()
     89        except NameError:
     90            shell()
     91        else:
     92            shell(local_ns=dict(ipython.user_ns))
    8793
    8894    def _pre_interact(self):
    8995        pass
  • sage/misc/displayhook.py

    diff --git a/sage/misc/displayhook.py b/sage/misc/displayhook.py
    a b  
    88- Bill Cauchois (2009): initial version
    99"""
    1010
    11 import IPython, sys, __builtin__
    12 from sage.matrix.matrix import is_Matrix
    13 from sage.modular.arithgroup.arithgroup_element import ArithmeticSubgroupElement
     11import sys, __builtin__
     12
    1413
    1514# This is used to wrap lines when printing "tall" lists.
    1615MAX_COLUMN = 70
     
    138137    # element is a matrix, or an ArithmeticSubgroupElement (a thin wrapper
    139138    # around a matrix). This should cover most cases.
    140139    if isinstance(obj, (tuple, list)):
     140        from sage.matrix.matrix import is_Matrix
     141        from sage.modular.arithgroup.arithgroup_element import ArithmeticSubgroupElement
    141142        if len(obj) > 0 and (is_Matrix(obj[0]) or isinstance(obj[0], ArithmeticSubgroupElement)):
    142143            if _check_tall_list_and_print(out_stream, obj):
    143144                return
    144145    print >>out_stream, `obj`
    145146
    146 def result_display(ip_self, obj):
    147     """
    148     This function implements the ``result_display`` hook for IPython.
    149     """
    150     # IPython's default result_display() uses the IPython.genutils.Term.cout stream.
    151     # See also local/lib/python2.6/site-packages/IPython/hooks.py.
    152     print_obj(IPython.genutils.Term.cout, obj)
    153 
    154147def displayhook(obj):
    155148    """
    156149    This function adheres to the displayhook protocol described in `PEP 217`_.
     
    175168    __builtin__._ = None
    176169    print_obj(sys.stdout, obj)
    177170    __builtin__._ = obj
    178 
    179 def install():
    180     """
    181     Install the new displayhook, so that subsequent output from the interpreter
    182     will be preprocessed by the mechanisms in this module.
    183     """
    184     # First, try to install the hook using the IPython hook API.
    185     ipapi = IPython.ipapi.get()
    186     if ipapi:
    187         ipapi.set_hook('result_display', result_display)
    188     else:
    189         # In certain modes where IPython is not in use, it is necessary to fall
    190         # back to setting Python's sys.displayhook.
    191         sys.displayhook = displayhook
  • sage/misc/edit_module.py

    diff --git a/sage/misc/edit_module.py b/sage/misc/edit_module.py
    a b  
    4545import inspect
    4646import os
    4747import re
    48 import IPython
    4948
    5049from string import Template
    5150
     
    302301    variable :envvar:`EDITOR`) with the file in which gcd is defined, and when your
    303302    editor supports it, also at the line in wich gcd is defined.
    304303    """
     304    import IPython.core.hooks
    305305    sageroot = sage.misc.sageinspect.SAGE_ROOT+'/'
    306306    runpathpattern = '^'+sageroot+'local/lib/python[^/]*/site-packages'
    307307    develbranch = sageroot+'devel/sage'
    308308    filename=re.sub(runpathpattern,develbranch,filename)
    309     IPython.hooks.editor(self, filename, linenum)
     309    IPython.core.hooks.editor(self, filename, linenum)
    310310
    311 
    312 ip = IPython.ipapi.get()
    313 if ip:
    314     ip.set_hook('editor', edit_devel)
    315 
    316 
  • sage/misc/interpreter.py

    diff --git a/sage/misc/interpreter.py b/sage/misc/interpreter.py
    a b  
    1 """
    2 Preparses input from the interpreter
     1r"""
     2Sage's IPython Modifications
    33
    4 Modified input.
     4This module contains all of Sage's customizations to the IPython
     5interpreter.  These changes consist of the following magjor components:
    56
    6   -- All ^'s (not in strings) are replaced by **'s.
     7  - :class:`SageTerminalApp`
     8  - :class:`SageInteractiveShell`
     9  - :func:`interface_shell_embed`
    710
    8   -- If M is a variable and i an integer,
    9      then M.i is replaced by M.gen(i), so generators can be
    10      accessed as in MAGMA.
     11SageTerminalApp
     12---------------
    1113
    12   -- quit alone on a line quits.
     14This is the main application object.  It is used by the
     15``$SAGE_ROOT/local/bin/sage-ipython`` script to start the Sage
     16command-line.  It's primary purpose is to
    1317
    14   -- load to load in scripts
     18  - Initialize the :class:`SageInteractiveShell`.
    1519
    16   -- Most int literals n are replaced by ZZ(n) Thus 2/3 is a rational
    17      number.  If they are in []'s right after a valid identifier they
    18      aren't replaced.
     20  - Provide default configuration options for the shell, and its
     21    subcomponents.  These work with (and can be overrided by)
     22    IPython's configuration system.
    1923
    20   -- real literals get wrapped in "RR" (with a precision)
    21      
    22   -- the R.<x,y,z> = ... notation
     24  - Monkey-patch IPython in order to support Sage's customization when
     25    introspecting objects.
    2326
    24 TODO:
     27  - Provide a custom :class:`SageCrashHandler` to give the user
     28    instructions on how to report the crash to the Sage support
     29    mailing list.
    2530
    26   I have no plans for anything further, except to improve the
    27   robustness of the above.  Preparsing may work incorrectly for
    28   multi-line input lines in some cases; this will be fixed.
    29  
    30 All other input is processed normally.
     31SageInteractiveShell
     32--------------------
    3133
    32 It automatically converts *most* integer literals to Sage Integer's and 
    33 decimal literals to Sage Reals.  It does not convert indexes into
    34 1-d arrays, since those have to be ints.   
    35  
    36 I also extended the load command so it *really* works exactly
    37 like the Sage interpreter, so e.g., ^ for exponentiation is
    38 allowed.  Also files being loaded can themselves load other files.
    39 Finally, I added an "attach" command, e.g.,
    40     attach 'file'
    41 that works kind of like attach in MAGMA.  Whenever you enter a blank
    42 line in the Sage interpreter, *all* attached files that have changed
    43 are automatically reloaded.  Moreover, the attached files work according
    44 to the Sage interpreter rules, i.e., ^ --> **, etc. 
    45  
    46 I also fixed it so ^ is not replaced by ** inside strings.
    47  
    48 Finally, I added back the M.n notation for the n-th generator
    49 of object M, again like in MAGMA.
     34The :class:`SageInteractiveShell` object is the object responsible for
     35accepting input from the user and evaluating it.  From the command-line,
     36this object can be retrieved by running::
    5037
    51 EXAMPLE::
     38    sage: shell = get_ipython() #not tested
    5239
    53     sage: 2/3
    54     2/3
    55     sage: type(2/3)
    56     <type 'sage.rings.rational.Rational'>
    57     sage: a = 49928420832092
    58     sage: type(a)
    59     <type 'sage.rings.integer.Integer'>
    60     sage: a.factor()
    61     2^2 * 11 * 1134736837093
    62     sage: v = [1,2,3]
    63     sage: type(v[0])
    64     <type 'sage.rings.integer.Integer'>
     40The :class:`SageInteractiveShell` provides the following
     41customizations:
    6542
    66 If we don't make potential list indices int's, then lots of stuff
    67 breaks, or users have to type v[int(7)], which is insane. 
    68 A fix would be to only not make what's in the brackets an
    69 Integer if what's before the bracket is a valid identifier,
    70 so the w = [5] above would work right.
    71 ::
     43  - Modifying the input before it is evaluated.  See
     44    :class:`SagePromptTransformer`, :class:`SagePreparseTransformer`,
     45    :class:`LoadAttachTransformer`,
     46    :class:`InterfaceMagicTransformer`, and
     47    :meth:`~SageInteractiveShell.init_prefilter`.
    7248
    73     sage: s = "x^3 + x + 1"
    74     sage: s
    75     'x^3 + x + 1'
    76     sage: pari(s)
    77     x^3 + x + 1
    78     sage: f = pari(s)
    79     sage: f^2
    80     x^6 + 2*x^4 + 2*x^3 + x^2 + 2*x + 1
    81     sage: V = VectorSpace(QQ,3)
    82     sage: V.0
    83     (1, 0, 0)
    84     sage: V.1
    85     (0, 1, 0)
    86     sage: s = "This. Is. It."
    87     sage: print s
    88     This. Is. It.
     49  - Provide a number of IPython magic functions that work with Sage
     50    and its preparser.  See :meth:`~SageInteractiveShell.magic_timeit`,
     51    :meth:`~SageInteractiveShell.magic_prun`,
     52    :meth:`~SageInteractiveShell.magic_load`,
     53    :meth:`~SageInteractiveShell.magic_attach`, and
     54    :meth:`~SageInteractiveShell.magic_iload`.
     55
     56  - Adding support for attached files.  See
     57    :meth:`~SageInteractiveShell.run_cell`.
     58
     59  - Cleanly deinitialize the Sage library before exiting.  See
     60    :meth:`~SageInteractiveShell.ask_exit`.
     61
     62  - Modify the libraries before calling system commands. See
     63    :meth:`~SageInteractiveShell.system_raw`.
     64
     65Interface Shell
     66---------------
     67
     68The function :func:`interface_shell_embed` takes a
     69:class:`~sage.interfaces.interface.Interface` object and returns an
     70embeddable IPython shell which can be used to directly interact with
     71that shell.  The bulk of this functionality is provided through
     72:class:`InterfaceShellTransformer`.
     73
     74Auto-generated Documentation
     75----------------------------
    8976"""
    9077
    9178#*****************************************************************************
    92 #       Copyright (C) 2004 William Stein <wstein@gmail.com>
     79#       Copyright (C) 2004-2012 William Stein <wstein@gmail.com>
    9380#
    9481#  Distributed under the terms of the GNU General Public License (GPL)
    9582#
    9683#                  http://www.gnu.org/licenses/
    9784#*****************************************************************************
    98 import IPython.ipapi
    99 _ip = IPython.ipapi.get()
    100 
    101 __author__ = 'William Stein <wstein@gmail.com> et al.'
    102 __license__ = 'GPL'
    103 
    104 import os
    105 import log
    106 import re
    107 
    108 import remote_file
    109 
    110 from IPython.iplib import InteractiveShell
    111 
    112 import preparser_ipython
    113 from preparser import preparse_file, load_wrap, modified_attached_files, attached_files
    114 
    115 import cython
    116 
    117 # IPython has a prefilter() function that analyzes each input line. We redefine
    118 # it here to first pre-process certain forms of input
    119 
    120 # The prototype of any alternate prefilter must be like this one (the name
    121 # doesn't matter):
    122 # - line is a string containing the user input line.
    123 # - continuation is a parameter which tells us if we are processing a first line of
    124 #   user input or the second or higher of a multi-line statement.
    125 
    126 
    127 
    128 def load_startup_file(file):
    129     if os.path.exists(file):
    130         X = do_prefilter_paste('load "%s"'%file,False)
    131         _ip.runlines(X)
    132     if os.path.exists('attach.sage'):
    133         X = do_prefilter_paste('attach "attach.sage"',False)
    134         _ip.runlines(X)
    135 
    136 
    137 def do_prefilter_paste(line, continuation):
    138     """
    139     Alternate prefilter for input.
    140 
    141     INPUT:
    142    
    143     - ``line`` -- a single line; must *not* have any newlines in it
    144     - ``continuation`` -- whether the input line is really part
    145       of the previous line, because of open parens or backslash.
    146     """
    147     if '\n' in line:
    148         raise RuntimeError, "bug in function that calls do_prefilter_paste -- there can be no newlines in the input"
    149 
    150     # This is so it's OK to have lots of blank space at the
    151     # beginning of any non-continuation line.
    152    
    153     if continuation:
    154         # strip ...'s that appear in examples
    155         L = line.lstrip()
    156         if L[:3] == '...':
    157             line = L[3:]
    158     else:
    159         line = line.lstrip()
    160        
    161     line = line.rstrip()
    162 
    163     # Process attached files.
    164     for F in modified_attached_files():
    165         # We attach the files again instead of loading them,
    166         # to preserve tracebacks or efficiency according
    167         # to the settings of load_attach_mode().
    168         _ip.runlines(load_wrap(F, attach=True))
    169        
    170     # Get rid of leading sage: prompts so that pasting of examples
    171     # from the documentation works.  This is like MAGMA's
    172     # SetLinePrompt(false).
    173     for prompt in ['sage:', '>>>']:
    174         if not continuation:
    175             while True:
    176                 strip = False
    177                 if line[:3] == prompt:
    178                     line = line[3:].lstrip()
    179                     strip = True
    180                 elif line[:5] == prompt:
    181                     line = line[5:].lstrip()
    182                     strip = True
    183                 if not strip:
    184                     break
    185                 else:
    186                     line = line.lstrip()
    187        
    188     # 'quit' alone on a line to quit.
    189     if line.lower() in ['quit', 'exit', 'quit;', 'exit;']:
    190         line = '%quit'
    191 
    192     # An interactive load command, like iload in MAGMA.
    193     if line[:6] == 'iload ':
    194         try:
    195             name = str(eval(line[6:]))
    196         except StandardError:
    197             name = str(line[6:].strip())
    198         try:
    199             F = open(name)
    200         except IOError:
    201             raise ImportError, 'Could not open file "%s"'%name
    202        
    203         print 'Interactively loading "%s"'%name
    204         n = len(__IPYTHON__.input_hist)
    205         for L in F.readlines():
    206             L = L.rstrip()
    207             Llstrip = L.lstrip()
    208             raw_input('sage: %s'%L.rstrip())
    209             __IPYTHON__.input_hist_raw.append(L)
    210             if Llstrip[:5] == 'load ' or Llstrip[:7] == 'attach ' \
    211                    or Llstrip[:6] == 'iload ':
    212                 log.offset -= 1                   
    213                 L = do_prefilter_paste(L, False)
    214                 if len(L.strip()) > 0:
    215                     _ip.runlines(L)
    216                 L = ''
    217             else:
    218                 L = preparser_ipython.preparse_ipython(L, not continuation)
    219             __IPYTHON__.input_hist.append(L)
    220             __IPYTHON__.push(L)
    221         log.offset += 1
    222         return ''
    223 
    224        
    225     #################################################################
    226     # load and attach commands
    227     #################################################################
    228     for cmd in ['load', 'attach']:
    229         if line.lstrip().startswith(cmd+' '):
    230             j = line.find(cmd+' ')
    231             s = line[j+len(cmd)+1:].strip()
    232             if not s.startswith('('):
    233                 line = ' '*j + load_wrap(s, cmd=='attach')
    234 
    235     if len(line) > 0:
    236         line = preparser_ipython.preparse_ipython(line, not continuation)
    237 
    238     return line
     85import os, log, re, new, sys
     86from preparser import (preparse, preparse_file, load_wrap,
     87                       modified_attached_files, attached_files)
    23988
    24089def load_cython(name):
     90    import cython
    24191    cur = os.path.abspath(os.curdir)
    24292    try:
    24393        mod, dir  = cython.cython(name, compile_message=True, use_cache=True)
     
    24999    return 'from %s import *'%mod
    250100
    251101def handle_encoding_declaration(contents, out):
    252     """Find a PEP 263-style Python encoding declaration in the first or
     102    r"""Find a PEP 263-style Python encoding declaration in the first or
    253103    second line of `contents`. If found, output it to `out` and return
    254104    `contents` without the encoding line; otherwise output a default
    255105    UTF-8 declaration and return `contents`.
     
    326176        '#!/usr/local/bin/python\nimport os, sys'
    327177
    328178
    329     NOTES:
     179    NOTES::
    330180
    331     - PEP 263: http://www.python.org/dev/peps/pep-0263/
    332     - PEP 263 says that Python will interpret a UTF-8 byte order mark
    333       as a declaration of UTF-8 encoding, but I don't think we do
    334       that; this function only sees a Python string so it can't
    335       account for a BOM.
    336     - We default to UTF-8 encoding even though PEP 263 says that
    337       Python files should default to ASCII.
    338     - Also see http://docs.python.org/ref/encodings.html.
     181        PEP 263: http://www.python.org/dev/peps/pep-0263/
    339182
    340     AUTHORS:
     183        PEP 263 says that Python will interpret a UTF-8 byte order mark
     184        as a declaration of UTF-8 encoding, but I don't think we do
     185        that; this function only sees a Python string so it can't
     186        account for a BOM.
    341187
    342     - Lars Fischer
    343     - Dan Drake (2010-12-08, rewrite for ticket #10440)
     188        We default to UTF-8 encoding even though PEP 263 says that
     189        Python files should default to ASCII.
     190
     191        Also see http://docs.python.org/ref/encodings.html.
     192
     193    AUTHORS::
     194
     195        - Lars Fischer
     196        - Dan Drake (2010-12-08, rewrite for ticket #10440)
    344197    """
    345198    lines = contents.splitlines()
    346199    for num, line in enumerate(lines[:2]):
     
    386239    out.close()
    387240    return tmpfilename
    388241
    389 def sage_prefilter(self, block, continuation):
     242def embedded():
    390243    """
    391     Sage's prefilter for input.  Given a string block (usually a
    392     line), return the preparsed version of it. 
     244    Returns True if Sage is being run from the notebook.
    393245
    394     INPUT:
    395 
    396     - block -- string (usually a single line, but not always)
    397     - continuation -- whether or not this line is a continuation.
     246    EXAMPLES::
     247   
     248        sage: from sage.misc.interpreter import embedded
     249        sage: embedded()
     250        False
    398251    """
    399     try:
    400         block2 = ''
    401         first = True
    402         B = block.split('\n')
    403         for i in range(len(B)):
    404             L = B[i]
    405             M = do_prefilter_paste(L, continuation or (not first))
    406             first = False
    407             # The L[:len(L)-len(L.lstrip())]  business here preserves
    408             # the whitespace at the beginning of L.
    409             if block2 != '':
    410                 block2 += '\n'
    411             lstrip = L.lstrip()
    412             if lstrip[:5] == 'sage:' or lstrip[:3] == '>>>' or i==0:
    413                 block2 += M
    414             else:
    415                 block2 += L[:len(L)-len(lstrip)] + M
    416 
    417     except None:
    418        
    419         print "WARNING: An error occurred in the Sage parser while"
    420         print "parsing the following block:"
    421         print block
    422         print "Please report this as a bug (include the output of typing '%hist')."
    423         block2 = block
    424        
    425     return InteractiveShell._prefilter(self, block2, continuation)
    426 
    427 
    428 import sage.server.support
    429 def embedded():
     252    import sage.server.support
    430253    return sage.server.support.EMBEDDED_MODE
    431254
    432 ipython_prefilter = InteractiveShell.prefilter
     255#TODO: This global variable do_preparse should be associtated with an
     256#IPython InteractiveShell as opposed to a global variable in this
     257#module.
    433258do_preparse=True
    434259def preparser(on=True):
    435260    """
    436261    Turn on or off the Sage preparser.
    437262
    438     INPUT:
    439 
    440     - ``on`` -- bool (default: True) if True turn on preparsing; if False, turn it off.
     263    :keyword on: if True turn on preparsing; if False, turn it off.
     264    :type on: bool
    441265
    442266    EXAMPLES::
    443267
     
    453277    global do_preparse
    454278    if on:
    455279        do_preparse = True
    456         InteractiveShell.prefilter = sage_prefilter
    457280    else:
    458281        do_preparse = False       
    459         InteractiveShell.prefilter = ipython_prefilter
    460282
    461283
    462 import sagedoc
    463 import sageinspect
    464 import IPython.OInspect
    465 IPython.OInspect.getdoc = sageinspect.sage_getdoc #sagedoc.my_getdoc
    466 IPython.OInspect.getsource = sagedoc.my_getsource
    467 IPython.OInspect.getargspec = sageinspect.sage_getargspec
     284###############################################################
     285# Old code for handling the sage prompt in previous verisons of
     286# IPython
     287###############################################################
     288def set_sage_prompt(s):
     289    """
     290    Sets the Sage prompt to the string ``s``.
    468291
    469 #We monkey-patch IPython to disable the showing of plots
    470 #when doing introspection on them. This fixes Trac #2163.
    471 old_pinfo = IPython.OInspect.Inspector.pinfo
    472 def sage_pinfo(self, *args, **kwds):
     292    :param s: the new prompt
     293    :type s: string
     294    :returns: None
     295
     296    EXAMPLES::
     297
     298        sage: from sage.misc.interpreter import get_test_shell
     299        sage: shell = get_test_shell()
     300        sage: shell.run_cell('from sage.misc.interpreter import set_sage_prompt')
     301        sage: shell.run_cell('set_sage_prompt(u"new: ")')
     302        sage: shell.prompt_manager.in_template
     303        u'new: '
     304        sage: shell.run_cell('set_sage_prompt(u"sage: ")')
     305
    473306    """
    474     A wrapper around IPython.OInspect.Inspector.pinfo which turns
    475     off show_default before it is called and then sets it back
    476     to its previous value.
    477 
    478     Since this requires an IPython shell to test and the doctests aren't,
    479     run under IPython, we cannot add doctests for this function.
    480     """
    481     from sage.plot.all import show_default
    482     old_value = show_default()
    483     show_default(False)
    484    
    485     result = old_pinfo(self, *args, **kwds)
    486    
    487     show_default(old_value)
    488     return result
    489 IPython.OInspect.Inspector.pinfo = sage_pinfo
    490 
    491 import __builtin__
    492 _prompt = 'sage'
    493 
    494 def set_sage_prompt(s):
    495     global _prompt
    496     _prompt = str(s)
     307    ipython = get_ipython()
     308    ipython.prompt_manager.in_template = s
    497309
    498310def sage_prompt():
    499     log.update()
    500     return '%s'%_prompt
     311    """
     312    Returns the current Sage prompt.
    501313
    502 __builtin__.sage_prompt = sage_prompt
     314    EXAMPLES::
    503315
     316        sage: from sage.misc.interpreter import get_test_shell
     317        sage: shell = get_test_shell()
     318        sage: shell.run_cell('sage_prompt()')
     319        u'sage: '
     320    """
     321    ipython = get_ipython()
     322    return ipython.prompt_manager.in_template
    504323
     324###############
     325# Displayhook #
     326###############
     327from IPython.core.displayhook import DisplayHook
     328class SageDisplayHook(DisplayHook):
     329    """
     330    A replacement for ``sys.displayhook`` which correctly print lists
     331    of matrices.
    505332
    506 #######################################
    507 #
    508 def load_a_file(argstr, globals):
    509     s = open(argstr).read()
    510     return preparse_file(s, globals=globals)
     333    EXAMPLES::
     334
     335        sage: from sage.misc.interpreter import SageDisplayHook, get_test_shell
     336        sage: shell = get_test_shell()
     337        sage: shell.displayhook
     338        <sage.misc.interpreter.SageDisplayHook object at 0x...>
     339        sage: shell.run_cell('a = identity_matrix(ZZ, 2); [a,a]')
     340        [
     341        [1 0]  [1 0]
     342        [0 1], [0 1]
     343        ]
     344    """
     345    def compute_format_data(self, result):
     346        r"""
     347        Computes the format data of ``result``.  If the
     348        :func:`sage.misc.displayhook.print_obj` writes a string, then
     349        we override IPython's :class:`DisplayHook` formatting.
     350
     351        EXAMPLES::
     352
     353            sage: from sage.misc.interpreter import get_test_shell
     354            sage: shell = get_test_shell()
     355            sage: shell.displayhook
     356            <sage.misc.interpreter.SageDisplayHook object at 0x...>
     357            sage: shell.displayhook.compute_format_data(2)
     358            {u'text/plain': '2'}
     359            sage: a = identity_matrix(ZZ, 2)
     360            sage: shell.displayhook.compute_format_data([a,a])
     361            {u'text/plain': '[\n[1 0]  [1 0]\n[0 1], [0 1]\n]'}
     362        """
     363        format_data = super(SageDisplayHook, self).compute_format_data(result)
     364
     365        from cStringIO import StringIO
     366        s = StringIO()
     367        from sage.misc.displayhook import print_obj
     368        print_obj(s, result)
     369        if s:
     370            format_data['text/plain'] = s.getvalue().strip()
     371        return format_data
     372
     373from IPython.frontend.terminal.interactiveshell import TerminalInteractiveShell
     374
     375class SageInteractiveShell(TerminalInteractiveShell):
     376    displayhook_class = SageDisplayHook #used by init_displayhook
    511377   
     378    def get_prefilter_transformer(self, cls):
     379        """
     380        Returns this shell's :class:`PrefilterTransformer` of type
     381        :class:`cls` if it has one.
     382       
     383        :param cls: the class of the transformer
     384        :type cls: a subclass of :class:`IPython.core.prefilter.PrefilterTransformer`
     385
     386        :rtype: :class:`cls`
     387        :raises: :exc:`ValueError` if the shell does not have a
     388                 :class:`PrefilterTransformer` of type :class:`cls`
     389
     390        EXAMPLES::
     391
     392            sage: from sage.misc.interpreter import get_test_shell, SagePreparseTransformer, InterfaceShellTransformer
     393            sage: shell = get_test_shell()
     394            sage: shell.get_prefilter_transformer(SagePreparseTransformer)
     395            <SagePreparseTransformer(priority=1000, enabled=True)>
     396            sage: shell.get_prefilter_transformer(InterfaceShellTransformer)
     397            Traceback (most recent call last):
     398            ...
     399            ValueError: could not find transformer InterfaceShellTransformer
     400
     401        """
     402        for transformer in self.prefilter_manager.transformers:
     403            if transformer.__class__ is cls:
     404                return transformer
     405        raise ValueError("could not find transformer %s"%cls.__name__)
     406       
     407    def init_prefilter(self):
     408        """
     409        Initialize the input transformers used by the Sage shell.
     410        Currently, we use
     411
     412          - :class:`SagePromptTransformer`
     413          - :class:`SagePreparseTransformer`
     414          - :class:`LoadAttachTransformer`
     415          - :class:`InterfaceMagicTransformer`
     416           
     417        EXAMPLES::
     418       
     419            sage: from sage.misc.interpreter import get_test_shell
     420            sage: shell = get_test_shell()
     421            sage: shell.prefilter_manager.transformers #indirect doctest
     422            [<SagePromptTransformer(priority=0, enabled=True)>,
     423             <PyPromptTransformer(priority=50, enabled=True)>,
     424             <IPyPromptTransformer(priority=50, enabled=True)>,
     425             <LoadAttachTransformer(priority=90, enabled=True)>,
     426             <AssignSystemTransformer(priority=100, enabled=True)>,
     427             <AssignMagicTransformer(priority=200, enabled=True)>,
     428             <InterfaceMagicTransformer(priority=900, enabled=True)>,
     429             <SagePreparseTransformer(priority=1000, enabled=True)>]
     430        """
     431        # Ideally, this code should be in a custom
     432        # :class:`PrefilterManager` class, but the code doesn't quite
     433        # make that clean as we'd have to reproduce the code from
     434        # :meth:`TerminalInteractiveShell.init_prefilter`
     435        super(SageInteractiveShell, self).init_prefilter()
     436       
     437        #Add the Sage input transformers
     438        for cls in [SagePreparseTransformer, SagePromptTransformer,
     439                    LoadAttachTransformer, InterfaceMagicTransformer]:
     440            t = cls(prefilter_manager=self.prefilter_manager,
     441                    shell=self, config=self.config)
     442        self.prefilter_manager.sort_transformers()
     443
     444    def run_cell(self, *args, **kwds):
     445        r"""
     446        This method loads all modified attached files before executing
     447        any code.  Any arguments and keyword arguments are passed to
     448        :meth:`TerminalInteractiveShell.run_cell`.
     449
     450        EXAMPLES::
     451
     452            sage: import os
     453            sage: from sage.misc.interpreter import get_test_shell
     454            sage: from sage.misc.misc import tmp_dir
     455            sage: shell = get_test_shell()
     456            sage: tmp = os.path.join(tmp_dir(), 'run_cell.py')
     457            sage: f = open(tmp, 'w'); f.write('a = 2\n'); f.close()
     458            sage: shell.run_cell('%attach ' + tmp)
     459            sage: shell.run_cell('a')
     460            2
     461            sage: import time; time.sleep(1)
     462            sage: f = open(tmp, 'w'); f.write('a = 3\n'); f.close()
     463            sage: shell.run_cell('a')
     464            3
     465        """
     466        for f in modified_attached_files():
     467            super(SageInteractiveShell, self).run_cell('%%load "%s"'%f)
     468        return super(SageInteractiveShell, self).run_cell(*args, **kwds)
     469
     470    def ask_exit(self):
     471        """
     472        We need to run the :func:`sage.all.quit_sage` function when we
     473        exit the shell.
     474
     475        EXAMPLES:
     476
     477        We install a fake :func:`sage.all.quit_sage`::
     478       
     479            sage: import sage.all
     480            sage: old_quit = sage.all.quit_sage
     481            sage: def new_quit(): print "Quitting..."
     482            sage: sage.all.quit_sage = new_quit
     483
     484
     485        Now, we can check to see that this method works::
     486       
     487            sage: from sage.misc.interpreter import get_test_shell
     488            sage: shell = get_test_shell()
     489            sage: shell.ask_exit()
     490            Quitting...
     491            sage: shell.exit_now
     492            True
     493
     494        Clean up after ourselves::
     495
     496            sage: shell.exit_now = False
     497            sage: sage.all.quit_sage = old_quit
     498        """
     499        from sage.all import quit_sage
     500        quit_sage()
     501        super(SageInteractiveShell, self).ask_exit()
     502
     503    def system_raw(self, cmd):
     504        """
     505        Adjust the libraries before calling system commands.  See Trac
     506        #975 for a discussion of this function.
     507
     508        .. note::
     509
     510           There does not seem to be a good way to doctest this
     511           function.
     512        """
     513        sage_commands = os.listdir(os.environ['SAGE_ROOT']+"/local/bin/")
     514        DARWIN_SYSTEM = os.uname()[0]=='Darwin'
     515        if cmd in sage_commands:
     516            return super(SageInteractiveShell, self).system_raw(cmd)
     517        else:
     518            libraries = 'LD_LIBRARY_PATH=$$SAGE_ORIG_LD_LIBRARY_PATH;'
     519            if DARWIN_SYSTEM:
     520                libraries += 'DYLD_LIBRARY_PATH=$$SAGE_ORIG_DYLD_LIBRARY_PATH;'
     521            return super(SageInteractiveShell, self).system_raw(cmd)
     522   
     523    #######################################
     524    # Magic functions
     525    #######################################
     526    def magic_timeit(self, s):
     527        """
     528        Runs :func:`sage_timeit` on the code s.  This is designed to
     529        be used from the command line as ``%timeit 2+2``.
     530
     531        :param s: code to be timed
     532        :type s: string
     533
     534        EXAMPLES::
     535
     536            sage: from sage.misc.interpreter import get_test_shell
     537            sage: shell = get_test_shell()
     538            sage: shell.magic_timeit('2+2') #random output
     539            625 loops, best of 3: 525 ns per loop
     540            sage: shell.magic_timeit('2r+2r').__class__
     541            <class sage.misc.sage_timeit.SageTimeitResult at 0x...>
     542        """
     543        from sage.misc.sage_timeit import sage_timeit
     544        return sage_timeit(s, self.user_ns)
     545
     546    def magic_prun(self, parameter_s='', **kwds):
     547        """
     548        Profiles the code contained in ``parameter_s``. This is
     549        designed to be used from the command line as ``%prun 2+2``.
     550
     551        :param parameter_s: code to be profiled
     552        :type parameter_s: string
     553
     554        EXAMPLES::
     555
     556            sage: from sage.misc.interpreter import get_test_shell
     557            sage: shell = get_test_shell()
     558            sage: shell.magic_prun('2+2')
     559                     2 function calls in 0.000 CPU seconds
     560            <BLANKLINE>
     561               Ordered by: internal time
     562            <BLANKLINE>
     563               ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     564                    1    0.000    0.000    0.000    0.000 <string>:1(<module>)
     565                    1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
     566        """
     567        return super(SageInteractiveShell, self).magic_prun(parameter_s=preparse(parameter_s),
     568                                                            **kwds)
     569
     570    def magic_load(self, s):
     571        r"""     
     572        Loads the code contained in the file ``s``. This is designed
     573        to be used from the command line as ``%load /path/to/file``.
     574
     575        :param s: file to be loaded
     576        :type s: string
     577
     578        EXAMPLES::
     579
     580            sage: import os
     581            sage: from sage.misc.interpreter import get_test_shell
     582            sage: from sage.misc.misc import tmp_dir
     583            sage: shell = get_test_shell()
     584            sage: tmp = os.path.join(tmp_dir(), 'run_cell.py')
     585            sage: f = open(tmp, 'w'); f.write('a = 2\n'); f.close()
     586            sage: shell.magic_load(tmp)
     587            sage: shell.run_cell('a')
     588            2
     589        """
     590        from sage.misc.preparser import load_wrap
     591        return self.ex(load_wrap(s, attach=False))
     592
     593    def magic_attach(self, s):
     594        r"""     
     595        Attaches the code contained in the file ``s``. This is
     596        designed to be used from the command line as
     597        ``%attach /path/to/file``.
     598
     599        :param s: file to be attached
     600        :type s: string
     601
     602        EXAMPLES::
     603
     604            sage: import os
     605            sage: from sage.misc.interpreter import get_test_shell
     606            sage: from sage.misc.misc import tmp_dir
     607            sage: shell = get_test_shell()
     608            sage: tmp = os.path.join(tmp_dir(), 'run_cell.py')
     609            sage: f = open(tmp, 'w'); f.write('a = 2\n'); f.close()
     610            sage: shell.magic_attach(tmp)
     611            sage: shell.run_cell('a')
     612            2
     613            sage: import time; time.sleep(1)
     614            sage: f = open(tmp, 'a'); f.write('a = 3\n'); f.close()
     615            sage: shell.run_cell('a')
     616            3
     617        """
     618        from sage.misc.preparser import load_wrap
     619        return self.ex(load_wrap(s, attach=True))
     620
     621    def magic_iload(self, s):
     622        """
     623        A magic command to interactively load a file as in MAGMA.
     624
     625        :param s: the file to be interactively loaded
     626        :type s: string
     627
     628        .. note::
     629
     630           Currently, this cannot be doctested as it relies on
     631           :func:`raw_input`.
     632        """
     633        try:
     634            name = str(eval(s))
     635        except Exception:
     636            name = s.strip()
     637
     638        try:
     639            F = open(name)
     640        except IOError:
     641            raise ImportError, 'could not open file "%s"'%name
     642
     643        #We need to update the execution count so that the history for the
     644        #iload command and the history for the first line of the loaded
     645        #file are not written to the history database with the same line
     646        #number (execution count).  This happens since the execution count
     647        #is updated only after the magic command is run.
     648        self.execution_count += 1
     649
     650        print 'Interactively loading "%s"'%name
     651
     652        # The following code is base on IPython's
     653        # InteractiveShell.interact,
     654        more = False
     655        for line in F.readlines():
     656            prompt = self.prompt_manager.render('in' if not more else 'in2', color=True)
     657            raw_input(prompt.encode('utf-8') + ' ' + line.rstrip())
     658
     659            self.input_splitter.push(line)
     660            more = self.input_splitter.push_accepts_more()
     661            if not more:
     662                source, source_raw = self.input_splitter.source_raw_reset()
     663                self.run_cell(source_raw, store_history=True)
     664
     665#######################################################
     666# Transformers - these modify the command line input before it gets
     667# evaluated by the interpreter. See IPython.core.prefilter f
     668#######################################################
     669from IPython.core.prefilter import PrefilterTransformer
     670
     671class SagePreparseTransformer(PrefilterTransformer):
     672    """
     673    This transformer preparses the line of code before it get
     674    evaluated by IPython.
     675    """
     676    priority = 1000
     677    def transform(self, line, continue_prompt):
     678        """
     679        Preparse *line* if necessary.
     680
     681        :param line: the line to be transformed
     682        :type line: string
     683        :param continue_prompt: is this line a continuation in a sequence of multiline input?
     684        :type continue_prompt: bool
     685
     686        EXAMPLES::
     687
     688            sage: from sage.misc.interpreter import get_test_shell, SagePreparseTransformer
     689            sage: shell = get_test_shell()
     690            sage: spt = shell.get_prefilter_transformer(SagePreparseTransformer); spt
     691            <SagePreparseTransformer(priority=1000, enabled=True)>
     692            sage: spt.transform('2', False)
     693            'Integer(2)'
     694            sage: shell.run_cell('preparser(False)')
     695            sage: spt.transform('2', False)
     696            '2'
     697            sage: shell.run_cell('preparser(True)')
     698        """
     699        if do_preparse and not line.startswith('%'):
     700            return preparse(line)
     701        else:
     702            return line
     703
     704class LoadAttachTransformer(PrefilterTransformer):
     705    r"""
     706    This transformer handles input lines that start out like
     707    ``load ...`` for ``attach ...``.  Since there are objects in the
     708    Sage namespace named ``load`` and ``attach``, IPython's automagic
     709    will not transform these lines into ``%load ...`` and
     710    ``%attach ...``, respectively.  Thus, we have to do it manually.
     711    """
     712    priority = 90
     713    def transform(self, line, continue_prompt):
     714        """
     715        :param line: the line to be transformed
     716        :type line: string
     717        :param continue_prompt: is this line a continuation in a sequence of multiline input?
     718        :type continue_prompt: bool
     719
     720        EXAMPLES::
     721
     722            sage: from sage.misc.interpreter import get_test_shell, LoadAttachTransformer
     723            sage: shell = get_test_shell()
     724            sage: lat = shell.get_prefilter_transformer(LoadAttachTransformer); lat
     725            <LoadAttachTransformer(priority=90, enabled=True)>
     726            sage: lat.transform('load /path/to/file', False)
     727            '%load /path/to/file'
     728            sage: lat.transform('attach /path/to/file', False)
     729            '%attach /path/to/file'
     730        """
     731        for cmd in ['load', 'attach']:
     732            if line.startswith(cmd + ' '):
     733                return '%' + line
     734        return line
     735   
     736class SagePromptTransformer(PrefilterTransformer):
     737    """
     738    This transformer removes Sage prompts from the imput line.
     739    """
     740    _sage_prompt_re = re.compile(r'(^[ \t]*sage: |^[ \t]*\.+: )+')
     741
     742    priority = 0
     743    def transform(self, line, continue_prompt):
     744        """
     745        :param line: the line to be transformed
     746        :type line: string
     747        :param continue_prompt: is this line a continuation in a sequence of multiline input?
     748        :type continue_prompt: bool
     749
     750        EXAMPLES::
     751
     752            sage: from sage.misc.interpreter import get_test_shell, SagePromptTransformer
     753            sage: shell = get_test_shell()
     754            sage: spt = shell.get_prefilter_transformer(SagePromptTransformer); spt
     755            <SagePromptTransformer(priority=0, enabled=True)>
     756            sage: spt.transform("sage: sage: 2 + 2", False)
     757            '2 + 2'
     758            sage: spt.transform('', False)
     759            ''
     760            sage: spt.transform("      sage: 2+2", False)
     761            '2+2'
     762
     763        """
     764        if not line or line.isspace() or line.strip() == '...':
     765            # This allows us to recognize multiple input prompts separated by
     766            # blank lines and pasted in a single chunk, very common when
     767            # pasting doctests or long tutorial passages.
     768            return ''
     769        while True:
     770            m = self._sage_prompt_re.match(line)
     771            if m:
     772                line = line[len(m.group(0)):]
     773            else:
     774                break
     775        return line
     776
     777class InterfaceMagicTransformer(PrefilterTransformer):
     778    """
     779    This transformer is for handling commands like ``%maxima`` which
     780    are designed to go into a Maxima shell.  This one is tricky since
     781    the magic commands are transformed in
     782    :mod:`IPython.core.inputsplitter` before they can even go into the
     783    :class:`PrefilterTransformer` framework.  Thus, we need to match
     784    the output of those transformations instead of something simple
     785    like ``"%maxima"``.
     786
     787    .. note::
     788
     789        This will only work if the corresponding object is of type
     790        :class:`sage.interfaces.interface.Interface`.
     791    """
     792    priority = 900
     793    _magic_command_re = re.compile(r"get_ipython\(\).magic\(u'([^\d\W]\w+)'\)", re.UNICODE)
     794    def transform(self, line, continue_prompt):
     795        """
     796        :param line: the line to be transformed
     797        :type line: string
     798        :param continue_prompt: is this line a continuation in a sequence of multiline input?
     799        :type continue_prompt: bool
     800
     801        EXAMPLES::
     802
     803            sage: from sage.misc.interpreter import get_test_shell, InterfaceMagicTransformer
     804            sage: shell = get_test_shell()
     805            sage: imt = shell.get_prefilter_transformer(InterfaceMagicTransformer); imt
     806            <InterfaceMagicTransformer(priority=900, enabled=True)>
     807            sage: imt.transform("get_ipython().magic(u'maxima')", False)
     808            'maxima.interact()'
     809            sage: imt.transform("get_ipython().magic(u'prun')", False)
     810            "get_ipython().magic(u'prun')"
     811        """
     812        match = self._magic_command_re.match(line)
     813        if match:
     814            interface, = match.groups()
     815            from sage.interfaces.interface import Interface
     816            if isinstance(self.shell.user_ns.get(interface, None), Interface):
     817                return interface + '.interact()'
     818        return line
     819
     820###################
     821# Interface shell #
     822###################
     823from IPython.frontend.terminal.embed import InteractiveShellEmbed
     824from IPython import Config
     825
     826class InterfaceShellTransformer(PrefilterTransformer):
     827    priority = 50
     828    def __init__(self, *args, **kwds):
     829        """
     830        Initialize this class.  All of the arguments get passed to
     831        :meth:`PrefilterTransformer.__init__`.
     832
     833        .. attribute::  lines_queue
     834
     835            a list of lines to be evaluated
     836
     837        .. attribute:: temporary_objects
     838
     839           a list of hold onto interface objects and keep them from being
     840           garbage collected
     841
     842        .. seealso:: :func:`interface_shell_embed`
     843
     844        EXAMPLES::
     845
     846            sage: from sage.misc.interpreter import interface_shell_embed, InterfaceShellTransformer
     847            sage: shell = interface_shell_embed(maxima)
     848            sage: ift = InterfaceShellTransformer(shell=shell, config=shell.config, prefilter_manager=shell.prefilter_manager)
     849            sage: ift.lines_queue
     850            []
     851            sage: ift.temporary_objects
     852            []
     853            sage: ift._sage_import_re.findall('sage(a) + maxima(b)')
     854            ['a', 'b']
     855        """
     856        super(InterfaceShellTransformer, self).__init__(*args, **kwds) 
     857        self.lines_queue = []
     858        self.temporary_objects = []
     859        self._sage_import_re = re.compile(r'(?:sage|%s)\((.*?)\)'%self.shell.interface.name())
     860
     861    def preparse_imports_from_sage(self, line):
     862        """
     863        Finds occurrences of strings such as ``sage(object)`` in
     864        *line*, converts ``object`` to :attr:`shell.interface`,
     865        and replaces those strings with their identifier in the new
     866        system.  This also works with strings such as
     867        ``maxima(object`` if :attr:`shell.interface` is
     868        ``maxima``.
     869       
     870        :param line: the line to transform
     871        :type line: string
     872
     873        .. warning::
     874           
     875            This does not parse nested parentheses correctly.  Thus,
     876            lines like ``sage(a.foo())`` will not work correctly.
     877            This can't be done in generality with regular expressions.
     878
     879        EXAMPLES::
     880
     881            sage: from sage.misc.interpreter import interface_shell_embed, InterfaceShellTransformer
     882            sage: maxima.quit()
     883            sage: shell = interface_shell_embed(maxima)
     884            sage: ift = InterfaceShellTransformer(shell=shell, config=shell.config, prefilter_manager=shell.prefilter_manager)
     885            sage: ift.shell.ex('a = 3')
     886            sage: ift.preparse_imports_from_sage('2 + sage(a)')
     887            '2 + sage0 '
     888            sage: maxima.eval('sage0')
     889            '3'
     890            sage: ift.preparse_imports_from_sage('2 + maxima(a)')
     891            '2 +  sage1 '
     892            sage: ift.preparse_imports_from_sage('2 + gap(a)')
     893            '2 + gap(a)'
     894        """
     895        from sage_eval import sage_eval
     896        for sage_code in self._sage_import_re.findall(line):
     897            expr = preparse(sage_code)
     898            result = self.shell.interface(sage_eval(expr, self.shell.user_ns))
     899            self.temporary_objects.append(result)
     900            line = self._sage_import_re.sub(' ' + result.name() + ' ', line, 1)
     901        return line
     902
     903    def transform(self, line, continue_prompt):
     904        r'''
     905        Evaluates *line* in :attr:`shell.interface` and returns a
     906        string representing the result of that evaluation.  If a line
     907        ends in backspace, then this method will store *line* in
     908        :attr:`lines_queue` until it receives a line not ending in
     909        backspace.
     910       
     911        :param line: the line to be transformed *and evaluated*
     912        :type line: string
     913        :param continue_prompt: is this line a continuation in a sequence of multiline input?
     914        :type continue_prompt: bool
     915
     916        EXAMPLES::
     917
     918            sage: from sage.misc.interpreter import interface_shell_embed, InterfaceShellTransformer
     919            sage: maxima.quit()
     920            sage: shell = interface_shell_embed(maxima)
     921            sage: ift = InterfaceShellTransformer(shell=shell, config=shell.config, prefilter_manager=shell.prefilter_manager)
     922            sage: ift.transform('2+2', False)
     923            'sage.misc.all.logstr("""4""")'
     924            sage: ift.shell.ex('a = 4')
     925            sage: ift.transform(r'sage(a)+\\', False)
     926            sage: ift.shell.prompt_manager.in_template
     927            u'....: '
     928            sage: ift.lines_queue
     929            [' sage0+']
     930            sage: ift.temporary_objects
     931            sage: ift.transform('4', False)
     932            'sage.misc.all.logstr("""8""")'
     933            sage: ift.lines_queue
     934            []
     935            sage: ift.temporary_objects
     936            []
     937
     938            sage: shell = interface_shell_embed(gap)
     939            sage: ift = InterfaceShellTransformer(shell=shell, config=shell.config, prefilter_manager=shell.prefilter_manager)
     940            sage: ift.transform('2+2', False)
     941            'sage.misc.all.logstr("""4""")'
     942        '''
     943        line = self.preparse_imports_from_sage(line)
     944        line = line.rstrip()
     945        if line.endswith('\\'):
     946            line = line.strip('\\')
     947            self.lines_queue.append(line)
     948            #TODO: This should beter handled by getting IPython to
     949            #switch to a continuation prompt
     950            self.shell.prompt_manager.in_template = self.shell.prompt_manager.in2_template
     951        else:
     952            self.lines_queue.append(line)
     953            line = "".join(self.lines_queue)
     954
     955            if self.shell.interface.name() in ['gap', 'magma', 'kash', 'singular']:
     956                if not line.endswith(';'):
     957                    line += ';'
     958            elif self.shell.interface.name() == 'mathematica':
     959                line = 'InputForm[%s]'%line
     960
     961            t = self.shell.interface.eval(line)
     962
     963            #Once we've evaluated the lines, we can clear the queue
     964            #and temporary objects and switch the prompt back
     965            self.lines_queue = []
     966            self.temporary_objects = []
     967            self.shell.prompt_manager.in_template = self.shell.interface.name() + ': '
     968            return 'sage.misc.all.logstr("""%s""")'%t.strip()
     969           
     970def interface_shell_embed(interface):
     971    """
     972    Returns an IPython shell which uses a Sage interface on the
     973    backend to perform the evaluations.  It uses
     974    :class:`InterfaceShellTransformer` to transform the input into the
     975    appropriate ``interface.eval(...)`` input.
     976
     977    EXAMPLES::
     978
     979        sage: from sage.misc.interpreter import interface_shell_embed
     980        sage: shell = interface_shell_embed(maxima)
     981        sage: shell.run_cell('integrate(sin(x), x)')
     982        -cos(x)
     983    """
     984    cfg = Config()
     985    cfg.PromptManager.in_template = interface.name() + ': '
     986    cfg.PromptManager.in2_template = u'....: '
     987    cfg.PromptManager.out_template = u''
     988    cfg.PromptManager.justify = False
     989    cfg.InteractiveShell.confirm_exit = False
     990
     991    ipshell = InteractiveShellEmbed(config=cfg,
     992                                    banner1='\n  --> Switching to %s <--\n'%interface,
     993                                    exit_msg = '\n  --> Exiting back to Sage <--\n')
     994    ipshell.interface = interface
     995
     996    #TODO: The following lines "should" be in the config
     997    ipshell.prompt_manager.color_scheme = 'NoColor'
     998    ipshell.separate_in = u''
     999
     1000    while ipshell.prefilter_manager.transformers:
     1001        ipshell.prefilter_manager.transformers.pop()
     1002    while ipshell.prefilter_manager.checkers:
     1003        ipshell.prefilter_manager.checkers.pop()
     1004    for cls in [InterfaceShellTransformer]:
     1005        cls(shell=ipshell, prefilter_manager=ipshell.prefilter_manager,
     1006            config=cfg)
     1007       
     1008    ipshell.ex('from sage.all import *')
     1009
     1010    return ipshell
     1011   
     1012def get_test_shell():
     1013    """
     1014    Returns a IPython shell that can be used in testing the functions
     1015    in this module.
     1016
     1017    :keyword sage_ext: load the Sage extension
     1018    :type sage_ext: bool
     1019    :returns: an IPython shell
     1020
     1021    EXAMPLES::
     1022
     1023        sage: from sage.misc.interpreter import get_test_shell
     1024        sage: shell = get_test_shell(); shell
     1025        <sage.misc.interpreter.SageInteractiveShell object at 0x...>
     1026    """
     1027    app = SageTerminalApp.instance()
     1028    app.test_shell = True
     1029    if app.shell is None:
     1030        app.initialize()
     1031    return app.shell
     1032
     1033
     1034#######################
     1035# IPython TerminalApp #
     1036#######################
     1037from IPython.frontend.terminal.ipapp import TerminalIPythonApp, IPAppCrashHandler
     1038from IPython.core.crashhandler import CrashHandler
     1039from IPython import Config
     1040
     1041class SageCrashHandler(IPAppCrashHandler):
     1042    def __init__(self, app):
     1043        """
     1044        A custom :class:`CrashHandler` which gives the user
     1045        instructions on how to post the problem to sage-support.
     1046       
     1047        EXAMPLES::
     1048
     1049            sage: from sage.misc.interpreter import SageTerminalApp, SageCrashHandler
     1050            sage: app = SageTerminalApp.instance()
     1051            sage: sch = SageCrashHandler(app); sch
     1052            <sage.misc.interpreter.SageCrashHandler object at 0x...>
     1053            sage: sorted(sch.info.items())
     1054            [('app_name', u'Sage'),
     1055             ('bug_tracker', 'http://trac.sagemath.org/sage_trac'),
     1056             ('contact_email', 'sage-support@googlegroups.com'),
     1057             ('contact_name', 'sage-support'),
     1058             ('crash_report_fname', u'Crash_report_Sage.txt')]
     1059        """
     1060        contact_name = 'sage-support'
     1061        contact_email = 'sage-support@googlegroups.com'
     1062        bug_tracker = 'http://trac.sagemath.org/sage_trac'
     1063        CrashHandler.__init__(self,
     1064            app, contact_name, contact_email, bug_tracker, show_crash_traceback=False
     1065        )
     1066        self.crash_report_fname = 'Sage_crash_report.txt'
     1067
     1068class SageTerminalApp(TerminalIPythonApp):
     1069    name = u'Sage'
     1070    ignore_old_config = True
     1071    crash_handler_class = SageCrashHandler
     1072    verbose_crash = True #Needed to use Sage Crash Handler
     1073    display_banner = False
     1074    test_shell = False
     1075   
     1076    DEFAULT_SAGE_CONFIG = Config({'PromptManager': {'in_template': u'sage: ',
     1077                                                    'in2_template': u'....: ',
     1078                                                    'out_template': u'',
     1079                                                    'justify': False},
     1080                                  'InteractiveShell': {'separate_in': u'',
     1081                                                       'colors': 'NoColor'},
     1082                                  })
     1083
     1084    def init_shell(self):
     1085        r"""
     1086        Initialize the :class:`SageInteractiveShell` instance.
     1087        Additionally, this also does the following:
     1088
     1089          - Merges the default shell configuration with the user's.
     1090         
     1091          - Monkey-patch :mod:`IPython.core.oinspect` to add Sage
     1092            introspection functions.
     1093
     1094          - Run additional Sage startup code.
     1095         
     1096        .. note::
     1097
     1098            This code is based on
     1099            :meth:`TermintalIPythonApp.init_shell`.
     1100
     1101        EXAMPLES::
     1102
     1103            sage: from sage.misc.interpreter import SageTerminalApp
     1104            sage: app = SageTerminalApp.instance()
     1105            sage: app.initialize() #indirect doctest
     1106            sage: app.shell
     1107            <sage.misc.interpreter.SageInteractiveShell object at 0x...>
     1108        """
     1109        sys.path.insert(0, '')
     1110
     1111        # Overwrite the default Sage configuration with the user's.
     1112        new_config = Config()
     1113        new_config._merge(self.DEFAULT_SAGE_CONFIG)
     1114        new_config._merge(self.config)
     1115
     1116        # Shell initialization
     1117        self.shell = SageInteractiveShell.instance(config=new_config,
     1118                        display_banner=False, profile_dir=self.profile_dir,
     1119                        ipython_dir=self.ipython_dir)
     1120        self.shell.configurables.append(self)
     1121
     1122
     1123        # Ideally, these would just be methods of the Inspector class
     1124        # that we could override; however, IPython looks them up in
     1125        # the global :class:`IPython.core.oinspect` module namespace.
     1126        # Thus, we have to monkey-patch.
     1127        import sagedoc, sageinspect, IPython.core.oinspect
     1128        IPython.core.oinspect.getdoc = sageinspect.sage_getdoc #sagedoc.my_getdoc
     1129        IPython.core.oinspect.getsource = sagedoc.my_getsource
     1130        IPython.core.oinspect.getargspec = sageinspect.sage_getargspec
     1131
     1132
     1133        from sage.misc.edit_module import edit_devel
     1134        self.shell.set_hook('editor', edit_devel)
     1135
     1136        if 'SAGE_CLEAN' in os.environ:
     1137            return
     1138       
     1139        # Additional initalization code
     1140        preparser(True)
     1141        os.chdir(os.environ["CUR"])
     1142
     1143        from sage.misc.misc import branch_current_hg_notice, branch_current_hg
     1144        branch = branch_current_hg_notice(branch_current_hg())
     1145        if branch and self.test_shell is False:
     1146            print branch
     1147
     1148        self.shell.ex('from sage.all import Integer, RealNumber')
     1149        self.shell.push(dict(sage_prompt=sage_prompt))
     1150
     1151        if os.environ.get('SAGE_IMPORTALL', 'yes') != "no":
     1152            self.shell.ex('from sage.all_cmdline import *')
     1153
     1154        startup_file = os.environ.get('SAGE_STARTUP_FILE', '')
     1155        if os.path.exists(startup_file):
     1156            self.shell.run_cell('%%load "%s"'%startup_file)
  • sage/misc/preparser.py

    diff --git a/sage/misc/preparser.py b/sage/misc/preparser.py
    a b  
    11371137## Apply the preparser to an entire file
    11381138######################################################
    11391139
     1140#TODO: This global variable attached should be associtated with an
     1141#IPython InteractiveShell as opposed to a global variable in this
     1142#module.
    11401143attached = {}
    11411144
    11421145load_debug_mode = False
  • deleted file sage/misc/preparser_ipython.py

    diff --git a/sage/misc/preparser_ipython.py b/sage/misc/preparser_ipython.py
    deleted file mode 100644
    + -  
    1 ###########################################################################
    2 #       Copyright (C) 2006 William Stein <wstein@gmail.com>
    3 #
    4 #  Distributed under the terms of the GNU General Public License (GPL)
    5 #                  http://www.gnu.org/licenses/
    6 ###########################################################################
    7 
    8 import sage.misc.interpreter
    9 
    10 import preparser
    11 
    12 interface_name  = 'sage'
    13 interface       = None
    14 num_lines       = 0
    15 
    16 # TODO: Do this right?
    17 magma_colon_equals = False
    18 
    19 q_lines = []
    20 
    21 
    22 def switch_interface_general(new_interface, verbose=True):
    23     global interface
    24     global interface_name
    25     if not (interface is None):
    26         interface._post_interact()
    27     interface = new_interface
    28     interface_name = new_interface.name().lower()
    29     sage.misc.interpreter.set_sage_prompt('%s'%interface_name)
    30     if verbose:
    31         print "\n  --> Switching to %s <-- \n"%interface
    32     interface._pre_interact()
    33 
    34 def switch_interface(name, verbose=True):
    35     I = __import__('sage.interfaces.all',{},{},name)
    36     if not name in I.interfaces:
    37         raise RuntimeError, "Invalid interface %s"%name
    38     sage.misc.interpreter.PROMPT = '%s'%name
    39    
    40     global interface, interface_name
    41     interface_name = name
    42     if name == 'sage':
    43         interface = None
    44         if verbose:
    45             print "\n  --> Exiting back to Sage <-- \n"
    46     else:
    47         if not (interface is None):
    48             interface._post_interact()
    49         interface = I.__dict__[name]
    50         if verbose:
    51             print "\n  --> Switching to %s <-- \n"%interface
    52         interface._pre_interact()
    53         if name in ['kash']:
    54             interface('0')     # hack that works.
    55            
    56     sage.misc.interpreter.set_sage_prompt('%s'%interface_name)
    57 
    58 def preparse_ipython(line, reset=True):
    59     """
    60     TESTS:
    61        
    62         Make sure #10933 is fixed
    63        
    64     ::
    65    
    66         sage: sage.misc.preparser_ipython.preparse_ipython("def foo(str):\n   time gp(str)\n\nprint gp('1')")
    67         'def foo(str):\n   __time__=misc.cputime(); __wall__=misc.walltime(); gp(str); print "Time: CPU %.2f s, Wall: %.2f s"%(misc.cputime(__time__), misc.walltime(__wall__))\n\nprint gp(\'1\')'
    68 
    69     """
    70     global num_lines
    71     global q_lines
    72    
    73     L = line.lstrip()
    74     if L.startswith('%'):
    75         # This should be installed as an Ipython magic command,
    76         # but I don't know how yet...
    77         L = L[1:].strip()
    78         import sage.interfaces.all
    79         if L.lower() in sage.interfaces.all.interfaces:
    80             switch_interface(L.lower())
    81             return "''"
    82         else:
    83             # only preparse non-magic lines
    84             return line
    85 
    86        
    87     if interface is None:
    88     #We could remove do_time=True if #10933 get's fixed upstream
    89         return preparser.preparse(line, reset=reset, do_time=True)
    90 
    91     if L.startswith('?') or L.endswith('?'):
    92         L = L.strip('?')
    93         interface.help(L)
    94         return ''
    95 
    96     line = preparse_imports_from_sage(interface, line)
    97     line = line.rstrip()
    98     ends_in_backslash = line.endswith('\\')
    99     if ends_in_backslash:
    100         line = line.rstrip('\\')
    101         num_lines += 1
    102     else:
    103         if interface_name in ['gap', 'magma', 'kash', 'singular']:
    104             if not line.endswith(';'):
    105                 line += ';'
    106         elif interface_name == 'mathematica':
    107             line = 'InputForm[%s]'%line
    108 
    109     if ends_in_backslash:
    110         q_lines.append(line)
    111     else:
    112         if len(q_lines) > 0:
    113             line = ''.join(q_lines) + line
    114         q_lines = []
    115         # TODO: do sage substitutions here
    116         #t = interface._eval_line(line)
    117         t = interface.eval(line)
    118        
    119     import sage.misc.interpreter
    120     if ends_in_backslash:
    121 
    122         sage.misc.interpreter.set_sage_prompt('.'*len(interface_name))
    123    
    124     else:
    125 
    126         sage.misc.interpreter.set_sage_prompt('%s'%interface_name)
    127         #print t
    128         #__IPYTHON__.output_hist[len(__IPYTHON__.input_hist_raw)] = t
    129 
    130     # TODO: this is a very lazy temporary bug fix.
    131     # Nobody uses this logging stuff anymore, anyways, because
    132     # of the Sage notebook.
    133     try:
    134         return """logstr(%r)"""%t
    135     except UnboundLocalError:
    136         return 'logstr("")'
    137 
    138 
    139 _v_ = None
    140 
    141 def preparse_imports_from_sage(interface, line, locals={}):
    142     """
    143     The input line is being fed to the given interface.
    144     This function extracts any "sage(zzz)"'s, parses
    145     them, and replaces them by appropriate objects
    146     in the interface.   This is used for moving
    147     objects from Sage back into the interface.
    148     """
    149     import sage_eval
    150     i = line.find('%s('%interface_name)
    151     n = len(interface_name)
    152     if i == -1:
    153         i = line.find('sage(')
    154         n = 4
    155         if i == -1:
    156             return line
    157     j = i + line[i:].find(')')
    158     expr = line[i+n+1:j]
    159     expr = preparser.preparse(expr)
    160     s = 'import sage.misc.preparser_ipython; \
    161          sage.misc.preparser_ipython._v_ = sage.misc.preparser_ipython.interface(%s)'%expr
    162     #print s
    163     __IPYTHON__.runsource(s)
    164     #print _v_
    165     line = line[:i] + _v_.name() + line[j+2:]
    166     return line
    167    
  • sage/misc/sage_unittest.py

    diff --git a/sage/misc/sage_unittest.py b/sage/misc/sage_unittest.py
    a b  
    105105
    106106     - Don't catch the exceptions if ``TestSuite(..).run()`` is called
    107107       under the debugger, or with ``%pdb`` on (how to detect this? see
    108        ``IPython.ipapi.get()``, ``IPython.Magic.shell.call_pdb``, ...)
     108       ``get_ipython()``, ``IPython.Magic.shell.call_pdb``, ...)
    109109       In the mean time, see the ``catch=False`` option.
    110110
    111111     - Run the tests according to the inheritance order, from most
  • sage/misc/trace.py

    diff --git a/sage/misc/trace.py b/sage/misc/trace.py
    a b  
    7575    if EMBEDDED_MODE:
    7676        raise NotImplementedError, "the trace command is not implemented in the Sage notebook; you must use the command line."
    7777
    78     import IPython.Debugger
    79     pdb = IPython.Debugger.Pdb()
     78    from IPython.core.debugger import Pdb
     79    pdb = Pdb()
    8080   
    81     import IPython.ipapi
    82     _ip = IPython.ipapi.get()
    83        
     81    try:
     82        ipython = get_ipython()
     83    except NameError:
     84        raise NotImplementedError("the trace command can only be run from the Sage command-line")
     85               
    8486    import preparser
    85 
    8687    code = preparser.preparse(code)
    87     return pdb.run(code, _ip.user_ns)
     88    return pdb.run(code, ipython.user_ns)
    8889   
    8990    # this could also be useful; it drops
    9091    # us into a debugger in an except block: