Ticket #12719: trac_12719-rebased-to-13211-vb.patch
File trac_12719-rebased-to-13211-vb.patch, 63.8 KB (added by , 9 years ago) |
---|
-
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 30 30 sage/misc/dist 31 31 sage/misc/hg 32 32 sage/misc/preparser 33 sage/misc/interpreter 33 34 sage/misc/functional 34 35 sage/misc/html 35 36 sage/misc/log -
sage/all.py
diff --git a/sage/all.py b/sage/all.py
a b 255 255 from sage.libs.all import symmetrica 256 256 symmetrica.end() 257 257 258 def _quit_sage_(self):259 import sage.misc.preparser_ipython260 if sage.misc.preparser_ipython.interface != None:261 sage.misc.preparser_ipython.switch_interface('sage')262 self.exit_now = False263 return264 265 from IPython.genutils import ask_yes_no266 if self.rc.confirm_exit:267 if ask_yes_no('Do you really want to exit ([y]/n)?','y'):268 self.exit_now = True269 else:270 self.exit_now = True271 if self.exit_now:272 quit_sage()273 self.exit_now = True274 275 return self.exit_now276 277 from IPython.iplib import InteractiveShell278 InteractiveShell.exit = _quit_sage_279 280 import sage.misc.displayhook281 sage.misc.displayhook.install()282 283 258 from sage.ext.interactive_constructors_c import inject_on, inject_off 284 259 285 260 sage.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 24 24 raise ValueError(msg) 25 25 26 26 27 sage.misc.session.init() 27 28 28 def _init_cmdline(globs):29 from sage.misc.inline_fortran import InlineFortran30 fortran = InlineFortran(globs)31 globs['fortran'] = fortran32 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 271 271 self._start() 272 272 return self._expect 273 273 274 def interact(self):275 r"""276 This allows you to interactively interact with the child277 interpreter. Press Ctrl-D or type 'quit' or 'exit' to exit and278 return to Sage.279 280 .. note::281 282 This is completely different than the console() member283 function. The console function opens a new copy of the284 child interpreter, whereas the interact function gives you285 interactive access to the interpreter that is being used by286 Sage. Use sage(xxx) or interpretername(xxx) to pull objects287 in from sage to the interpreter.288 """289 if self._expect is None:290 self._start()291 import sage.misc.preparser_ipython292 sage.misc.preparser_ipython.switch_interface_general(self)293 294 def _pre_interact(self):295 pass296 297 def _post_interact(self):298 pass299 300 274 def pid(self): 301 275 """ 302 276 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 178 178 import expect 179 179 from expect import Expect, ExpectElement, FunctionElement, ExpectFunction 180 180 from sage.misc.misc import SAGE_LOCAL, SAGE_EXTCODE, DOT_SAGE, is_64_bit, is_in_string 181 from IPython.genutils import page182 181 import re 183 182 import os 184 183 import pexpect … … 1275 1274 F = open(self._local_tmpfile(),"r") 1276 1275 help = F.read() 1277 1276 if pager: 1277 from IPython.core.page import page 1278 1278 page(help, start = int(sline)-1) 1279 1279 else: 1280 1280 return help -
sage/interfaces/interface.py
diff --git a/sage/interfaces/interface.py b/sage/interfaces/interface.py
a b 82 82 Sage. Use sage(xxx) or interpretername(xxx) to pull objects 83 83 in from sage to the interpreter. 84 84 """ 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)) 87 93 88 94 def _pre_interact(self): 89 95 pass -
sage/misc/displayhook.py
diff --git a/sage/misc/displayhook.py b/sage/misc/displayhook.py
a b 8 8 - Bill Cauchois (2009): initial version 9 9 """ 10 10 11 import IPython, sys, __builtin__ 12 from sage.matrix.matrix import is_Matrix 13 from sage.modular.arithgroup.arithgroup_element import ArithmeticSubgroupElement 11 import sys, __builtin__ 12 14 13 15 14 # This is used to wrap lines when printing "tall" lists. 16 15 MAX_COLUMN = 70 … … 138 137 # element is a matrix, or an ArithmeticSubgroupElement (a thin wrapper 139 138 # around a matrix). This should cover most cases. 140 139 if isinstance(obj, (tuple, list)): 140 from sage.matrix.matrix import is_Matrix 141 from sage.modular.arithgroup.arithgroup_element import ArithmeticSubgroupElement 141 142 if len(obj) > 0 and (is_Matrix(obj[0]) or isinstance(obj[0], ArithmeticSubgroupElement)): 142 143 if _check_tall_list_and_print(out_stream, obj): 143 144 return 144 145 print >>out_stream, `obj` 145 146 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 154 147 def displayhook(obj): 155 148 """ 156 149 This function adheres to the displayhook protocol described in `PEP 217`_. … … 175 168 __builtin__._ = None 176 169 print_obj(sys.stdout, obj) 177 170 __builtin__._ = obj 178 179 def install():180 """181 Install the new displayhook, so that subsequent output from the interpreter182 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 fall190 # 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 45 45 import inspect 46 46 import os 47 47 import re 48 import IPython49 48 50 49 from string import Template 51 50 … … 302 301 variable :envvar:`EDITOR`) with the file in which gcd is defined, and when your 303 302 editor supports it, also at the line in wich gcd is defined. 304 303 """ 304 import IPython.core.hooks 305 305 sageroot = sage.misc.sageinspect.SAGE_ROOT+'/' 306 306 runpathpattern = '^'+sageroot+'local/lib/python[^/]*/site-packages' 307 307 develbranch = sageroot+'devel/sage' 308 308 filename=re.sub(runpathpattern,develbranch,filename) 309 IPython. hooks.editor(self, filename, linenum)309 IPython.core.hooks.editor(self, filename, linenum) 310 310 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 1 r""" 2 Sage's IPython Modifications 3 3 4 Modified input. 4 This module contains all of Sage's customizations to the IPython 5 interpreter. These changes consist of the following magjor components: 5 6 6 -- All ^'s (not in strings) are replaced by **'s. 7 - :class:`SageTerminalApp` 8 - :class:`SageInteractiveShell` 9 - :func:`interface_shell_embed` 7 10 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. 11 SageTerminalApp 12 --------------- 11 13 12 -- quit alone on a line quits. 14 This is the main application object. It is used by the 15 ``$SAGE_ROOT/local/bin/sage-ipython`` script to start the Sage 16 command-line. It's primary purpose is to 13 17 14 - - load to load in scripts18 - Initialize the :class:`SageInteractiveShell`. 15 19 16 - - Most int literals n are replaced by ZZ(n) Thus 2/3 is a rational17 number. If they are in []'s right after a valid identifier they18 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. 19 23 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. 23 26 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. 25 30 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. 31 SageInteractiveShell 32 -------------------- 31 33 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. 34 The :class:`SageInteractiveShell` object is the object responsible for 35 accepting input from the user and evaluating it. From the command-line, 36 this object can be retrieved by running:: 50 37 51 EXAMPLE:: 38 sage: shell = get_ipython() #not tested 52 39 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'> 40 The :class:`SageInteractiveShell` provides the following 41 customizations: 65 42 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`. 72 48 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 65 Interface Shell 66 --------------- 67 68 The function :func:`interface_shell_embed` takes a 69 :class:`~sage.interfaces.interface.Interface` object and returns an 70 embeddable IPython shell which can be used to directly interact with 71 that shell. The bulk of this functionality is provided through 72 :class:`InterfaceShellTransformer`. 73 74 Auto-generated Documentation 75 ---------------------------- 89 76 """ 90 77 91 78 #***************************************************************************** 92 # Copyright (C) 2004 William Stein <wstein@gmail.com>79 # Copyright (C) 2004-2012 William Stein <wstein@gmail.com> 93 80 # 94 81 # Distributed under the terms of the GNU General Public License (GPL) 95 82 # 96 83 # http://www.gnu.org/licenses/ 97 84 #***************************************************************************** 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 85 import os, log, re, new, sys 86 from preparser import (preparse, preparse_file, load_wrap, 87 modified_attached_files, attached_files) 239 88 240 89 def load_cython(name): 90 import cython 241 91 cur = os.path.abspath(os.curdir) 242 92 try: 243 93 mod, dir = cython.cython(name, compile_message=True, use_cache=True) … … 249 99 return 'from %s import *'%mod 250 100 251 101 def handle_encoding_declaration(contents, out): 252 """Find a PEP 263-style Python encoding declaration in the first or102 r"""Find a PEP 263-style Python encoding declaration in the first or 253 103 second line of `contents`. If found, output it to `out` and return 254 104 `contents` without the encoding line; otherwise output a default 255 105 UTF-8 declaration and return `contents`. … … 326 176 '#!/usr/local/bin/python\nimport os, sys' 327 177 328 178 329 NOTES: 179 NOTES:: 330 180 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/ 339 182 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. 341 187 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) 344 197 """ 345 198 lines = contents.splitlines() 346 199 for num, line in enumerate(lines[:2]): … … 386 239 out.close() 387 240 return tmpfilename 388 241 389 def sage_prefilter(self, block, continuation):242 def embedded(): 390 243 """ 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. 393 245 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 398 251 """ 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 430 253 return sage.server.support.EMBEDDED_MODE 431 254 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. 433 258 do_preparse=True 434 259 def preparser(on=True): 435 260 """ 436 261 Turn on or off the Sage preparser. 437 262 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 441 265 442 266 EXAMPLES:: 443 267 … … 453 277 global do_preparse 454 278 if on: 455 279 do_preparse = True 456 InteractiveShell.prefilter = sage_prefilter457 280 else: 458 281 do_preparse = False 459 InteractiveShell.prefilter = ipython_prefilter460 282 461 283 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 ############################################################### 288 def set_sage_prompt(s): 289 """ 290 Sets the Sage prompt to the string ``s``. 468 291 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 473 306 """ 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 497 309 498 310 def sage_prompt(): 499 log.update()500 return '%s'%_prompt311 """ 312 Returns the current Sage prompt. 501 313 502 __builtin__.sage_prompt = sage_prompt 314 EXAMPLES:: 503 315 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 504 323 324 ############### 325 # Displayhook # 326 ############### 327 from IPython.core.displayhook import DisplayHook 328 class SageDisplayHook(DisplayHook): 329 """ 330 A replacement for ``sys.displayhook`` which correctly print lists 331 of matrices. 505 332 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 373 from IPython.frontend.terminal.interactiveshell import TerminalInteractiveShell 374 375 class SageInteractiveShell(TerminalInteractiveShell): 376 displayhook_class = SageDisplayHook #used by init_displayhook 511 377 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 ####################################################### 669 from IPython.core.prefilter import PrefilterTransformer 670 671 class 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 704 class 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 736 class 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 777 class 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 ################### 823 from IPython.frontend.terminal.embed import InteractiveShellEmbed 824 from IPython import Config 825 826 class 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 970 def 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 1012 def 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 ####################### 1037 from IPython.frontend.terminal.ipapp import TerminalIPythonApp, IPAppCrashHandler 1038 from IPython.core.crashhandler import CrashHandler 1039 from IPython import Config 1040 1041 class 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 1068 class 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 1137 1137 ## Apply the preparser to an entire file 1138 1138 ###################################################### 1139 1139 1140 #TODO: This global variable attached should be associtated with an 1141 #IPython InteractiveShell as opposed to a global variable in this 1142 #module. 1140 1143 attached = {} 1141 1144 1142 1145 load_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.interpreter9 10 import preparser11 12 interface_name = 'sage'13 interface = None14 num_lines = 015 16 # TODO: Do this right?17 magma_colon_equals = False18 19 q_lines = []20 21 22 def switch_interface_general(new_interface, verbose=True):23 global interface24 global interface_name25 if not (interface is None):26 interface._post_interact()27 interface = new_interface28 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"%interface32 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"%name38 sage.misc.interpreter.PROMPT = '%s'%name39 40 global interface, interface_name41 interface_name = name42 if name == 'sage':43 interface = None44 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"%interface52 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 fixed63 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_lines71 global q_lines72 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.all79 if L.lower() in sage.interfaces.all.interfaces:80 switch_interface(L.lower())81 return "''"82 else:83 # only preparse non-magic lines84 return line85 86 87 if interface is None:88 #We could remove do_time=True if #10933 get's fixed upstream89 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 += 1102 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]'%line108 109 if ends_in_backslash:110 q_lines.append(line)111 else:112 if len(q_lines) > 0:113 line = ''.join(q_lines) + line114 q_lines = []115 # TODO: do sage substitutions here116 #t = interface._eval_line(line)117 t = interface.eval(line)118 119 import sage.misc.interpreter120 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 t128 #__IPYTHON__.output_hist[len(__IPYTHON__.input_hist_raw)] = t129 130 # TODO: this is a very lazy temporary bug fix.131 # Nobody uses this logging stuff anymore, anyways, because132 # of the Sage notebook.133 try:134 return """logstr(%r)"""%t135 except UnboundLocalError:136 return 'logstr("")'137 138 139 _v_ = None140 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, parses145 them, and replaces them by appropriate objects146 in the interface. This is used for moving147 objects from Sage back into the interface.148 """149 import sage_eval150 i = line.find('%s('%interface_name)151 n = len(interface_name)152 if i == -1:153 i = line.find('sage(')154 n = 4155 if i == -1:156 return line157 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)'%expr162 #print s163 __IPYTHON__.runsource(s)164 #print _v_165 line = line[:i] + _v_.name() + line[j+2:]166 return line167 -
sage/misc/sage_unittest.py
diff --git a/sage/misc/sage_unittest.py b/sage/misc/sage_unittest.py
a b 105 105 106 106 - Don't catch the exceptions if ``TestSuite(..).run()`` is called 107 107 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``, ...) 109 109 In the mean time, see the ``catch=False`` option. 110 110 111 111 - 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 75 75 if EMBEDDED_MODE: 76 76 raise NotImplementedError, "the trace command is not implemented in the Sage notebook; you must use the command line." 77 77 78 import IPython.Debugger79 pdb = IPython.Debugger.Pdb()78 from IPython.core.debugger import Pdb 79 pdb = Pdb() 80 80 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 84 86 import preparser 85 86 87 code = preparser.preparse(code) 87 return pdb.run(code, _ip.user_ns)88 return pdb.run(code, ipython.user_ns) 88 89 89 90 # this could also be useful; it drops 90 91 # us into a debugger in an except block: