##// END OF EJS Templates
Merging with upstream
Fernando Perez -
r1996:7a6a76a5 merge
parent child Browse files
Show More

The requested changes are too big and content was truncated. Show full diff

@@ -0,0 +1,37 b''
1 # encoding: utf-8
2 """
3 Test the LineFrontEnd
4 """
5
6 __docformat__ = "restructuredtext en"
7
8 #-------------------------------------------------------------------------------
9 # Copyright (C) 2008 The IPython Development Team
10 #
11 # Distributed under the terms of the BSD License. The full license is
12 # in the file COPYING, distributed as part of this software.
13 #-------------------------------------------------------------------------------
14
15 from IPython.frontend.linefrontendbase import LineFrontEndBase
16 from copy import deepcopy
17 import nose.tools as nt
18
19 class ConcreteLineFrontEnd(LineFrontEndBase):
20 """ A concrete class to test the LineFrontEndBase.
21 """
22 def capture_output(self):
23 pass
24
25 def release_output(self):
26 pass
27
28
29 def test_is_complete():
30 """ Tests line completion heuristic.
31 """
32 frontend = ConcreteLineFrontEnd()
33 yield nt.assert_true, not frontend.is_complete('for x in \\')
34 yield nt.assert_true, not frontend.is_complete('for x in (1, ):')
35 yield nt.assert_true, frontend.is_complete('for x in (1, ):\n pass')
36
37
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
@@ -1,75 +1,75 b''
1 1 """ Greedy completer extension for IPython
2 2
3 3 Normal tab completer refuses to evaluate nonsafe stuff. This will evaluate
4 4 everything, so you need to consider the consequences of pressing tab
5 5 yourself!
6 6
7 7 Note that this extension simplifies readline interaction by setting
8 8 only whitespace as completer delimiter. If this works well, we will
9 9 do the same in default completer.
10 10
11 11 """
12 12 from IPython import generics,ipapi
13 13 from IPython.genutils import dir2
14 14
15 15 def attr_matches(self, text):
16 16 """Compute matches when text contains a dot.
17 17
18 18 MONKEYPATCHED VERSION (ipy_greedycompleter.py)
19 19
20 20 Assuming the text is of the form NAME.NAME....[NAME], and is
21 21 evaluatable in self.namespace or self.global_namespace, it will be
22 22 evaluated and its attributes (as revealed by dir()) are used as
23 23 possible completions. (For class instances, class members are are
24 24 also considered.)
25 25
26 26 WARNING: this can still invoke arbitrary C code, if an object
27 27 with a __getattr__ hook is evaluated.
28 28
29 29 """
30 30 import re
31 31
32 32 force_complete = 1
33 33 # Another option, seems to work great. Catches things like ''.<tab>
34 34 m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text)
35 35
36 36 if m:
37 37 expr, attr = m.group(1, 3)
38 38 else:
39 39 # force match - eval anything that ends with colon
40 40 if not force_complete:
41 41 return []
42 42
43 43 m2 = re.match(r"(.+)\.(\w*)$", self.lbuf)
44 44 if not m2:
45 45 return []
46 46 expr, attr = m2.group(1,2)
47 47
48 48
49 49 try:
50 50 obj = eval(expr, self.namespace)
51 51 except:
52 52 try:
53 53 obj = eval(expr, self.global_namespace)
54 54 except:
55 55 return []
56 56
57 57 words = dir2(obj)
58 58
59 59 try:
60 60 words = generics.complete_object(obj, words)
61 61 except ipapi.TryNext:
62 62 pass
63 63 # Build match list to return
64 64 n = len(attr)
65 65 res = ["%s.%s" % (expr, w) for w in words if w[:n] == attr ]
66 66 return res
67 67
68 68 def main():
69 import readline
69 import IPython.rlineimpl as readline
70 70 readline.set_completer_delims(" \n\t")
71 71 # monkeypatch - the code will be folded to normal completer later on
72 72 import IPython.completer
73 73 IPython.completer.Completer.attr_matches = attr_matches
74 74
75 75 main() No newline at end of file
@@ -1,116 +1,114 b''
1 1 """ User configuration file for IPython
2 2
3 3 This is a more flexible and safe way to configure ipython than *rc files
4 4 (ipythonrc, ipythonrc-pysh etc.)
5 5
6 6 This file is always imported on ipython startup. You can import the
7 7 ipython extensions you need here (see IPython/Extensions directory).
8 8
9 9 Feel free to edit this file to customize your ipython experience.
10 10
11 11 Note that as such this file does nothing, for backwards compatibility.
12 12 Consult e.g. file 'ipy_profile_sh.py' for an example of the things
13 13 you can do here.
14 14
15 15 See http://ipython.scipy.org/moin/IpythonExtensionApi for detailed
16 16 description on what you could do here.
17 17 """
18 18
19 19 # Most of your config files and extensions will probably start with this import
20 20
21 21 import IPython.ipapi
22 22 ip = IPython.ipapi.get()
23 23
24 24 # You probably want to uncomment this if you did %upgrade -nolegacy
25 25 # import ipy_defaults
26 26
27 27 import os
28 28
29 29 def main():
30 30
31 31 # uncomment if you want to get ipython -p sh behaviour
32 32 # without having to use command line switches
33 33 # import ipy_profile_sh
34 34
35 35 # Configure your favourite editor?
36 36 # Good idea e.g. for %edit os.path.isfile
37 37
38 38 #import ipy_editors
39 39
40 40 # Choose one of these:
41 41
42 42 #ipy_editors.scite()
43 43 #ipy_editors.scite('c:/opt/scite/scite.exe')
44 44 #ipy_editors.komodo()
45 45 #ipy_editors.idle()
46 46 # ... or many others, try 'ipy_editors??' after import to see them
47 47
48 48 # Or roll your own:
49 49 #ipy_editors.install_editor("c:/opt/jed +$line $file")
50 50
51 51
52 52 o = ip.options
53 53 # An example on how to set options
54 54 #o.autocall = 1
55 55 o.system_verbose = 0
56 56
57 57 #import_all("os sys")
58 58 #execf('~/_ipython/ns.py')
59 59
60 60
61 61 # -- prompt
62 62 # A different, more compact set of prompts from the default ones, that
63 63 # always show your current location in the filesystem:
64 64
65 65 #o.prompt_in1 = r'\C_LightBlue[\C_LightCyan\Y2\C_LightBlue]\C_Normal\n\C_Green|\#>'
66 66 #o.prompt_in2 = r'.\D: '
67 67 #o.prompt_out = r'[\#] '
68 68
69 69 # Try one of these color settings if you can't read the text easily
70 70 # autoexec is a list of IPython commands to execute on startup
71 71 #o.autoexec.append('%colors LightBG')
72 72 #o.autoexec.append('%colors NoColor')
73 73 #o.autoexec.append('%colors Linux')
74 74
75 75 # for sane integer division that converts to float (1/2 == 0.5)
76 76 #o.autoexec.append('from __future__ import division')
77 77
78 78 # For %tasks and %kill
79 79 #import jobctrl
80 80
81 81 # For autoreloading of modules (%autoreload, %aimport)
82 82 #import ipy_autoreload
83 83
84 84 # For winpdb support (%wdb)
85 85 #import ipy_winpdb
86 86
87 87 # For bzr completer, requires bzrlib (the python installation of bzr)
88 88 #ip.load('ipy_bzr')
89 89
90 90 # Tab completer that is not quite so picky (i.e.
91 91 # "foo".<TAB> and str(2).<TAB> will work). Complete
92 92 # at your own risk!
93 93 #import ipy_greedycompleter
94 94
95 95 # If you are on Linux, you may be annoyed by
96 96 # "Display all N possibilities? (y or n)" on tab completion,
97 97 # as well as the paging through "more". Uncomment the following
98 98 # lines to disable that behaviour
99 99 #import readline
100 100 #readline.parse_and_bind('set completion-query-items 1000')
101 101 #readline.parse_and_bind('set page-completions no')
102
103
104
105
102
103
106 104 # some config helper functions you can use
107 105 def import_all(modules):
108 106 """ Usage: import_all("os sys") """
109 107 for m in modules.split():
110 108 ip.ex("from %s import *" % m)
111
109
112 110 def execf(fname):
113 111 """ Execute a file in user namespace """
114 112 ip.ex('execfile("%s")' % os.path.expanduser(fname))
115 113
116 114 main()
@@ -1,76 +1,77 b''
1 1 """
2 2 Base front end class for all async frontends.
3 3 """
4 4 __docformat__ = "restructuredtext en"
5 5
6 6 #-------------------------------------------------------------------------------
7 7 # Copyright (C) 2008 The IPython Development Team
8 8 #
9 9 # Distributed under the terms of the BSD License. The full license is in
10 10 # the file COPYING, distributed as part of this software.
11 11 #-------------------------------------------------------------------------------
12 12
13 13
14 14 #-------------------------------------------------------------------------------
15 15 # Imports
16 16 #-------------------------------------------------------------------------------
17 from IPython.external import guid
18 17
18 from IPython.external import guid
19 19
20 20 from zope.interface import Interface, Attribute, implements, classProvides
21 21 from twisted.python.failure import Failure
22 from IPython.frontend.frontendbase import FrontEndBase, IFrontEnd, IFrontEndFactory
22 from IPython.frontend.frontendbase import (
23 FrontEndBase, IFrontEnd, IFrontEndFactory)
23 24 from IPython.kernel.core.history import FrontEndHistory
24 25 from IPython.kernel.engineservice import IEngineCore
25 26
26 27
27 28 class AsyncFrontEndBase(FrontEndBase):
28 29 """
29 30 Overrides FrontEndBase to wrap execute in a deferred result.
30 31 All callbacks are made as callbacks on the deferred result.
31 32 """
32 33
33 34 implements(IFrontEnd)
34 35 classProvides(IFrontEndFactory)
35 36
36 37 def __init__(self, engine=None, history=None):
37 38 assert(engine==None or IEngineCore.providedBy(engine))
38 39 self.engine = IEngineCore(engine)
39 40 if history is None:
40 41 self.history = FrontEndHistory(input_cache=[''])
41 42 else:
42 43 self.history = history
43 44
44 45
45 46 def execute(self, block, blockID=None):
46 47 """Execute the block and return the deferred result.
47 48
48 49 Parameters:
49 50 block : {str, AST}
50 51 blockID : any
51 52 Caller may provide an ID to identify this block.
52 53 result['blockID'] := blockID
53 54
54 55 Result:
55 56 Deferred result of self.interpreter.execute
56 57 """
57 58
58 59 if(not self.is_complete(block)):
59 60 return Failure(Exception("Block is not compilable"))
60 61
61 62 if(blockID == None):
62 63 blockID = guid.generate()
63 64
64 65 d = self.engine.execute(block)
65 66 d.addCallback(self._add_history, block=block)
66 67 d.addCallbacks(self._add_block_id_for_result,
67 68 errback=self._add_block_id_for_failure,
68 69 callbackArgs=(blockID,),
69 70 errbackArgs=(blockID,))
70 71 d.addBoth(self.update_cell_prompt, blockID=blockID)
71 72 d.addCallbacks(self.render_result,
72 73 errback=self.render_error)
73 74
74 75 return d
75 76
76 77
@@ -1,94 +1,100 b''
1 1 # encoding: utf-8
2 2 """This file contains unittests for the
3 3 IPython.frontend.cocoa.cocoa_frontend module.
4 4 """
5 5 __docformat__ = "restructuredtext en"
6 6
7 7 #---------------------------------------------------------------------------
8 8 # Copyright (C) 2005 The IPython Development Team
9 9 #
10 10 # Distributed under the terms of the BSD License. The full license is in
11 11 # the file COPYING, distributed as part of this software.
12 12 #---------------------------------------------------------------------------
13 13
14 14 #---------------------------------------------------------------------------
15 15 # Imports
16 16 #---------------------------------------------------------------------------
17 17
18 # Tell nose to skip this module
19 __test__ = {}
20
21 from twisted.trial import unittest
22 from twisted.internet.defer import succeed
23
24 from IPython.kernel.core.interpreter import Interpreter
25 import IPython.kernel.engineservice as es
26
18 27 try:
19 from IPython.kernel.core.interpreter import Interpreter
20 import IPython.kernel.engineservice as es
21 from IPython.testing.util import DeferredTestCase
22 from twisted.internet.defer import succeed
23 from IPython.frontend.cocoa.cocoa_frontend import IPythonCocoaController
28 from IPython.frontend.cocoa.cocoa_frontend import IPythonCocoaController
24 29 from Foundation import NSMakeRect
25 from AppKit import NSTextView, NSScrollView
30 from AppKit import NSTextView, NSScrollView
26 31 except ImportError:
27 import nose
28 raise nose.SkipTest("This test requires zope.interface, Twisted, Foolscap and PyObjC")
32 # This tells twisted.trial to skip this module if PyObjC is not found
33 skip = True
29 34
30 class TestIPythonCocoaControler(DeferredTestCase):
35 #---------------------------------------------------------------------------
36 # Tests
37 #---------------------------------------------------------------------------
38 class TestIPythonCocoaControler(unittest.TestCase):
31 39 """Tests for IPythonCocoaController"""
32
40
33 41 def setUp(self):
34 42 self.controller = IPythonCocoaController.alloc().init()
35 43 self.engine = es.EngineService()
36 44 self.engine.startService()
37
45
38 46 def tearDown(self):
39 47 self.controller = None
40 48 self.engine.stopService()
41
49
42 50 def testControllerExecutesCode(self):
43 51 code ="""5+5"""
44 52 expected = Interpreter().execute(code)
45 53 del expected['number']
46 54 def removeNumberAndID(result):
47 55 del result['number']
48 56 del result['id']
49 57 return result
50 self.assertDeferredEquals(
51 self.controller.execute(code).addCallback(removeNumberAndID),
52 expected)
53
58 d = self.controller.execute(code)
59 d.addCallback(removeNumberAndID)
60 d.addCallback(lambda r: self.assertEquals(r, expected))
61
54 62 def testControllerMirrorsUserNSWithValuesAsStrings(self):
55 63 code = """userns1=1;userns2=2"""
56 64 def testControllerUserNS(result):
57 65 self.assertEquals(self.controller.userNS['userns1'], 1)
58 66 self.assertEquals(self.controller.userNS['userns2'], 2)
59
60 67 self.controller.execute(code).addCallback(testControllerUserNS)
61
62
68
63 69 def testControllerInstantiatesIEngine(self):
64 70 self.assert_(es.IEngineBase.providedBy(self.controller.engine))
65
71
66 72 def testControllerCompletesToken(self):
67 73 code = """longNameVariable=10"""
68 74 def testCompletes(result):
69 75 self.assert_("longNameVariable" in result)
70
76
71 77 def testCompleteToken(result):
72 78 self.controller.complete("longNa").addCallback(testCompletes)
73
79
74 80 self.controller.execute(code).addCallback(testCompletes)
75
76
81
82
77 83 def testCurrentIndent(self):
78 84 """test that current_indent_string returns current indent or None.
79 85 Uses _indent_for_block for direct unit testing.
80 86 """
81
87
82 88 self.controller.tabUsesSpaces = True
83 89 self.assert_(self.controller._indent_for_block("""a=3""") == None)
84 90 self.assert_(self.controller._indent_for_block("") == None)
85 91 block = """def test():\n a=3"""
86 92 self.assert_(self.controller._indent_for_block(block) == \
87 93 ' ' * self.controller.tabSpaces)
88
94
89 95 block = """if(True):\n%sif(False):\n%spass""" % \
90 96 (' '*self.controller.tabSpaces,
91 97 2*' '*self.controller.tabSpaces)
92 98 self.assert_(self.controller._indent_for_block(block) == \
93 99 2*(' '*self.controller.tabSpaces))
94
100
@@ -1,333 +1,372 b''
1 1 """
2 2 Base front end class for all line-oriented frontends, rather than
3 3 block-oriented.
4 4
5 5 Currently this focuses on synchronous frontends.
6 6 """
7 7 __docformat__ = "restructuredtext en"
8 8
9 9 #-------------------------------------------------------------------------------
10 10 # Copyright (C) 2008 The IPython Development Team
11 11 #
12 12 # Distributed under the terms of the BSD License. The full license is in
13 13 # the file COPYING, distributed as part of this software.
14 14 #-------------------------------------------------------------------------------
15 15
16 16 #-------------------------------------------------------------------------------
17 17 # Imports
18 18 #-------------------------------------------------------------------------------
19 19 import re
20 20
21 import IPython
22 21 import sys
23 22 import codeop
24 import traceback
25 23
26 24 from frontendbase import FrontEndBase
27 25 from IPython.kernel.core.interpreter import Interpreter
28 26
29 27 def common_prefix(strings):
30 28 """ Given a list of strings, return the common prefix between all
31 29 these strings.
32 30 """
33 31 ref = strings[0]
34 32 prefix = ''
35 33 for size in range(len(ref)):
36 34 test_prefix = ref[:size+1]
37 35 for string in strings[1:]:
38 36 if not string.startswith(test_prefix):
39 37 return prefix
40 38 prefix = test_prefix
41 39
42 40 return prefix
43 41
44 42 #-------------------------------------------------------------------------------
45 43 # Base class for the line-oriented front ends
46 44 #-------------------------------------------------------------------------------
47 45 class LineFrontEndBase(FrontEndBase):
48 46 """ Concrete implementation of the FrontEndBase class. This is meant
49 47 to be the base class behind all the frontend that are line-oriented,
50 48 rather than block-oriented.
51 49 """
52 50
53 51 # We need to keep the prompt number, to be able to increment
54 52 # it when there is an exception.
55 53 prompt_number = 1
56 54
57 55 # We keep a reference to the last result: it helps testing and
58 56 # programatic control of the frontend.
59 57 last_result = dict(number=0)
60 58
59 # The last prompt displayed. Useful for continuation prompts.
60 last_prompt = ''
61
61 62 # The input buffer being edited
62 63 input_buffer = ''
63 64
64 65 # Set to true for debug output
65 66 debug = False
66 67
67 68 # A banner to print at startup
68 69 banner = None
69 70
70 71 #--------------------------------------------------------------------------
71 72 # FrontEndBase interface
72 73 #--------------------------------------------------------------------------
73 74
74 75 def __init__(self, shell=None, history=None, banner=None, *args, **kwargs):
75 76 if shell is None:
76 77 shell = Interpreter()
77 78 FrontEndBase.__init__(self, shell=shell, history=history)
78 79
79 80 if banner is not None:
80 81 self.banner = banner
81 82
82 83 def start(self):
83 84 """ Put the frontend in a state where it is ready for user
84 85 interaction.
85 86 """
86 87 if self.banner is not None:
87 88 self.write(self.banner, refresh=False)
88 89
89 90 self.new_prompt(self.input_prompt_template.substitute(number=1))
90 91
91 92
92 93 def complete(self, line):
93 94 """Complete line in engine's user_ns
94 95
95 96 Parameters
96 97 ----------
97 98 line : string
98 99
99 100 Result
100 101 ------
101 102 The replacement for the line and the list of possible completions.
102 103 """
103 104 completions = self.shell.complete(line)
104 105 complete_sep = re.compile('[\s\{\}\[\]\(\)\=]')
105 106 if completions:
106 107 prefix = common_prefix(completions)
107 108 residual = complete_sep.split(line)[:-1]
108 109 line = line[:-len(residual)] + prefix
109 110 return line, completions
110 111
111 112
112 113 def render_result(self, result):
113 114 """ Frontend-specific rendering of the result of a calculation
114 115 that has been sent to an engine.
115 116 """
116 117 if 'stdout' in result and result['stdout']:
117 118 self.write('\n' + result['stdout'])
118 119 if 'display' in result and result['display']:
119 120 self.write("%s%s\n" % (
120 121 self.output_prompt_template.substitute(
121 122 number=result['number']),
122 123 result['display']['pprint']
123 124 ) )
124 125
125 126
126 127 def render_error(self, failure):
127 128 """ Frontend-specific rendering of error.
128 129 """
129 130 self.write('\n\n'+str(failure)+'\n\n')
130 131 return failure
131 132
132 133
133 134 def is_complete(self, string):
134 135 """ Check if a string forms a complete, executable set of
135 136 commands.
136 137
137 138 For the line-oriented frontend, multi-line code is not executed
138 139 as soon as it is complete: the users has to enter two line
139 140 returns.
140 141 """
141 142 if string in ('', '\n'):
142 143 # Prefiltering, eg through ipython0, may return an empty
143 144 # string although some operations have been accomplished. We
144 145 # thus want to consider an empty string as a complete
145 146 # statement.
146 147 return True
147 148 elif ( len(self.input_buffer.split('\n'))>2
148 149 and not re.findall(r"\n[\t ]*\n[\t ]*$", string)):
149 150 return False
150 151 else:
151 152 self.capture_output()
152 153 try:
153 154 # Add line returns here, to make sure that the statement is
154 # complete.
155 is_complete = codeop.compile_command(string.rstrip() + '\n\n',
155 # complete (except if '\' was used).
156 # This should probably be done in a different place (like
157 # maybe 'prefilter_input' method? For now, this works.
158 clean_string = string.rstrip('\n')
159 if not clean_string.endswith('\\'): clean_string +='\n\n'
160 is_complete = codeop.compile_command(clean_string,
156 161 "<string>", "exec")
157 162 self.release_output()
158 163 except Exception, e:
159 164 # XXX: Hack: return True so that the
160 165 # code gets executed and the error captured.
161 166 is_complete = True
162 167 return is_complete
163 168
164 169
165 170 def write(self, string, refresh=True):
166 171 """ Write some characters to the display.
167 172
168 173 Subclass should overide this method.
169 174
170 175 The refresh keyword argument is used in frontends with an
171 176 event loop, to choose whether the write should trigget an UI
172 177 refresh, and thus be syncrhonous, or not.
173 178 """
174 179 print >>sys.__stderr__, string
175 180
176 181
177 182 def execute(self, python_string, raw_string=None):
178 183 """ Stores the raw_string in the history, and sends the
179 184 python string to the interpreter.
180 185 """
181 186 if raw_string is None:
182 187 raw_string = python_string
183 188 # Create a false result, in case there is an exception
184 189 self.last_result = dict(number=self.prompt_number)
185 190
186 ## try:
187 ## self.history.input_cache[-1] = raw_string.rstrip()
188 ## result = self.shell.execute(python_string)
189 ## self.last_result = result
190 ## self.render_result(result)
191 ## except:
192 ## self.show_traceback()
193 ## finally:
194 ## self.after_execute()
195
196 191 try:
197 192 try:
198 193 self.history.input_cache[-1] = raw_string.rstrip()
199 194 result = self.shell.execute(python_string)
200 195 self.last_result = result
201 196 self.render_result(result)
202 197 except:
203 198 self.show_traceback()
204 199 finally:
205 200 self.after_execute()
206 201
207 202
208 203 #--------------------------------------------------------------------------
209 204 # LineFrontEndBase interface
210 205 #--------------------------------------------------------------------------
211 206
212 207 def prefilter_input(self, string):
213 208 """ Prefilter the input to turn it in valid python.
214 209 """
215 210 string = string.replace('\r\n', '\n')
216 211 string = string.replace('\t', 4*' ')
217 212 # Clean the trailing whitespace
218 213 string = '\n'.join(l.rstrip() for l in string.split('\n'))
219 214 return string
220 215
221 216
222 217 def after_execute(self):
223 218 """ All the operations required after an execution to put the
224 219 terminal back in a shape where it is usable.
225 220 """
226 221 self.prompt_number += 1
227 222 self.new_prompt(self.input_prompt_template.substitute(
228 223 number=(self.last_result['number'] + 1)))
229 224 # Start a new empty history entry
230 225 self._add_history(None, '')
231 226 self.history_cursor = len(self.history.input_cache) - 1
232 227
233 228
234 229 def complete_current_input(self):
235 230 """ Do code completion on current line.
236 231 """
237 232 if self.debug:
238 233 print >>sys.__stdout__, "complete_current_input",
239 234 line = self.input_buffer
240 235 new_line, completions = self.complete(line)
241 236 if len(completions)>1:
242 237 self.write_completion(completions, new_line=new_line)
243 238 elif not line == new_line:
244 239 self.input_buffer = new_line
245 240 if self.debug:
246 241 print >>sys.__stdout__, 'line', line
247 242 print >>sys.__stdout__, 'new_line', new_line
248 243 print >>sys.__stdout__, completions
249 244
250 245
251 246 def get_line_width(self):
252 247 """ Return the width of the line in characters.
253 248 """
254 249 return 80
255 250
256 251
257 252 def write_completion(self, possibilities, new_line=None):
258 253 """ Write the list of possible completions.
259 254
260 255 new_line is the completed input line that should be displayed
261 256 after the completion are writen. If None, the input_buffer
262 257 before the completion is used.
263 258 """
264 259 if new_line is None:
265 260 new_line = self.input_buffer
266 261
267 262 self.write('\n')
268 263 max_len = len(max(possibilities, key=len)) + 1
269 264
270 265 # Now we check how much symbol we can put on a line...
271 266 chars_per_line = self.get_line_width()
272 267 symbols_per_line = max(1, chars_per_line/max_len)
273 268
274 269 pos = 1
275 buf = []
270 completion_string = []
276 271 for symbol in possibilities:
277 272 if pos < symbols_per_line:
278 buf.append(symbol.ljust(max_len))
273 completion_string.append(symbol.ljust(max_len))
279 274 pos += 1
280 275 else:
281 buf.append(symbol.rstrip() + '\n')
276 completion_string.append(symbol.rstrip() + '\n')
282 277 pos = 1
283 self.write(''.join(buf))
278 self.write(''.join(completion_string))
284 279 self.new_prompt(self.input_prompt_template.substitute(
285 280 number=self.last_result['number'] + 1))
286 281 self.input_buffer = new_line
287 282
288 283
289 284 def new_prompt(self, prompt):
290 285 """ Prints a prompt and starts a new editing buffer.
291 286
292 287 Subclasses should use this method to make sure that the
293 288 terminal is put in a state favorable for a new line
294 289 input.
295 290 """
296 291 self.input_buffer = ''
297 292 self.write(prompt)
298 293
299 294
295 def continuation_prompt(self):
296 """Returns the current continuation prompt.
297 """
298 return ("."*(len(self.last_prompt)-2) + ': ')
299
300
301 def execute_command(self, command, hidden=False):
302 """ Execute a command, not only in the model, but also in the
303 view, if any.
304 """
305 return self.shell.execute(command)
306
300 307 #--------------------------------------------------------------------------
301 308 # Private API
302 309 #--------------------------------------------------------------------------
303 310
304 def _on_enter(self):
311 def _on_enter(self, new_line_pos=0):
305 312 """ Called when the return key is pressed in a line editing
306 313 buffer.
314
315 Parameters
316 ----------
317 new_line_pos : integer, optional
318 Position of the new line to add, starting from the
319 end (0 adds a new line after the last line, -1 before
320 the last line...)
321
322 Returns
323 -------
324 True if execution is triggered
307 325 """
308 326 current_buffer = self.input_buffer
309 cleaned_buffer = self.prefilter_input(current_buffer)
327 # XXX: This string replace is ugly, but there should be no way it
328 # fails.
329 prompt_less_buffer = re.sub('^' + self.continuation_prompt(),
330 '', current_buffer).replace('\n' + self.continuation_prompt(),
331 '\n')
332 cleaned_buffer = self.prefilter_input(prompt_less_buffer)
310 333 if self.is_complete(cleaned_buffer):
311 334 self.execute(cleaned_buffer, raw_string=current_buffer)
335 return True
312 336 else:
313 self.input_buffer += self._get_indent_string(
314 current_buffer[:-1])
315 if len(current_buffer.split('\n')) == 2:
316 self.input_buffer += '\t\t'
317 if current_buffer[:-1].split('\n')[-1].rstrip().endswith(':'):
318 self.input_buffer += '\t'
319
337 # Start a new line.
338 new_line_pos = -new_line_pos
339 lines = current_buffer.split('\n')[:-1]
340 prompt_less_lines = prompt_less_buffer.split('\n')
341 # Create the new line, with the continuation prompt, and the
342 # same amount of indent than the line above it.
343 new_line = self.continuation_prompt() + \
344 self._get_indent_string('\n'.join(
345 prompt_less_lines[:new_line_pos-1]))
346 if len(lines) == 1:
347 # We are starting a first continuation line. Indent it.
348 new_line += '\t'
349 elif current_buffer[:-1].split('\n')[-1].rstrip().endswith(':'):
350 # The last line ends with ":", autoindent the new line.
351 new_line += '\t'
352
353 if new_line_pos == 0:
354 lines.append(new_line)
355 else:
356 lines.insert(new_line_pos, new_line)
357 self.input_buffer = '\n'.join(lines)
358
320 359
321 360 def _get_indent_string(self, string):
322 361 """ Return the string of whitespace that prefixes a line. Used to
323 362 add the right amount of indendation when creating a new line.
324 363 """
325 364 string = string.replace('\t', ' '*4)
326 365 string = string.split('\n')[-1]
327 366 indent_chars = len(string) - len(string.lstrip())
328 367 indent_string = '\t'*(indent_chars // 4) + \
329 368 ' '*(indent_chars % 4)
330 369
331 370 return indent_string
332 371
333 372
@@ -1,246 +1,285 b''
1 1 """
2 2 Frontend class that uses IPython0 to prefilter the inputs.
3 3
4 4 Using the IPython0 mechanism gives us access to the magics.
5 5
6 6 This is a transitory class, used here to do the transition between
7 7 ipython0 and ipython1. This class is meant to be short-lived as more
8 8 functionnality is abstracted out of ipython0 in reusable functions and
9 9 is added on the interpreter. This class can be a used to guide this
10 10 refactoring.
11 11 """
12 12 __docformat__ = "restructuredtext en"
13 13
14 14 #-------------------------------------------------------------------------------
15 15 # Copyright (C) 2008 The IPython Development Team
16 16 #
17 17 # Distributed under the terms of the BSD License. The full license is in
18 18 # the file COPYING, distributed as part of this software.
19 19 #-------------------------------------------------------------------------------
20 20
21 21 #-------------------------------------------------------------------------------
22 22 # Imports
23 23 #-------------------------------------------------------------------------------
24 24 import sys
25
26 from linefrontendbase import LineFrontEndBase, common_prefix
27 from frontendbase import FrontEndBase
25 import pydoc
26 import os
27 import re
28 import __builtin__
28 29
29 30 from IPython.ipmaker import make_IPython
30 31 from IPython.ipapi import IPApi
31 32 from IPython.kernel.core.redirector_output_trap import RedirectorOutputTrap
32 33
33 34 from IPython.kernel.core.sync_traceback_trap import SyncTracebackTrap
34 35
35 36 from IPython.genutils import Term
36 import pydoc
37 import os
38 import sys
37
38 from linefrontendbase import LineFrontEndBase, common_prefix
39 39
40 40
41 41 def mk_system_call(system_call_function, command):
42 42 """ given a os.system replacement, and a leading string command,
43 43 returns a function that will execute the command with the given
44 44 argument string.
45 45 """
46 46 def my_system_call(args):
47 47 system_call_function("%s %s" % (command, args))
48
49 my_system_call.__doc__ = "Calls %s" % command
48 50 return my_system_call
49 51
50 52 #-------------------------------------------------------------------------------
51 53 # Frontend class using ipython0 to do the prefiltering.
52 54 #-------------------------------------------------------------------------------
53 55 class PrefilterFrontEnd(LineFrontEndBase):
54 56 """ Class that uses ipython0 to do prefilter the input, do the
55 57 completion and the magics.
56 58
57 59 The core trick is to use an ipython0 instance to prefilter the
58 60 input, and share the namespace between the interpreter instance used
59 61 to execute the statements and the ipython0 used for code
60 62 completion...
61 63 """
62 64
63 65 debug = False
64 66
65 def __init__(self, ipython0=None, *args, **kwargs):
67 def __init__(self, ipython0=None, argv=None, *args, **kwargs):
66 68 """ Parameters:
67 69 -----------
68 70
69 71 ipython0: an optional ipython0 instance to use for command
70 72 prefiltering and completion.
73
74 argv : list, optional
75 Used as the instance's argv value. If not given, [] is used.
71 76 """
77 if argv is None:
78 argv = []
79 # This is a hack to avoid the IPython exception hook to trigger
80 # on exceptions (https://bugs.launchpad.net/bugs/337105)
81 # XXX: This is horrible: module-leve monkey patching -> side
82 # effects.
83 from IPython import iplib
84 iplib.InteractiveShell.isthreaded = True
85
72 86 LineFrontEndBase.__init__(self, *args, **kwargs)
73 87 self.shell.output_trap = RedirectorOutputTrap(
74 88 out_callback=self.write,
75 89 err_callback=self.write,
76 90 )
77 91 self.shell.traceback_trap = SyncTracebackTrap(
78 92 formatters=self.shell.traceback_trap.formatters,
79 93 )
80 94
81 95 # Start the ipython0 instance:
82 96 self.save_output_hooks()
83 97 if ipython0 is None:
84 98 # Instanciate an IPython0 interpreter to be able to use the
85 99 # prefiltering.
100 # Suppress all key input, to avoid waiting
101 def my_rawinput(x=None):
102 return '\n'
103 old_rawinput = __builtin__.raw_input
104 __builtin__.raw_input = my_rawinput
86 105 # XXX: argv=[] is a bit bold.
87 ipython0 = make_IPython(argv=[],
106 ipython0 = make_IPython(argv=argv,
88 107 user_ns=self.shell.user_ns,
89 108 user_global_ns=self.shell.user_global_ns)
109 __builtin__.raw_input = old_rawinput
90 110 self.ipython0 = ipython0
91 111 # Set the pager:
92 112 self.ipython0.set_hook('show_in_pager',
93 113 lambda s, string: self.write("\n" + string))
94 114 self.ipython0.write = self.write
95 115 self._ip = _ip = IPApi(self.ipython0)
96 116 # Make sure the raw system call doesn't get called, as we don't
97 117 # have a stdin accessible.
98 118 self._ip.system = self.system_call
99 119 # XXX: Muck around with magics so that they work better
100 120 # in our environment
101 self.ipython0.magic_ls = mk_system_call(self.system_call,
102 'ls -CF')
121 if not sys.platform.startswith('win'):
122 self.ipython0.magic_ls = mk_system_call(self.system_call,
123 'ls -CF')
103 124 # And now clean up the mess created by ipython0
104 125 self.release_output()
105 126
106 127
107 128 if not 'banner' in kwargs and self.banner is None:
108 self.banner = self.ipython0.BANNER + """
109 This is the wx frontend, by Gael Varoquaux. This is EXPERIMENTAL code."""
129 self.banner = self.ipython0.BANNER
110 130
131 # FIXME: __init__ and start should be two different steps
111 132 self.start()
112 133
113 134 #--------------------------------------------------------------------------
114 135 # FrontEndBase interface
115 136 #--------------------------------------------------------------------------
116 137
117 138 def show_traceback(self):
118 139 """ Use ipython0 to capture the last traceback and display it.
119 140 """
120 self.capture_output()
141 # Don't do the capture; the except_hook has already done some
142 # modifications to the IO streams, if we store them, we'll be
143 # storing the wrong ones.
144 #self.capture_output()
121 145 self.ipython0.showtraceback(tb_offset=-1)
122 146 self.release_output()
123 147
124 148
125 149 def execute(self, python_string, raw_string=None):
126 150 if self.debug:
127 151 print 'Executing Python code:', repr(python_string)
128 152 self.capture_output()
129 153 LineFrontEndBase.execute(self, python_string,
130 154 raw_string=raw_string)
131 155 self.release_output()
132 156
133 157
134 158 def save_output_hooks(self):
135 159 """ Store all the output hooks we can think of, to be able to
136 160 restore them.
137 161
138 162 We need to do this early, as starting the ipython0 instance will
139 163 screw ouput hooks.
140 164 """
141 165 self.__old_cout_write = Term.cout.write
142 166 self.__old_cerr_write = Term.cerr.write
143 167 self.__old_stdout = sys.stdout
144 168 self.__old_stderr= sys.stderr
145 169 self.__old_help_output = pydoc.help.output
146 170 self.__old_display_hook = sys.displayhook
147 171
148 172
149 173 def capture_output(self):
150 174 """ Capture all the output mechanisms we can think of.
151 175 """
152 176 self.save_output_hooks()
153 177 Term.cout.write = self.write
154 178 Term.cerr.write = self.write
155 179 sys.stdout = Term.cout
156 180 sys.stderr = Term.cerr
157 181 pydoc.help.output = self.shell.output_trap.out
158 182
159 183
160 184 def release_output(self):
161 185 """ Release all the different captures we have made.
162 186 """
163 187 Term.cout.write = self.__old_cout_write
164 188 Term.cerr.write = self.__old_cerr_write
165 189 sys.stdout = self.__old_stdout
166 190 sys.stderr = self.__old_stderr
167 191 pydoc.help.output = self.__old_help_output
168 192 sys.displayhook = self.__old_display_hook
169 193
170 194
171 195 def complete(self, line):
172 196 # FIXME: This should be factored out in the linefrontendbase
173 197 # method.
174 word = line.split('\n')[-1].split(' ')[-1]
198 word = self._get_completion_text(line)
175 199 completions = self.ipython0.complete(word)
176 200 # FIXME: The proper sort should be done in the complete method.
177 201 key = lambda x: x.replace('_', '')
178 202 completions.sort(key=key)
179 203 if completions:
180 204 prefix = common_prefix(completions)
181 205 line = line[:-len(word)] + prefix
182 206 return line, completions
183 207
184 208
185 209 #--------------------------------------------------------------------------
186 210 # LineFrontEndBase interface
187 211 #--------------------------------------------------------------------------
188 212
189 213 def prefilter_input(self, input_string):
190 214 """ Using IPython0 to prefilter the commands to turn them
191 215 in executable statements that are valid Python strings.
192 216 """
193 217 input_string = LineFrontEndBase.prefilter_input(self, input_string)
194 218 filtered_lines = []
195 219 # The IPython0 prefilters sometime produce output. We need to
196 220 # capture it.
197 221 self.capture_output()
198 222 self.last_result = dict(number=self.prompt_number)
199 223
200 224 ## try:
201 225 ## for line in input_string.split('\n'):
202 226 ## filtered_lines.append(
203 227 ## self.ipython0.prefilter(line, False).rstrip())
204 228 ## except:
205 229 ## # XXX: probably not the right thing to do.
206 230 ## self.ipython0.showsyntaxerror()
207 231 ## self.after_execute()
208 232 ## finally:
209 233 ## self.release_output()
210 234
211 235
212 236 try:
213 237 try:
214 238 for line in input_string.split('\n'):
215 239 filtered_lines.append(
216 240 self.ipython0.prefilter(line, False).rstrip())
217 241 except:
218 242 # XXX: probably not the right thing to do.
219 243 self.ipython0.showsyntaxerror()
220 244 self.after_execute()
221 245 finally:
222 246 self.release_output()
223 247
224 248
225 249
226 250 # Clean up the trailing whitespace, to avoid indentation errors
227 251 filtered_string = '\n'.join(filtered_lines)
228 252 return filtered_string
229 253
230 254
231 255 #--------------------------------------------------------------------------
232 256 # PrefilterFrontEnd interface
233 257 #--------------------------------------------------------------------------
234 258
235 259 def system_call(self, command_string):
236 260 """ Allows for frontend to define their own system call, to be
237 261 able capture output and redirect input.
238 262 """
239 263 return os.system(command_string)
240 264
241 265
242 266 def do_exit(self):
243 267 """ Exit the shell, cleanup and save the history.
244 268 """
245 269 self.ipython0.atexit_operations()
246 270
271
272 def _get_completion_text(self, line):
273 """ Returns the text to be completed by breaking the line at specified
274 delimiters.
275 """
276 # Break at: spaces, '=', all parentheses (except if balanced).
277 # FIXME2: In the future, we need to make the implementation similar to
278 # that in the 'pyreadline' module (modes/basemode.py) where we break at
279 # each delimiter and try to complete the residual line, until we get a
280 # successful list of completions.
281 expression = '\s|=|,|:|\((?!.*\))|\[(?!.*\])|\{(?!.*\})'
282 complete_sep = re.compile(expression)
283 text = complete_sep.split(line)[-1]
284 return text
285
1 NO CONTENT: file renamed from IPython/frontend/_process/__init__.py to IPython/frontend/process/__init__.py
@@ -1,179 +1,184 b''
1 1 # Addapted from killableprocess.py.
2 2 #______________________________________________________________________________
3 3 #
4 4 # killableprocess - subprocesses which can be reliably killed
5 5 #
6 6 # Parts of this module are copied from the subprocess.py file contained
7 7 # in the Python distribution.
8 8 #
9 9 # Copyright (c) 2003-2004 by Peter Astrand <astrand@lysator.liu.se>
10 10 #
11 11 # Additions and modifications written by Benjamin Smedberg
12 12 # <benjamin@smedbergs.us> are Copyright (c) 2006 by the Mozilla Foundation
13 13 # <http://www.mozilla.org/>
14 14 #
15 15 # By obtaining, using, and/or copying this software and/or its
16 16 # associated documentation, you agree that you have read, understood,
17 17 # and will comply with the following terms and conditions:
18 18 #
19 19 # Permission to use, copy, modify, and distribute this software and
20 20 # its associated documentation for any purpose and without fee is
21 21 # hereby granted, provided that the above copyright notice appears in
22 22 # all copies, and that both that copyright notice and this permission
23 23 # notice appear in supporting documentation, and that the name of the
24 24 # author not be used in advertising or publicity pertaining to
25 25 # distribution of the software without specific, written prior
26 26 # permission.
27 27 #
28 28 # THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
29 29 # INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
30 30 # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
31 31 # CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
32 32 # OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
33 33 # NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
34 34 # WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
35 35
36 36 r"""killableprocess - Subprocesses which can be reliably killed
37 37
38 38 This module is a subclass of the builtin "subprocess" module. It allows
39 39 processes that launch subprocesses to be reliably killed on Windows (via the Popen.kill() method.
40 40
41 41 It also adds a timeout argument to Wait() for a limited period of time before
42 42 forcefully killing the process.
43 43
44 44 Note: On Windows, this module requires Windows 2000 or higher (no support for
45 45 Windows 95, 98, or NT 4.0). It also requires ctypes, which is bundled with
46 46 Python 2.5+ or available from http://python.net/crew/theller/ctypes/
47 47 """
48 48
49 49 import subprocess
50 50 from subprocess import PIPE
51 51 import sys
52 52 import os
53 53 import types
54 54
55 55 try:
56 56 from subprocess import CalledProcessError
57 57 except ImportError:
58 58 # Python 2.4 doesn't implement CalledProcessError
59 59 class CalledProcessError(Exception):
60 60 """This exception is raised when a process run by check_call() returns
61 61 a non-zero exit status. The exit status will be stored in the
62 62 returncode attribute."""
63 63 def __init__(self, returncode, cmd):
64 64 self.returncode = returncode
65 65 self.cmd = cmd
66 66 def __str__(self):
67 67 return "Command '%s' returned non-zero exit status %d" % (self.cmd, self.returncode)
68 68
69 69 mswindows = (sys.platform == "win32")
70 70
71 71 skip = False
72 72
73 73 if mswindows:
74 74 import platform
75 75 if platform.uname()[3] == '' or platform.uname()[3] > '6.0.6000':
76 76 # Killable process does not work under vista when starting for
77 77 # something else than cmd.
78 78 skip = True
79 79 else:
80 80 import winprocess
81 81 else:
82 82 import signal
83 83
84 84 if not mswindows:
85 85 def DoNothing(*args):
86 86 pass
87 87
88 88
89 89 if skip:
90 90 Popen = subprocess.Popen
91 91 else:
92 92 class Popen(subprocess.Popen):
93 93 if not mswindows:
94 94 # Override __init__ to set a preexec_fn
95 95 def __init__(self, *args, **kwargs):
96 96 if len(args) >= 7:
97 97 raise Exception("Arguments preexec_fn and after must be passed by keyword.")
98 98
99 99 real_preexec_fn = kwargs.pop("preexec_fn", None)
100 100 def setpgid_preexec_fn():
101 101 os.setpgid(0, 0)
102 102 if real_preexec_fn:
103 103 apply(real_preexec_fn)
104 104
105 105 kwargs['preexec_fn'] = setpgid_preexec_fn
106 106
107 107 subprocess.Popen.__init__(self, *args, **kwargs)
108 108
109 109 if mswindows:
110 110 def _execute_child(self, args, executable, preexec_fn, close_fds,
111 111 cwd, env, universal_newlines, startupinfo,
112 112 creationflags, shell,
113 113 p2cread, p2cwrite,
114 114 c2pread, c2pwrite,
115 115 errread, errwrite):
116 116 if not isinstance(args, types.StringTypes):
117 117 args = subprocess.list2cmdline(args)
118 118
119 119 if startupinfo is None:
120 120 startupinfo = winprocess.STARTUPINFO()
121 121
122 122 if None not in (p2cread, c2pwrite, errwrite):
123 123 startupinfo.dwFlags |= winprocess.STARTF_USESTDHANDLES
124 124
125 125 startupinfo.hStdInput = int(p2cread)
126 126 startupinfo.hStdOutput = int(c2pwrite)
127 127 startupinfo.hStdError = int(errwrite)
128 128 if shell:
129 129 startupinfo.dwFlags |= winprocess.STARTF_USESHOWWINDOW
130 130 startupinfo.wShowWindow = winprocess.SW_HIDE
131 131 comspec = os.environ.get("COMSPEC", "cmd.exe")
132 132 args = comspec + " /c " + args
133 133
134 134 # We create a new job for this process, so that we can kill
135 135 # the process and any sub-processes
136 136 self._job = winprocess.CreateJobObject()
137 137
138 138 creationflags |= winprocess.CREATE_SUSPENDED
139 139 creationflags |= winprocess.CREATE_UNICODE_ENVIRONMENT
140 140
141 141 hp, ht, pid, tid = winprocess.CreateProcess(
142 142 executable, args,
143 143 None, None, # No special security
144 144 1, # Must inherit handles!
145 145 creationflags,
146 146 winprocess.EnvironmentBlock(env),
147 147 cwd, startupinfo)
148 148
149 149 self._child_created = True
150 150 self._handle = hp
151 151 self._thread = ht
152 152 self.pid = pid
153 153
154 winprocess.AssignProcessToJobObject(self._job, hp)
154 # XXX: A try/except to fix UAC-related problems under
155 # Windows Vista, when reparenting jobs.
156 try:
157 winprocess.AssignProcessToJobObject(self._job, hp)
158 except WindowsError:
159 pass
155 160 winprocess.ResumeThread(ht)
156 161
157 162 if p2cread is not None:
158 163 p2cread.Close()
159 164 if c2pwrite is not None:
160 165 c2pwrite.Close()
161 166 if errwrite is not None:
162 167 errwrite.Close()
163 168
164 169 def kill(self, group=True):
165 170 """Kill the process. If group=True, all sub-processes will also be killed."""
166 171 if mswindows:
167 172 if group:
168 173 winprocess.TerminateJobObject(self._job, 127)
169 174 else:
170 175 winprocess.TerminateProcess(self._handle, 127)
171 176 self.returncode = 127
172 177 else:
173 178 if group:
174 179 os.killpg(self.pid, signal.SIGKILL)
175 180 else:
176 181 os.kill(self.pid, signal.SIGKILL)
177 182 self.returncode = -9
178 183
179 184
1 NO CONTENT: file renamed from IPython/frontend/_process/pipedprocess.py to IPython/frontend/process/pipedprocess.py
1 NO CONTENT: file renamed from IPython/frontend/_process/winprocess.py to IPython/frontend/process/winprocess.py
@@ -1,155 +1,109 b''
1 1 # encoding: utf-8
2 2
3 """This file contains unittests for the frontendbase module."""
3 """This file contains unittests for the asyncfrontendbase module."""
4 4
5 5 __docformat__ = "restructuredtext en"
6 6
7 7 #---------------------------------------------------------------------------
8 8 # Copyright (C) 2008 The IPython Development Team
9 9 #
10 10 # Distributed under the terms of the BSD License. The full license is in
11 11 # the file COPYING, distributed as part of this software.
12 12 #---------------------------------------------------------------------------
13 13
14 14 #---------------------------------------------------------------------------
15 15 # Imports
16 16 #---------------------------------------------------------------------------
17 17
18 import unittest
18 # Tell nose to skip this module
19 __test__ = {}
19 20
20 try:
21 from IPython.frontend.asyncfrontendbase import AsyncFrontEndBase
22 from IPython.frontend import frontendbase
23 from IPython.kernel.engineservice import EngineService
24 except ImportError:
25 import nose
26 raise nose.SkipTest("This test requires zope.interface, Twisted and Foolscap")
21 from twisted.trial import unittest
22 from IPython.frontend.asyncfrontendbase import AsyncFrontEndBase
23 from IPython.frontend import frontendbase
24 from IPython.kernel.engineservice import EngineService
25 from IPython.testing.parametric import Parametric, parametric
27 26
28 from IPython.testing.decorators import skip
29 27
30 28 class FrontEndCallbackChecker(AsyncFrontEndBase):
31 29 """FrontEndBase subclass for checking callbacks"""
32 30 def __init__(self, engine=None, history=None):
33 31 super(FrontEndCallbackChecker, self).__init__(engine=engine,
34 32 history=history)
35 33 self.updateCalled = False
36 34 self.renderResultCalled = False
37 35 self.renderErrorCalled = False
38 36
39 37 def update_cell_prompt(self, result, blockID=None):
40 38 self.updateCalled = True
41 39 return result
42 40
43 41 def render_result(self, result):
44 42 self.renderResultCalled = True
45 43 return result
46 44
47
48 45 def render_error(self, failure):
49 46 self.renderErrorCalled = True
50 47 return failure
51
52 48
53 49
54
55 50 class TestAsyncFrontendBase(unittest.TestCase):
56 51 def setUp(self):
57 52 """Setup the EngineService and FrontEndBase"""
58 53
59 54 self.fb = FrontEndCallbackChecker(engine=EngineService())
60 55
61 56 def test_implements_IFrontEnd(self):
62 assert(frontendbase.IFrontEnd.implementedBy(
57 self.assert_(frontendbase.IFrontEnd.implementedBy(
63 58 AsyncFrontEndBase))
64 59
65 60 def test_is_complete_returns_False_for_incomplete_block(self):
66 """"""
67
68 61 block = """def test(a):"""
69
70 assert(self.fb.is_complete(block) == False)
62 self.assert_(self.fb.is_complete(block) == False)
71 63
72 64 def test_is_complete_returns_True_for_complete_block(self):
73 """"""
74
75 65 block = """def test(a): pass"""
76
77 assert(self.fb.is_complete(block))
78
66 self.assert_(self.fb.is_complete(block))
79 67 block = """a=3"""
80
81 assert(self.fb.is_complete(block))
68 self.assert_(self.fb.is_complete(block))
82 69
83 70 def test_blockID_added_to_result(self):
84 71 block = """3+3"""
85
86 72 d = self.fb.execute(block, blockID='TEST_ID')
87
88 d.addCallback(self.checkBlockID, expected='TEST_ID')
73 d.addCallback(lambda r: self.assert_(r['blockID']=='TEST_ID'))
74 return d
89 75
90 76 def test_blockID_added_to_failure(self):
91 77 block = "raise Exception()"
92
93 78 d = self.fb.execute(block,blockID='TEST_ID')
94 d.addErrback(self.checkFailureID, expected='TEST_ID')
95
96 def checkBlockID(self, result, expected=""):
97 assert(result['blockID'] == expected)
98
99
100 def checkFailureID(self, failure, expected=""):
101 assert(failure.blockID == expected)
102
79 d.addErrback(lambda f: self.assert_(f.blockID=='TEST_ID'))
80 return d
103 81
104 82 def test_callbacks_added_to_execute(self):
105 """test that
106 update_cell_prompt
107 render_result
108
109 are added to execute request
110 """
111
112 83 d = self.fb.execute("10+10")
113 d.addCallback(self.checkCallbacks)
84 d.addCallback(lambda r: self.assert_(self.fb.updateCalled and self.fb.renderResultCalled))
85 return d
114 86
115 def checkCallbacks(self, result):
116 assert(self.fb.updateCalled)
117 assert(self.fb.renderResultCalled)
118
119 @skip("This test fails and lead to an unhandled error in a Deferred.")
120 87 def test_error_callback_added_to_execute(self):
121 """test that render_error called on execution error"""
88 """Test that render_error called on execution error."""
122 89
123 90 d = self.fb.execute("raise Exception()")
124 d.addCallback(self.checkRenderError)
125
126 def checkRenderError(self, result):
127 assert(self.fb.renderErrorCalled)
91 d.addErrback(lambda f: self.assert_(self.fb.renderErrorCalled))
92 return d
128 93
129 94 def test_history_returns_expected_block(self):
130 """Make sure history browsing doesn't fail"""
95 """Make sure history browsing doesn't fail."""
131 96
132 97 blocks = ["a=1","a=2","a=3"]
133 for b in blocks:
134 d = self.fb.execute(b)
135
136 # d is now the deferred for the last executed block
137 d.addCallback(self.historyTests, blocks)
138
139
140 def historyTests(self, result, blocks):
141 """historyTests"""
142
143 assert(len(blocks) >= 3)
144 assert(self.fb.get_history_previous("") == blocks[-2])
145 assert(self.fb.get_history_previous("") == blocks[-3])
146 assert(self.fb.get_history_next() == blocks[-2])
147
148
149 def test_history_returns_none_at_startup(self):
150 """test_history_returns_none_at_startup"""
151
152 assert(self.fb.get_history_previous("")==None)
153 assert(self.fb.get_history_next()==None)
154
155
98 d = self.fb.execute(blocks[0])
99 d.addCallback(lambda _: self.fb.execute(blocks[1]))
100 d.addCallback(lambda _: self.fb.execute(blocks[2]))
101 d.addCallback(lambda _: self.assert_(self.fb.get_history_previous("")==blocks[-2]))
102 d.addCallback(lambda _: self.assert_(self.fb.get_history_previous("")==blocks[-3]))
103 d.addCallback(lambda _: self.assert_(self.fb.get_history_next()==blocks[-2]))
104 return d
105
106 def test_history_returns_none_at_startup(self):
107 self.assert_(self.fb.get_history_previous("")==None)
108 self.assert_(self.fb.get_history_next()==None)
109
@@ -1,180 +1,252 b''
1 1 # encoding: utf-8
2 2 """
3 3 Test process execution and IO redirection.
4 4 """
5 5
6 6 __docformat__ = "restructuredtext en"
7 7
8 8 #-------------------------------------------------------------------------------
9 9 # Copyright (C) 2008 The IPython Development Team
10 10 #
11 11 # Distributed under the terms of the BSD License. The full license is
12 12 # in the file COPYING, distributed as part of this software.
13 13 #-------------------------------------------------------------------------------
14 14
15 from copy import copy, deepcopy
15 16 from cStringIO import StringIO
16 17 import string
17 18
18 from IPython.ipapi import get as get_ipython0
19 from nose.tools import assert_equal
20
19 21 from IPython.frontend.prefilterfrontend import PrefilterFrontEnd
20 from copy import deepcopy
22 from IPython.ipapi import get as get_ipython0
23 from IPython.testing.plugin.ipdoctest import default_argv
24
25
26 def safe_deepcopy(d):
27 """ Deep copy every key of the given dict, when possible. Elsewhere
28 do a copy.
29 """
30 copied_d = dict()
31 for key, value in d.iteritems():
32 try:
33 copied_d[key] = deepcopy(value)
34 except:
35 try:
36 copied_d[key] = copy(value)
37 except:
38 copied_d[key] = value
39 return copied_d
40
21 41
22 42 class TestPrefilterFrontEnd(PrefilterFrontEnd):
23 43
24 44 input_prompt_template = string.Template('')
25 45 output_prompt_template = string.Template('')
26 46 banner = ''
27 47
28 48 def __init__(self):
29 ipython0 = get_ipython0().IP
30 49 self.out = StringIO()
31 PrefilterFrontEnd.__init__(self, ipython0=ipython0)
32 # Clean up the namespace for isolation between tests
33 user_ns = self.ipython0.user_ns
34 # We need to keep references to things so that they don't
35 # get garbage collected (this stinks).
36 self.shadow_ns = dict()
37 for i in self.ipython0.magic_who_ls():
38 self.shadow_ns[i] = user_ns.pop(i)
50 PrefilterFrontEnd.__init__(self,argv=default_argv())
39 51 # Some more code for isolation (yeah, crazy)
40 52 self._on_enter()
41 53 self.out.flush()
42 54 self.out.reset()
43 55 self.out.truncate()
44 56
45 57 def write(self, string, *args, **kwargs):
46 58 self.out.write(string)
47 59
48 60 def _on_enter(self):
49 61 self.input_buffer += '\n'
50 62 PrefilterFrontEnd._on_enter(self)
51 63
52 64
53 65 def isolate_ipython0(func):
54 66 """ Decorator to isolate execution that involves an iptyhon0.
67
68 Notes
69 -----
70
71 Apply only to functions with no arguments. Nose skips functions
72 with arguments.
55 73 """
56 def my_func(*args, **kwargs):
57 ipython0 = get_ipython0().IP
58 user_ns = deepcopy(ipython0.user_ns)
59 global_ns = deepcopy(ipython0.global_ns)
74 def my_func():
75 iplib = get_ipython0()
76 if iplib is None:
77 return func()
78 ipython0 = iplib.IP
79 global_ns = safe_deepcopy(ipython0.user_global_ns)
80 user_ns = safe_deepcopy(ipython0.user_ns)
60 81 try:
61 func(*args, **kwargs)
82 out = func()
62 83 finally:
63 84 ipython0.user_ns = user_ns
64 ipython0.global_ns = global_ns
85 ipython0.user_global_ns = global_ns
86 # Undo the hack at creation of PrefilterFrontEnd
87 from IPython import iplib
88 iplib.InteractiveShell.isthreaded = False
89 return out
65 90
91 my_func.__name__ = func.__name__
66 92 return my_func
67 93
68 94
69 95 @isolate_ipython0
70 96 def test_execution():
71 97 """ Test execution of a command.
72 98 """
73 99 f = TestPrefilterFrontEnd()
74 100 f.input_buffer = 'print 1'
75 101 f._on_enter()
76 102 out_value = f.out.getvalue()
77 assert out_value == '1\n'
103 assert_equal(out_value, '1\n')
78 104
79 105
80 106 @isolate_ipython0
81 107 def test_multiline():
82 108 """ Test execution of a multiline command.
83 109 """
84 110 f = TestPrefilterFrontEnd()
85 111 f.input_buffer = 'if True:'
86 112 f._on_enter()
87 113 f.input_buffer += 'print 1'
88 114 f._on_enter()
89 115 out_value = f.out.getvalue()
90 assert out_value == ''
116 yield assert_equal, out_value, ''
91 117 f._on_enter()
92 118 out_value = f.out.getvalue()
93 assert out_value == '1\n'
119 yield assert_equal, out_value, '1\n'
94 120 f = TestPrefilterFrontEnd()
95 121 f.input_buffer='(1 +'
96 122 f._on_enter()
97 123 f.input_buffer += '0)'
98 124 f._on_enter()
99 125 out_value = f.out.getvalue()
100 assert out_value == ''
126 yield assert_equal, out_value, ''
101 127 f._on_enter()
102 128 out_value = f.out.getvalue()
103 assert out_value == '1\n'
129 yield assert_equal, out_value, '1\n'
104 130
105 131
106 132 @isolate_ipython0
107 133 def test_capture():
108 134 """ Test the capture of output in different channels.
109 135 """
110 136 # Test on the OS-level stdout, stderr.
111 137 f = TestPrefilterFrontEnd()
112 138 f.input_buffer = \
113 139 'import os; out=os.fdopen(1, "w"); out.write("1") ; out.flush()'
114 140 f._on_enter()
115 141 out_value = f.out.getvalue()
116 assert out_value == '1'
142 yield assert_equal, out_value, '1'
117 143 f = TestPrefilterFrontEnd()
118 144 f.input_buffer = \
119 145 'import os; out=os.fdopen(2, "w"); out.write("1") ; out.flush()'
120 146 f._on_enter()
121 147 out_value = f.out.getvalue()
122 assert out_value == '1'
148 yield assert_equal, out_value, '1'
123 149
124 150
125 151 @isolate_ipython0
126 152 def test_magic():
127 153 """ Test the magic expansion and history.
128 154
129 155 This test is fairly fragile and will break when magics change.
130 156 """
131 157 f = TestPrefilterFrontEnd()
158 # Before checking the interactive namespace, make sure it's clear (it can
159 # otherwise pick up things stored in the user's local db)
160 f.input_buffer += '%reset -f'
161 f._on_enter()
162 f.complete_current_input()
163 # Now, run the %who magic and check output
132 164 f.input_buffer += '%who'
133 165 f._on_enter()
134 166 out_value = f.out.getvalue()
135 assert out_value == 'Interactive namespace is empty.\n'
167 assert_equal(out_value, 'Interactive namespace is empty.\n')
136 168
137 169
138 170 @isolate_ipython0
139 171 def test_help():
140 172 """ Test object inspection.
141 173 """
142 174 f = TestPrefilterFrontEnd()
143 175 f.input_buffer += "def f():"
144 176 f._on_enter()
145 177 f.input_buffer += "'foobar'"
146 178 f._on_enter()
147 179 f.input_buffer += "pass"
148 180 f._on_enter()
149 181 f._on_enter()
150 182 f.input_buffer += "f?"
151 183 f._on_enter()
152 184 assert 'traceback' not in f.last_result
153 185 ## XXX: ipython doctest magic breaks this. I have no clue why
154 186 #out_value = f.out.getvalue()
155 187 #assert out_value.split()[-1] == 'foobar'
156 188
157 189
158 190 @isolate_ipython0
159 def test_completion():
160 """ Test command-line completion.
191 def test_completion_simple():
192 """ Test command-line completion on trivial examples.
161 193 """
162 194 f = TestPrefilterFrontEnd()
163 195 f.input_buffer = 'zzza = 1'
164 196 f._on_enter()
165 197 f.input_buffer = 'zzzb = 2'
166 198 f._on_enter()
167 199 f.input_buffer = 'zz'
168 200 f.complete_current_input()
169 201 out_value = f.out.getvalue()
170 assert out_value == '\nzzza zzzb '
171 assert f.input_buffer == 'zzz'
202 yield assert_equal, out_value, '\nzzza zzzb '
203 yield assert_equal, f.input_buffer, 'zzz'
204
205
206 @isolate_ipython0
207 def test_completion_parenthesis():
208 """ Test command-line completion when a parenthesis is open.
209 """
210 f = TestPrefilterFrontEnd()
211 f.input_buffer = 'zzza = 1'
212 f._on_enter()
213 f.input_buffer = 'zzzb = 2'
214 f._on_enter()
215 f.input_buffer = 'map(zz'
216 f.complete_current_input()
217 out_value = f.out.getvalue()
218 yield assert_equal, out_value, '\nzzza zzzb '
219 yield assert_equal, f.input_buffer, 'map(zzz'
220
221
222 @isolate_ipython0
223 def test_completion_indexing():
224 """ Test command-line completion when indexing on objects.
225 """
226 f = TestPrefilterFrontEnd()
227 f.input_buffer = 'a = [0]'
228 f._on_enter()
229 f.input_buffer = 'a[0].'
230 f.complete_current_input()
231 assert_equal(f.input_buffer, 'a[0].__')
232
233
234 @isolate_ipython0
235 def test_completion_equal():
236 """ Test command-line completion when the delimiter is "=", not " ".
237 """
238 f = TestPrefilterFrontEnd()
239 f.input_buffer = 'a=1.'
240 f.complete_current_input()
241 assert_equal(f.input_buffer, 'a=1.__')
242
172 243
173 244
174 245 if __name__ == '__main__':
175 246 test_magic()
176 247 test_help()
177 248 test_execution()
178 249 test_multiline()
179 250 test_capture()
180 test_completion()
251 test_completion_simple()
252 test_completion_complex()
@@ -1,67 +1,67 b''
1 1 # encoding: utf-8
2 2 """
3 3 Test process execution and IO redirection.
4 4 """
5 5
6 6 __docformat__ = "restructuredtext en"
7 7
8 #-------------------------------------------------------------------------------
9 # Copyright (C) 2008 The IPython Development Team
8 #-----------------------------------------------------------------------------
9 # Copyright (C) 2008-2009 The IPython Development Team
10 10 #
11 11 # Distributed under the terms of the BSD License. The full license is
12 12 # in the file COPYING, distributed as part of this software.
13 #-------------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 14
15 15 from cStringIO import StringIO
16 16 from time import sleep
17 17 import sys
18 18
19 from IPython.frontend._process import PipedProcess
19 from IPython.frontend.process import PipedProcess
20 20 from IPython.testing import decorators as testdec
21 21
22 22
23 23 def test_capture_out():
24 24 """ A simple test to see if we can execute a process and get the output.
25 25 """
26 26 s = StringIO()
27 27 p = PipedProcess('echo 1', out_callback=s.write, )
28 28 p.start()
29 29 p.join()
30 30 result = s.getvalue().rstrip()
31 31 assert result == '1'
32 32
33 33
34 34 def test_io():
35 35 """ Checks that we can send characters on stdin to the process.
36 36 """
37 37 s = StringIO()
38 38 p = PipedProcess(sys.executable + ' -c "a = raw_input(); print a"',
39 39 out_callback=s.write, )
40 40 p.start()
41 41 test_string = '12345\n'
42 42 while not hasattr(p, 'process'):
43 43 sleep(0.1)
44 44 p.process.stdin.write(test_string)
45 45 p.join()
46 46 result = s.getvalue()
47 47 assert result == test_string
48 48
49 49
50 50 def test_kill():
51 51 """ Check that we can kill a process, and its subprocess.
52 52 """
53 53 s = StringIO()
54 54 p = PipedProcess(sys.executable + ' -c "a = raw_input();"',
55 55 out_callback=s.write, )
56 56 p.start()
57 57 while not hasattr(p, 'process'):
58 58 sleep(0.1)
59 59 p.process.kill()
60 60 assert p.process.poll() is not None
61 61
62 62
63 63 if __name__ == '__main__':
64 64 test_capture_out()
65 65 test_io()
66 66 test_kill()
67 67
@@ -1,436 +1,625 b''
1 1 # encoding: utf-8
2 2 """
3 3 A Wx widget to act as a console and input commands.
4 4
5 5 This widget deals with prompts and provides an edit buffer
6 6 restricted to after the last prompt.
7 7 """
8 8
9 9 __docformat__ = "restructuredtext en"
10 10
11 11 #-------------------------------------------------------------------------------
12 12 # Copyright (C) 2008 The IPython Development Team
13 13 #
14 14 # Distributed under the terms of the BSD License. The full license is
15 15 # in the file COPYING, distributed as part of this software.
16 16 #-------------------------------------------------------------------------------
17 17
18 18 #-------------------------------------------------------------------------------
19 19 # Imports
20 20 #-------------------------------------------------------------------------------
21 21
22 22 import wx
23 23 import wx.stc as stc
24 24
25 25 from wx.py import editwindow
26 26 import time
27 27 import sys
28 import string
29
28 30 LINESEP = '\n'
29 31 if sys.platform == 'win32':
30 32 LINESEP = '\n\r'
31 33
32 34 import re
33 35
34 36 # FIXME: Need to provide an API for non user-generated display on the
35 37 # screen: this should not be editable by the user.
38 #-------------------------------------------------------------------------------
39 # Constants
40 #-------------------------------------------------------------------------------
41 _COMPLETE_BUFFER_MARKER = 31
42 _ERROR_MARKER = 30
43 _INPUT_MARKER = 29
36 44
37 45 _DEFAULT_SIZE = 10
38 46 if sys.platform == 'darwin':
39 47 _DEFAULT_SIZE = 12
40 48
41 49 _DEFAULT_STYLE = {
42 'stdout' : 'fore:#0000FF',
43 'stderr' : 'fore:#007f00',
44 'trace' : 'fore:#FF0000',
45
50 #background definition
46 51 'default' : 'size:%d' % _DEFAULT_SIZE,
47 52 'bracegood' : 'fore:#00AA00,back:#000000,bold',
48 53 'bracebad' : 'fore:#FF0000,back:#000000,bold',
49 54
55 # Edge column: a number of None
56 'edge_column' : -1,
57
50 58 # properties for the various Python lexer styles
51 59 'comment' : 'fore:#007F00',
52 60 'number' : 'fore:#007F7F',
53 61 'string' : 'fore:#7F007F,italic',
54 62 'char' : 'fore:#7F007F,italic',
55 63 'keyword' : 'fore:#00007F,bold',
56 64 'triple' : 'fore:#7F0000',
57 65 'tripledouble' : 'fore:#7F0000',
58 66 'class' : 'fore:#0000FF,bold,underline',
59 67 'def' : 'fore:#007F7F,bold',
60 'operator' : 'bold'
68 'operator' : 'bold',
69
70 # Default colors
71 'trace' : '#FAFAF1', # Nice green
72 'stdout' : '#FDFFD3', # Nice yellow
73 'stderr' : '#FFF1F1', # Nice red
74
75 # Default scintilla settings
76 'antialiasing' : True,
77 'carret_color' : 'BLACK',
78 'background_color' :'WHITE',
79
80 #prompt definition
81 'prompt_in1' : \
82 '\n\x01\x1b[0;34m\x02In [\x01\x1b[1;34m\x02$number\x01\x1b[0;34m\x02]: \x01\x1b[0m\x02',
83
84 'prompt_out': \
85 '\x01\x1b[0;31m\x02Out[\x01\x1b[1;31m\x02$number\x01\x1b[0;31m\x02]: \x01\x1b[0m\x02',
61 86 }
62 87
63 88 # new style numbers
64 89 _STDOUT_STYLE = 15
65 90 _STDERR_STYLE = 16
66 91 _TRACE_STYLE = 17
67 92
68 93
69 94 # system colors
70 95 #SYS_COLOUR_BACKGROUND = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BACKGROUND)
71 96
97 # Translation table from ANSI escape sequences to color.
98 ANSI_STYLES = {'0;30': [0, 'BLACK'], '0;31': [1, 'RED'],
99 '0;32': [2, 'GREEN'], '0;33': [3, 'BROWN'],
100 '0;34': [4, 'BLUE'], '0;35': [5, 'PURPLE'],
101 '0;36': [6, 'CYAN'], '0;37': [7, 'LIGHT GREY'],
102 '1;30': [8, 'DARK GREY'], '1;31': [9, 'RED'],
103 '1;32': [10, 'SEA GREEN'], '1;33': [11, 'YELLOW'],
104 '1;34': [12, 'LIGHT BLUE'], '1;35':
105 [13, 'MEDIUM VIOLET RED'],
106 '1;36': [14, 'LIGHT STEEL BLUE'], '1;37': [15, 'YELLOW']}
107
108 # XXX: Maybe one day we should factor this code with ColorANSI. Right now
109 # ColorANSI is hard to reuse and makes our code more complex.
110
111 #we define platform specific fonts
112 if wx.Platform == '__WXMSW__':
113 FACES = { 'times': 'Times New Roman',
114 'mono' : 'Courier New',
115 'helv' : 'Arial',
116 'other': 'Comic Sans MS',
117 'size' : 10,
118 'size2': 8,
119 }
120 elif wx.Platform == '__WXMAC__':
121 FACES = { 'times': 'Times New Roman',
122 'mono' : 'Monaco',
123 'helv' : 'Arial',
124 'other': 'Comic Sans MS',
125 'size' : 10,
126 'size2': 8,
127 }
128 else:
129 FACES = { 'times': 'Times',
130 'mono' : 'Courier',
131 'helv' : 'Helvetica',
132 'other': 'new century schoolbook',
133 'size' : 10,
134 'size2': 8,
135 }
136
137
72 138 #-------------------------------------------------------------------------------
73 139 # The console widget class
74 140 #-------------------------------------------------------------------------------
75 141 class ConsoleWidget(editwindow.EditWindow):
76 142 """ Specialized styled text control view for console-like workflow.
77 143
78 144 This widget is mainly interested in dealing with the prompt and
79 145 keeping the cursor inside the editing line.
80 146 """
81 147
82 148 # This is where the title captured from the ANSI escape sequences are
83 149 # stored.
84 150 title = 'Console'
85 151
152 # Last prompt printed
153 last_prompt = ''
154
86 155 # The buffer being edited.
87 156 def _set_input_buffer(self, string):
88 157 self.SetSelection(self.current_prompt_pos, self.GetLength())
89 158 self.ReplaceSelection(string)
90 159 self.GotoPos(self.GetLength())
91 160
92 161 def _get_input_buffer(self):
93 162 """ Returns the text in current edit buffer.
94 163 """
95 164 input_buffer = self.GetTextRange(self.current_prompt_pos,
96 165 self.GetLength())
97 166 input_buffer = input_buffer.replace(LINESEP, '\n')
98 167 return input_buffer
99 168
100 169 input_buffer = property(_get_input_buffer, _set_input_buffer)
101 170
102 171 style = _DEFAULT_STYLE.copy()
103 172
104 173 # Translation table from ANSI escape sequences to color. Override
105 174 # this to specify your colors.
106 ANSI_STYLES = {'0;30': [0, 'BLACK'], '0;31': [1, 'RED'],
107 '0;32': [2, 'GREEN'], '0;33': [3, 'BROWN'],
108 '0;34': [4, 'BLUE'], '0;35': [5, 'PURPLE'],
109 '0;36': [6, 'CYAN'], '0;37': [7, 'LIGHT GREY'],
110 '1;30': [8, 'DARK GREY'], '1;31': [9, 'RED'],
111 '1;32': [10, 'SEA GREEN'], '1;33': [11, 'YELLOW'],
112 '1;34': [12, 'LIGHT BLUE'], '1;35':
113 [13, 'MEDIUM VIOLET RED'],
114 '1;36': [14, 'LIGHT STEEL BLUE'], '1;37': [15, 'YELLOW']}
115
116 # The color of the carret (call _apply_style() after setting)
117 carret_color = 'BLACK'
175 ANSI_STYLES = ANSI_STYLES.copy()
118 176
177 # Font faces
178 faces = FACES.copy()
179
119 180 # Store the last time a refresh was done
120 181 _last_refresh_time = 0
121 182
122 183 #--------------------------------------------------------------------------
123 184 # Public API
124 185 #--------------------------------------------------------------------------
125 186
126 187 def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
127 188 size=wx.DefaultSize, style=wx.WANTS_CHARS, ):
128 189 editwindow.EditWindow.__init__(self, parent, id, pos, size, style)
129 self._configure_scintilla()
190 self.configure_scintilla()
191 # Track if 'enter' key as ever been processed
192 # This variable will only be reallowed until key goes up
193 self.enter_catched = False
194 self.current_prompt_pos = 0
130 195
131 196 self.Bind(wx.EVT_KEY_DOWN, self._on_key_down)
132 197 self.Bind(wx.EVT_KEY_UP, self._on_key_up)
133 198
134 199
135 200 def write(self, text, refresh=True):
136 201 """ Write given text to buffer, while translating the ansi escape
137 202 sequences.
138 203 """
139 204 # XXX: do not put print statements to sys.stdout/sys.stderr in
140 205 # this method, the print statements will call this method, as
141 206 # you will end up with an infinit loop
142 207 title = self.title_pat.split(text)
143 208 if len(title)>1:
144 209 self.title = title[-2]
145 210
146 211 text = self.title_pat.sub('', text)
147 212 segments = self.color_pat.split(text)
148 213 segment = segments.pop(0)
149 214 self.GotoPos(self.GetLength())
150 215 self.StartStyling(self.GetLength(), 0xFF)
151 216 try:
152 217 self.AppendText(segment)
153 218 except UnicodeDecodeError:
154 219 # XXX: Do I really want to skip the exception?
155 220 pass
156 221
157 222 if segments:
158 223 for ansi_tag, text in zip(segments[::2], segments[1::2]):
159 224 self.StartStyling(self.GetLength(), 0xFF)
160 225 try:
161 226 self.AppendText(text)
162 227 except UnicodeDecodeError:
163 228 # XXX: Do I really want to skip the exception?
164 229 pass
165 230
166 231 if ansi_tag not in self.ANSI_STYLES:
167 232 style = 0
168 233 else:
169 234 style = self.ANSI_STYLES[ansi_tag][0]
170 235
171 236 self.SetStyling(len(text), style)
172 237
173 238 self.GotoPos(self.GetLength())
174 239 if refresh:
175 240 current_time = time.time()
176 241 if current_time - self._last_refresh_time > 0.03:
177 242 if sys.platform == 'win32':
178 243 wx.SafeYield()
179 244 else:
180 245 wx.Yield()
181 246 # self.ProcessEvent(wx.PaintEvent())
182 247 self._last_refresh_time = current_time
183 248
184 249
185 250 def new_prompt(self, prompt):
186 251 """ Prints a prompt at start of line, and move the start of the
187 252 current block there.
188 253
189 254 The prompt can be given with ascii escape sequences.
190 255 """
191 256 self.write(prompt, refresh=False)
192 257 # now we update our cursor giving end of prompt
193 258 self.current_prompt_pos = self.GetLength()
194 259 self.current_prompt_line = self.GetCurrentLine()
195 260 self.EnsureCaretVisible()
261 self.last_prompt = prompt
196 262
197 263
264 def continuation_prompt(self):
265 """ Returns the current continuation prompt.
266 We need to implement this method here to deal with the
267 ascii escape sequences cleaning up.
268 """
269 # ASCII-less prompt
270 ascii_less = ''.join(self.color_pat.split(self.last_prompt)[2::2])
271 return "."*(len(ascii_less)-2) + ': '
272
273
198 274 def scroll_to_bottom(self):
199 275 maxrange = self.GetScrollRange(wx.VERTICAL)
200 276 self.ScrollLines(maxrange)
201 277
202 278
203 279 def pop_completion(self, possibilities, offset=0):
204 280 """ Pops up an autocompletion menu. Offset is the offset
205 281 in characters of the position at which the menu should
206 282 appear, relativ to the cursor.
207 283 """
208 284 self.AutoCompSetIgnoreCase(False)
209 285 self.AutoCompSetAutoHide(False)
210 286 self.AutoCompSetMaxHeight(len(possibilities))
211 287 self.AutoCompShow(offset, " ".join(possibilities))
212 288
213 289
214 290 def get_line_width(self):
215 291 """ Return the width of the line in characters.
216 292 """
217 293 return self.GetSize()[0]/self.GetCharWidth()
218 294
219 #--------------------------------------------------------------------------
220 # EditWindow API
221 #--------------------------------------------------------------------------
222 295
223 def OnUpdateUI(self, event):
224 """ Override the OnUpdateUI of the EditWindow class, to prevent
225 syntax highlighting both for faster redraw, and for more
226 consistent look and feel.
296 def configure_scintilla(self):
297 """ Set up all the styling option of the embedded scintilla
298 widget.
227 299 """
300 p = self.style.copy()
301
302 # Marker for complete buffer.
303 self.MarkerDefine(_COMPLETE_BUFFER_MARKER, stc.STC_MARK_BACKGROUND,
304 background=p['trace'])
228 305
229 #--------------------------------------------------------------------------
230 # Private API
231 #--------------------------------------------------------------------------
232
233 def _apply_style(self):
234 """ Applies the colors for the different text elements and the
235 carret.
236 """
237 self.SetCaretForeground(self.carret_color)
238
239 #self.StyleClearAll()
240 self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT,
241 "fore:#FF0000,back:#0000FF,bold")
242 self.StyleSetSpec(stc.STC_STYLE_BRACEBAD,
243 "fore:#000000,back:#FF0000,bold")
244
245 for style in self.ANSI_STYLES.values():
246 self.StyleSetSpec(style[0], "bold,fore:%s" % style[1])
306 # Marker for current input buffer.
307 self.MarkerDefine(_INPUT_MARKER, stc.STC_MARK_BACKGROUND,
308 background=p['stdout'])
309 # Marker for tracebacks.
310 self.MarkerDefine(_ERROR_MARKER, stc.STC_MARK_BACKGROUND,
311 background=p['stderr'])
247 312
248
249 def _configure_scintilla(self):
250 313 self.SetEOLMode(stc.STC_EOL_LF)
251 314
252 315 # Ctrl"+" or Ctrl "-" can be used to zoomin/zoomout the text inside
253 316 # the widget
254 317 self.CmdKeyAssign(ord('+'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN)
255 318 self.CmdKeyAssign(ord('-'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT)
256 319 # Also allow Ctrl Shift "=" for poor non US keyboard users.
257 320 self.CmdKeyAssign(ord('='), stc.STC_SCMOD_CTRL|stc.STC_SCMOD_SHIFT,
258 321 stc.STC_CMD_ZOOMIN)
259 322
260 323 # Keys: we need to clear some of the keys the that don't play
261 324 # well with a console.
262 325 self.CmdKeyClear(ord('D'), stc.STC_SCMOD_CTRL)
263 326 self.CmdKeyClear(ord('L'), stc.STC_SCMOD_CTRL)
264 327 self.CmdKeyClear(ord('T'), stc.STC_SCMOD_CTRL)
265 328 self.CmdKeyClear(ord('A'), stc.STC_SCMOD_CTRL)
266 329
267 330 self.SetEOLMode(stc.STC_EOL_CRLF)
268 331 self.SetWrapMode(stc.STC_WRAP_CHAR)
269 332 self.SetWrapMode(stc.STC_WRAP_WORD)
270 333 self.SetBufferedDraw(True)
271 self.SetUseAntiAliasing(True)
334
335 self.SetUseAntiAliasing(p['antialiasing'])
336
272 337 self.SetLayoutCache(stc.STC_CACHE_PAGE)
273 338 self.SetUndoCollection(False)
274 339 self.SetUseTabs(True)
275 340 self.SetIndent(4)
276 341 self.SetTabWidth(4)
277 342
278 343 # we don't want scintilla's autocompletion to choose
279 344 # automaticaly out of a single choice list, as we pop it up
280 345 # automaticaly
281 346 self.AutoCompSetChooseSingle(False)
282 347 self.AutoCompSetMaxHeight(10)
283 348 # XXX: this doesn't seem to have an effect.
284 349 self.AutoCompSetFillUps('\n')
285 350
286 351 self.SetMargins(3, 3) #text is moved away from border with 3px
287 352 # Suppressing Scintilla margins
288 353 self.SetMarginWidth(0, 0)
289 354 self.SetMarginWidth(1, 0)
290 355 self.SetMarginWidth(2, 0)
291 356
292 self._apply_style()
293
294 357 # Xterm escape sequences
295 358 self.color_pat = re.compile('\x01?\x1b\[(.*?)m\x02?')
296 359 self.title_pat = re.compile('\x1b]0;(.*?)\x07')
297 360
298 #self.SetEdgeMode(stc.STC_EDGE_LINE)
299 #self.SetEdgeColumn(80)
300
301 361 # styles
302 p = self.style
303 self.StyleSetSpec(stc.STC_STYLE_DEFAULT, p['default'])
362
363 self.SetCaretForeground(p['carret_color'])
364
365 background_color = p['background_color']
366
367 if 'default' in p:
368 if 'back' not in p['default']:
369 p['default'] += ',back:%s' % background_color
370 if 'size' not in p['default']:
371 p['default'] += ',size:%s' % self.faces['size']
372 if 'face' not in p['default']:
373 p['default'] += ',face:%s' % self.faces['mono']
374
375 self.StyleSetSpec(stc.STC_STYLE_DEFAULT, p['default'])
376 else:
377 self.StyleSetSpec(stc.STC_STYLE_DEFAULT,
378 "fore:%s,back:%s,size:%d,face:%s"
379 % (self.ANSI_STYLES['0;30'][1],
380 background_color,
381 self.faces['size'], self.faces['mono']))
382
304 383 self.StyleClearAll()
384
385 # XXX: two lines below are usefull if not using the lexer
386 #for style in self.ANSI_STYLES.values():
387 # self.StyleSetSpec(style[0], "bold,fore:%s" % style[1])
388
389 # prompt definition
390 self.prompt_in1 = p['prompt_in1']
391 self.prompt_out = p['prompt_out']
392
393 self.output_prompt_template = string.Template(self.prompt_out)
394 self.input_prompt_template = string.Template(self.prompt_in1)
395
305 396 self.StyleSetSpec(_STDOUT_STYLE, p['stdout'])
306 397 self.StyleSetSpec(_STDERR_STYLE, p['stderr'])
307 398 self.StyleSetSpec(_TRACE_STYLE, p['trace'])
308
309 399 self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT, p['bracegood'])
310 400 self.StyleSetSpec(stc.STC_STYLE_BRACEBAD, p['bracebad'])
311 401 self.StyleSetSpec(stc.STC_P_COMMENTLINE, p['comment'])
312 402 self.StyleSetSpec(stc.STC_P_NUMBER, p['number'])
313 403 self.StyleSetSpec(stc.STC_P_STRING, p['string'])
314 404 self.StyleSetSpec(stc.STC_P_CHARACTER, p['char'])
315 405 self.StyleSetSpec(stc.STC_P_WORD, p['keyword'])
316 406 self.StyleSetSpec(stc.STC_P_WORD2, p['keyword'])
317 407 self.StyleSetSpec(stc.STC_P_TRIPLE, p['triple'])
318 408 self.StyleSetSpec(stc.STC_P_TRIPLEDOUBLE, p['tripledouble'])
319 409 self.StyleSetSpec(stc.STC_P_CLASSNAME, p['class'])
320 410 self.StyleSetSpec(stc.STC_P_DEFNAME, p['def'])
321 411 self.StyleSetSpec(stc.STC_P_OPERATOR, p['operator'])
322 412 self.StyleSetSpec(stc.STC_P_COMMENTBLOCK, p['comment'])
323 413
414 edge_column = p['edge_column']
415 if edge_column is not None and edge_column > 0:
416 #we add a vertical line to console widget
417 self.SetEdgeMode(stc.STC_EDGE_LINE)
418 self.SetEdgeColumn(edge_column)
419
420
421 #--------------------------------------------------------------------------
422 # EditWindow API
423 #--------------------------------------------------------------------------
424
425 def OnUpdateUI(self, event):
426 """ Override the OnUpdateUI of the EditWindow class, to prevent
427 syntax highlighting both for faster redraw, and for more
428 consistent look and feel.
429 """
430
431
432 #--------------------------------------------------------------------------
433 # Private API
434 #--------------------------------------------------------------------------
435
324 436 def _on_key_down(self, event, skip=True):
325 437 """ Key press callback used for correcting behavior for
326 438 console-like interfaces: the cursor is constraint to be after
327 439 the last prompt.
328 440
329 441 Return True if event as been catched.
330 442 """
331 443 catched = True
444 # XXX: Would the right way to do this be to have a
445 # dictionary at the instance level associating keys with
446 # callbacks? How would we deal with inheritance? And Do the
447 # different callbacks share local variables?
448
332 449 # Intercept some specific keys.
333 450 if event.KeyCode == ord('L') and event.ControlDown() :
334 451 self.scroll_to_bottom()
335 452 elif event.KeyCode == ord('K') and event.ControlDown() :
336 453 self.input_buffer = ''
337 454 elif event.KeyCode == ord('A') and event.ControlDown() :
338 455 self.GotoPos(self.GetLength())
339 456 self.SetSelectionStart(self.current_prompt_pos)
340 457 self.SetSelectionEnd(self.GetCurrentPos())
341 458 catched = True
342 459 elif event.KeyCode == ord('E') and event.ControlDown() :
343 460 self.GotoPos(self.GetLength())
344 461 catched = True
345 462 elif event.KeyCode == wx.WXK_PAGEUP:
346 463 self.ScrollPages(-1)
347 464 elif event.KeyCode == wx.WXK_PAGEDOWN:
348 465 self.ScrollPages(1)
466 elif event.KeyCode == wx.WXK_HOME:
467 self.GotoPos(self.GetLength())
468 elif event.KeyCode == wx.WXK_END:
469 self.GotoPos(self.GetLength())
349 470 elif event.KeyCode == wx.WXK_UP and event.ShiftDown():
350 471 self.ScrollLines(-1)
351 472 elif event.KeyCode == wx.WXK_DOWN and event.ShiftDown():
352 473 self.ScrollLines(1)
353 474 else:
354 475 catched = False
355 476
356 477 if self.AutoCompActive():
357 478 event.Skip()
358 479 else:
359 480 if event.KeyCode in (13, wx.WXK_NUMPAD_ENTER) and \
360 event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN):
481 event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN,
482 wx.MOD_SHIFT):
361 483 catched = True
362 self.CallTipCancel()
363 self.write('\n', refresh=False)
364 # Under windows scintilla seems to be doing funny stuff to the
365 # line returns here, but the getter for input_buffer filters
366 # this out.
367 if sys.platform == 'win32':
368 self.input_buffer = self.input_buffer
369 self._on_enter()
484 if not self.enter_catched:
485 self.CallTipCancel()
486 if event.Modifiers == wx.MOD_SHIFT:
487 # Try to force execution
488 self.GotoPos(self.GetLength())
489 self.write('\n' + self.continuation_prompt(),
490 refresh=False)
491 self._on_enter()
492 else:
493 self._on_enter()
494 self.enter_catched = True
370 495
371 496 elif event.KeyCode == wx.WXK_HOME:
372 497 if event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN):
373 498 self.GotoPos(self.current_prompt_pos)
374 499 catched = True
375 500
376 501 elif event.Modifiers == wx.MOD_SHIFT:
377 502 # FIXME: This behavior is not ideal: if the selection
378 503 # is already started, it will jump.
379 504 self.SetSelectionStart(self.current_prompt_pos)
380 505 self.SetSelectionEnd(self.GetCurrentPos())
381 506 catched = True
382 507
383 508 elif event.KeyCode == wx.WXK_UP:
384 509 if self.GetCurrentLine() > self.current_prompt_line:
385 510 if self.GetCurrentLine() == self.current_prompt_line + 1 \
386 511 and self.GetColumn(self.GetCurrentPos()) < \
387 512 self.GetColumn(self.current_prompt_pos):
388 513 self.GotoPos(self.current_prompt_pos)
389 514 else:
390 515 event.Skip()
391 516 catched = True
392 517
393 518 elif event.KeyCode in (wx.WXK_LEFT, wx.WXK_BACK):
394 if self.GetCurrentPos() > self.current_prompt_pos:
519 if not self._keep_cursor_in_buffer(self.GetCurrentPos() - 1):
520 event.Skip()
521 catched = True
522
523 elif event.KeyCode == wx.WXK_RIGHT:
524 if not self._keep_cursor_in_buffer(self.GetCurrentPos() + 1):
525 event.Skip()
526 catched = True
527
528
529 elif event.KeyCode == wx.WXK_DELETE:
530 if not self._keep_cursor_in_buffer(self.GetCurrentPos() - 1):
395 531 event.Skip()
396 532 catched = True
397 533
398 534 if skip and not catched:
399 535 # Put the cursor back in the edit region
400 if self.GetCurrentPos() < self.current_prompt_pos:
401 self.GotoPos(self.current_prompt_pos)
402 else:
403 event.Skip()
536 if not self._keep_cursor_in_buffer():
537 if not (self.GetCurrentPos() == self.GetLength()
538 and event.KeyCode == wx.WXK_DELETE):
539 event.Skip()
540 catched = True
404 541
405 542 return catched
406 543
407 544
408 545 def _on_key_up(self, event, skip=True):
409 546 """ If cursor is outside the editing region, put it back.
410 547 """
411 event.Skip()
412 if self.GetCurrentPos() < self.current_prompt_pos:
413 self.GotoPos(self.current_prompt_pos)
548 if skip:
549 event.Skip()
550 self._keep_cursor_in_buffer()
551
552
553 # XXX: I need to avoid the problem of having an empty glass;
554 def _keep_cursor_in_buffer(self, pos=None):
555 """ Checks if the cursor is where it is allowed to be. If not,
556 put it back.
414 557
558 Returns
559 -------
560 cursor_moved: Boolean
561 whether or not the cursor was moved by this routine.
562
563 Notes
564 ------
565 WARNING: This does proper checks only for horizontal
566 movements.
567 """
568 if pos is None:
569 current_pos = self.GetCurrentPos()
570 else:
571 current_pos = pos
572 if current_pos < self.current_prompt_pos:
573 self.GotoPos(self.current_prompt_pos)
574 return True
575 line_num = self.LineFromPosition(current_pos)
576 if not current_pos > self.GetLength():
577 line_pos = self.GetColumn(current_pos)
578 else:
579 line_pos = self.GetColumn(self.GetLength())
580 line = self.GetLine(line_num)
581 # Jump the continuation prompt
582 continuation_prompt = self.continuation_prompt()
583 if ( line.startswith(continuation_prompt)
584 and line_pos < len(continuation_prompt)):
585 if line_pos < 2:
586 # We are at the beginning of the line, trying to move
587 # forward: jump forward.
588 self.GotoPos(current_pos + 1 +
589 len(continuation_prompt) - line_pos)
590 else:
591 # Jump back up
592 self.GotoPos(self.GetLineEndPosition(line_num-1))
593 return True
594 elif ( current_pos > self.GetLineEndPosition(line_num)
595 and not current_pos == self.GetLength()):
596 # Jump to next line
597 self.GotoPos(current_pos + 1 +
598 len(continuation_prompt))
599 return True
600
601 # We re-allow enter event processing
602 self.enter_catched = False
603 return False
415 604
416 605
417 606 if __name__ == '__main__':
418 607 # Some simple code to test the console widget.
419 608 class MainWindow(wx.Frame):
420 609 def __init__(self, parent, id, title):
421 wx.Frame.__init__(self, parent, id, title, size=(300,250))
610 wx.Frame.__init__(self, parent, id, title, size=(300, 250))
422 611 self._sizer = wx.BoxSizer(wx.VERTICAL)
423 612 self.console_widget = ConsoleWidget(self)
424 613 self._sizer.Add(self.console_widget, 1, wx.EXPAND)
425 614 self.SetSizer(self._sizer)
426 615 self.SetAutoLayout(1)
427 616 self.Show(True)
428 617
429 618 app = wx.PySimpleApp()
430 619 w = MainWindow(None, wx.ID_ANY, 'ConsoleWidget')
431 620 w.SetSize((780, 460))
432 621 w.Show()
433 622
434 623 app.MainLoop()
435 624
436 625
@@ -1,110 +1,119 b''
1 1 """
2 2 Entry point for a simple application giving a graphical frontend to
3 3 ipython.
4 4 """
5 5
6 6 try:
7 7 import wx
8 8 except ImportError, e:
9 9 e.message = """%s
10 10 ________________________________________________________________________________
11 11 You need wxPython to run this application.
12 12 """ % e.message
13 13 e.args = (e.message, ) + e.args[1:]
14 14 raise e
15 15
16 16 from wx_frontend import WxController
17 17 import __builtin__
18 18
19 19
20 20 class IPythonXController(WxController):
21 21 """ Sub class of WxController that adds some application-specific
22 22 bindings.
23 23 """
24 24
25 25 debug = False
26 26
27 27 def __init__(self, *args, **kwargs):
28 28 WxController.__init__(self, *args, **kwargs)
29 29 self.ipython0.ask_exit = self.do_exit
30 30 # Scroll to top
31 31 maxrange = self.GetScrollRange(wx.VERTICAL)
32 32 self.ScrollLines(-maxrange)
33 33
34 34
35 35 def _on_key_down(self, event, skip=True):
36 36 # Intercept Ctrl-D to quit
37 37 if event.KeyCode == ord('D') and event.ControlDown() and \
38 38 self.input_buffer == '' and \
39 39 self._input_state == 'readline':
40 40 wx.CallAfter(self.ask_exit)
41 41 else:
42 42 WxController._on_key_down(self, event, skip=skip)
43 43
44 44
45 45 def ask_exit(self):
46 46 """ Ask the user whether to exit.
47 47 """
48 48 self._input_state = 'subprocess'
49 49 self.write('\n', refresh=False)
50 50 self.capture_output()
51 51 self.ipython0.shell.exit()
52 52 self.release_output()
53 53 if not self.ipython0.exit_now:
54 54 wx.CallAfter(self.new_prompt,
55 55 self.input_prompt_template.substitute(
56 56 number=self.last_result['number'] + 1))
57 57 else:
58 58 wx.CallAfter(wx.GetApp().Exit)
59 59 self.write('Exiting ...', refresh=False)
60 60
61 61
62 62 def do_exit(self):
63 63 """ Exits the interpreter, kills the windows.
64 64 """
65 65 WxController.do_exit(self)
66 66 self.release_output()
67 67 wx.CallAfter(wx.Exit)
68 68
69 69
70 70
71 71 class IPythonX(wx.Frame):
72 72 """ Main frame of the IPythonX app.
73 73 """
74 74
75 75 def __init__(self, parent, id, title, debug=False):
76 76 wx.Frame.__init__(self, parent, id, title, size=(300,250))
77 77 self._sizer = wx.BoxSizer(wx.VERTICAL)
78 78 self.shell = IPythonXController(self, debug=debug)
79 79 self._sizer.Add(self.shell, 1, wx.EXPAND)
80 80 self.SetSizer(self._sizer)
81 81 self.SetAutoLayout(1)
82 82 self.Show(True)
83 wx.EVT_CLOSE(self, self.on_close)
84
85
86 def on_close(self, event):
87 """ Called on closing the windows.
88
89 Stops the event loop, to close all the child windows.
90 """
91 wx.CallAfter(wx.Exit)
83 92
84 93
85 94 def main():
86 95 from optparse import OptionParser
87 96 usage = """usage: %prog [options]
88 97
89 98 Simple graphical frontend to IPython, using WxWidgets."""
90 99 parser = OptionParser(usage=usage)
91 100 parser.add_option("-d", "--debug",
92 101 action="store_true", dest="debug", default=False,
93 102 help="Enable debug message for the wx frontend.")
94 103
95 104 options, args = parser.parse_args()
96 105
97 106 # Clear the options, to avoid having the ipython0 instance complain
98 107 import sys
99 108 sys.argv = sys.argv[:1]
100 109
101 110 app = wx.PySimpleApp()
102 111 frame = IPythonX(None, wx.ID_ANY, 'IPythonX', debug=options.debug)
103 112 frame.shell.SetFocus()
104 113 frame.shell.app = app
105 114 frame.SetSize((680, 460))
106 115
107 116 app.MainLoop()
108 117
109 118 if __name__ == '__main__':
110 119 main()
@@ -1,526 +1,601 b''
1 1 # encoding: utf-8 -*- test-case-name:
2 2 # FIXME: Need to add tests.
3 3 # ipython1.frontend.wx.tests.test_wx_frontend -*-
4 4
5 5 """Classes to provide a Wx frontend to the
6 6 IPython.kernel.core.interpreter.
7 7
8 8 This class inherits from ConsoleWidget, that provides a console-like
9 9 widget to provide a text-rendering widget suitable for a terminal.
10 10 """
11 11
12 12 __docformat__ = "restructuredtext en"
13 13
14 14 #-------------------------------------------------------------------------------
15 15 # Copyright (C) 2008 The IPython Development Team
16 16 #
17 17 # Distributed under the terms of the BSD License. The full license is in
18 18 # the file COPYING, distributed as part of this software.
19 19 #-------------------------------------------------------------------------------
20 20
21 21 #-------------------------------------------------------------------------------
22 22 # Imports
23 23 #-------------------------------------------------------------------------------
24 24
25 25 # Major library imports
26 26 import re
27 27 import __builtin__
28 from time import sleep
29 28 import sys
30 29 from threading import Lock
31 import string
32 30
33 31 import wx
34 32 from wx import stc
35 33
36 34 # Ipython-specific imports.
37 from IPython.frontend._process import PipedProcess
38 from console_widget import ConsoleWidget
35 from IPython.frontend.process import PipedProcess
36 from console_widget import ConsoleWidget, _COMPLETE_BUFFER_MARKER, \
37 _ERROR_MARKER, _INPUT_MARKER
39 38 from IPython.frontend.prefilterfrontend import PrefilterFrontEnd
40 39
41 40 #-------------------------------------------------------------------------------
42 # Constants
43 #-------------------------------------------------------------------------------
44
45 _COMPLETE_BUFFER_BG = '#FAFAF1' # Nice green
46 _INPUT_BUFFER_BG = '#FDFFD3' # Nice yellow
47 _ERROR_BG = '#FFF1F1' # Nice red
48
49 _COMPLETE_BUFFER_MARKER = 31
50 _ERROR_MARKER = 30
51 _INPUT_MARKER = 29
52
53 prompt_in1 = \
54 '\n\x01\x1b[0;34m\x02In [\x01\x1b[1;34m\x02$number\x01\x1b[0;34m\x02]: \x01\x1b[0m\x02'
55
56 prompt_out = \
57 '\x01\x1b[0;31m\x02Out[\x01\x1b[1;31m\x02$number\x01\x1b[0;31m\x02]: \x01\x1b[0m\x02'
58
59 #-------------------------------------------------------------------------------
60 41 # Classes to implement the Wx frontend
61 42 #-------------------------------------------------------------------------------
62 43 class WxController(ConsoleWidget, PrefilterFrontEnd):
63 44 """Classes to provide a Wx frontend to the
64 45 IPython.kernel.core.interpreter.
65 46
66 47 This class inherits from ConsoleWidget, that provides a console-like
67 48 widget to provide a text-rendering widget suitable for a terminal.
68 49 """
69
70 output_prompt_template = string.Template(prompt_out)
71
72 input_prompt_template = string.Template(prompt_in1)
73
50
74 51 # Print debug info on what is happening to the console.
75 52 debug = False
76 53
77 54 # The title of the terminal, as captured through the ANSI escape
78 55 # sequences.
79 56 def _set_title(self, title):
80 57 return self.Parent.SetTitle(title)
81 58
82 59 def _get_title(self):
83 60 return self.Parent.GetTitle()
84 61
85 62 title = property(_get_title, _set_title)
86 63
87 64
88 65 # The buffer being edited.
89 66 # We are duplicating the definition here because of multiple
90 67 # inheritence
91 68 def _set_input_buffer(self, string):
92 69 ConsoleWidget._set_input_buffer(self, string)
93 70 self._colorize_input_buffer()
94 71
95 72 def _get_input_buffer(self):
96 73 """ Returns the text in current edit buffer.
97 74 """
98 75 return ConsoleWidget._get_input_buffer(self)
99 76
100 77 input_buffer = property(_get_input_buffer, _set_input_buffer)
101 78
102 79
103 80 #--------------------------------------------------------------------------
104 81 # Private Attributes
105 82 #--------------------------------------------------------------------------
106 83
107 84 # A flag governing the behavior of the input. Can be:
108 85 #
109 86 # 'readline' for readline-like behavior with a prompt
110 87 # and an edit buffer.
111 88 # 'raw_input' similar to readline, but triggered by a raw-input
112 89 # call. Can be used by subclasses to act differently.
113 90 # 'subprocess' for sending the raw input directly to a
114 91 # subprocess.
115 92 # 'buffering' for buffering of the input, that will be used
116 93 # when the input state switches back to another state.
117 94 _input_state = 'readline'
118 95
119 96 # Attribute to store reference to the pipes of a subprocess, if we
120 97 # are running any.
121 98 _running_process = False
122 99
123 100 # A queue for writing fast streams to the screen without flooding the
124 101 # event loop
125 102 _out_buffer = []
126 103
127 104 # A lock to lock the _out_buffer to make sure we don't empty it
128 105 # while it is being swapped
129 106 _out_buffer_lock = Lock()
130 107
131 108 # The different line markers used to higlight the prompts.
132 109 _markers = dict()
133 110
134 111 #--------------------------------------------------------------------------
135 112 # Public API
136 113 #--------------------------------------------------------------------------
137 114
138 115 def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
139 116 size=wx.DefaultSize,
140 117 style=wx.CLIP_CHILDREN|wx.WANTS_CHARS,
118 styledef=None,
141 119 *args, **kwds):
142 120 """ Create Shell instance.
121
122 Parameters
123 -----------
124 styledef : dict, optional
125 styledef is the dictionary of options used to define the
126 style.
143 127 """
128 if styledef is not None:
129 self.style = styledef
144 130 ConsoleWidget.__init__(self, parent, id, pos, size, style)
145 131 PrefilterFrontEnd.__init__(self, **kwds)
146 132
147 133 # Stick in our own raw_input:
148 134 self.ipython0.raw_input = self.raw_input
149 135
150 # Marker for complete buffer.
151 self.MarkerDefine(_COMPLETE_BUFFER_MARKER, stc.STC_MARK_BACKGROUND,
152 background=_COMPLETE_BUFFER_BG)
153 # Marker for current input buffer.
154 self.MarkerDefine(_INPUT_MARKER, stc.STC_MARK_BACKGROUND,
155 background=_INPUT_BUFFER_BG)
156 # Marker for tracebacks.
157 self.MarkerDefine(_ERROR_MARKER, stc.STC_MARK_BACKGROUND,
158 background=_ERROR_BG)
159
160 136 # A time for flushing the write buffer
161 137 BUFFER_FLUSH_TIMER_ID = 100
162 138 self._buffer_flush_timer = wx.Timer(self, BUFFER_FLUSH_TIMER_ID)
163 139 wx.EVT_TIMER(self, BUFFER_FLUSH_TIMER_ID, self._buffer_flush)
164 140
165 141 if 'debug' in kwds:
166 142 self.debug = kwds['debug']
167 143 kwds.pop('debug')
168 144
169 145 # Inject self in namespace, for debug
170 146 if self.debug:
171 147 self.shell.user_ns['self'] = self
172 148 # Inject our own raw_input in namespace
173 149 self.shell.user_ns['raw_input'] = self.raw_input
174
175
150
176 151 def raw_input(self, prompt=''):
177 152 """ A replacement from python's raw_input.
178 153 """
179 154 self.new_prompt(prompt)
180 155 self._input_state = 'raw_input'
181 156 if hasattr(self, '_cursor'):
182 157 del self._cursor
183 158 self.SetCursor(wx.StockCursor(wx.CURSOR_CROSS))
184 159 self.__old_on_enter = self._on_enter
185 160 event_loop = wx.EventLoop()
186 161 def my_on_enter():
187 162 event_loop.Exit()
188 163 self._on_enter = my_on_enter
189 164 # XXX: Running a separate event_loop. Ugly.
190 165 event_loop.Run()
191 166 self._on_enter = self.__old_on_enter
192 167 self._input_state = 'buffering'
193 168 self._cursor = wx.BusyCursor()
194 169 return self.input_buffer.rstrip('\n')
195 170
196 171
197 172 def system_call(self, command_string):
198 173 self._input_state = 'subprocess'
199 174 event_loop = wx.EventLoop()
200 175 def _end_system_call():
201 176 self._input_state = 'buffering'
202 177 self._running_process = False
203 178 event_loop.Exit()
204 179
205 180 self._running_process = PipedProcess(command_string,
206 181 out_callback=self.buffered_write,
207 182 end_callback = _end_system_call)
208 183 self._running_process.start()
209 184 # XXX: Running a separate event_loop. Ugly.
210 185 event_loop.Run()
211 186 # Be sure to flush the buffer.
212 187 self._buffer_flush(event=None)
213 188
214 189
215 190 def do_calltip(self):
216 191 """ Analyse current and displays useful calltip for it.
217 192 """
218 193 if self.debug:
219 194 print >>sys.__stdout__, "do_calltip"
220 195 separators = re.compile('[\s\{\}\[\]\(\)\= ,:]')
221 196 symbol = self.input_buffer
222 197 symbol_string = separators.split(symbol)[-1]
223 198 base_symbol_string = symbol_string.split('.')[0]
224 199 if base_symbol_string in self.shell.user_ns:
225 200 symbol = self.shell.user_ns[base_symbol_string]
226 201 elif base_symbol_string in self.shell.user_global_ns:
227 202 symbol = self.shell.user_global_ns[base_symbol_string]
228 203 elif base_symbol_string in __builtin__.__dict__:
229 204 symbol = __builtin__.__dict__[base_symbol_string]
230 205 else:
231 206 return False
232 207 try:
233 208 for name in symbol_string.split('.')[1:] + ['__doc__']:
234 209 symbol = getattr(symbol, name)
235 210 self.AutoCompCancel()
236 211 # Check that the symbol can indeed be converted to a string:
237 212 symbol += ''
238 213 wx.CallAfter(self.CallTipShow, self.GetCurrentPos(), symbol)
239 214 except:
240 215 # The retrieve symbol couldn't be converted to a string
241 216 pass
242 217
243 218
244 219 def _popup_completion(self, create=False):
245 220 """ Updates the popup completion menu if it exists. If create is
246 221 true, open the menu.
247 222 """
248 223 if self.debug:
249 224 print >>sys.__stdout__, "_popup_completion"
250 225 line = self.input_buffer
251 226 if (self.AutoCompActive() and line and not line[-1] == '.') \
252 227 or create==True:
253 228 suggestion, completions = self.complete(line)
254 offset=0
255 229 if completions:
256 complete_sep = re.compile('[\s\{\}\[\]\(\)\= ,:]')
257 residual = complete_sep.split(line)[-1]
258 offset = len(residual)
230 offset = len(self._get_completion_text(line))
259 231 self.pop_completion(completions, offset=offset)
260 232 if self.debug:
261 233 print >>sys.__stdout__, completions
262 234
263 235
264 236 def buffered_write(self, text):
265 237 """ A write method for streams, that caches the stream in order
266 238 to avoid flooding the event loop.
267 239
268 240 This can be called outside of the main loop, in separate
269 241 threads.
270 242 """
271 243 self._out_buffer_lock.acquire()
272 244 self._out_buffer.append(text)
273 245 self._out_buffer_lock.release()
274 246 if not self._buffer_flush_timer.IsRunning():
275 247 wx.CallAfter(self._buffer_flush_timer.Start,
276 248 milliseconds=100, oneShot=True)
277 249
278 250
251 def clear_screen(self):
252 """ Empty completely the widget.
253 """
254 self.ClearAll()
255 self.new_prompt(self.input_prompt_template.substitute(
256 number=(self.last_result['number'] + 1)))
257
258
279 259 #--------------------------------------------------------------------------
280 260 # LineFrontEnd interface
281 261 #--------------------------------------------------------------------------
282 262
283 263 def execute(self, python_string, raw_string=None):
284 264 self._input_state = 'buffering'
285 265 self.CallTipCancel()
286 266 self._cursor = wx.BusyCursor()
287 267 if raw_string is None:
288 268 raw_string = python_string
289 269 end_line = self.current_prompt_line \
290 270 + max(1, len(raw_string.split('\n'))-1)
291 271 for i in range(self.current_prompt_line, end_line):
292 272 if i in self._markers:
293 273 self.MarkerDeleteHandle(self._markers[i])
294 274 self._markers[i] = self.MarkerAdd(i, _COMPLETE_BUFFER_MARKER)
295 275 # Use a callafter to update the display robustly under windows
296 276 def callback():
297 277 self.GotoPos(self.GetLength())
298 278 PrefilterFrontEnd.execute(self, python_string,
299 279 raw_string=raw_string)
300 280 wx.CallAfter(callback)
301 281
282
283 def execute_command(self, command, hidden=False):
284 """ Execute a command, not only in the model, but also in the
285 view.
286 """
287 # XXX: This method needs to be integrated in the base fronted
288 # interface
289 if hidden:
290 return self.shell.execute(command)
291 else:
292 # XXX: we are not storing the input buffer previous to the
293 # execution, as this forces us to run the execution
294 # input_buffer a yield, which is not good.
295 ##current_buffer = self.shell.control.input_buffer
296 command = command.rstrip()
297 if len(command.split('\n')) > 1:
298 # The input command is several lines long, we need to
299 # force the execution to happen
300 command += '\n'
301 cleaned_command = self.prefilter_input(command)
302 self.input_buffer = command
303 # Do not use wx.Yield() (aka GUI.process_events()) to avoid
304 # recursive yields.
305 self.ProcessEvent(wx.PaintEvent())
306 self.write('\n')
307 if not self.is_complete(cleaned_command + '\n'):
308 self._colorize_input_buffer()
309 self.render_error('Incomplete or invalid input')
310 self.new_prompt(self.input_prompt_template.substitute(
311 number=(self.last_result['number'] + 1)))
312 return False
313 self._on_enter()
314 return True
315
316
302 317 def save_output_hooks(self):
303 318 self.__old_raw_input = __builtin__.raw_input
304 319 PrefilterFrontEnd.save_output_hooks(self)
305 320
306 321 def capture_output(self):
307 322 self.SetLexer(stc.STC_LEX_NULL)
308 323 PrefilterFrontEnd.capture_output(self)
309 324 __builtin__.raw_input = self.raw_input
310 325
311 326
312 327 def release_output(self):
313 328 __builtin__.raw_input = self.__old_raw_input
314 329 PrefilterFrontEnd.release_output(self)
315 330 self.SetLexer(stc.STC_LEX_PYTHON)
316 331
317 332
318 333 def after_execute(self):
319 334 PrefilterFrontEnd.after_execute(self)
320 335 # Clear the wait cursor
321 336 if hasattr(self, '_cursor'):
322 337 del self._cursor
323 338 self.SetCursor(wx.StockCursor(wx.CURSOR_CHAR))
324 339
325 340
326 341 def show_traceback(self):
327 342 start_line = self.GetCurrentLine()
328 343 PrefilterFrontEnd.show_traceback(self)
329 344 self.ProcessEvent(wx.PaintEvent())
330 345 #wx.Yield()
331 346 for i in range(start_line, self.GetCurrentLine()):
332 347 self._markers[i] = self.MarkerAdd(i, _ERROR_MARKER)
333 348
334 349
335 350 #--------------------------------------------------------------------------
336 351 # FrontEndBase interface
337 352 #--------------------------------------------------------------------------
338 353
339 354 def render_error(self, e):
340 355 start_line = self.GetCurrentLine()
341 356 self.write('\n' + e + '\n')
342 357 for i in range(start_line, self.GetCurrentLine()):
343 358 self._markers[i] = self.MarkerAdd(i, _ERROR_MARKER)
344 359
345 360
346 361 #--------------------------------------------------------------------------
347 362 # ConsoleWidget interface
348 363 #--------------------------------------------------------------------------
349 364
350 365 def new_prompt(self, prompt):
351 366 """ Display a new prompt, and start a new input buffer.
352 367 """
353 368 self._input_state = 'readline'
354 369 ConsoleWidget.new_prompt(self, prompt)
355 370 i = self.current_prompt_line
356 371 self._markers[i] = self.MarkerAdd(i, _INPUT_MARKER)
357 372
358 373
374 def continuation_prompt(self, *args, **kwargs):
375 # Avoid multiple inheritence, be explicit about which
376 # parent method class gets called
377 return ConsoleWidget.continuation_prompt(self, *args, **kwargs)
378
379
359 380 def write(self, *args, **kwargs):
360 381 # Avoid multiple inheritence, be explicit about which
361 382 # parent method class gets called
362 ConsoleWidget.write(self, *args, **kwargs)
383 return ConsoleWidget.write(self, *args, **kwargs)
363 384
364 385
365 386 def _on_key_down(self, event, skip=True):
366 387 """ Capture the character events, let the parent
367 388 widget handle them, and put our logic afterward.
368 389 """
369 390 # FIXME: This method needs to be broken down in smaller ones.
370 current_line_number = self.GetCurrentLine()
391 current_line_num = self.GetCurrentLine()
371 392 if event.KeyCode in (ord('c'), ord('C')) and event.ControlDown():
372 393 # Capture Control-C
373 394 if self._input_state == 'subprocess':
374 395 if self.debug:
375 396 print >>sys.__stderr__, 'Killing running process'
376 397 if hasattr(self._running_process, 'process'):
377 398 self._running_process.process.kill()
378 399 elif self._input_state == 'buffering':
379 400 if self.debug:
380 401 print >>sys.__stderr__, 'Raising KeyboardInterrupt'
381 402 raise KeyboardInterrupt
382 403 # XXX: We need to make really sure we
383 404 # get back to a prompt.
384 405 elif self._input_state == 'subprocess' and (
385 406 ( event.KeyCode<256 and
386 407 not event.ControlDown() )
387 408 or
388 409 ( event.KeyCode in (ord('d'), ord('D')) and
389 410 event.ControlDown())):
390 411 # We are running a process, we redirect keys.
391 412 ConsoleWidget._on_key_down(self, event, skip=skip)
392 413 char = chr(event.KeyCode)
393 414 # Deal with some inconsistency in wx keycodes:
394 415 if char == '\r':
395 416 char = '\n'
396 417 elif not event.ShiftDown():
397 418 char = char.lower()
398 419 if event.ControlDown() and event.KeyCode in (ord('d'), ord('D')):
399 420 char = '\04'
400 421 self._running_process.process.stdin.write(char)
401 422 self._running_process.process.stdin.flush()
402 423 elif event.KeyCode in (ord('('), 57, 53):
403 424 # Calltips
404 425 event.Skip()
405 426 self.do_calltip()
406 427 elif self.AutoCompActive() and not event.KeyCode == ord('\t'):
407 428 event.Skip()
408 429 if event.KeyCode in (wx.WXK_BACK, wx.WXK_DELETE):
409 430 wx.CallAfter(self._popup_completion, create=True)
410 431 elif not event.KeyCode in (wx.WXK_UP, wx.WXK_DOWN, wx.WXK_LEFT,
411 432 wx.WXK_RIGHT, wx.WXK_ESCAPE):
412 433 wx.CallAfter(self._popup_completion)
413 434 else:
414 435 # Up history
415 436 if event.KeyCode == wx.WXK_UP and (
416 ( current_line_number == self.current_prompt_line and
437 ( current_line_num == self.current_prompt_line and
417 438 event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN) )
418 439 or event.ControlDown() ):
419 440 new_buffer = self.get_history_previous(
420 441 self.input_buffer)
421 442 if new_buffer is not None:
422 443 self.input_buffer = new_buffer
423 444 if self.GetCurrentLine() > self.current_prompt_line:
424 445 # Go to first line, for seemless history up.
425 446 self.GotoPos(self.current_prompt_pos)
426 447 # Down history
427 448 elif event.KeyCode == wx.WXK_DOWN and (
428 ( current_line_number == self.LineCount -1 and
449 ( current_line_num == self.LineCount -1 and
429 450 event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN) )
430 451 or event.ControlDown() ):
431 452 new_buffer = self.get_history_next()
432 453 if new_buffer is not None:
433 454 self.input_buffer = new_buffer
434 455 # Tab-completion
435 456 elif event.KeyCode == ord('\t'):
436 current_line, current_line_number = self.CurLine
457 current_line, current_line_num = self.CurLine
437 458 if not re.match(r'^\s*$', current_line):
438 459 self.complete_current_input()
439 460 if self.AutoCompActive():
440 461 wx.CallAfter(self._popup_completion, create=True)
441 462 else:
442 463 event.Skip()
464 elif event.KeyCode == wx.WXK_BACK:
465 # If characters where erased, check if we have to
466 # remove a line.
467 # XXX: What about DEL?
468 # FIXME: This logics should be in ConsoleWidget, as it is
469 # independant of IPython
470 current_line, _ = self.CurLine
471 current_pos = self.GetCurrentPos()
472 current_line_num = self.LineFromPosition(current_pos)
473 current_col = self.GetColumn(current_pos)
474 len_prompt = len(self.continuation_prompt())
475 if ( current_line.startswith(self.continuation_prompt())
476 and current_col == len_prompt):
477 new_lines = []
478 for line_num, line in enumerate(
479 self.input_buffer.split('\n')):
480 if (line_num + self.current_prompt_line ==
481 current_line_num):
482 new_lines.append(line[len_prompt:])
483 else:
484 new_lines.append('\n'+line)
485 # The first character is '\n', due to the above
486 # code:
487 self.input_buffer = ''.join(new_lines)[1:]
488 self.GotoPos(current_pos - 1 - len_prompt)
489 else:
490 ConsoleWidget._on_key_down(self, event, skip=skip)
443 491 else:
444 492 ConsoleWidget._on_key_down(self, event, skip=skip)
493
445 494
446 495
447 496 def _on_key_up(self, event, skip=True):
448 497 """ Called when any key is released.
449 498 """
450 499 if event.KeyCode in (59, ord('.')):
451 500 # Intercepting '.'
452 501 event.Skip()
453 502 wx.CallAfter(self._popup_completion, create=True)
454 503 else:
455 504 ConsoleWidget._on_key_up(self, event, skip=skip)
505 # Make sure the continuation_prompts are always followed by a
506 # whitespace
507 new_lines = []
508 if self._input_state == 'readline':
509 position = self.GetCurrentPos()
510 continuation_prompt = self.continuation_prompt()[:-1]
511 for line in self.input_buffer.split('\n'):
512 if not line == continuation_prompt:
513 new_lines.append(line)
514 self.input_buffer = '\n'.join(new_lines)
515 self.GotoPos(position)
456 516
457 517
458 518 def _on_enter(self):
459 519 """ Called on return key down, in readline input_state.
460 520 """
521 last_line_num = self.LineFromPosition(self.GetLength())
522 current_line_num = self.LineFromPosition(self.GetCurrentPos())
523 new_line_pos = (last_line_num - current_line_num)
461 524 if self.debug:
462 525 print >>sys.__stdout__, repr(self.input_buffer)
463 PrefilterFrontEnd._on_enter(self)
526 self.write('\n', refresh=False)
527 # Under windows scintilla seems to be doing funny
528 # stuff to the line returns here, but the getter for
529 # input_buffer filters this out.
530 if sys.platform == 'win32':
531 self.input_buffer = self.input_buffer
532 old_prompt_num = self.current_prompt_pos
533 has_executed = PrefilterFrontEnd._on_enter(self,
534 new_line_pos=new_line_pos)
535 if old_prompt_num == self.current_prompt_pos:
536 # No execution has happened
537 self.GotoPos(self.GetLineEndPosition(current_line_num + 1))
538 return has_executed
464 539
465 540
466 541 #--------------------------------------------------------------------------
467 542 # EditWindow API
468 543 #--------------------------------------------------------------------------
469 544
470 545 def OnUpdateUI(self, event):
471 546 """ Override the OnUpdateUI of the EditWindow class, to prevent
472 547 syntax highlighting both for faster redraw, and for more
473 548 consistent look and feel.
474 549 """
475 550 if not self._input_state == 'readline':
476 551 ConsoleWidget.OnUpdateUI(self, event)
477 552
478 553 #--------------------------------------------------------------------------
479 554 # Private API
480 555 #--------------------------------------------------------------------------
481 556
482 557 def _buffer_flush(self, event):
483 558 """ Called by the timer to flush the write buffer.
484 559
485 560 This is always called in the mainloop, by the wx timer.
486 561 """
487 562 self._out_buffer_lock.acquire()
488 563 _out_buffer = self._out_buffer
489 564 self._out_buffer = []
490 565 self._out_buffer_lock.release()
491 566 self.write(''.join(_out_buffer), refresh=False)
492 567
493 568
494 569 def _colorize_input_buffer(self):
495 570 """ Keep the input buffer lines at a bright color.
496 571 """
497 572 if not self._input_state in ('readline', 'raw_input'):
498 573 return
499 574 end_line = self.GetCurrentLine()
500 575 if not sys.platform == 'win32':
501 576 end_line += 1
502 577 for i in range(self.current_prompt_line, end_line):
503 578 if i in self._markers:
504 579 self.MarkerDeleteHandle(self._markers[i])
505 580 self._markers[i] = self.MarkerAdd(i, _INPUT_MARKER)
506 581
507 582
508 583 if __name__ == '__main__':
509 584 class MainWindow(wx.Frame):
510 585 def __init__(self, parent, id, title):
511 586 wx.Frame.__init__(self, parent, id, title, size=(300,250))
512 587 self._sizer = wx.BoxSizer(wx.VERTICAL)
513 588 self.shell = WxController(self)
514 589 self._sizer.Add(self.shell, 1, wx.EXPAND)
515 590 self.SetSizer(self._sizer)
516 591 self.SetAutoLayout(1)
517 592 self.Show(True)
518 593
519 594 app = wx.PySimpleApp()
520 595 frame = MainWindow(None, wx.ID_ANY, 'Ipython')
521 596 frame.shell.SetFocus()
522 597 frame.SetSize((680, 460))
523 598 self = frame.shell
524 599
525 600 app.MainLoop()
526 601
@@ -1,2161 +1,2171 b''
1 1 # -*- coding: utf-8 -*-
2 2 """General purpose utilities.
3 3
4 4 This is a grab-bag of stuff I find useful in most programs I write. Some of
5 5 these things are also convenient when working at the command line.
6 6 """
7 7
8 8 #*****************************************************************************
9 9 # Copyright (C) 2001-2006 Fernando Perez. <fperez@colorado.edu>
10 10 #
11 11 # Distributed under the terms of the BSD License. The full license is in
12 12 # the file COPYING, distributed as part of this software.
13 13 #*****************************************************************************
14 14
15 15 #****************************************************************************
16 16 # required modules from the Python standard library
17 17 import __main__
18 18 import commands
19 19 try:
20 20 import doctest
21 21 except ImportError:
22 22 pass
23 23 import os
24 24 import platform
25 25 import re
26 26 import shlex
27 27 import shutil
28 28 import subprocess
29 29 import sys
30 30 import tempfile
31 31 import time
32 32 import types
33 33 import warnings
34 34
35 35 # Curses and termios are Unix-only modules
36 36 try:
37 37 import curses
38 38 # We need termios as well, so if its import happens to raise, we bail on
39 39 # using curses altogether.
40 40 import termios
41 41 except ImportError:
42 42 USE_CURSES = False
43 43 else:
44 44 # Curses on Solaris may not be complete, so we can't use it there
45 45 USE_CURSES = hasattr(curses,'initscr')
46 46
47 47 # Other IPython utilities
48 48 import IPython
49 49 from IPython.Itpl import Itpl,itpl,printpl
50 50 from IPython import DPyGetOpt, platutils
51 51 from IPython.generics import result_display
52 52 import IPython.ipapi
53 53 from IPython.external.path import path
54 54 if os.name == "nt":
55 55 from IPython.winconsole import get_console_size
56 56
57 57 try:
58 58 set
59 59 except:
60 60 from sets import Set as set
61 61
62 62
63 63 #****************************************************************************
64 64 # Exceptions
65 65 class Error(Exception):
66 66 """Base class for exceptions in this module."""
67 67 pass
68 68
69 69 #----------------------------------------------------------------------------
70 70 class IOStream:
71 71 def __init__(self,stream,fallback):
72 72 if not hasattr(stream,'write') or not hasattr(stream,'flush'):
73 73 stream = fallback
74 74 self.stream = stream
75 75 self._swrite = stream.write
76 76 self.flush = stream.flush
77 77
78 78 def write(self,data):
79 79 try:
80 80 self._swrite(data)
81 81 except:
82 82 try:
83 83 # print handles some unicode issues which may trip a plain
84 84 # write() call. Attempt to emulate write() by using a
85 85 # trailing comma
86 86 print >> self.stream, data,
87 87 except:
88 88 # if we get here, something is seriously broken.
89 89 print >> sys.stderr, \
90 90 'ERROR - failed to write data to stream:', self.stream
91 91
92 92 def close(self):
93 93 pass
94 94
95 95
96 96 class IOTerm:
97 97 """ Term holds the file or file-like objects for handling I/O operations.
98 98
99 99 These are normally just sys.stdin, sys.stdout and sys.stderr but for
100 100 Windows they can can replaced to allow editing the strings before they are
101 101 displayed."""
102 102
103 103 # In the future, having IPython channel all its I/O operations through
104 104 # this class will make it easier to embed it into other environments which
105 105 # are not a normal terminal (such as a GUI-based shell)
106 106 def __init__(self,cin=None,cout=None,cerr=None):
107 107 self.cin = IOStream(cin,sys.stdin)
108 108 self.cout = IOStream(cout,sys.stdout)
109 109 self.cerr = IOStream(cerr,sys.stderr)
110 110
111 111 # Global variable to be used for all I/O
112 112 Term = IOTerm()
113 113
114 114 import IPython.rlineimpl as readline
115 115 # Remake Term to use the readline i/o facilities
116 116 if sys.platform == 'win32' and readline.have_readline:
117 117
118 118 Term = IOTerm(cout=readline._outputfile,cerr=readline._outputfile)
119 119
120 120
121 121 #****************************************************************************
122 122 # Generic warning/error printer, used by everything else
123 123 def warn(msg,level=2,exit_val=1):
124 124 """Standard warning printer. Gives formatting consistency.
125 125
126 126 Output is sent to Term.cerr (sys.stderr by default).
127 127
128 128 Options:
129 129
130 130 -level(2): allows finer control:
131 131 0 -> Do nothing, dummy function.
132 132 1 -> Print message.
133 133 2 -> Print 'WARNING:' + message. (Default level).
134 134 3 -> Print 'ERROR:' + message.
135 135 4 -> Print 'FATAL ERROR:' + message and trigger a sys.exit(exit_val).
136 136
137 137 -exit_val (1): exit value returned by sys.exit() for a level 4
138 138 warning. Ignored for all other levels."""
139 139
140 140 if level>0:
141 141 header = ['','','WARNING: ','ERROR: ','FATAL ERROR: ']
142 142 print >> Term.cerr, '%s%s' % (header[level],msg)
143 143 if level == 4:
144 144 print >> Term.cerr,'Exiting.\n'
145 145 sys.exit(exit_val)
146 146
147 147 def info(msg):
148 148 """Equivalent to warn(msg,level=1)."""
149 149
150 150 warn(msg,level=1)
151 151
152 152 def error(msg):
153 153 """Equivalent to warn(msg,level=3)."""
154 154
155 155 warn(msg,level=3)
156 156
157 157 def fatal(msg,exit_val=1):
158 158 """Equivalent to warn(msg,exit_val=exit_val,level=4)."""
159 159
160 160 warn(msg,exit_val=exit_val,level=4)
161 161
162 162 #---------------------------------------------------------------------------
163 163 # Debugging routines
164 164 #
165 165 def debugx(expr,pre_msg=''):
166 166 """Print the value of an expression from the caller's frame.
167 167
168 168 Takes an expression, evaluates it in the caller's frame and prints both
169 169 the given expression and the resulting value (as well as a debug mark
170 170 indicating the name of the calling function. The input must be of a form
171 171 suitable for eval().
172 172
173 173 An optional message can be passed, which will be prepended to the printed
174 174 expr->value pair."""
175 175
176 176 cf = sys._getframe(1)
177 177 print '[DBG:%s] %s%s -> %r' % (cf.f_code.co_name,pre_msg,expr,
178 178 eval(expr,cf.f_globals,cf.f_locals))
179 179
180 180 # deactivate it by uncommenting the following line, which makes it a no-op
181 181 #def debugx(expr,pre_msg=''): pass
182 182
183 183 #----------------------------------------------------------------------------
184 184 StringTypes = types.StringTypes
185 185
186 186 # Basic timing functionality
187 187
188 188 # If possible (Unix), use the resource module instead of time.clock()
189 189 try:
190 190 import resource
191 191 def clocku():
192 192 """clocku() -> floating point number
193 193
194 194 Return the *USER* CPU time in seconds since the start of the process.
195 195 This is done via a call to resource.getrusage, so it avoids the
196 196 wraparound problems in time.clock()."""
197 197
198 198 return resource.getrusage(resource.RUSAGE_SELF)[0]
199 199
200 200 def clocks():
201 201 """clocks() -> floating point number
202 202
203 203 Return the *SYSTEM* CPU time in seconds since the start of the process.
204 204 This is done via a call to resource.getrusage, so it avoids the
205 205 wraparound problems in time.clock()."""
206 206
207 207 return resource.getrusage(resource.RUSAGE_SELF)[1]
208 208
209 209 def clock():
210 210 """clock() -> floating point number
211 211
212 212 Return the *TOTAL USER+SYSTEM* CPU time in seconds since the start of
213 213 the process. This is done via a call to resource.getrusage, so it
214 214 avoids the wraparound problems in time.clock()."""
215 215
216 216 u,s = resource.getrusage(resource.RUSAGE_SELF)[:2]
217 217 return u+s
218 218
219 219 def clock2():
220 220 """clock2() -> (t_user,t_system)
221 221
222 222 Similar to clock(), but return a tuple of user/system times."""
223 223 return resource.getrusage(resource.RUSAGE_SELF)[:2]
224 224
225 225 except ImportError:
226 226 # There is no distinction of user/system time under windows, so we just use
227 227 # time.clock() for everything...
228 228 clocku = clocks = clock = time.clock
229 229 def clock2():
230 230 """Under windows, system CPU time can't be measured.
231 231
232 232 This just returns clock() and zero."""
233 233 return time.clock(),0.0
234 234
235 235 def timings_out(reps,func,*args,**kw):
236 236 """timings_out(reps,func,*args,**kw) -> (t_total,t_per_call,output)
237 237
238 238 Execute a function reps times, return a tuple with the elapsed total
239 239 CPU time in seconds, the time per call and the function's output.
240 240
241 241 Under Unix, the return value is the sum of user+system time consumed by
242 242 the process, computed via the resource module. This prevents problems
243 243 related to the wraparound effect which the time.clock() function has.
244 244
245 245 Under Windows the return value is in wall clock seconds. See the
246 246 documentation for the time module for more details."""
247 247
248 248 reps = int(reps)
249 249 assert reps >=1, 'reps must be >= 1'
250 250 if reps==1:
251 251 start = clock()
252 252 out = func(*args,**kw)
253 253 tot_time = clock()-start
254 254 else:
255 255 rng = xrange(reps-1) # the last time is executed separately to store output
256 256 start = clock()
257 257 for dummy in rng: func(*args,**kw)
258 258 out = func(*args,**kw) # one last time
259 259 tot_time = clock()-start
260 260 av_time = tot_time / reps
261 261 return tot_time,av_time,out
262 262
263 263 def timings(reps,func,*args,**kw):
264 264 """timings(reps,func,*args,**kw) -> (t_total,t_per_call)
265 265
266 266 Execute a function reps times, return a tuple with the elapsed total CPU
267 267 time in seconds and the time per call. These are just the first two values
268 268 in timings_out()."""
269 269
270 270 return timings_out(reps,func,*args,**kw)[0:2]
271 271
272 272 def timing(func,*args,**kw):
273 273 """timing(func,*args,**kw) -> t_total
274 274
275 275 Execute a function once, return the elapsed total CPU time in
276 276 seconds. This is just the first value in timings_out()."""
277 277
278 278 return timings_out(1,func,*args,**kw)[0]
279 279
280 280 #****************************************************************************
281 281 # file and system
282 282
283 283 def arg_split(s,posix=False):
284 284 """Split a command line's arguments in a shell-like manner.
285 285
286 286 This is a modified version of the standard library's shlex.split()
287 287 function, but with a default of posix=False for splitting, so that quotes
288 288 in inputs are respected."""
289 289
290 290 # XXX - there may be unicode-related problems here!!! I'm not sure that
291 291 # shlex is truly unicode-safe, so it might be necessary to do
292 292 #
293 293 # s = s.encode(sys.stdin.encoding)
294 294 #
295 295 # first, to ensure that shlex gets a normal string. Input from anyone who
296 296 # knows more about unicode and shlex than I would be good to have here...
297 297 lex = shlex.shlex(s, posix=posix)
298 298 lex.whitespace_split = True
299 299 return list(lex)
300 300
301 301 def system(cmd,verbose=0,debug=0,header=''):
302 302 """Execute a system command, return its exit status.
303 303
304 304 Options:
305 305
306 306 - verbose (0): print the command to be executed.
307 307
308 308 - debug (0): only print, do not actually execute.
309 309
310 310 - header (''): Header to print on screen prior to the executed command (it
311 311 is only prepended to the command, no newlines are added).
312 312
313 313 Note: a stateful version of this function is available through the
314 314 SystemExec class."""
315 315
316 316 stat = 0
317 317 if verbose or debug: print header+cmd
318 318 sys.stdout.flush()
319 319 if not debug: stat = os.system(cmd)
320 320 return stat
321 321
322 322 def abbrev_cwd():
323 323 """ Return abbreviated version of cwd, e.g. d:mydir """
324 324 cwd = os.getcwd().replace('\\','/')
325 325 drivepart = ''
326 326 tail = cwd
327 327 if sys.platform == 'win32':
328 328 if len(cwd) < 4:
329 329 return cwd
330 330 drivepart,tail = os.path.splitdrive(cwd)
331 331
332 332
333 333 parts = tail.split('/')
334 334 if len(parts) > 2:
335 335 tail = '/'.join(parts[-2:])
336 336
337 337 return (drivepart + (
338 338 cwd == '/' and '/' or tail))
339 339
340 340
341 341 # This function is used by ipython in a lot of places to make system calls.
342 342 # We need it to be slightly different under win32, due to the vagaries of
343 343 # 'network shares'. A win32 override is below.
344 344
345 345 def shell(cmd,verbose=0,debug=0,header=''):
346 346 """Execute a command in the system shell, always return None.
347 347
348 348 Options:
349 349
350 350 - verbose (0): print the command to be executed.
351 351
352 352 - debug (0): only print, do not actually execute.
353 353
354 354 - header (''): Header to print on screen prior to the executed command (it
355 355 is only prepended to the command, no newlines are added).
356 356
357 357 Note: this is similar to genutils.system(), but it returns None so it can
358 358 be conveniently used in interactive loops without getting the return value
359 359 (typically 0) printed many times."""
360 360
361 361 stat = 0
362 362 if verbose or debug: print header+cmd
363 363 # flush stdout so we don't mangle python's buffering
364 364 sys.stdout.flush()
365 365
366 366 if not debug:
367 367 platutils.set_term_title("IPy " + cmd)
368 368 os.system(cmd)
369 369 platutils.set_term_title("IPy " + abbrev_cwd())
370 370
371 371 # override shell() for win32 to deal with network shares
372 372 if os.name in ('nt','dos'):
373 373
374 374 shell_ori = shell
375 375
376 376 def shell(cmd,verbose=0,debug=0,header=''):
377 377 if os.getcwd().startswith(r"\\"):
378 378 path = os.getcwd()
379 379 # change to c drive (cannot be on UNC-share when issuing os.system,
380 380 # as cmd.exe cannot handle UNC addresses)
381 381 os.chdir("c:")
382 382 # issue pushd to the UNC-share and then run the command
383 383 try:
384 384 shell_ori('"pushd %s&&"'%path+cmd,verbose,debug,header)
385 385 finally:
386 386 os.chdir(path)
387 387 else:
388 388 shell_ori(cmd,verbose,debug,header)
389 389
390 390 shell.__doc__ = shell_ori.__doc__
391 391
392 392 def getoutput(cmd,verbose=0,debug=0,header='',split=0):
393 393 """Dummy substitute for perl's backquotes.
394 394
395 395 Executes a command and returns the output.
396 396
397 397 Accepts the same arguments as system(), plus:
398 398
399 399 - split(0): if true, the output is returned as a list split on newlines.
400 400
401 401 Note: a stateful version of this function is available through the
402 402 SystemExec class.
403 403
404 404 This is pretty much deprecated and rarely used,
405 405 genutils.getoutputerror may be what you need.
406 406
407 407 """
408 408
409 409 if verbose or debug: print header+cmd
410 410 if not debug:
411 411 output = os.popen(cmd).read()
412 412 # stipping last \n is here for backwards compat.
413 413 if output.endswith('\n'):
414 414 output = output[:-1]
415 415 if split:
416 416 return output.split('\n')
417 417 else:
418 418 return output
419 419
420 420 def getoutputerror(cmd,verbose=0,debug=0,header='',split=0):
421 421 """Return (standard output,standard error) of executing cmd in a shell.
422 422
423 423 Accepts the same arguments as system(), plus:
424 424
425 425 - split(0): if true, each of stdout/err is returned as a list split on
426 426 newlines.
427 427
428 428 Note: a stateful version of this function is available through the
429 429 SystemExec class."""
430 430
431 431 if verbose or debug: print header+cmd
432 432 if not cmd:
433 433 if split:
434 434 return [],[]
435 435 else:
436 436 return '',''
437 437 if not debug:
438 438 pin,pout,perr = os.popen3(cmd)
439 439 tout = pout.read().rstrip()
440 440 terr = perr.read().rstrip()
441 441 pin.close()
442 442 pout.close()
443 443 perr.close()
444 444 if split:
445 445 return tout.split('\n'),terr.split('\n')
446 446 else:
447 447 return tout,terr
448 448
449 449 # for compatibility with older naming conventions
450 450 xsys = system
451 451 bq = getoutput
452 452
453 453 class SystemExec:
454 454 """Access the system and getoutput functions through a stateful interface.
455 455
456 456 Note: here we refer to the system and getoutput functions from this
457 457 library, not the ones from the standard python library.
458 458
459 459 This class offers the system and getoutput functions as methods, but the
460 460 verbose, debug and header parameters can be set for the instance (at
461 461 creation time or later) so that they don't need to be specified on each
462 462 call.
463 463
464 464 For efficiency reasons, there's no way to override the parameters on a
465 465 per-call basis other than by setting instance attributes. If you need
466 466 local overrides, it's best to directly call system() or getoutput().
467 467
468 468 The following names are provided as alternate options:
469 469 - xsys: alias to system
470 470 - bq: alias to getoutput
471 471
472 472 An instance can then be created as:
473 473 >>> sysexec = SystemExec(verbose=1,debug=0,header='Calling: ')
474 474 """
475 475
476 476 def __init__(self,verbose=0,debug=0,header='',split=0):
477 477 """Specify the instance's values for verbose, debug and header."""
478 478 setattr_list(self,'verbose debug header split')
479 479
480 480 def system(self,cmd):
481 481 """Stateful interface to system(), with the same keyword parameters."""
482 482
483 483 system(cmd,self.verbose,self.debug,self.header)
484 484
485 485 def shell(self,cmd):
486 486 """Stateful interface to shell(), with the same keyword parameters."""
487 487
488 488 shell(cmd,self.verbose,self.debug,self.header)
489 489
490 490 xsys = system # alias
491 491
492 492 def getoutput(self,cmd):
493 493 """Stateful interface to getoutput()."""
494 494
495 495 return getoutput(cmd,self.verbose,self.debug,self.header,self.split)
496 496
497 497 def getoutputerror(self,cmd):
498 498 """Stateful interface to getoutputerror()."""
499 499
500 500 return getoutputerror(cmd,self.verbose,self.debug,self.header,self.split)
501 501
502 502 bq = getoutput # alias
503 503
504 504 #-----------------------------------------------------------------------------
505 505 def mutex_opts(dict,ex_op):
506 506 """Check for presence of mutually exclusive keys in a dict.
507 507
508 508 Call: mutex_opts(dict,[[op1a,op1b],[op2a,op2b]...]"""
509 509 for op1,op2 in ex_op:
510 510 if op1 in dict and op2 in dict:
511 511 raise ValueError,'\n*** ERROR in Arguments *** '\
512 512 'Options '+op1+' and '+op2+' are mutually exclusive.'
513 513
514 514 #-----------------------------------------------------------------------------
515 515 def get_py_filename(name):
516 516 """Return a valid python filename in the current directory.
517 517
518 518 If the given name is not a file, it adds '.py' and searches again.
519 519 Raises IOError with an informative message if the file isn't found."""
520 520
521 521 name = os.path.expanduser(name)
522 522 if not os.path.isfile(name) and not name.endswith('.py'):
523 523 name += '.py'
524 524 if os.path.isfile(name):
525 525 return name
526 526 else:
527 527 raise IOError,'File `%s` not found.' % name
528 528
529 529 #-----------------------------------------------------------------------------
530 530 def filefind(fname,alt_dirs = None):
531 531 """Return the given filename either in the current directory, if it
532 532 exists, or in a specified list of directories.
533 533
534 534 ~ expansion is done on all file and directory names.
535 535
536 536 Upon an unsuccessful search, raise an IOError exception."""
537 537
538 538 if alt_dirs is None:
539 539 try:
540 540 alt_dirs = get_home_dir()
541 541 except HomeDirError:
542 542 alt_dirs = os.getcwd()
543 543 search = [fname] + list_strings(alt_dirs)
544 544 search = map(os.path.expanduser,search)
545 545 #print 'search list for',fname,'list:',search # dbg
546 546 fname = search[0]
547 547 if os.path.isfile(fname):
548 548 return fname
549 549 for direc in search[1:]:
550 550 testname = os.path.join(direc,fname)
551 551 #print 'testname',testname # dbg
552 552 if os.path.isfile(testname):
553 553 return testname
554 554 raise IOError,'File' + `fname` + \
555 555 ' not found in current or supplied directories:' + `alt_dirs`
556 556
557 557 #----------------------------------------------------------------------------
558 558 def file_read(filename):
559 559 """Read a file and close it. Returns the file source."""
560 560 fobj = open(filename,'r');
561 561 source = fobj.read();
562 562 fobj.close()
563 563 return source
564 564
565 565 def file_readlines(filename):
566 566 """Read a file and close it. Returns the file source using readlines()."""
567 567 fobj = open(filename,'r');
568 568 lines = fobj.readlines();
569 569 fobj.close()
570 570 return lines
571 571
572 572 #----------------------------------------------------------------------------
573 573 def target_outdated(target,deps):
574 574 """Determine whether a target is out of date.
575 575
576 576 target_outdated(target,deps) -> 1/0
577 577
578 578 deps: list of filenames which MUST exist.
579 579 target: single filename which may or may not exist.
580 580
581 581 If target doesn't exist or is older than any file listed in deps, return
582 582 true, otherwise return false.
583 583 """
584 584 try:
585 585 target_time = os.path.getmtime(target)
586 586 except os.error:
587 587 return 1
588 588 for dep in deps:
589 589 dep_time = os.path.getmtime(dep)
590 590 if dep_time > target_time:
591 591 #print "For target",target,"Dep failed:",dep # dbg
592 592 #print "times (dep,tar):",dep_time,target_time # dbg
593 593 return 1
594 594 return 0
595 595
596 596 #-----------------------------------------------------------------------------
597 597 def target_update(target,deps,cmd):
598 598 """Update a target with a given command given a list of dependencies.
599 599
600 600 target_update(target,deps,cmd) -> runs cmd if target is outdated.
601 601
602 602 This is just a wrapper around target_outdated() which calls the given
603 603 command if target is outdated."""
604 604
605 605 if target_outdated(target,deps):
606 606 xsys(cmd)
607 607
608 608 #----------------------------------------------------------------------------
609 609 def unquote_ends(istr):
610 610 """Remove a single pair of quotes from the endpoints of a string."""
611 611
612 612 if not istr:
613 613 return istr
614 614 if (istr[0]=="'" and istr[-1]=="'") or \
615 615 (istr[0]=='"' and istr[-1]=='"'):
616 616 return istr[1:-1]
617 617 else:
618 618 return istr
619 619
620 620 #----------------------------------------------------------------------------
621 621 def process_cmdline(argv,names=[],defaults={},usage=''):
622 622 """ Process command-line options and arguments.
623 623
624 624 Arguments:
625 625
626 626 - argv: list of arguments, typically sys.argv.
627 627
628 628 - names: list of option names. See DPyGetOpt docs for details on options
629 629 syntax.
630 630
631 631 - defaults: dict of default values.
632 632
633 633 - usage: optional usage notice to print if a wrong argument is passed.
634 634
635 635 Return a dict of options and a list of free arguments."""
636 636
637 637 getopt = DPyGetOpt.DPyGetOpt()
638 638 getopt.setIgnoreCase(0)
639 639 getopt.parseConfiguration(names)
640 640
641 641 try:
642 642 getopt.processArguments(argv)
643 643 except DPyGetOpt.ArgumentError, exc:
644 644 print usage
645 645 warn('"%s"' % exc,level=4)
646 646
647 647 defaults.update(getopt.optionValues)
648 648 args = getopt.freeValues
649 649
650 650 return defaults,args
651 651
652 652 #----------------------------------------------------------------------------
653 653 def optstr2types(ostr):
654 654 """Convert a string of option names to a dict of type mappings.
655 655
656 656 optstr2types(str) -> {None:'string_opts',int:'int_opts',float:'float_opts'}
657 657
658 658 This is used to get the types of all the options in a string formatted
659 659 with the conventions of DPyGetOpt. The 'type' None is used for options
660 660 which are strings (they need no further conversion). This function's main
661 661 use is to get a typemap for use with read_dict().
662 662 """
663 663
664 664 typeconv = {None:'',int:'',float:''}
665 665 typemap = {'s':None,'i':int,'f':float}
666 666 opt_re = re.compile(r'([\w]*)([^:=]*:?=?)([sif]?)')
667 667
668 668 for w in ostr.split():
669 669 oname,alias,otype = opt_re.match(w).groups()
670 670 if otype == '' or alias == '!': # simple switches are integers too
671 671 otype = 'i'
672 672 typeconv[typemap[otype]] += oname + ' '
673 673 return typeconv
674 674
675 675 #----------------------------------------------------------------------------
676 676 def read_dict(filename,type_conv=None,**opt):
677 677 r"""Read a dictionary of key=value pairs from an input file, optionally
678 678 performing conversions on the resulting values.
679 679
680 680 read_dict(filename,type_conv,**opt) -> dict
681 681
682 682 Only one value per line is accepted, the format should be
683 683 # optional comments are ignored
684 684 key value\n
685 685
686 686 Args:
687 687
688 688 - type_conv: A dictionary specifying which keys need to be converted to
689 689 which types. By default all keys are read as strings. This dictionary
690 690 should have as its keys valid conversion functions for strings
691 691 (int,long,float,complex, or your own). The value for each key
692 692 (converter) should be a whitespace separated string containing the names
693 693 of all the entries in the file to be converted using that function. For
694 694 keys to be left alone, use None as the conversion function (only needed
695 695 with purge=1, see below).
696 696
697 697 - opt: dictionary with extra options as below (default in parens)
698 698
699 699 purge(0): if set to 1, all keys *not* listed in type_conv are purged out
700 700 of the dictionary to be returned. If purge is going to be used, the
701 701 set of keys to be left as strings also has to be explicitly specified
702 702 using the (non-existent) conversion function None.
703 703
704 704 fs(None): field separator. This is the key/value separator to be used
705 705 when parsing the file. The None default means any whitespace [behavior
706 706 of string.split()].
707 707
708 708 strip(0): if 1, strip string values of leading/trailinig whitespace.
709 709
710 710 warn(1): warning level if requested keys are not found in file.
711 711 - 0: silently ignore.
712 712 - 1: inform but proceed.
713 713 - 2: raise KeyError exception.
714 714
715 715 no_empty(0): if 1, remove keys with whitespace strings as a value.
716 716
717 717 unique([]): list of keys (or space separated string) which can't be
718 718 repeated. If one such key is found in the file, each new instance
719 719 overwrites the previous one. For keys not listed here, the behavior is
720 720 to make a list of all appearances.
721 721
722 722 Example:
723 723
724 724 If the input file test.ini contains (we put it in a string to keep the test
725 725 self-contained):
726 726
727 727 >>> test_ini = '''\
728 728 ... i 3
729 729 ... x 4.5
730 730 ... y 5.5
731 731 ... s hi ho'''
732 732
733 733 Then we can use it as follows:
734 734 >>> type_conv={int:'i',float:'x',None:'s'}
735 735
736 736 >>> d = read_dict(test_ini)
737 737
738 738 >>> sorted(d.items())
739 739 [('i', '3'), ('s', 'hi ho'), ('x', '4.5'), ('y', '5.5')]
740 740
741 741 >>> d = read_dict(test_ini,type_conv)
742 742
743 743 >>> sorted(d.items())
744 744 [('i', 3), ('s', 'hi ho'), ('x', 4.5), ('y', '5.5')]
745 745
746 746 >>> d = read_dict(test_ini,type_conv,purge=True)
747 747
748 748 >>> sorted(d.items())
749 749 [('i', 3), ('s', 'hi ho'), ('x', 4.5)]
750 750 """
751 751
752 752 # starting config
753 753 opt.setdefault('purge',0)
754 754 opt.setdefault('fs',None) # field sep defaults to any whitespace
755 755 opt.setdefault('strip',0)
756 756 opt.setdefault('warn',1)
757 757 opt.setdefault('no_empty',0)
758 758 opt.setdefault('unique','')
759 759 if type(opt['unique']) in StringTypes:
760 760 unique_keys = qw(opt['unique'])
761 761 elif type(opt['unique']) in (types.TupleType,types.ListType):
762 762 unique_keys = opt['unique']
763 763 else:
764 764 raise ValueError, 'Unique keys must be given as a string, List or Tuple'
765 765
766 766 dict = {}
767 767
768 768 # first read in table of values as strings
769 769 if '\n' in filename:
770 770 lines = filename.splitlines()
771 771 file = None
772 772 else:
773 773 file = open(filename,'r')
774 774 lines = file.readlines()
775 775 for line in lines:
776 776 line = line.strip()
777 777 if len(line) and line[0]=='#': continue
778 778 if len(line)>0:
779 779 lsplit = line.split(opt['fs'],1)
780 780 try:
781 781 key,val = lsplit
782 782 except ValueError:
783 783 key,val = lsplit[0],''
784 784 key = key.strip()
785 785 if opt['strip']: val = val.strip()
786 786 if val == "''" or val == '""': val = ''
787 787 if opt['no_empty'] and (val=='' or val.isspace()):
788 788 continue
789 789 # if a key is found more than once in the file, build a list
790 790 # unless it's in the 'unique' list. In that case, last found in file
791 791 # takes precedence. User beware.
792 792 try:
793 793 if dict[key] and key in unique_keys:
794 794 dict[key] = val
795 795 elif type(dict[key]) is types.ListType:
796 796 dict[key].append(val)
797 797 else:
798 798 dict[key] = [dict[key],val]
799 799 except KeyError:
800 800 dict[key] = val
801 801 # purge if requested
802 802 if opt['purge']:
803 803 accepted_keys = qwflat(type_conv.values())
804 804 for key in dict.keys():
805 805 if key in accepted_keys: continue
806 806 del(dict[key])
807 807 # now convert if requested
808 808 if type_conv==None: return dict
809 809 conversions = type_conv.keys()
810 810 try: conversions.remove(None)
811 811 except: pass
812 812 for convert in conversions:
813 813 for val in qw(type_conv[convert]):
814 814 try:
815 815 dict[val] = convert(dict[val])
816 816 except KeyError,e:
817 817 if opt['warn'] == 0:
818 818 pass
819 819 elif opt['warn'] == 1:
820 820 print >>sys.stderr, 'Warning: key',val,\
821 821 'not found in file',filename
822 822 elif opt['warn'] == 2:
823 823 raise KeyError,e
824 824 else:
825 825 raise ValueError,'Warning level must be 0,1 or 2'
826 826
827 827 return dict
828 828
829 829 #----------------------------------------------------------------------------
830 830 def flag_calls(func):
831 831 """Wrap a function to detect and flag when it gets called.
832 832
833 833 This is a decorator which takes a function and wraps it in a function with
834 834 a 'called' attribute. wrapper.called is initialized to False.
835 835
836 836 The wrapper.called attribute is set to False right before each call to the
837 837 wrapped function, so if the call fails it remains False. After the call
838 838 completes, wrapper.called is set to True and the output is returned.
839 839
840 840 Testing for truth in wrapper.called allows you to determine if a call to
841 841 func() was attempted and succeeded."""
842 842
843 843 def wrapper(*args,**kw):
844 844 wrapper.called = False
845 845 out = func(*args,**kw)
846 846 wrapper.called = True
847 847 return out
848 848
849 849 wrapper.called = False
850 850 wrapper.__doc__ = func.__doc__
851 851 return wrapper
852 852
853 853 #----------------------------------------------------------------------------
854 854 def dhook_wrap(func,*a,**k):
855 855 """Wrap a function call in a sys.displayhook controller.
856 856
857 857 Returns a wrapper around func which calls func, with all its arguments and
858 858 keywords unmodified, using the default sys.displayhook. Since IPython
859 859 modifies sys.displayhook, it breaks the behavior of certain systems that
860 860 rely on the default behavior, notably doctest.
861 861 """
862 862
863 863 def f(*a,**k):
864 864
865 865 dhook_s = sys.displayhook
866 866 sys.displayhook = sys.__displayhook__
867 867 try:
868 868 out = func(*a,**k)
869 869 finally:
870 870 sys.displayhook = dhook_s
871 871
872 872 return out
873 873
874 874 f.__doc__ = func.__doc__
875 875 return f
876 876
877 877 #----------------------------------------------------------------------------
878 878 def doctest_reload():
879 879 """Properly reload doctest to reuse it interactively.
880 880
881 881 This routine:
882 882
883 883 - reloads doctest
884 884
885 885 - resets its global 'master' attribute to None, so that multiple uses of
886 886 the module interactively don't produce cumulative reports.
887 887
888 888 - Monkeypatches its core test runner method to protect it from IPython's
889 889 modified displayhook. Doctest expects the default displayhook behavior
890 890 deep down, so our modification breaks it completely. For this reason, a
891 891 hard monkeypatch seems like a reasonable solution rather than asking
892 892 users to manually use a different doctest runner when under IPython."""
893 893
894 894 import doctest
895 895 reload(doctest)
896 896 doctest.master=None
897 897
898 898 try:
899 899 doctest.DocTestRunner
900 900 except AttributeError:
901 901 # This is only for python 2.3 compatibility, remove once we move to
902 902 # 2.4 only.
903 903 pass
904 904 else:
905 905 doctest.DocTestRunner.run = dhook_wrap(doctest.DocTestRunner.run)
906 906
907 907 #----------------------------------------------------------------------------
908 908 class HomeDirError(Error):
909 909 pass
910 910
911 911 def get_home_dir():
912 912 """Return the closest possible equivalent to a 'home' directory.
913 913
914 914 We first try $HOME. Absent that, on NT it's $HOMEDRIVE\$HOMEPATH.
915 915
916 916 Currently only Posix and NT are implemented, a HomeDirError exception is
917 917 raised for all other OSes. """
918 918
919 919 isdir = os.path.isdir
920 920 env = os.environ
921 921
922 922 # first, check py2exe distribution root directory for _ipython.
923 923 # This overrides all. Normally does not exist.
924 924
925 925 if hasattr(sys, "frozen"): #Is frozen by py2exe
926 926 if '\\library.zip\\' in IPython.__file__.lower():#libraries compressed to zip-file
927 927 root, rest = IPython.__file__.lower().split('library.zip')
928 928 else:
929 929 root=os.path.join(os.path.split(IPython.__file__)[0],"../../")
930 930 root=os.path.abspath(root).rstrip('\\')
931 931 if isdir(os.path.join(root, '_ipython')):
932 932 os.environ["IPYKITROOT"] = root
933 933 return root
934 934 try:
935 935 homedir = env['HOME']
936 936 if not isdir(homedir):
937 937 # in case a user stuck some string which does NOT resolve to a
938 938 # valid path, it's as good as if we hadn't foud it
939 939 raise KeyError
940 940 return homedir
941 941 except KeyError:
942 942 if os.name == 'posix':
943 943 raise HomeDirError,'undefined $HOME, IPython can not proceed.'
944 944 elif os.name == 'nt':
945 945 # For some strange reason, win9x returns 'nt' for os.name.
946 946 try:
947 947 homedir = os.path.join(env['HOMEDRIVE'],env['HOMEPATH'])
948 948 if not isdir(homedir):
949 949 homedir = os.path.join(env['USERPROFILE'])
950 950 if not isdir(homedir):
951 951 raise HomeDirError
952 952 return homedir
953 953 except KeyError:
954 954 try:
955 955 # Use the registry to get the 'My Documents' folder.
956 956 import _winreg as wreg
957 957 key = wreg.OpenKey(wreg.HKEY_CURRENT_USER,
958 958 "Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders")
959 959 homedir = wreg.QueryValueEx(key,'Personal')[0]
960 960 key.Close()
961 961 if not isdir(homedir):
962 962 e = ('Invalid "Personal" folder registry key '
963 963 'typically "My Documents".\n'
964 964 'Value: %s\n'
965 965 'This is not a valid directory on your system.' %
966 966 homedir)
967 967 raise HomeDirError(e)
968 968 return homedir
969 969 except HomeDirError:
970 970 raise
971 971 except:
972 972 return 'C:\\'
973 973 elif os.name == 'dos':
974 974 # Desperate, may do absurd things in classic MacOS. May work under DOS.
975 975 return 'C:\\'
976 976 else:
977 977 raise HomeDirError,'support for your operating system not implemented.'
978 978
979 979
980 980 def get_ipython_dir():
981 981 """Get the IPython directory for this platform and user.
982 982
983 983 This uses the logic in `get_home_dir` to find the home directory
984 984 and the adds either .ipython or _ipython to the end of the path.
985 985 """
986 986 if os.name == 'posix':
987 987 ipdir_def = '.ipython'
988 988 else:
989 989 ipdir_def = '_ipython'
990 990 home_dir = get_home_dir()
991 991 ipdir = os.path.abspath(os.environ.get('IPYTHONDIR',
992 992 os.path.join(home_dir, ipdir_def)))
993 993 return ipdir.decode(sys.getfilesystemencoding())
994 994
995 995 def get_security_dir():
996 996 """Get the IPython security directory.
997 997
998 998 This directory is the default location for all security related files,
999 999 including SSL/TLS certificates and FURL files.
1000 1000
1001 1001 If the directory does not exist, it is created with 0700 permissions.
1002 1002 If it exists, permissions are set to 0700.
1003 1003 """
1004 1004 security_dir = os.path.join(get_ipython_dir(), 'security')
1005 1005 if not os.path.isdir(security_dir):
1006 1006 os.mkdir(security_dir, 0700)
1007 1007 else:
1008 1008 os.chmod(security_dir, 0700)
1009 1009 return security_dir
1010
1010
1011 def get_log_dir():
1012 """Get the IPython log directory.
1013
1014 If the log directory does not exist, it is created.
1015 """
1016 log_dir = os.path.join(get_ipython_dir(), 'log')
1017 if not os.path.isdir(log_dir):
1018 os.mkdir(log_dir, 0777)
1019 return log_dir
1020
1011 1021 #****************************************************************************
1012 1022 # strings and text
1013 1023
1014 1024 class LSString(str):
1015 1025 """String derivative with a special access attributes.
1016 1026
1017 1027 These are normal strings, but with the special attributes:
1018 1028
1019 1029 .l (or .list) : value as list (split on newlines).
1020 1030 .n (or .nlstr): original value (the string itself).
1021 1031 .s (or .spstr): value as whitespace-separated string.
1022 1032 .p (or .paths): list of path objects
1023 1033
1024 1034 Any values which require transformations are computed only once and
1025 1035 cached.
1026 1036
1027 1037 Such strings are very useful to efficiently interact with the shell, which
1028 1038 typically only understands whitespace-separated options for commands."""
1029 1039
1030 1040 def get_list(self):
1031 1041 try:
1032 1042 return self.__list
1033 1043 except AttributeError:
1034 1044 self.__list = self.split('\n')
1035 1045 return self.__list
1036 1046
1037 1047 l = list = property(get_list)
1038 1048
1039 1049 def get_spstr(self):
1040 1050 try:
1041 1051 return self.__spstr
1042 1052 except AttributeError:
1043 1053 self.__spstr = self.replace('\n',' ')
1044 1054 return self.__spstr
1045 1055
1046 1056 s = spstr = property(get_spstr)
1047 1057
1048 1058 def get_nlstr(self):
1049 1059 return self
1050 1060
1051 1061 n = nlstr = property(get_nlstr)
1052 1062
1053 1063 def get_paths(self):
1054 1064 try:
1055 1065 return self.__paths
1056 1066 except AttributeError:
1057 1067 self.__paths = [path(p) for p in self.split('\n') if os.path.exists(p)]
1058 1068 return self.__paths
1059 1069
1060 1070 p = paths = property(get_paths)
1061 1071
1062 1072 def print_lsstring(arg):
1063 1073 """ Prettier (non-repr-like) and more informative printer for LSString """
1064 1074 print "LSString (.p, .n, .l, .s available). Value:"
1065 1075 print arg
1066 1076
1067 1077 print_lsstring = result_display.when_type(LSString)(print_lsstring)
1068 1078
1069 1079 #----------------------------------------------------------------------------
1070 1080 class SList(list):
1071 1081 """List derivative with a special access attributes.
1072 1082
1073 1083 These are normal lists, but with the special attributes:
1074 1084
1075 1085 .l (or .list) : value as list (the list itself).
1076 1086 .n (or .nlstr): value as a string, joined on newlines.
1077 1087 .s (or .spstr): value as a string, joined on spaces.
1078 1088 .p (or .paths): list of path objects
1079 1089
1080 1090 Any values which require transformations are computed only once and
1081 1091 cached."""
1082 1092
1083 1093 def get_list(self):
1084 1094 return self
1085 1095
1086 1096 l = list = property(get_list)
1087 1097
1088 1098 def get_spstr(self):
1089 1099 try:
1090 1100 return self.__spstr
1091 1101 except AttributeError:
1092 1102 self.__spstr = ' '.join(self)
1093 1103 return self.__spstr
1094 1104
1095 1105 s = spstr = property(get_spstr)
1096 1106
1097 1107 def get_nlstr(self):
1098 1108 try:
1099 1109 return self.__nlstr
1100 1110 except AttributeError:
1101 1111 self.__nlstr = '\n'.join(self)
1102 1112 return self.__nlstr
1103 1113
1104 1114 n = nlstr = property(get_nlstr)
1105 1115
1106 1116 def get_paths(self):
1107 1117 try:
1108 1118 return self.__paths
1109 1119 except AttributeError:
1110 1120 self.__paths = [path(p) for p in self if os.path.exists(p)]
1111 1121 return self.__paths
1112 1122
1113 1123 p = paths = property(get_paths)
1114 1124
1115 1125 def grep(self, pattern, prune = False, field = None):
1116 1126 """ Return all strings matching 'pattern' (a regex or callable)
1117 1127
1118 1128 This is case-insensitive. If prune is true, return all items
1119 1129 NOT matching the pattern.
1120 1130
1121 1131 If field is specified, the match must occur in the specified
1122 1132 whitespace-separated field.
1123 1133
1124 1134 Examples::
1125 1135
1126 1136 a.grep( lambda x: x.startswith('C') )
1127 1137 a.grep('Cha.*log', prune=1)
1128 1138 a.grep('chm', field=-1)
1129 1139 """
1130 1140
1131 1141 def match_target(s):
1132 1142 if field is None:
1133 1143 return s
1134 1144 parts = s.split()
1135 1145 try:
1136 1146 tgt = parts[field]
1137 1147 return tgt
1138 1148 except IndexError:
1139 1149 return ""
1140 1150
1141 1151 if isinstance(pattern, basestring):
1142 1152 pred = lambda x : re.search(pattern, x, re.IGNORECASE)
1143 1153 else:
1144 1154 pred = pattern
1145 1155 if not prune:
1146 1156 return SList([el for el in self if pred(match_target(el))])
1147 1157 else:
1148 1158 return SList([el for el in self if not pred(match_target(el))])
1149 1159 def fields(self, *fields):
1150 1160 """ Collect whitespace-separated fields from string list
1151 1161
1152 1162 Allows quick awk-like usage of string lists.
1153 1163
1154 1164 Example data (in var a, created by 'a = !ls -l')::
1155 1165 -rwxrwxrwx 1 ville None 18 Dec 14 2006 ChangeLog
1156 1166 drwxrwxrwx+ 6 ville None 0 Oct 24 18:05 IPython
1157 1167
1158 1168 a.fields(0) is ['-rwxrwxrwx', 'drwxrwxrwx+']
1159 1169 a.fields(1,0) is ['1 -rwxrwxrwx', '6 drwxrwxrwx+']
1160 1170 (note the joining by space).
1161 1171 a.fields(-1) is ['ChangeLog', 'IPython']
1162 1172
1163 1173 IndexErrors are ignored.
1164 1174
1165 1175 Without args, fields() just split()'s the strings.
1166 1176 """
1167 1177 if len(fields) == 0:
1168 1178 return [el.split() for el in self]
1169 1179
1170 1180 res = SList()
1171 1181 for el in [f.split() for f in self]:
1172 1182 lineparts = []
1173 1183
1174 1184 for fd in fields:
1175 1185 try:
1176 1186 lineparts.append(el[fd])
1177 1187 except IndexError:
1178 1188 pass
1179 1189 if lineparts:
1180 1190 res.append(" ".join(lineparts))
1181 1191
1182 1192 return res
1183 1193 def sort(self,field= None, nums = False):
1184 1194 """ sort by specified fields (see fields())
1185 1195
1186 1196 Example::
1187 1197 a.sort(1, nums = True)
1188 1198
1189 1199 Sorts a by second field, in numerical order (so that 21 > 3)
1190 1200
1191 1201 """
1192 1202
1193 1203 #decorate, sort, undecorate
1194 1204 if field is not None:
1195 1205 dsu = [[SList([line]).fields(field), line] for line in self]
1196 1206 else:
1197 1207 dsu = [[line, line] for line in self]
1198 1208 if nums:
1199 1209 for i in range(len(dsu)):
1200 1210 numstr = "".join([ch for ch in dsu[i][0] if ch.isdigit()])
1201 1211 try:
1202 1212 n = int(numstr)
1203 1213 except ValueError:
1204 1214 n = 0;
1205 1215 dsu[i][0] = n
1206 1216
1207 1217
1208 1218 dsu.sort()
1209 1219 return SList([t[1] for t in dsu])
1210 1220
1211 1221 def print_slist(arg):
1212 1222 """ Prettier (non-repr-like) and more informative printer for SList """
1213 1223 print "SList (.p, .n, .l, .s, .grep(), .fields(), sort() available):"
1214 1224 if hasattr(arg, 'hideonce') and arg.hideonce:
1215 1225 arg.hideonce = False
1216 1226 return
1217 1227
1218 1228 nlprint(arg)
1219 1229
1220 1230 print_slist = result_display.when_type(SList)(print_slist)
1221 1231
1222 1232
1223 1233
1224 1234 #----------------------------------------------------------------------------
1225 1235 def esc_quotes(strng):
1226 1236 """Return the input string with single and double quotes escaped out"""
1227 1237
1228 1238 return strng.replace('"','\\"').replace("'","\\'")
1229 1239
1230 1240 #----------------------------------------------------------------------------
1231 1241 def make_quoted_expr(s):
1232 1242 """Return string s in appropriate quotes, using raw string if possible.
1233 1243
1234 1244 XXX - example removed because it caused encoding errors in documentation
1235 1245 generation. We need a new example that doesn't contain invalid chars.
1236 1246
1237 1247 Note the use of raw string and padding at the end to allow trailing
1238 1248 backslash.
1239 1249 """
1240 1250
1241 1251 tail = ''
1242 1252 tailpadding = ''
1243 1253 raw = ''
1244 1254 if "\\" in s:
1245 1255 raw = 'r'
1246 1256 if s.endswith('\\'):
1247 1257 tail = '[:-1]'
1248 1258 tailpadding = '_'
1249 1259 if '"' not in s:
1250 1260 quote = '"'
1251 1261 elif "'" not in s:
1252 1262 quote = "'"
1253 1263 elif '"""' not in s and not s.endswith('"'):
1254 1264 quote = '"""'
1255 1265 elif "'''" not in s and not s.endswith("'"):
1256 1266 quote = "'''"
1257 1267 else:
1258 1268 # give up, backslash-escaped string will do
1259 1269 return '"%s"' % esc_quotes(s)
1260 1270 res = raw + quote + s + tailpadding + quote + tail
1261 1271 return res
1262 1272
1263 1273
1264 1274 #----------------------------------------------------------------------------
1265 1275 def raw_input_multi(header='', ps1='==> ', ps2='..> ',terminate_str = '.'):
1266 1276 """Take multiple lines of input.
1267 1277
1268 1278 A list with each line of input as a separate element is returned when a
1269 1279 termination string is entered (defaults to a single '.'). Input can also
1270 1280 terminate via EOF (^D in Unix, ^Z-RET in Windows).
1271 1281
1272 1282 Lines of input which end in \\ are joined into single entries (and a
1273 1283 secondary continuation prompt is issued as long as the user terminates
1274 1284 lines with \\). This allows entering very long strings which are still
1275 1285 meant to be treated as single entities.
1276 1286 """
1277 1287
1278 1288 try:
1279 1289 if header:
1280 1290 header += '\n'
1281 1291 lines = [raw_input(header + ps1)]
1282 1292 except EOFError:
1283 1293 return []
1284 1294 terminate = [terminate_str]
1285 1295 try:
1286 1296 while lines[-1:] != terminate:
1287 1297 new_line = raw_input(ps1)
1288 1298 while new_line.endswith('\\'):
1289 1299 new_line = new_line[:-1] + raw_input(ps2)
1290 1300 lines.append(new_line)
1291 1301
1292 1302 return lines[:-1] # don't return the termination command
1293 1303 except EOFError:
1294 1304 print
1295 1305 return lines
1296 1306
1297 1307 #----------------------------------------------------------------------------
1298 1308 def raw_input_ext(prompt='', ps2='... '):
1299 1309 """Similar to raw_input(), but accepts extended lines if input ends with \\."""
1300 1310
1301 1311 line = raw_input(prompt)
1302 1312 while line.endswith('\\'):
1303 1313 line = line[:-1] + raw_input(ps2)
1304 1314 return line
1305 1315
1306 1316 #----------------------------------------------------------------------------
1307 1317 def ask_yes_no(prompt,default=None):
1308 1318 """Asks a question and returns a boolean (y/n) answer.
1309 1319
1310 1320 If default is given (one of 'y','n'), it is used if the user input is
1311 1321 empty. Otherwise the question is repeated until an answer is given.
1312 1322
1313 1323 An EOF is treated as the default answer. If there is no default, an
1314 1324 exception is raised to prevent infinite loops.
1315 1325
1316 1326 Valid answers are: y/yes/n/no (match is not case sensitive)."""
1317 1327
1318 1328 answers = {'y':True,'n':False,'yes':True,'no':False}
1319 1329 ans = None
1320 1330 while ans not in answers.keys():
1321 1331 try:
1322 1332 ans = raw_input(prompt+' ').lower()
1323 1333 if not ans: # response was an empty string
1324 1334 ans = default
1325 1335 except KeyboardInterrupt:
1326 1336 pass
1327 1337 except EOFError:
1328 1338 if default in answers.keys():
1329 1339 ans = default
1330 1340 print
1331 1341 else:
1332 1342 raise
1333 1343
1334 1344 return answers[ans]
1335 1345
1336 1346 #----------------------------------------------------------------------------
1337 1347 def marquee(txt='',width=78,mark='*'):
1338 1348 """Return the input string centered in a 'marquee'."""
1339 1349 if not txt:
1340 1350 return (mark*width)[:width]
1341 1351 nmark = (width-len(txt)-2)/len(mark)/2
1342 1352 if nmark < 0: nmark =0
1343 1353 marks = mark*nmark
1344 1354 return '%s %s %s' % (marks,txt,marks)
1345 1355
1346 1356 #----------------------------------------------------------------------------
1347 1357 class EvalDict:
1348 1358 """
1349 1359 Emulate a dict which evaluates its contents in the caller's frame.
1350 1360
1351 1361 Usage:
1352 1362 >>> number = 19
1353 1363
1354 1364 >>> text = "python"
1355 1365
1356 1366 >>> print "%(text.capitalize())s %(number/9.0).1f rules!" % EvalDict()
1357 1367 Python 2.1 rules!
1358 1368 """
1359 1369
1360 1370 # This version is due to sismex01@hebmex.com on c.l.py, and is basically a
1361 1371 # modified (shorter) version of:
1362 1372 # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66018 by
1363 1373 # Skip Montanaro (skip@pobox.com).
1364 1374
1365 1375 def __getitem__(self, name):
1366 1376 frame = sys._getframe(1)
1367 1377 return eval(name, frame.f_globals, frame.f_locals)
1368 1378
1369 1379 EvalString = EvalDict # for backwards compatibility
1370 1380 #----------------------------------------------------------------------------
1371 1381 def qw(words,flat=0,sep=None,maxsplit=-1):
1372 1382 """Similar to Perl's qw() operator, but with some more options.
1373 1383
1374 1384 qw(words,flat=0,sep=' ',maxsplit=-1) -> words.split(sep,maxsplit)
1375 1385
1376 1386 words can also be a list itself, and with flat=1, the output will be
1377 1387 recursively flattened.
1378 1388
1379 1389 Examples:
1380 1390
1381 1391 >>> qw('1 2')
1382 1392 ['1', '2']
1383 1393
1384 1394 >>> qw(['a b','1 2',['m n','p q']])
1385 1395 [['a', 'b'], ['1', '2'], [['m', 'n'], ['p', 'q']]]
1386 1396
1387 1397 >>> qw(['a b','1 2',['m n','p q']],flat=1)
1388 1398 ['a', 'b', '1', '2', 'm', 'n', 'p', 'q']
1389 1399 """
1390 1400
1391 1401 if type(words) in StringTypes:
1392 1402 return [word.strip() for word in words.split(sep,maxsplit)
1393 1403 if word and not word.isspace() ]
1394 1404 if flat:
1395 1405 return flatten(map(qw,words,[1]*len(words)))
1396 1406 return map(qw,words)
1397 1407
1398 1408 #----------------------------------------------------------------------------
1399 1409 def qwflat(words,sep=None,maxsplit=-1):
1400 1410 """Calls qw(words) in flat mode. It's just a convenient shorthand."""
1401 1411 return qw(words,1,sep,maxsplit)
1402 1412
1403 1413 #----------------------------------------------------------------------------
1404 1414 def qw_lol(indata):
1405 1415 """qw_lol('a b') -> [['a','b']],
1406 1416 otherwise it's just a call to qw().
1407 1417
1408 1418 We need this to make sure the modules_some keys *always* end up as a
1409 1419 list of lists."""
1410 1420
1411 1421 if type(indata) in StringTypes:
1412 1422 return [qw(indata)]
1413 1423 else:
1414 1424 return qw(indata)
1415 1425
1416 1426 #-----------------------------------------------------------------------------
1417 1427 def list_strings(arg):
1418 1428 """Always return a list of strings, given a string or list of strings
1419 1429 as input."""
1420 1430
1421 1431 if type(arg) in StringTypes: return [arg]
1422 1432 else: return arg
1423 1433
1424 1434 #----------------------------------------------------------------------------
1425 1435 def grep(pat,list,case=1):
1426 1436 """Simple minded grep-like function.
1427 1437 grep(pat,list) returns occurrences of pat in list, None on failure.
1428 1438
1429 1439 It only does simple string matching, with no support for regexps. Use the
1430 1440 option case=0 for case-insensitive matching."""
1431 1441
1432 1442 # This is pretty crude. At least it should implement copying only references
1433 1443 # to the original data in case it's big. Now it copies the data for output.
1434 1444 out=[]
1435 1445 if case:
1436 1446 for term in list:
1437 1447 if term.find(pat)>-1: out.append(term)
1438 1448 else:
1439 1449 lpat=pat.lower()
1440 1450 for term in list:
1441 1451 if term.lower().find(lpat)>-1: out.append(term)
1442 1452
1443 1453 if len(out): return out
1444 1454 else: return None
1445 1455
1446 1456 #----------------------------------------------------------------------------
1447 1457 def dgrep(pat,*opts):
1448 1458 """Return grep() on dir()+dir(__builtins__).
1449 1459
1450 1460 A very common use of grep() when working interactively."""
1451 1461
1452 1462 return grep(pat,dir(__main__)+dir(__main__.__builtins__),*opts)
1453 1463
1454 1464 #----------------------------------------------------------------------------
1455 1465 def idgrep(pat):
1456 1466 """Case-insensitive dgrep()"""
1457 1467
1458 1468 return dgrep(pat,0)
1459 1469
1460 1470 #----------------------------------------------------------------------------
1461 1471 def igrep(pat,list):
1462 1472 """Synonym for case-insensitive grep."""
1463 1473
1464 1474 return grep(pat,list,case=0)
1465 1475
1466 1476 #----------------------------------------------------------------------------
1467 1477 def indent(str,nspaces=4,ntabs=0):
1468 1478 """Indent a string a given number of spaces or tabstops.
1469 1479
1470 1480 indent(str,nspaces=4,ntabs=0) -> indent str by ntabs+nspaces.
1471 1481 """
1472 1482 if str is None:
1473 1483 return
1474 1484 ind = '\t'*ntabs+' '*nspaces
1475 1485 outstr = '%s%s' % (ind,str.replace(os.linesep,os.linesep+ind))
1476 1486 if outstr.endswith(os.linesep+ind):
1477 1487 return outstr[:-len(ind)]
1478 1488 else:
1479 1489 return outstr
1480 1490
1481 1491 #-----------------------------------------------------------------------------
1482 1492 def native_line_ends(filename,backup=1):
1483 1493 """Convert (in-place) a file to line-ends native to the current OS.
1484 1494
1485 1495 If the optional backup argument is given as false, no backup of the
1486 1496 original file is left. """
1487 1497
1488 1498 backup_suffixes = {'posix':'~','dos':'.bak','nt':'.bak','mac':'.bak'}
1489 1499
1490 1500 bak_filename = filename + backup_suffixes[os.name]
1491 1501
1492 1502 original = open(filename).read()
1493 1503 shutil.copy2(filename,bak_filename)
1494 1504 try:
1495 1505 new = open(filename,'wb')
1496 1506 new.write(os.linesep.join(original.splitlines()))
1497 1507 new.write(os.linesep) # ALWAYS put an eol at the end of the file
1498 1508 new.close()
1499 1509 except:
1500 1510 os.rename(bak_filename,filename)
1501 1511 if not backup:
1502 1512 try:
1503 1513 os.remove(bak_filename)
1504 1514 except:
1505 1515 pass
1506 1516
1507 1517 #----------------------------------------------------------------------------
1508 1518 def get_pager_cmd(pager_cmd = None):
1509 1519 """Return a pager command.
1510 1520
1511 1521 Makes some attempts at finding an OS-correct one."""
1512 1522
1513 1523 if os.name == 'posix':
1514 1524 default_pager_cmd = 'less -r' # -r for color control sequences
1515 1525 elif os.name in ['nt','dos']:
1516 1526 default_pager_cmd = 'type'
1517 1527
1518 1528 if pager_cmd is None:
1519 1529 try:
1520 1530 pager_cmd = os.environ['PAGER']
1521 1531 except:
1522 1532 pager_cmd = default_pager_cmd
1523 1533 return pager_cmd
1524 1534
1525 1535 #-----------------------------------------------------------------------------
1526 1536 def get_pager_start(pager,start):
1527 1537 """Return the string for paging files with an offset.
1528 1538
1529 1539 This is the '+N' argument which less and more (under Unix) accept.
1530 1540 """
1531 1541
1532 1542 if pager in ['less','more']:
1533 1543 if start:
1534 1544 start_string = '+' + str(start)
1535 1545 else:
1536 1546 start_string = ''
1537 1547 else:
1538 1548 start_string = ''
1539 1549 return start_string
1540 1550
1541 1551 #----------------------------------------------------------------------------
1542 1552 # (X)emacs on W32 doesn't like to be bypassed with msvcrt.getch()
1543 1553 if os.name == 'nt' and os.environ.get('TERM','dumb') != 'emacs':
1544 1554 import msvcrt
1545 1555 def page_more():
1546 1556 """ Smart pausing between pages
1547 1557
1548 1558 @return: True if need print more lines, False if quit
1549 1559 """
1550 1560 Term.cout.write('---Return to continue, q to quit--- ')
1551 1561 ans = msvcrt.getch()
1552 1562 if ans in ("q", "Q"):
1553 1563 result = False
1554 1564 else:
1555 1565 result = True
1556 1566 Term.cout.write("\b"*37 + " "*37 + "\b"*37)
1557 1567 return result
1558 1568 else:
1559 1569 def page_more():
1560 1570 ans = raw_input('---Return to continue, q to quit--- ')
1561 1571 if ans.lower().startswith('q'):
1562 1572 return False
1563 1573 else:
1564 1574 return True
1565 1575
1566 1576 esc_re = re.compile(r"(\x1b[^m]+m)")
1567 1577
1568 1578 def page_dumb(strng,start=0,screen_lines=25):
1569 1579 """Very dumb 'pager' in Python, for when nothing else works.
1570 1580
1571 1581 Only moves forward, same interface as page(), except for pager_cmd and
1572 1582 mode."""
1573 1583
1574 1584 out_ln = strng.splitlines()[start:]
1575 1585 screens = chop(out_ln,screen_lines-1)
1576 1586 if len(screens) == 1:
1577 1587 print >>Term.cout, os.linesep.join(screens[0])
1578 1588 else:
1579 1589 last_escape = ""
1580 1590 for scr in screens[0:-1]:
1581 1591 hunk = os.linesep.join(scr)
1582 1592 print >>Term.cout, last_escape + hunk
1583 1593 if not page_more():
1584 1594 return
1585 1595 esc_list = esc_re.findall(hunk)
1586 1596 if len(esc_list) > 0:
1587 1597 last_escape = esc_list[-1]
1588 1598 print >>Term.cout, last_escape + os.linesep.join(screens[-1])
1589 1599
1590 1600 #----------------------------------------------------------------------------
1591 1601 def page(strng,start=0,screen_lines=0,pager_cmd = None):
1592 1602 """Print a string, piping through a pager after a certain length.
1593 1603
1594 1604 The screen_lines parameter specifies the number of *usable* lines of your
1595 1605 terminal screen (total lines minus lines you need to reserve to show other
1596 1606 information).
1597 1607
1598 1608 If you set screen_lines to a number <=0, page() will try to auto-determine
1599 1609 your screen size and will only use up to (screen_size+screen_lines) for
1600 1610 printing, paging after that. That is, if you want auto-detection but need
1601 1611 to reserve the bottom 3 lines of the screen, use screen_lines = -3, and for
1602 1612 auto-detection without any lines reserved simply use screen_lines = 0.
1603 1613
1604 1614 If a string won't fit in the allowed lines, it is sent through the
1605 1615 specified pager command. If none given, look for PAGER in the environment,
1606 1616 and ultimately default to less.
1607 1617
1608 1618 If no system pager works, the string is sent through a 'dumb pager'
1609 1619 written in python, very simplistic.
1610 1620 """
1611 1621
1612 1622 # Some routines may auto-compute start offsets incorrectly and pass a
1613 1623 # negative value. Offset to 0 for robustness.
1614 1624 start = max(0,start)
1615 1625
1616 1626 # first, try the hook
1617 1627 ip = IPython.ipapi.get()
1618 1628 if ip:
1619 1629 try:
1620 1630 ip.IP.hooks.show_in_pager(strng)
1621 1631 return
1622 1632 except IPython.ipapi.TryNext:
1623 1633 pass
1624 1634
1625 1635 # Ugly kludge, but calling curses.initscr() flat out crashes in emacs
1626 1636 TERM = os.environ.get('TERM','dumb')
1627 1637 if TERM in ['dumb','emacs'] and os.name != 'nt':
1628 1638 print strng
1629 1639 return
1630 1640 # chop off the topmost part of the string we don't want to see
1631 1641 str_lines = strng.split(os.linesep)[start:]
1632 1642 str_toprint = os.linesep.join(str_lines)
1633 1643 num_newlines = len(str_lines)
1634 1644 len_str = len(str_toprint)
1635 1645
1636 1646 # Dumb heuristics to guesstimate number of on-screen lines the string
1637 1647 # takes. Very basic, but good enough for docstrings in reasonable
1638 1648 # terminals. If someone later feels like refining it, it's not hard.
1639 1649 numlines = max(num_newlines,int(len_str/80)+1)
1640 1650
1641 1651 if os.name == "nt":
1642 1652 screen_lines_def = get_console_size(defaulty=25)[1]
1643 1653 else:
1644 1654 screen_lines_def = 25 # default value if we can't auto-determine
1645 1655
1646 1656 # auto-determine screen size
1647 1657 if screen_lines <= 0:
1648 1658 if TERM=='xterm':
1649 1659 use_curses = USE_CURSES
1650 1660 else:
1651 1661 # curses causes problems on many terminals other than xterm.
1652 1662 use_curses = False
1653 1663 if use_curses:
1654 1664 # There is a bug in curses, where *sometimes* it fails to properly
1655 1665 # initialize, and then after the endwin() call is made, the
1656 1666 # terminal is left in an unusable state. Rather than trying to
1657 1667 # check everytime for this (by requesting and comparing termios
1658 1668 # flags each time), we just save the initial terminal state and
1659 1669 # unconditionally reset it every time. It's cheaper than making
1660 1670 # the checks.
1661 1671 term_flags = termios.tcgetattr(sys.stdout)
1662 1672 scr = curses.initscr()
1663 1673 screen_lines_real,screen_cols = scr.getmaxyx()
1664 1674 curses.endwin()
1665 1675 # Restore terminal state in case endwin() didn't.
1666 1676 termios.tcsetattr(sys.stdout,termios.TCSANOW,term_flags)
1667 1677 # Now we have what we needed: the screen size in rows/columns
1668 1678 screen_lines += screen_lines_real
1669 1679 #print '***Screen size:',screen_lines_real,'lines x',\
1670 1680 #screen_cols,'columns.' # dbg
1671 1681 else:
1672 1682 screen_lines += screen_lines_def
1673 1683
1674 1684 #print 'numlines',numlines,'screenlines',screen_lines # dbg
1675 1685 if numlines <= screen_lines :
1676 1686 #print '*** normal print' # dbg
1677 1687 print >>Term.cout, str_toprint
1678 1688 else:
1679 1689 # Try to open pager and default to internal one if that fails.
1680 1690 # All failure modes are tagged as 'retval=1', to match the return
1681 1691 # value of a failed system command. If any intermediate attempt
1682 1692 # sets retval to 1, at the end we resort to our own page_dumb() pager.
1683 1693 pager_cmd = get_pager_cmd(pager_cmd)
1684 1694 pager_cmd += ' ' + get_pager_start(pager_cmd,start)
1685 1695 if os.name == 'nt':
1686 1696 if pager_cmd.startswith('type'):
1687 1697 # The default WinXP 'type' command is failing on complex strings.
1688 1698 retval = 1
1689 1699 else:
1690 1700 tmpname = tempfile.mktemp('.txt')
1691 1701 tmpfile = file(tmpname,'wt')
1692 1702 tmpfile.write(strng)
1693 1703 tmpfile.close()
1694 1704 cmd = "%s < %s" % (pager_cmd,tmpname)
1695 1705 if os.system(cmd):
1696 1706 retval = 1
1697 1707 else:
1698 1708 retval = None
1699 1709 os.remove(tmpname)
1700 1710 else:
1701 1711 try:
1702 1712 retval = None
1703 1713 # if I use popen4, things hang. No idea why.
1704 1714 #pager,shell_out = os.popen4(pager_cmd)
1705 1715 pager = os.popen(pager_cmd,'w')
1706 1716 pager.write(strng)
1707 1717 pager.close()
1708 1718 retval = pager.close() # success returns None
1709 1719 except IOError,msg: # broken pipe when user quits
1710 1720 if msg.args == (32,'Broken pipe'):
1711 1721 retval = None
1712 1722 else:
1713 1723 retval = 1
1714 1724 except OSError:
1715 1725 # Other strange problems, sometimes seen in Win2k/cygwin
1716 1726 retval = 1
1717 1727 if retval is not None:
1718 1728 page_dumb(strng,screen_lines=screen_lines)
1719 1729
1720 1730 #----------------------------------------------------------------------------
1721 1731 def page_file(fname,start = 0, pager_cmd = None):
1722 1732 """Page a file, using an optional pager command and starting line.
1723 1733 """
1724 1734
1725 1735 pager_cmd = get_pager_cmd(pager_cmd)
1726 1736 pager_cmd += ' ' + get_pager_start(pager_cmd,start)
1727 1737
1728 1738 try:
1729 1739 if os.environ['TERM'] in ['emacs','dumb']:
1730 1740 raise EnvironmentError
1731 1741 xsys(pager_cmd + ' ' + fname)
1732 1742 except:
1733 1743 try:
1734 1744 if start > 0:
1735 1745 start -= 1
1736 1746 page(open(fname).read(),start)
1737 1747 except:
1738 1748 print 'Unable to show file',`fname`
1739 1749
1740 1750
1741 1751 #----------------------------------------------------------------------------
1742 1752 def snip_print(str,width = 75,print_full = 0,header = ''):
1743 1753 """Print a string snipping the midsection to fit in width.
1744 1754
1745 1755 print_full: mode control:
1746 1756 - 0: only snip long strings
1747 1757 - 1: send to page() directly.
1748 1758 - 2: snip long strings and ask for full length viewing with page()
1749 1759 Return 1 if snipping was necessary, 0 otherwise."""
1750 1760
1751 1761 if print_full == 1:
1752 1762 page(header+str)
1753 1763 return 0
1754 1764
1755 1765 print header,
1756 1766 if len(str) < width:
1757 1767 print str
1758 1768 snip = 0
1759 1769 else:
1760 1770 whalf = int((width -5)/2)
1761 1771 print str[:whalf] + ' <...> ' + str[-whalf:]
1762 1772 snip = 1
1763 1773 if snip and print_full == 2:
1764 1774 if raw_input(header+' Snipped. View (y/n)? [N]').lower() == 'y':
1765 1775 page(str)
1766 1776 return snip
1767 1777
1768 1778 #****************************************************************************
1769 1779 # lists, dicts and structures
1770 1780
1771 1781 def belong(candidates,checklist):
1772 1782 """Check whether a list of items appear in a given list of options.
1773 1783
1774 1784 Returns a list of 1 and 0, one for each candidate given."""
1775 1785
1776 1786 return [x in checklist for x in candidates]
1777 1787
1778 1788 #----------------------------------------------------------------------------
1779 1789 def uniq_stable(elems):
1780 1790 """uniq_stable(elems) -> list
1781 1791
1782 1792 Return from an iterable, a list of all the unique elements in the input,
1783 1793 but maintaining the order in which they first appear.
1784 1794
1785 1795 A naive solution to this problem which just makes a dictionary with the
1786 1796 elements as keys fails to respect the stability condition, since
1787 1797 dictionaries are unsorted by nature.
1788 1798
1789 1799 Note: All elements in the input must be valid dictionary keys for this
1790 1800 routine to work, as it internally uses a dictionary for efficiency
1791 1801 reasons."""
1792 1802
1793 1803 unique = []
1794 1804 unique_dict = {}
1795 1805 for nn in elems:
1796 1806 if nn not in unique_dict:
1797 1807 unique.append(nn)
1798 1808 unique_dict[nn] = None
1799 1809 return unique
1800 1810
1801 1811 #----------------------------------------------------------------------------
1802 1812 class NLprinter:
1803 1813 """Print an arbitrarily nested list, indicating index numbers.
1804 1814
1805 1815 An instance of this class called nlprint is available and callable as a
1806 1816 function.
1807 1817
1808 1818 nlprint(list,indent=' ',sep=': ') -> prints indenting each level by 'indent'
1809 1819 and using 'sep' to separate the index from the value. """
1810 1820
1811 1821 def __init__(self):
1812 1822 self.depth = 0
1813 1823
1814 1824 def __call__(self,lst,pos='',**kw):
1815 1825 """Prints the nested list numbering levels."""
1816 1826 kw.setdefault('indent',' ')
1817 1827 kw.setdefault('sep',': ')
1818 1828 kw.setdefault('start',0)
1819 1829 kw.setdefault('stop',len(lst))
1820 1830 # we need to remove start and stop from kw so they don't propagate
1821 1831 # into a recursive call for a nested list.
1822 1832 start = kw['start']; del kw['start']
1823 1833 stop = kw['stop']; del kw['stop']
1824 1834 if self.depth == 0 and 'header' in kw.keys():
1825 1835 print kw['header']
1826 1836
1827 1837 for idx in range(start,stop):
1828 1838 elem = lst[idx]
1829 1839 if type(elem)==type([]):
1830 1840 self.depth += 1
1831 1841 self.__call__(elem,itpl('$pos$idx,'),**kw)
1832 1842 self.depth -= 1
1833 1843 else:
1834 1844 printpl(kw['indent']*self.depth+'$pos$idx$kw["sep"]$elem')
1835 1845
1836 1846 nlprint = NLprinter()
1837 1847 #----------------------------------------------------------------------------
1838 1848 def all_belong(candidates,checklist):
1839 1849 """Check whether a list of items ALL appear in a given list of options.
1840 1850
1841 1851 Returns a single 1 or 0 value."""
1842 1852
1843 1853 return 1-(0 in [x in checklist for x in candidates])
1844 1854
1845 1855 #----------------------------------------------------------------------------
1846 1856 def sort_compare(lst1,lst2,inplace = 1):
1847 1857 """Sort and compare two lists.
1848 1858
1849 1859 By default it does it in place, thus modifying the lists. Use inplace = 0
1850 1860 to avoid that (at the cost of temporary copy creation)."""
1851 1861 if not inplace:
1852 1862 lst1 = lst1[:]
1853 1863 lst2 = lst2[:]
1854 1864 lst1.sort(); lst2.sort()
1855 1865 return lst1 == lst2
1856 1866
1857 1867 #----------------------------------------------------------------------------
1858 1868 def list2dict(lst):
1859 1869 """Takes a list of (key,value) pairs and turns it into a dict."""
1860 1870
1861 1871 dic = {}
1862 1872 for k,v in lst: dic[k] = v
1863 1873 return dic
1864 1874
1865 1875 #----------------------------------------------------------------------------
1866 1876 def list2dict2(lst,default=''):
1867 1877 """Takes a list and turns it into a dict.
1868 1878 Much slower than list2dict, but more versatile. This version can take
1869 1879 lists with sublists of arbitrary length (including sclars)."""
1870 1880
1871 1881 dic = {}
1872 1882 for elem in lst:
1873 1883 if type(elem) in (types.ListType,types.TupleType):
1874 1884 size = len(elem)
1875 1885 if size == 0:
1876 1886 pass
1877 1887 elif size == 1:
1878 1888 dic[elem] = default
1879 1889 else:
1880 1890 k,v = elem[0], elem[1:]
1881 1891 if len(v) == 1: v = v[0]
1882 1892 dic[k] = v
1883 1893 else:
1884 1894 dic[elem] = default
1885 1895 return dic
1886 1896
1887 1897 #----------------------------------------------------------------------------
1888 1898 def flatten(seq):
1889 1899 """Flatten a list of lists (NOT recursive, only works for 2d lists)."""
1890 1900
1891 1901 return [x for subseq in seq for x in subseq]
1892 1902
1893 1903 #----------------------------------------------------------------------------
1894 1904 def get_slice(seq,start=0,stop=None,step=1):
1895 1905 """Get a slice of a sequence with variable step. Specify start,stop,step."""
1896 1906 if stop == None:
1897 1907 stop = len(seq)
1898 1908 item = lambda i: seq[i]
1899 1909 return map(item,xrange(start,stop,step))
1900 1910
1901 1911 #----------------------------------------------------------------------------
1902 1912 def chop(seq,size):
1903 1913 """Chop a sequence into chunks of the given size."""
1904 1914 chunk = lambda i: seq[i:i+size]
1905 1915 return map(chunk,xrange(0,len(seq),size))
1906 1916
1907 1917 #----------------------------------------------------------------------------
1908 1918 # with is a keyword as of python 2.5, so this function is renamed to withobj
1909 1919 # from its old 'with' name.
1910 1920 def with_obj(object, **args):
1911 1921 """Set multiple attributes for an object, similar to Pascal's with.
1912 1922
1913 1923 Example:
1914 1924 with_obj(jim,
1915 1925 born = 1960,
1916 1926 haircolour = 'Brown',
1917 1927 eyecolour = 'Green')
1918 1928
1919 1929 Credit: Greg Ewing, in
1920 1930 http://mail.python.org/pipermail/python-list/2001-May/040703.html.
1921 1931
1922 1932 NOTE: up until IPython 0.7.2, this was called simply 'with', but 'with'
1923 1933 has become a keyword for Python 2.5, so we had to rename it."""
1924 1934
1925 1935 object.__dict__.update(args)
1926 1936
1927 1937 #----------------------------------------------------------------------------
1928 1938 def setattr_list(obj,alist,nspace = None):
1929 1939 """Set a list of attributes for an object taken from a namespace.
1930 1940
1931 1941 setattr_list(obj,alist,nspace) -> sets in obj all the attributes listed in
1932 1942 alist with their values taken from nspace, which must be a dict (something
1933 1943 like locals() will often do) If nspace isn't given, locals() of the
1934 1944 *caller* is used, so in most cases you can omit it.
1935 1945
1936 1946 Note that alist can be given as a string, which will be automatically
1937 1947 split into a list on whitespace. If given as a list, it must be a list of
1938 1948 *strings* (the variable names themselves), not of variables."""
1939 1949
1940 1950 # this grabs the local variables from the *previous* call frame -- that is
1941 1951 # the locals from the function that called setattr_list().
1942 1952 # - snipped from weave.inline()
1943 1953 if nspace is None:
1944 1954 call_frame = sys._getframe().f_back
1945 1955 nspace = call_frame.f_locals
1946 1956
1947 1957 if type(alist) in StringTypes:
1948 1958 alist = alist.split()
1949 1959 for attr in alist:
1950 1960 val = eval(attr,nspace)
1951 1961 setattr(obj,attr,val)
1952 1962
1953 1963 #----------------------------------------------------------------------------
1954 1964 def getattr_list(obj,alist,*args):
1955 1965 """getattr_list(obj,alist[, default]) -> attribute list.
1956 1966
1957 1967 Get a list of named attributes for an object. When a default argument is
1958 1968 given, it is returned when the attribute doesn't exist; without it, an
1959 1969 exception is raised in that case.
1960 1970
1961 1971 Note that alist can be given as a string, which will be automatically
1962 1972 split into a list on whitespace. If given as a list, it must be a list of
1963 1973 *strings* (the variable names themselves), not of variables."""
1964 1974
1965 1975 if type(alist) in StringTypes:
1966 1976 alist = alist.split()
1967 1977 if args:
1968 1978 if len(args)==1:
1969 1979 default = args[0]
1970 1980 return map(lambda attr: getattr(obj,attr,default),alist)
1971 1981 else:
1972 1982 raise ValueError,'getattr_list() takes only one optional argument'
1973 1983 else:
1974 1984 return map(lambda attr: getattr(obj,attr),alist)
1975 1985
1976 1986 #----------------------------------------------------------------------------
1977 1987 def map_method(method,object_list,*argseq,**kw):
1978 1988 """map_method(method,object_list,*args,**kw) -> list
1979 1989
1980 1990 Return a list of the results of applying the methods to the items of the
1981 1991 argument sequence(s). If more than one sequence is given, the method is
1982 1992 called with an argument list consisting of the corresponding item of each
1983 1993 sequence. All sequences must be of the same length.
1984 1994
1985 1995 Keyword arguments are passed verbatim to all objects called.
1986 1996
1987 1997 This is Python code, so it's not nearly as fast as the builtin map()."""
1988 1998
1989 1999 out_list = []
1990 2000 idx = 0
1991 2001 for object in object_list:
1992 2002 try:
1993 2003 handler = getattr(object, method)
1994 2004 except AttributeError:
1995 2005 out_list.append(None)
1996 2006 else:
1997 2007 if argseq:
1998 2008 args = map(lambda lst:lst[idx],argseq)
1999 2009 #print 'ob',object,'hand',handler,'ar',args # dbg
2000 2010 out_list.append(handler(args,**kw))
2001 2011 else:
2002 2012 out_list.append(handler(**kw))
2003 2013 idx += 1
2004 2014 return out_list
2005 2015
2006 2016 #----------------------------------------------------------------------------
2007 2017 def get_class_members(cls):
2008 2018 ret = dir(cls)
2009 2019 if hasattr(cls,'__bases__'):
2010 2020 for base in cls.__bases__:
2011 2021 ret.extend(get_class_members(base))
2012 2022 return ret
2013 2023
2014 2024 #----------------------------------------------------------------------------
2015 2025 def dir2(obj):
2016 2026 """dir2(obj) -> list of strings
2017 2027
2018 2028 Extended version of the Python builtin dir(), which does a few extra
2019 2029 checks, and supports common objects with unusual internals that confuse
2020 2030 dir(), such as Traits and PyCrust.
2021 2031
2022 2032 This version is guaranteed to return only a list of true strings, whereas
2023 2033 dir() returns anything that objects inject into themselves, even if they
2024 2034 are later not really valid for attribute access (many extension libraries
2025 2035 have such bugs).
2026 2036 """
2027 2037
2028 2038 # Start building the attribute list via dir(), and then complete it
2029 2039 # with a few extra special-purpose calls.
2030 2040 words = dir(obj)
2031 2041
2032 2042 if hasattr(obj,'__class__'):
2033 2043 words.append('__class__')
2034 2044 words.extend(get_class_members(obj.__class__))
2035 2045 #if '__base__' in words: 1/0
2036 2046
2037 2047 # Some libraries (such as traits) may introduce duplicates, we want to
2038 2048 # track and clean this up if it happens
2039 2049 may_have_dupes = False
2040 2050
2041 2051 # this is the 'dir' function for objects with Enthought's traits
2042 2052 if hasattr(obj, 'trait_names'):
2043 2053 try:
2044 2054 words.extend(obj.trait_names())
2045 2055 may_have_dupes = True
2046 2056 except TypeError:
2047 2057 # This will happen if `obj` is a class and not an instance.
2048 2058 pass
2049 2059
2050 2060 # Support for PyCrust-style _getAttributeNames magic method.
2051 2061 if hasattr(obj, '_getAttributeNames'):
2052 2062 try:
2053 2063 words.extend(obj._getAttributeNames())
2054 2064 may_have_dupes = True
2055 2065 except TypeError:
2056 2066 # `obj` is a class and not an instance. Ignore
2057 2067 # this error.
2058 2068 pass
2059 2069
2060 2070 if may_have_dupes:
2061 2071 # eliminate possible duplicates, as some traits may also
2062 2072 # appear as normal attributes in the dir() call.
2063 2073 words = list(set(words))
2064 2074 words.sort()
2065 2075
2066 2076 # filter out non-string attributes which may be stuffed by dir() calls
2067 2077 # and poor coding in third-party modules
2068 2078 return [w for w in words if isinstance(w, basestring)]
2069 2079
2070 2080 #----------------------------------------------------------------------------
2071 2081 def import_fail_info(mod_name,fns=None):
2072 2082 """Inform load failure for a module."""
2073 2083
2074 2084 if fns == None:
2075 2085 warn("Loading of %s failed.\n" % (mod_name,))
2076 2086 else:
2077 2087 warn("Loading of %s from %s failed.\n" % (fns,mod_name))
2078 2088
2079 2089 #----------------------------------------------------------------------------
2080 2090 # Proposed popitem() extension, written as a method
2081 2091
2082 2092
2083 2093 class NotGiven: pass
2084 2094
2085 2095 def popkey(dct,key,default=NotGiven):
2086 2096 """Return dct[key] and delete dct[key].
2087 2097
2088 2098 If default is given, return it if dct[key] doesn't exist, otherwise raise
2089 2099 KeyError. """
2090 2100
2091 2101 try:
2092 2102 val = dct[key]
2093 2103 except KeyError:
2094 2104 if default is NotGiven:
2095 2105 raise
2096 2106 else:
2097 2107 return default
2098 2108 else:
2099 2109 del dct[key]
2100 2110 return val
2101 2111
2102 2112 def wrap_deprecated(func, suggest = '<nothing>'):
2103 2113 def newFunc(*args, **kwargs):
2104 2114 warnings.warn("Call to deprecated function %s, use %s instead" %
2105 2115 ( func.__name__, suggest),
2106 2116 category=DeprecationWarning,
2107 2117 stacklevel = 2)
2108 2118 return func(*args, **kwargs)
2109 2119 return newFunc
2110 2120
2111 2121
2112 2122 def _num_cpus_unix():
2113 2123 """Return the number of active CPUs on a Unix system."""
2114 2124 return os.sysconf("SC_NPROCESSORS_ONLN")
2115 2125
2116 2126
2117 2127 def _num_cpus_darwin():
2118 2128 """Return the number of active CPUs on a Darwin system."""
2119 2129 p = subprocess.Popen(['sysctl','-n','hw.ncpu'],stdout=subprocess.PIPE)
2120 2130 return p.stdout.read()
2121 2131
2122 2132
2123 2133 def _num_cpus_windows():
2124 2134 """Return the number of active CPUs on a Windows system."""
2125 2135 return os.environ.get("NUMBER_OF_PROCESSORS")
2126 2136
2127 2137
2128 2138 def num_cpus():
2129 2139 """Return the effective number of CPUs in the system as an integer.
2130 2140
2131 2141 This cross-platform function makes an attempt at finding the total number of
2132 2142 available CPUs in the system, as returned by various underlying system and
2133 2143 python calls.
2134 2144
2135 2145 If it can't find a sensible answer, it returns 1 (though an error *may* make
2136 2146 it return a large positive number that's actually incorrect).
2137 2147 """
2138 2148
2139 2149 # Many thanks to the Parallel Python project (http://www.parallelpython.com)
2140 2150 # for the names of the keys we needed to look up for this function. This
2141 2151 # code was inspired by their equivalent function.
2142 2152
2143 2153 ncpufuncs = {'Linux':_num_cpus_unix,
2144 2154 'Darwin':_num_cpus_darwin,
2145 2155 'Windows':_num_cpus_windows,
2146 2156 # On Vista, python < 2.5.2 has a bug and returns 'Microsoft'
2147 2157 # See http://bugs.python.org/issue1082 for details.
2148 2158 'Microsoft':_num_cpus_windows,
2149 2159 }
2150 2160
2151 2161 ncpufunc = ncpufuncs.get(platform.system(),
2152 2162 # default to unix version (Solaris, AIX, etc)
2153 2163 _num_cpus_unix)
2154 2164
2155 2165 try:
2156 2166 ncpus = max(1,int(ncpufunc()))
2157 2167 except:
2158 2168 ncpus = 1
2159 2169 return ncpus
2160 2170
2161 2171 #*************************** end of file <genutils.py> **********************
@@ -1,2865 +1,2870 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 IPython -- An enhanced Interactive Python
4 4
5 5 Requires Python 2.4 or newer.
6 6
7 7 This file contains all the classes and helper functions specific to IPython.
8 8 """
9 9
10 10 #*****************************************************************************
11 11 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and
12 12 # Copyright (C) 2001-2006 Fernando Perez. <fperez@colorado.edu>
13 13 #
14 14 # Distributed under the terms of the BSD License. The full license is in
15 15 # the file COPYING, distributed as part of this software.
16 16 #
17 17 # Note: this code originally subclassed code.InteractiveConsole from the
18 18 # Python standard library. Over time, all of that class has been copied
19 19 # verbatim here for modifications which could not be accomplished by
20 20 # subclassing. At this point, there are no dependencies at all on the code
21 21 # module anymore (it is not even imported). The Python License (sec. 2)
22 22 # allows for this, but it's always nice to acknowledge credit where credit is
23 23 # due.
24 24 #*****************************************************************************
25 25
26 26 #****************************************************************************
27 27 # Modules and globals
28 28
29 29 # Python standard modules
30 30 import __main__
31 31 import __builtin__
32 32 import StringIO
33 33 import bdb
34 34 import cPickle as pickle
35 35 import codeop
36 36 import exceptions
37 37 import glob
38 38 import inspect
39 39 import keyword
40 40 import new
41 41 import os
42 42 import pydoc
43 43 import re
44 44 import shutil
45 45 import string
46 46 import sys
47 47 import tempfile
48 48 import traceback
49 49 import types
50 50 from pprint import pprint, pformat
51 51
52 52 # IPython's own modules
53 53 #import IPython
54 54 from IPython import Debugger,OInspect,PyColorize,ultraTB
55 55 from IPython.ColorANSI import ColorScheme,ColorSchemeTable # too long names
56 56 from IPython.Extensions import pickleshare
57 57 from IPython.FakeModule import FakeModule, init_fakemod_dict
58 58 from IPython.Itpl import Itpl,itpl,printpl,ItplNS,itplns
59 59 from IPython.Logger import Logger
60 60 from IPython.Magic import Magic
61 61 from IPython.Prompts import CachedOutput
62 62 from IPython.ipstruct import Struct
63 63 from IPython.background_jobs import BackgroundJobManager
64 64 from IPython.usage import cmd_line_usage,interactive_usage
65 65 from IPython.genutils import *
66 66 from IPython.strdispatch import StrDispatch
67 67 import IPython.ipapi
68 68 import IPython.history
69 69 import IPython.prefilter as prefilter
70 70 import IPython.shadowns
71 71 # Globals
72 72
73 73 # store the builtin raw_input globally, and use this always, in case user code
74 74 # overwrites it (like wx.py.PyShell does)
75 75 raw_input_original = raw_input
76 76
77 77 # compiled regexps for autoindent management
78 78 dedent_re = re.compile(r'^\s+raise|^\s+return|^\s+pass')
79 79
80 80
81 81 #****************************************************************************
82 82 # Some utility function definitions
83 83
84 84 ini_spaces_re = re.compile(r'^(\s+)')
85 85
86 86 def num_ini_spaces(strng):
87 87 """Return the number of initial spaces in a string"""
88 88
89 89 ini_spaces = ini_spaces_re.match(strng)
90 90 if ini_spaces:
91 91 return ini_spaces.end()
92 92 else:
93 93 return 0
94 94
95 95 def softspace(file, newvalue):
96 96 """Copied from code.py, to remove the dependency"""
97 97
98 98 oldvalue = 0
99 99 try:
100 100 oldvalue = file.softspace
101 101 except AttributeError:
102 102 pass
103 103 try:
104 104 file.softspace = newvalue
105 105 except (AttributeError, TypeError):
106 106 # "attribute-less object" or "read-only attributes"
107 107 pass
108 108 return oldvalue
109 109
110 110
111 111 def user_setup(ipythondir,rc_suffix,mode='install',interactive=True):
112 112 """Install or upgrade the user configuration directory.
113 113
114 114 Can be called when running for the first time or to upgrade the user's
115 115 .ipython/ directory.
116 116
117 117 Parameters
118 118 ----------
119 119 ipythondir : path
120 120 The directory to be used for installation/upgrade. In 'install' mode,
121 121 if this path already exists, the function exits immediately.
122 122
123 123 rc_suffix : str
124 124 Extension for the config files. On *nix platforms it is typically the
125 125 empty string, while Windows normally uses '.ini'.
126 126
127 127 mode : str, optional
128 128 Valid modes are 'install' and 'upgrade'.
129 129
130 130 interactive : bool, optional
131 131 If False, do not wait for user input on any errors. Normally after
132 132 printing its status information, this function waits for the user to
133 133 hit Return before proceeding. This is because the default use case is
134 134 when first installing the IPython configuration, so we want the user to
135 135 acknowledge the initial message, which contains some useful
136 136 information.
137 137 """
138 138
139 139 # For automatic use, deactivate all i/o
140 140 if interactive:
141 141 def wait():
142 142 try:
143 143 raw_input("Please press <RETURN> to start IPython.")
144 144 except EOFError:
145 145 print >> Term.cout
146 146 print '*'*70
147 147
148 148 def printf(s):
149 149 print s
150 150 else:
151 151 wait = lambda : None
152 152 printf = lambda s : None
153 153
154 154 # Install mode should be re-entrant: if the install dir already exists,
155 # bail out cleanly
155 # bail out cleanly.
156 # XXX. This is too hasty to return. We need to check to make sure that
157 # all the expected config files and directories are actually there. We
158 # currently have a failure mode if someone deletes a needed config file
159 # but still has the ipythondir.
156 160 if mode == 'install' and os.path.isdir(ipythondir):
157 161 return
158 162
159 163 cwd = os.getcwd() # remember where we started
160 164 glb = glob.glob
161 165
162 166 printf('*'*70)
163 167 if mode == 'install':
164 168 printf(
165 169 """Welcome to IPython. I will try to create a personal configuration directory
166 170 where you can customize many aspects of IPython's functionality in:\n""")
167 171 else:
168 172 printf('I am going to upgrade your configuration in:')
169 173
170 174 printf(ipythondir)
171 175
172 176 rcdirend = os.path.join('IPython','UserConfig')
173 177 cfg = lambda d: os.path.join(d,rcdirend)
174 178 try:
175 179 rcdir = filter(os.path.isdir,map(cfg,sys.path))[0]
176 180 printf("Initializing from configuration: %s" % rcdir)
177 181 except IndexError:
178 182 warning = """
179 183 Installation error. IPython's directory was not found.
180 184
181 185 Check the following:
182 186
183 187 The ipython/IPython directory should be in a directory belonging to your
184 188 PYTHONPATH environment variable (that is, it should be in a directory
185 189 belonging to sys.path). You can copy it explicitly there or just link to it.
186 190
187 191 IPython will create a minimal default configuration for you.
188 192
189 193 """
190 194 warn(warning)
191 195 wait()
192 196
193 197 if sys.platform =='win32':
194 198 inif = 'ipythonrc.ini'
195 199 else:
196 200 inif = 'ipythonrc'
197 201 minimal_setup = {'ipy_user_conf.py' : 'import ipy_defaults',
198 202 inif : '# intentionally left blank' }
199 203 os.makedirs(ipythondir, mode = 0777)
200 204 for f, cont in minimal_setup.items():
201 205 # In 2.5, this can be more cleanly done using 'with'
202 206 fobj = file(ipythondir + '/' + f,'w')
203 207 fobj.write(cont)
204 208 fobj.close()
205 209
206 210 return
207 211
208 212 if mode == 'install':
209 213 try:
210 214 shutil.copytree(rcdir,ipythondir)
211 215 os.chdir(ipythondir)
212 216 rc_files = glb("ipythonrc*")
213 217 for rc_file in rc_files:
214 218 os.rename(rc_file,rc_file+rc_suffix)
215 219 except:
216 220 warning = """
217 221
218 222 There was a problem with the installation:
219 223 %s
220 224 Try to correct it or contact the developers if you think it's a bug.
221 225 IPython will proceed with builtin defaults.""" % sys.exc_info()[1]
222 226 warn(warning)
223 227 wait()
224 228 return
225 229
226 230 elif mode == 'upgrade':
227 231 try:
228 232 os.chdir(ipythondir)
229 233 except:
230 234 printf("""
231 235 Can not upgrade: changing to directory %s failed. Details:
232 236 %s
233 237 """ % (ipythondir,sys.exc_info()[1]) )
234 238 wait()
235 239 return
236 240 else:
237 241 sources = glb(os.path.join(rcdir,'[A-Za-z]*'))
238 242 for new_full_path in sources:
239 243 new_filename = os.path.basename(new_full_path)
240 244 if new_filename.startswith('ipythonrc'):
241 245 new_filename = new_filename + rc_suffix
242 246 # The config directory should only contain files, skip any
243 247 # directories which may be there (like CVS)
244 248 if os.path.isdir(new_full_path):
245 249 continue
246 250 if os.path.exists(new_filename):
247 251 old_file = new_filename+'.old'
248 252 if os.path.exists(old_file):
249 253 os.remove(old_file)
250 254 os.rename(new_filename,old_file)
251 255 shutil.copy(new_full_path,new_filename)
252 256 else:
253 257 raise ValueError('unrecognized mode for install: %r' % mode)
254 258
255 259 # Fix line-endings to those native to each platform in the config
256 260 # directory.
257 261 try:
258 262 os.chdir(ipythondir)
259 263 except:
260 264 printf("""
261 265 Problem: changing to directory %s failed.
262 266 Details:
263 267 %s
264 268
265 269 Some configuration files may have incorrect line endings. This should not
266 270 cause any problems during execution. """ % (ipythondir,sys.exc_info()[1]) )
267 271 wait()
268 272 else:
269 273 for fname in glb('ipythonrc*'):
270 274 try:
271 275 native_line_ends(fname,backup=0)
272 276 except IOError:
273 277 pass
274 278
275 279 if mode == 'install':
276 280 printf("""
277 281 Successful installation!
278 282
279 283 Please read the sections 'Initial Configuration' and 'Quick Tips' in the
280 284 IPython manual (there are both HTML and PDF versions supplied with the
281 285 distribution) to make sure that your system environment is properly configured
282 286 to take advantage of IPython's features.
283 287
284 288 Important note: the configuration system has changed! The old system is
285 289 still in place, but its setting may be partly overridden by the settings in
286 290 "~/.ipython/ipy_user_conf.py" config file. Please take a look at the file
287 291 if some of the new settings bother you.
288 292
289 293 """)
290 294 else:
291 295 printf("""
292 296 Successful upgrade!
293 297
294 298 All files in your directory:
295 299 %(ipythondir)s
296 300 which would have been overwritten by the upgrade were backed up with a .old
297 301 extension. If you had made particular customizations in those files you may
298 302 want to merge them back into the new files.""" % locals() )
299 303 wait()
300 304 os.chdir(cwd)
301 305
302 306 #****************************************************************************
303 307 # Local use exceptions
304 308 class SpaceInInput(exceptions.Exception): pass
305 309
306 310
307 311 #****************************************************************************
308 312 # Local use classes
309 313 class Bunch: pass
310 314
311 315 class Undefined: pass
312 316
313 317 class Quitter(object):
314 318 """Simple class to handle exit, similar to Python 2.5's.
315 319
316 320 It handles exiting in an ipython-safe manner, which the one in Python 2.5
317 321 doesn't do (obviously, since it doesn't know about ipython)."""
318 322
319 323 def __init__(self,shell,name):
320 324 self.shell = shell
321 325 self.name = name
322 326
323 327 def __repr__(self):
324 328 return 'Type %s() to exit.' % self.name
325 329 __str__ = __repr__
326 330
327 331 def __call__(self):
328 332 self.shell.exit()
329 333
330 334 class InputList(list):
331 335 """Class to store user input.
332 336
333 337 It's basically a list, but slices return a string instead of a list, thus
334 338 allowing things like (assuming 'In' is an instance):
335 339
336 340 exec In[4:7]
337 341
338 342 or
339 343
340 344 exec In[5:9] + In[14] + In[21:25]"""
341 345
342 346 def __getslice__(self,i,j):
343 347 return ''.join(list.__getslice__(self,i,j))
344 348
345 349 class SyntaxTB(ultraTB.ListTB):
346 350 """Extension which holds some state: the last exception value"""
347 351
348 352 def __init__(self,color_scheme = 'NoColor'):
349 353 ultraTB.ListTB.__init__(self,color_scheme)
350 354 self.last_syntax_error = None
351 355
352 356 def __call__(self, etype, value, elist):
353 357 self.last_syntax_error = value
354 358 ultraTB.ListTB.__call__(self,etype,value,elist)
355 359
356 360 def clear_err_state(self):
357 361 """Return the current error state and clear it"""
358 362 e = self.last_syntax_error
359 363 self.last_syntax_error = None
360 364 return e
361 365
362 366 #****************************************************************************
363 367 # Main IPython class
364 368
365 369 # FIXME: the Magic class is a mixin for now, and will unfortunately remain so
366 370 # until a full rewrite is made. I've cleaned all cross-class uses of
367 371 # attributes and methods, but too much user code out there relies on the
368 372 # equlity %foo == __IP.magic_foo, so I can't actually remove the mixin usage.
369 373 #
370 374 # But at least now, all the pieces have been separated and we could, in
371 375 # principle, stop using the mixin. This will ease the transition to the
372 376 # chainsaw branch.
373 377
374 378 # For reference, the following is the list of 'self.foo' uses in the Magic
375 379 # class as of 2005-12-28. These are names we CAN'T use in the main ipython
376 380 # class, to prevent clashes.
377 381
378 382 # ['self.__class__', 'self.__dict__', 'self._inspect', 'self._ofind',
379 383 # 'self.arg_err', 'self.extract_input', 'self.format_', 'self.lsmagic',
380 384 # 'self.magic_', 'self.options_table', 'self.parse', 'self.shell',
381 385 # 'self.value']
382 386
383 387 class InteractiveShell(object,Magic):
384 388 """An enhanced console for Python."""
385 389
386 390 # class attribute to indicate whether the class supports threads or not.
387 391 # Subclasses with thread support should override this as needed.
388 392 isthreaded = False
389 393
390 394 def __init__(self,name,usage=None,rc=Struct(opts=None,args=None),
391 395 user_ns=None,user_global_ns=None,banner2='',
392 396 custom_exceptions=((),None),embedded=False):
393 397
394 398 # log system
395 399 self.logger = Logger(self,logfname='ipython_log.py',logmode='rotate')
396 400
397 401 # Job manager (for jobs run as background threads)
398 402 self.jobs = BackgroundJobManager()
399 403
400 404 # Store the actual shell's name
401 405 self.name = name
402 406 self.more = False
403 407
404 408 # We need to know whether the instance is meant for embedding, since
405 409 # global/local namespaces need to be handled differently in that case
406 410 self.embedded = embedded
407 411 if embedded:
408 412 # Control variable so users can, from within the embedded instance,
409 413 # permanently deactivate it.
410 414 self.embedded_active = True
411 415
412 416 # command compiler
413 417 self.compile = codeop.CommandCompiler()
414 418
415 419 # User input buffer
416 420 self.buffer = []
417 421
418 422 # Default name given in compilation of code
419 423 self.filename = '<ipython console>'
420 424
421 425 # Install our own quitter instead of the builtins. For python2.3-2.4,
422 426 # this brings in behavior like 2.5, and for 2.5 it's identical.
423 427 __builtin__.exit = Quitter(self,'exit')
424 428 __builtin__.quit = Quitter(self,'quit')
425 429
426 430 # Make an empty namespace, which extension writers can rely on both
427 431 # existing and NEVER being used by ipython itself. This gives them a
428 432 # convenient location for storing additional information and state
429 433 # their extensions may require, without fear of collisions with other
430 434 # ipython names that may develop later.
431 435 self.meta = Struct()
432 436
433 437 # Create the namespace where the user will operate. user_ns is
434 438 # normally the only one used, and it is passed to the exec calls as
435 439 # the locals argument. But we do carry a user_global_ns namespace
436 440 # given as the exec 'globals' argument, This is useful in embedding
437 441 # situations where the ipython shell opens in a context where the
438 442 # distinction between locals and globals is meaningful. For
439 443 # non-embedded contexts, it is just the same object as the user_ns dict.
440 444
441 445 # FIXME. For some strange reason, __builtins__ is showing up at user
442 446 # level as a dict instead of a module. This is a manual fix, but I
443 447 # should really track down where the problem is coming from. Alex
444 448 # Schmolck reported this problem first.
445 449
446 450 # A useful post by Alex Martelli on this topic:
447 451 # Re: inconsistent value from __builtins__
448 452 # Von: Alex Martelli <aleaxit@yahoo.com>
449 453 # Datum: Freitag 01 Oktober 2004 04:45:34 nachmittags/abends
450 454 # Gruppen: comp.lang.python
451 455
452 456 # Michael Hohn <hohn@hooknose.lbl.gov> wrote:
453 457 # > >>> print type(builtin_check.get_global_binding('__builtins__'))
454 458 # > <type 'dict'>
455 459 # > >>> print type(__builtins__)
456 460 # > <type 'module'>
457 461 # > Is this difference in return value intentional?
458 462
459 463 # Well, it's documented that '__builtins__' can be either a dictionary
460 464 # or a module, and it's been that way for a long time. Whether it's
461 465 # intentional (or sensible), I don't know. In any case, the idea is
462 466 # that if you need to access the built-in namespace directly, you
463 467 # should start with "import __builtin__" (note, no 's') which will
464 468 # definitely give you a module. Yeah, it's somewhat confusing:-(.
465 469
466 470 # These routines return properly built dicts as needed by the rest of
467 471 # the code, and can also be used by extension writers to generate
468 472 # properly initialized namespaces.
469 473 user_ns, user_global_ns = IPython.ipapi.make_user_namespaces(user_ns,
470 474 user_global_ns)
471 475
472 476 # Assign namespaces
473 477 # This is the namespace where all normal user variables live
474 478 self.user_ns = user_ns
475 479 self.user_global_ns = user_global_ns
476 480
477 481 # An auxiliary namespace that checks what parts of the user_ns were
478 482 # loaded at startup, so we can list later only variables defined in
479 483 # actual interactive use. Since it is always a subset of user_ns, it
480 484 # doesn't need to be seaparately tracked in the ns_table
481 485 self.user_config_ns = {}
482 486
483 487 # A namespace to keep track of internal data structures to prevent
484 488 # them from cluttering user-visible stuff. Will be updated later
485 489 self.internal_ns = {}
486 490
487 491 # Namespace of system aliases. Each entry in the alias
488 492 # table must be a 2-tuple of the form (N,name), where N is the number
489 493 # of positional arguments of the alias.
490 494 self.alias_table = {}
491 495
492 496 # Now that FakeModule produces a real module, we've run into a nasty
493 497 # problem: after script execution (via %run), the module where the user
494 498 # code ran is deleted. Now that this object is a true module (needed
495 499 # so docetst and other tools work correctly), the Python module
496 500 # teardown mechanism runs over it, and sets to None every variable
497 501 # present in that module. Top-level references to objects from the
498 502 # script survive, because the user_ns is updated with them. However,
499 503 # calling functions defined in the script that use other things from
500 504 # the script will fail, because the function's closure had references
501 505 # to the original objects, which are now all None. So we must protect
502 506 # these modules from deletion by keeping a cache.
503 507 #
504 508 # To avoid keeping stale modules around (we only need the one from the
505 509 # last run), we use a dict keyed with the full path to the script, so
506 510 # only the last version of the module is held in the cache. Note,
507 511 # however, that we must cache the module *namespace contents* (their
508 512 # __dict__). Because if we try to cache the actual modules, old ones
509 513 # (uncached) could be destroyed while still holding references (such as
510 514 # those held by GUI objects that tend to be long-lived)>
511 515 #
512 516 # The %reset command will flush this cache. See the cache_main_mod()
513 517 # and clear_main_mod_cache() methods for details on use.
514 518
515 519 # This is the cache used for 'main' namespaces
516 520 self._main_ns_cache = {}
517 521 # And this is the single instance of FakeModule whose __dict__ we keep
518 522 # copying and clearing for reuse on each %run
519 523 self._user_main_module = FakeModule()
520 524
521 525 # A table holding all the namespaces IPython deals with, so that
522 526 # introspection facilities can search easily.
523 527 self.ns_table = {'user':user_ns,
524 528 'user_global':user_global_ns,
525 529 'alias':self.alias_table,
526 530 'internal':self.internal_ns,
527 531 'builtin':__builtin__.__dict__
528 532 }
529 533
530 534 # Similarly, track all namespaces where references can be held and that
531 535 # we can safely clear (so it can NOT include builtin). This one can be
532 536 # a simple list.
533 537 self.ns_refs_table = [ user_ns, user_global_ns, self.user_config_ns,
534 538 self.alias_table, self.internal_ns,
535 539 self._main_ns_cache ]
536 540
537 541 # We need to insert into sys.modules something that looks like a
538 542 # module but which accesses the IPython namespace, for shelve and
539 543 # pickle to work interactively. Normally they rely on getting
540 544 # everything out of __main__, but for embedding purposes each IPython
541 545 # instance has its own private namespace, so we can't go shoving
542 546 # everything into __main__.
543 547
544 548 # note, however, that we should only do this for non-embedded
545 549 # ipythons, which really mimic the __main__.__dict__ with their own
546 550 # namespace. Embedded instances, on the other hand, should not do
547 551 # this because they need to manage the user local/global namespaces
548 552 # only, but they live within a 'normal' __main__ (meaning, they
549 553 # shouldn't overtake the execution environment of the script they're
550 554 # embedded in).
551 555
552 556 if not embedded:
553 557 try:
554 558 main_name = self.user_ns['__name__']
555 559 except KeyError:
556 560 raise KeyError,'user_ns dictionary MUST have a "__name__" key'
557 561 else:
558 562 #print "pickle hack in place" # dbg
559 563 #print 'main_name:',main_name # dbg
560 564 sys.modules[main_name] = FakeModule(self.user_ns)
561 565
562 566 # List of input with multi-line handling.
563 567 self.input_hist = InputList()
564 568 # This one will hold the 'raw' input history, without any
565 569 # pre-processing. This will allow users to retrieve the input just as
566 570 # it was exactly typed in by the user, with %hist -r.
567 571 self.input_hist_raw = InputList()
568 572
569 573 # list of visited directories
570 574 try:
571 575 self.dir_hist = [os.getcwd()]
572 576 except OSError:
573 577 self.dir_hist = []
574 578
575 579 # dict of output history
576 580 self.output_hist = {}
577 581
578 582 # Get system encoding at startup time. Certain terminals (like Emacs
579 583 # under Win32 have it set to None, and we need to have a known valid
580 584 # encoding to use in the raw_input() method
581 585 try:
582 586 self.stdin_encoding = sys.stdin.encoding or 'ascii'
583 587 except AttributeError:
584 588 self.stdin_encoding = 'ascii'
585 589
586 590 # dict of things NOT to alias (keywords, builtins and some magics)
587 591 no_alias = {}
588 592 no_alias_magics = ['cd','popd','pushd','dhist','alias','unalias']
589 593 for key in keyword.kwlist + no_alias_magics:
590 594 no_alias[key] = 1
591 595 no_alias.update(__builtin__.__dict__)
592 596 self.no_alias = no_alias
593 597
594 598 # Object variable to store code object waiting execution. This is
595 599 # used mainly by the multithreaded shells, but it can come in handy in
596 600 # other situations. No need to use a Queue here, since it's a single
597 601 # item which gets cleared once run.
598 602 self.code_to_run = None
599 603
600 604 # escapes for automatic behavior on the command line
601 605 self.ESC_SHELL = '!'
602 606 self.ESC_SH_CAP = '!!'
603 607 self.ESC_HELP = '?'
604 608 self.ESC_MAGIC = '%'
605 609 self.ESC_QUOTE = ','
606 610 self.ESC_QUOTE2 = ';'
607 611 self.ESC_PAREN = '/'
608 612
609 613 # And their associated handlers
610 614 self.esc_handlers = {self.ESC_PAREN : self.handle_auto,
611 615 self.ESC_QUOTE : self.handle_auto,
612 616 self.ESC_QUOTE2 : self.handle_auto,
613 617 self.ESC_MAGIC : self.handle_magic,
614 618 self.ESC_HELP : self.handle_help,
615 619 self.ESC_SHELL : self.handle_shell_escape,
616 620 self.ESC_SH_CAP : self.handle_shell_escape,
617 621 }
618 622
619 623 # class initializations
620 624 Magic.__init__(self,self)
621 625
622 626 # Python source parser/formatter for syntax highlighting
623 627 pyformat = PyColorize.Parser().format
624 628 self.pycolorize = lambda src: pyformat(src,'str',self.rc['colors'])
625 629
626 630 # hooks holds pointers used for user-side customizations
627 631 self.hooks = Struct()
628 632
629 633 self.strdispatchers = {}
630 634
631 635 # Set all default hooks, defined in the IPython.hooks module.
632 636 hooks = IPython.hooks
633 637 for hook_name in hooks.__all__:
634 638 # default hooks have priority 100, i.e. low; user hooks should have
635 639 # 0-100 priority
636 640 self.set_hook(hook_name,getattr(hooks,hook_name), 100)
637 641 #print "bound hook",hook_name
638 642
639 643 # Flag to mark unconditional exit
640 644 self.exit_now = False
641 645
642 646 self.usage_min = """\
643 647 An enhanced console for Python.
644 648 Some of its features are:
645 649 - Readline support if the readline library is present.
646 650 - Tab completion in the local namespace.
647 651 - Logging of input, see command-line options.
648 652 - System shell escape via ! , eg !ls.
649 653 - Magic commands, starting with a % (like %ls, %pwd, %cd, etc.)
650 654 - Keeps track of locally defined variables via %who, %whos.
651 655 - Show object information with a ? eg ?x or x? (use ?? for more info).
652 656 """
653 657 if usage: self.usage = usage
654 658 else: self.usage = self.usage_min
655 659
656 660 # Storage
657 661 self.rc = rc # This will hold all configuration information
658 662 self.pager = 'less'
659 663 # temporary files used for various purposes. Deleted at exit.
660 664 self.tempfiles = []
661 665
662 666 # Keep track of readline usage (later set by init_readline)
663 667 self.has_readline = False
664 668
665 669 # template for logfile headers. It gets resolved at runtime by the
666 670 # logstart method.
667 671 self.loghead_tpl = \
668 672 """#log# Automatic Logger file. *** THIS MUST BE THE FIRST LINE ***
669 673 #log# DO NOT CHANGE THIS LINE OR THE TWO BELOW
670 674 #log# opts = %s
671 675 #log# args = %s
672 676 #log# It is safe to make manual edits below here.
673 677 #log#-----------------------------------------------------------------------
674 678 """
675 679 # for pushd/popd management
676 680 try:
677 681 self.home_dir = get_home_dir()
678 682 except HomeDirError,msg:
679 683 fatal(msg)
680 684
681 685 self.dir_stack = []
682 686
683 687 # Functions to call the underlying shell.
684 688
685 689 # The first is similar to os.system, but it doesn't return a value,
686 690 # and it allows interpolation of variables in the user's namespace.
687 691 self.system = lambda cmd: \
688 692 self.hooks.shell_hook(self.var_expand(cmd,depth=2))
689 693
690 694 # These are for getoutput and getoutputerror:
691 695 self.getoutput = lambda cmd: \
692 696 getoutput(self.var_expand(cmd,depth=2),
693 697 header=self.rc.system_header,
694 698 verbose=self.rc.system_verbose)
695 699
696 700 self.getoutputerror = lambda cmd: \
697 701 getoutputerror(self.var_expand(cmd,depth=2),
698 702 header=self.rc.system_header,
699 703 verbose=self.rc.system_verbose)
700 704
701 705
702 706 # keep track of where we started running (mainly for crash post-mortem)
703 707 self.starting_dir = os.getcwd()
704 708
705 709 # Various switches which can be set
706 710 self.CACHELENGTH = 5000 # this is cheap, it's just text
707 711 self.BANNER = "Python %(version)s on %(platform)s\n" % sys.__dict__
708 712 self.banner2 = banner2
709 713
710 714 # TraceBack handlers:
711 715
712 716 # Syntax error handler.
713 717 self.SyntaxTB = SyntaxTB(color_scheme='NoColor')
714 718
715 719 # The interactive one is initialized with an offset, meaning we always
716 720 # want to remove the topmost item in the traceback, which is our own
717 721 # internal code. Valid modes: ['Plain','Context','Verbose']
718 722 self.InteractiveTB = ultraTB.AutoFormattedTB(mode = 'Plain',
719 723 color_scheme='NoColor',
720 724 tb_offset = 1)
721 725
722 726 # IPython itself shouldn't crash. This will produce a detailed
723 727 # post-mortem if it does. But we only install the crash handler for
724 728 # non-threaded shells, the threaded ones use a normal verbose reporter
725 729 # and lose the crash handler. This is because exceptions in the main
726 730 # thread (such as in GUI code) propagate directly to sys.excepthook,
727 731 # and there's no point in printing crash dumps for every user exception.
728 732 if self.isthreaded:
729 733 ipCrashHandler = ultraTB.FormattedTB()
730 734 else:
731 735 from IPython import CrashHandler
732 736 ipCrashHandler = CrashHandler.IPythonCrashHandler(self)
733 737 self.set_crash_handler(ipCrashHandler)
734 738
735 739 # and add any custom exception handlers the user may have specified
736 740 self.set_custom_exc(*custom_exceptions)
737 741
738 742 # indentation management
739 743 self.autoindent = False
740 744 self.indent_current_nsp = 0
741 745
742 746 # Make some aliases automatically
743 747 # Prepare list of shell aliases to auto-define
744 748 if os.name == 'posix':
745 749 auto_alias = ('mkdir mkdir', 'rmdir rmdir',
746 750 'mv mv -i','rm rm -i','cp cp -i',
747 751 'cat cat','less less','clear clear',
748 752 # a better ls
749 753 'ls ls -F',
750 754 # long ls
751 755 'll ls -lF')
752 756 # Extra ls aliases with color, which need special treatment on BSD
753 757 # variants
754 758 ls_extra = ( # color ls
755 759 'lc ls -F -o --color',
756 760 # ls normal files only
757 761 'lf ls -F -o --color %l | grep ^-',
758 762 # ls symbolic links
759 763 'lk ls -F -o --color %l | grep ^l',
760 764 # directories or links to directories,
761 765 'ldir ls -F -o --color %l | grep /$',
762 766 # things which are executable
763 767 'lx ls -F -o --color %l | grep ^-..x',
764 768 )
765 769 # The BSDs don't ship GNU ls, so they don't understand the
766 770 # --color switch out of the box
767 771 if 'bsd' in sys.platform:
768 772 ls_extra = ( # ls normal files only
769 773 'lf ls -lF | grep ^-',
770 774 # ls symbolic links
771 775 'lk ls -lF | grep ^l',
772 776 # directories or links to directories,
773 777 'ldir ls -lF | grep /$',
774 778 # things which are executable
775 779 'lx ls -lF | grep ^-..x',
776 780 )
777 781 auto_alias = auto_alias + ls_extra
778 782 elif os.name in ['nt','dos']:
779 783 auto_alias = ('ls dir /on',
780 784 'ddir dir /ad /on', 'ldir dir /ad /on',
781 785 'mkdir mkdir','rmdir rmdir','echo echo',
782 786 'ren ren','cls cls','copy copy')
783 787 else:
784 788 auto_alias = ()
785 789 self.auto_alias = [s.split(None,1) for s in auto_alias]
786 790
787 791 # Produce a public API instance
788 792 self.api = IPython.ipapi.IPApi(self)
789 793
790 794 # Initialize all user-visible namespaces
791 795 self.init_namespaces()
792 796
793 797 # Call the actual (public) initializer
794 798 self.init_auto_alias()
795 799
796 800 # track which builtins we add, so we can clean up later
797 801 self.builtins_added = {}
798 802 # This method will add the necessary builtins for operation, but
799 803 # tracking what it did via the builtins_added dict.
800 804
801 805 #TODO: remove this, redundant
802 806 self.add_builtins()
803 807 # end __init__
804 808
805 809 def var_expand(self,cmd,depth=0):
806 810 """Expand python variables in a string.
807 811
808 812 The depth argument indicates how many frames above the caller should
809 813 be walked to look for the local namespace where to expand variables.
810 814
811 815 The global namespace for expansion is always the user's interactive
812 816 namespace.
813 817 """
814 818
815 819 return str(ItplNS(cmd,
816 820 self.user_ns, # globals
817 821 # Skip our own frame in searching for locals:
818 822 sys._getframe(depth+1).f_locals # locals
819 823 ))
820 824
821 825 def pre_config_initialization(self):
822 826 """Pre-configuration init method
823 827
824 828 This is called before the configuration files are processed to
825 829 prepare the services the config files might need.
826 830
827 831 self.rc already has reasonable default values at this point.
828 832 """
829 833 rc = self.rc
830 834 try:
831 835 self.db = pickleshare.PickleShareDB(rc.ipythondir + "/db")
832 836 except exceptions.UnicodeDecodeError:
833 837 print "Your ipythondir can't be decoded to unicode!"
834 838 print "Please set HOME environment variable to something that"
835 839 print r"only has ASCII characters, e.g. c:\home"
836 840 print "Now it is",rc.ipythondir
837 841 sys.exit()
838 842 self.shadowhist = IPython.history.ShadowHist(self.db)
839 843
840 844 def post_config_initialization(self):
841 845 """Post configuration init method
842 846
843 847 This is called after the configuration files have been processed to
844 848 'finalize' the initialization."""
845 849
846 850 rc = self.rc
847 851
848 852 # Object inspector
849 853 self.inspector = OInspect.Inspector(OInspect.InspectColors,
850 854 PyColorize.ANSICodeColors,
851 855 'NoColor',
852 856 rc.object_info_string_level)
853 857
854 858 self.rl_next_input = None
855 859 self.rl_do_indent = False
856 860 # Load readline proper
857 861 if rc.readline:
858 862 self.init_readline()
859 863
860 864 # local shortcut, this is used a LOT
861 865 self.log = self.logger.log
862 866
863 867 # Initialize cache, set in/out prompts and printing system
864 868 self.outputcache = CachedOutput(self,
865 869 rc.cache_size,
866 870 rc.pprint,
867 871 input_sep = rc.separate_in,
868 872 output_sep = rc.separate_out,
869 873 output_sep2 = rc.separate_out2,
870 874 ps1 = rc.prompt_in1,
871 875 ps2 = rc.prompt_in2,
872 876 ps_out = rc.prompt_out,
873 877 pad_left = rc.prompts_pad_left)
874 878
875 879 # user may have over-ridden the default print hook:
876 880 try:
877 881 self.outputcache.__class__.display = self.hooks.display
878 882 except AttributeError:
879 883 pass
880 884
881 885 # I don't like assigning globally to sys, because it means when
882 886 # embedding instances, each embedded instance overrides the previous
883 887 # choice. But sys.displayhook seems to be called internally by exec,
884 888 # so I don't see a way around it. We first save the original and then
885 889 # overwrite it.
886 890 self.sys_displayhook = sys.displayhook
887 891 sys.displayhook = self.outputcache
888 892
889 893 # Do a proper resetting of doctest, including the necessary displayhook
890 894 # monkeypatching
891 895 try:
892 896 doctest_reload()
893 897 except ImportError:
894 898 warn("doctest module does not exist.")
895 899
896 900 # Set user colors (don't do it in the constructor above so that it
897 901 # doesn't crash if colors option is invalid)
898 902 self.magic_colors(rc.colors)
899 903
900 904 # Set calling of pdb on exceptions
901 905 self.call_pdb = rc.pdb
902 906
903 907 # Load user aliases
904 908 for alias in rc.alias:
905 909 self.magic_alias(alias)
906 910
907 911 self.hooks.late_startup_hook()
908 912
909 913 for cmd in self.rc.autoexec:
910 914 #print "autoexec>",cmd #dbg
911 915 self.api.runlines(cmd)
912 916
913 917 batchrun = False
914 918 for batchfile in [path(arg) for arg in self.rc.args
915 919 if arg.lower().endswith('.ipy')]:
916 920 if not batchfile.isfile():
917 921 print "No such batch file:", batchfile
918 922 continue
919 923 self.api.runlines(batchfile.text())
920 924 batchrun = True
921 925 # without -i option, exit after running the batch file
922 926 if batchrun and not self.rc.interact:
923 927 self.ask_exit()
924 928
925 929 def init_namespaces(self):
926 930 """Initialize all user-visible namespaces to their minimum defaults.
927 931
928 932 Certain history lists are also initialized here, as they effectively
929 933 act as user namespaces.
930 934
931 935 Note
932 936 ----
933 937 All data structures here are only filled in, they are NOT reset by this
934 938 method. If they were not empty before, data will simply be added to
935 939 therm.
936 940 """
937 941 # The user namespace MUST have a pointer to the shell itself.
938 942 self.user_ns[self.name] = self
939 943
940 944 # Store the public api instance
941 945 self.user_ns['_ip'] = self.api
942 946
943 947 # make global variables for user access to the histories
944 948 self.user_ns['_ih'] = self.input_hist
945 949 self.user_ns['_oh'] = self.output_hist
946 950 self.user_ns['_dh'] = self.dir_hist
947 951
948 952 # user aliases to input and output histories
949 953 self.user_ns['In'] = self.input_hist
950 954 self.user_ns['Out'] = self.output_hist
951 955
952 956 self.user_ns['_sh'] = IPython.shadowns
953 957
954 958 # Fill the history zero entry, user counter starts at 1
955 959 self.input_hist.append('\n')
956 960 self.input_hist_raw.append('\n')
957 961
958 962 def add_builtins(self):
959 963 """Store ipython references into the builtin namespace.
960 964
961 965 Some parts of ipython operate via builtins injected here, which hold a
962 966 reference to IPython itself."""
963 967
964 968 # TODO: deprecate all of these, they are unsafe
965 969 builtins_new = dict(__IPYTHON__ = self,
966 970 ip_set_hook = self.set_hook,
967 971 jobs = self.jobs,
968 972 ipmagic = wrap_deprecated(self.ipmagic,'_ip.magic()'),
969 973 ipalias = wrap_deprecated(self.ipalias),
970 974 ipsystem = wrap_deprecated(self.ipsystem,'_ip.system()'),
971 975 #_ip = self.api
972 976 )
973 977 for biname,bival in builtins_new.items():
974 978 try:
975 979 # store the orignal value so we can restore it
976 980 self.builtins_added[biname] = __builtin__.__dict__[biname]
977 981 except KeyError:
978 982 # or mark that it wasn't defined, and we'll just delete it at
979 983 # cleanup
980 984 self.builtins_added[biname] = Undefined
981 985 __builtin__.__dict__[biname] = bival
982 986
983 987 # Keep in the builtins a flag for when IPython is active. We set it
984 988 # with setdefault so that multiple nested IPythons don't clobber one
985 989 # another. Each will increase its value by one upon being activated,
986 990 # which also gives us a way to determine the nesting level.
987 991 __builtin__.__dict__.setdefault('__IPYTHON__active',0)
988 992
989 993 def clean_builtins(self):
990 994 """Remove any builtins which might have been added by add_builtins, or
991 995 restore overwritten ones to their previous values."""
992 996 for biname,bival in self.builtins_added.items():
993 997 if bival is Undefined:
994 998 del __builtin__.__dict__[biname]
995 999 else:
996 1000 __builtin__.__dict__[biname] = bival
997 1001 self.builtins_added.clear()
998 1002
999 1003 def set_hook(self,name,hook, priority = 50, str_key = None, re_key = None):
1000 1004 """set_hook(name,hook) -> sets an internal IPython hook.
1001 1005
1002 1006 IPython exposes some of its internal API as user-modifiable hooks. By
1003 1007 adding your function to one of these hooks, you can modify IPython's
1004 1008 behavior to call at runtime your own routines."""
1005 1009
1006 1010 # At some point in the future, this should validate the hook before it
1007 1011 # accepts it. Probably at least check that the hook takes the number
1008 1012 # of args it's supposed to.
1009 1013
1010 1014 f = new.instancemethod(hook,self,self.__class__)
1011 1015
1012 1016 # check if the hook is for strdispatcher first
1013 1017 if str_key is not None:
1014 1018 sdp = self.strdispatchers.get(name, StrDispatch())
1015 1019 sdp.add_s(str_key, f, priority )
1016 1020 self.strdispatchers[name] = sdp
1017 1021 return
1018 1022 if re_key is not None:
1019 1023 sdp = self.strdispatchers.get(name, StrDispatch())
1020 1024 sdp.add_re(re.compile(re_key), f, priority )
1021 1025 self.strdispatchers[name] = sdp
1022 1026 return
1023 1027
1024 1028 dp = getattr(self.hooks, name, None)
1025 1029 if name not in IPython.hooks.__all__:
1026 1030 print "Warning! Hook '%s' is not one of %s" % (name, IPython.hooks.__all__ )
1027 1031 if not dp:
1028 1032 dp = IPython.hooks.CommandChainDispatcher()
1029 1033
1030 1034 try:
1031 1035 dp.add(f,priority)
1032 1036 except AttributeError:
1033 1037 # it was not commandchain, plain old func - replace
1034 1038 dp = f
1035 1039
1036 1040 setattr(self.hooks,name, dp)
1037 1041
1038 1042
1039 1043 #setattr(self.hooks,name,new.instancemethod(hook,self,self.__class__))
1040 1044
1041 1045 def set_crash_handler(self,crashHandler):
1042 1046 """Set the IPython crash handler.
1043 1047
1044 1048 This must be a callable with a signature suitable for use as
1045 1049 sys.excepthook."""
1046 1050
1047 1051 # Install the given crash handler as the Python exception hook
1048 1052 sys.excepthook = crashHandler
1049 1053
1050 1054 # The instance will store a pointer to this, so that runtime code
1051 1055 # (such as magics) can access it. This is because during the
1052 1056 # read-eval loop, it gets temporarily overwritten (to deal with GUI
1053 1057 # frameworks).
1054 1058 self.sys_excepthook = sys.excepthook
1055 1059
1056 1060
1057 1061 def set_custom_exc(self,exc_tuple,handler):
1058 1062 """set_custom_exc(exc_tuple,handler)
1059 1063
1060 1064 Set a custom exception handler, which will be called if any of the
1061 1065 exceptions in exc_tuple occur in the mainloop (specifically, in the
1062 1066 runcode() method.
1063 1067
1064 1068 Inputs:
1065 1069
1066 1070 - exc_tuple: a *tuple* of valid exceptions to call the defined
1067 1071 handler for. It is very important that you use a tuple, and NOT A
1068 1072 LIST here, because of the way Python's except statement works. If
1069 1073 you only want to trap a single exception, use a singleton tuple:
1070 1074
1071 1075 exc_tuple == (MyCustomException,)
1072 1076
1073 1077 - handler: this must be defined as a function with the following
1074 1078 basic interface: def my_handler(self,etype,value,tb).
1075 1079
1076 1080 This will be made into an instance method (via new.instancemethod)
1077 1081 of IPython itself, and it will be called if any of the exceptions
1078 1082 listed in the exc_tuple are caught. If the handler is None, an
1079 1083 internal basic one is used, which just prints basic info.
1080 1084
1081 1085 WARNING: by putting in your own exception handler into IPython's main
1082 1086 execution loop, you run a very good chance of nasty crashes. This
1083 1087 facility should only be used if you really know what you are doing."""
1084 1088
1085 1089 assert type(exc_tuple)==type(()) , \
1086 1090 "The custom exceptions must be given AS A TUPLE."
1087 1091
1088 1092 def dummy_handler(self,etype,value,tb):
1089 1093 print '*** Simple custom exception handler ***'
1090 1094 print 'Exception type :',etype
1091 1095 print 'Exception value:',value
1092 1096 print 'Traceback :',tb
1093 1097 print 'Source code :','\n'.join(self.buffer)
1094 1098
1095 1099 if handler is None: handler = dummy_handler
1096 1100
1097 1101 self.CustomTB = new.instancemethod(handler,self,self.__class__)
1098 1102 self.custom_exceptions = exc_tuple
1099 1103
1100 1104 def set_custom_completer(self,completer,pos=0):
1101 1105 """set_custom_completer(completer,pos=0)
1102 1106
1103 1107 Adds a new custom completer function.
1104 1108
1105 1109 The position argument (defaults to 0) is the index in the completers
1106 1110 list where you want the completer to be inserted."""
1107 1111
1108 1112 newcomp = new.instancemethod(completer,self.Completer,
1109 1113 self.Completer.__class__)
1110 1114 self.Completer.matchers.insert(pos,newcomp)
1111 1115
1112 1116 def set_completer(self):
1113 1117 """reset readline's completer to be our own."""
1114 1118 self.readline.set_completer(self.Completer.complete)
1115 1119
1116 1120 def _get_call_pdb(self):
1117 1121 return self._call_pdb
1118 1122
1119 1123 def _set_call_pdb(self,val):
1120 1124
1121 1125 if val not in (0,1,False,True):
1122 1126 raise ValueError,'new call_pdb value must be boolean'
1123 1127
1124 1128 # store value in instance
1125 1129 self._call_pdb = val
1126 1130
1127 1131 # notify the actual exception handlers
1128 1132 self.InteractiveTB.call_pdb = val
1129 1133 if self.isthreaded:
1130 1134 try:
1131 1135 self.sys_excepthook.call_pdb = val
1132 1136 except:
1133 1137 warn('Failed to activate pdb for threaded exception handler')
1134 1138
1135 1139 call_pdb = property(_get_call_pdb,_set_call_pdb,None,
1136 1140 'Control auto-activation of pdb at exceptions')
1137 1141
1138 1142 # These special functions get installed in the builtin namespace, to
1139 1143 # provide programmatic (pure python) access to magics, aliases and system
1140 1144 # calls. This is important for logging, user scripting, and more.
1141 1145
1142 1146 # We are basically exposing, via normal python functions, the three
1143 1147 # mechanisms in which ipython offers special call modes (magics for
1144 1148 # internal control, aliases for direct system access via pre-selected
1145 1149 # names, and !cmd for calling arbitrary system commands).
1146 1150
1147 1151 def ipmagic(self,arg_s):
1148 1152 """Call a magic function by name.
1149 1153
1150 1154 Input: a string containing the name of the magic function to call and any
1151 1155 additional arguments to be passed to the magic.
1152 1156
1153 1157 ipmagic('name -opt foo bar') is equivalent to typing at the ipython
1154 1158 prompt:
1155 1159
1156 1160 In[1]: %name -opt foo bar
1157 1161
1158 1162 To call a magic without arguments, simply use ipmagic('name').
1159 1163
1160 1164 This provides a proper Python function to call IPython's magics in any
1161 1165 valid Python code you can type at the interpreter, including loops and
1162 1166 compound statements. It is added by IPython to the Python builtin
1163 1167 namespace upon initialization."""
1164 1168
1165 1169 args = arg_s.split(' ',1)
1166 1170 magic_name = args[0]
1167 1171 magic_name = magic_name.lstrip(self.ESC_MAGIC)
1168 1172
1169 1173 try:
1170 1174 magic_args = args[1]
1171 1175 except IndexError:
1172 1176 magic_args = ''
1173 1177 fn = getattr(self,'magic_'+magic_name,None)
1174 1178 if fn is None:
1175 1179 error("Magic function `%s` not found." % magic_name)
1176 1180 else:
1177 1181 magic_args = self.var_expand(magic_args,1)
1178 1182 return fn(magic_args)
1179 1183
1180 1184 def ipalias(self,arg_s):
1181 1185 """Call an alias by name.
1182 1186
1183 1187 Input: a string containing the name of the alias to call and any
1184 1188 additional arguments to be passed to the magic.
1185 1189
1186 1190 ipalias('name -opt foo bar') is equivalent to typing at the ipython
1187 1191 prompt:
1188 1192
1189 1193 In[1]: name -opt foo bar
1190 1194
1191 1195 To call an alias without arguments, simply use ipalias('name').
1192 1196
1193 1197 This provides a proper Python function to call IPython's aliases in any
1194 1198 valid Python code you can type at the interpreter, including loops and
1195 1199 compound statements. It is added by IPython to the Python builtin
1196 1200 namespace upon initialization."""
1197 1201
1198 1202 args = arg_s.split(' ',1)
1199 1203 alias_name = args[0]
1200 1204 try:
1201 1205 alias_args = args[1]
1202 1206 except IndexError:
1203 1207 alias_args = ''
1204 1208 if alias_name in self.alias_table:
1205 1209 self.call_alias(alias_name,alias_args)
1206 1210 else:
1207 1211 error("Alias `%s` not found." % alias_name)
1208 1212
1209 1213 def ipsystem(self,arg_s):
1210 1214 """Make a system call, using IPython."""
1211 1215
1212 1216 self.system(arg_s)
1213 1217
1214 1218 def complete(self,text):
1215 1219 """Return a sorted list of all possible completions on text.
1216 1220
1217 1221 Inputs:
1218 1222
1219 1223 - text: a string of text to be completed on.
1220 1224
1221 1225 This is a wrapper around the completion mechanism, similar to what
1222 1226 readline does at the command line when the TAB key is hit. By
1223 1227 exposing it as a method, it can be used by other non-readline
1224 1228 environments (such as GUIs) for text completion.
1225 1229
1226 1230 Simple usage example:
1227 1231
1228 1232 In [7]: x = 'hello'
1229 1233
1230 1234 In [8]: x
1231 1235 Out[8]: 'hello'
1232 1236
1233 1237 In [9]: print x
1234 1238 hello
1235 1239
1236 1240 In [10]: _ip.IP.complete('x.l')
1237 1241 Out[10]: ['x.ljust', 'x.lower', 'x.lstrip']
1238 1242 """
1239 1243
1240 1244 complete = self.Completer.complete
1241 1245 state = 0
1242 1246 # use a dict so we get unique keys, since ipyhton's multiple
1243 1247 # completers can return duplicates. When we make 2.4 a requirement,
1244 1248 # start using sets instead, which are faster.
1245 1249 comps = {}
1246 1250 while True:
1247 1251 newcomp = complete(text,state,line_buffer=text)
1248 1252 if newcomp is None:
1249 1253 break
1250 1254 comps[newcomp] = 1
1251 1255 state += 1
1252 1256 outcomps = comps.keys()
1253 1257 outcomps.sort()
1254 1258 #print "T:",text,"OC:",outcomps # dbg
1255 1259 #print "vars:",self.user_ns.keys()
1256 1260 return outcomps
1257 1261
1258 1262 def set_completer_frame(self, frame=None):
1259 1263 if frame:
1260 1264 self.Completer.namespace = frame.f_locals
1261 1265 self.Completer.global_namespace = frame.f_globals
1262 1266 else:
1263 1267 self.Completer.namespace = self.user_ns
1264 1268 self.Completer.global_namespace = self.user_global_ns
1265 1269
1266 1270 def init_auto_alias(self):
1267 1271 """Define some aliases automatically.
1268 1272
1269 1273 These are ALL parameter-less aliases"""
1270 1274
1271 1275 for alias,cmd in self.auto_alias:
1272 1276 self.getapi().defalias(alias,cmd)
1273 1277
1274 1278
1275 1279 def alias_table_validate(self,verbose=0):
1276 1280 """Update information about the alias table.
1277 1281
1278 1282 In particular, make sure no Python keywords/builtins are in it."""
1279 1283
1280 1284 no_alias = self.no_alias
1281 1285 for k in self.alias_table.keys():
1282 1286 if k in no_alias:
1283 1287 del self.alias_table[k]
1284 1288 if verbose:
1285 1289 print ("Deleting alias <%s>, it's a Python "
1286 1290 "keyword or builtin." % k)
1287 1291
1288 1292 def set_autoindent(self,value=None):
1289 1293 """Set the autoindent flag, checking for readline support.
1290 1294
1291 1295 If called with no arguments, it acts as a toggle."""
1292 1296
1293 1297 if not self.has_readline:
1294 1298 if os.name == 'posix':
1295 1299 warn("The auto-indent feature requires the readline library")
1296 1300 self.autoindent = 0
1297 1301 return
1298 1302 if value is None:
1299 1303 self.autoindent = not self.autoindent
1300 1304 else:
1301 1305 self.autoindent = value
1302 1306
1303 1307 def rc_set_toggle(self,rc_field,value=None):
1304 1308 """Set or toggle a field in IPython's rc config. structure.
1305 1309
1306 1310 If called with no arguments, it acts as a toggle.
1307 1311
1308 1312 If called with a non-existent field, the resulting AttributeError
1309 1313 exception will propagate out."""
1310 1314
1311 1315 rc_val = getattr(self.rc,rc_field)
1312 1316 if value is None:
1313 1317 value = not rc_val
1314 1318 setattr(self.rc,rc_field,value)
1315 1319
1316 1320 def user_setup(self,ipythondir,rc_suffix,mode='install'):
1317 1321 """Install the user configuration directory.
1318 1322
1319 1323 Note
1320 1324 ----
1321 1325 DEPRECATED: use the top-level user_setup() function instead.
1322 1326 """
1323 1327 return user_setup(ipythondir,rc_suffix,mode)
1324 1328
1325 1329 def atexit_operations(self):
1326 1330 """This will be executed at the time of exit.
1327 1331
1328 1332 Saving of persistent data should be performed here. """
1329 1333
1330 1334 #print '*** IPython exit cleanup ***' # dbg
1331 1335 # input history
1332 1336 self.savehist()
1333 1337
1334 1338 # Cleanup all tempfiles left around
1335 1339 for tfile in self.tempfiles:
1336 1340 try:
1337 1341 os.unlink(tfile)
1338 1342 except OSError:
1339 1343 pass
1340 1344
1341 1345 # Clear all user namespaces to release all references cleanly.
1342 1346 self.reset()
1343 1347
1344 1348 # Run user hooks
1345 1349 self.hooks.shutdown_hook()
1346 1350
1347 1351 def reset(self):
1348 1352 """Clear all internal namespaces.
1349 1353
1350 1354 Note that this is much more aggressive than %reset, since it clears
1351 1355 fully all namespaces, as well as all input/output lists.
1352 1356 """
1353 1357 for ns in self.ns_refs_table:
1354 1358 ns.clear()
1355 1359
1356 1360 # Clear input and output histories
1357 1361 self.input_hist[:] = []
1358 1362 self.input_hist_raw[:] = []
1359 1363 self.output_hist.clear()
1360 1364 # Restore the user namespaces to minimal usability
1361 1365 self.init_namespaces()
1362 1366
1363 1367 def savehist(self):
1364 1368 """Save input history to a file (via readline library)."""
1365 1369
1366 1370 if not self.has_readline:
1367 1371 return
1368 1372
1369 1373 try:
1370 1374 self.readline.write_history_file(self.histfile)
1371 1375 except:
1372 1376 print 'Unable to save IPython command history to file: ' + \
1373 1377 `self.histfile`
1374 1378
1375 1379 def reloadhist(self):
1376 1380 """Reload the input history from disk file."""
1377 1381
1378 1382 if self.has_readline:
1379 1383 try:
1380 1384 self.readline.clear_history()
1381 1385 self.readline.read_history_file(self.shell.histfile)
1382 1386 except AttributeError:
1383 1387 pass
1384 1388
1385 1389
1386 1390 def history_saving_wrapper(self, func):
1387 1391 """ Wrap func for readline history saving
1388 1392
1389 1393 Convert func into callable that saves & restores
1390 1394 history around the call """
1391 1395
1392 1396 if not self.has_readline:
1393 1397 return func
1394 1398
1395 1399 def wrapper():
1396 1400 self.savehist()
1397 1401 try:
1398 1402 func()
1399 1403 finally:
1400 1404 readline.read_history_file(self.histfile)
1401 1405 return wrapper
1402 1406
1403 1407 def pre_readline(self):
1404 1408 """readline hook to be used at the start of each line.
1405 1409
1406 1410 Currently it handles auto-indent only."""
1407 1411
1408 1412 #debugx('self.indent_current_nsp','pre_readline:')
1409 1413
1410 1414 if self.rl_do_indent:
1411 1415 self.readline.insert_text(self.indent_current_str())
1412 1416 if self.rl_next_input is not None:
1413 1417 self.readline.insert_text(self.rl_next_input)
1414 1418 self.rl_next_input = None
1415 1419
1416 1420 def init_readline(self):
1417 1421 """Command history completion/saving/reloading."""
1418 1422
1419 1423
1420 1424 import IPython.rlineimpl as readline
1421 1425
1422 1426 if not readline.have_readline:
1423 1427 self.has_readline = 0
1424 1428 self.readline = None
1425 1429 # no point in bugging windows users with this every time:
1426 1430 warn('Readline services not available on this platform.')
1427 1431 else:
1428 1432 sys.modules['readline'] = readline
1429 1433 import atexit
1430 1434 from IPython.completer import IPCompleter
1431 1435 self.Completer = IPCompleter(self,
1432 1436 self.user_ns,
1433 1437 self.user_global_ns,
1434 1438 self.rc.readline_omit__names,
1435 1439 self.alias_table)
1436 1440 sdisp = self.strdispatchers.get('complete_command', StrDispatch())
1437 1441 self.strdispatchers['complete_command'] = sdisp
1438 1442 self.Completer.custom_completers = sdisp
1439 1443 # Platform-specific configuration
1440 1444 if os.name == 'nt':
1441 1445 self.readline_startup_hook = readline.set_pre_input_hook
1442 1446 else:
1443 1447 self.readline_startup_hook = readline.set_startup_hook
1444 1448
1445 1449 # Load user's initrc file (readline config)
1446 1450 # Or if libedit is used, load editrc.
1447 1451 inputrc_name = os.environ.get('INPUTRC')
1448 1452 if inputrc_name is None:
1449 1453 home_dir = get_home_dir()
1450 1454 if home_dir is not None:
1451 1455 inputrc_name = '.inputrc'
1452 1456 if readline.uses_libedit:
1453 1457 inputrc_name = '.editrc'
1454 1458 inputrc_name = os.path.join(home_dir, inputrc_name)
1455 1459 if os.path.isfile(inputrc_name):
1456 1460 try:
1457 1461 readline.read_init_file(inputrc_name)
1458 1462 except:
1459 1463 warn('Problems reading readline initialization file <%s>'
1460 1464 % inputrc_name)
1461 1465
1462 1466 self.has_readline = 1
1463 1467 self.readline = readline
1464 1468 # save this in sys so embedded copies can restore it properly
1465 1469 sys.ipcompleter = self.Completer.complete
1466 1470 self.set_completer()
1467 1471
1468 1472 # Configure readline according to user's prefs
1469 1473 # This is only done if GNU readline is being used. If libedit
1470 1474 # is being used (as on Leopard) the readline config is
1471 1475 # not run as the syntax for libedit is different.
1472 1476 if not readline.uses_libedit:
1473 1477 for rlcommand in self.rc.readline_parse_and_bind:
1474 1478 #print "loading rl:",rlcommand # dbg
1475 1479 readline.parse_and_bind(rlcommand)
1476 1480
1477 # remove some chars from the delimiters list
1478 delims = readline.get_completer_delims()
1481 # Remove some chars from the delimiters list. If we encounter
1482 # unicode chars, discard them.
1483 delims = readline.get_completer_delims().encode("ascii", "ignore")
1479 1484 delims = delims.translate(string._idmap,
1480 1485 self.rc.readline_remove_delims)
1481 1486 readline.set_completer_delims(delims)
1482 1487 # otherwise we end up with a monster history after a while:
1483 1488 readline.set_history_length(1000)
1484 1489 try:
1485 1490 #print '*** Reading readline history' # dbg
1486 1491 readline.read_history_file(self.histfile)
1487 1492 except IOError:
1488 1493 pass # It doesn't exist yet.
1489 1494
1490 1495 atexit.register(self.atexit_operations)
1491 1496 del atexit
1492 1497
1493 1498 # Configure auto-indent for all platforms
1494 1499 self.set_autoindent(self.rc.autoindent)
1495 1500
1496 1501 def ask_yes_no(self,prompt,default=True):
1497 1502 if self.rc.quiet:
1498 1503 return True
1499 1504 return ask_yes_no(prompt,default)
1500 1505
1501 1506 def new_main_mod(self,ns=None):
1502 1507 """Return a new 'main' module object for user code execution.
1503 1508 """
1504 1509 main_mod = self._user_main_module
1505 1510 init_fakemod_dict(main_mod,ns)
1506 1511 return main_mod
1507 1512
1508 1513 def cache_main_mod(self,ns,fname):
1509 1514 """Cache a main module's namespace.
1510 1515
1511 1516 When scripts are executed via %run, we must keep a reference to the
1512 1517 namespace of their __main__ module (a FakeModule instance) around so
1513 1518 that Python doesn't clear it, rendering objects defined therein
1514 1519 useless.
1515 1520
1516 1521 This method keeps said reference in a private dict, keyed by the
1517 1522 absolute path of the module object (which corresponds to the script
1518 1523 path). This way, for multiple executions of the same script we only
1519 1524 keep one copy of the namespace (the last one), thus preventing memory
1520 1525 leaks from old references while allowing the objects from the last
1521 1526 execution to be accessible.
1522 1527
1523 1528 Note: we can not allow the actual FakeModule instances to be deleted,
1524 1529 because of how Python tears down modules (it hard-sets all their
1525 1530 references to None without regard for reference counts). This method
1526 1531 must therefore make a *copy* of the given namespace, to allow the
1527 1532 original module's __dict__ to be cleared and reused.
1528 1533
1529 1534
1530 1535 Parameters
1531 1536 ----------
1532 1537 ns : a namespace (a dict, typically)
1533 1538
1534 1539 fname : str
1535 1540 Filename associated with the namespace.
1536 1541
1537 1542 Examples
1538 1543 --------
1539 1544
1540 1545 In [10]: import IPython
1541 1546
1542 1547 In [11]: _ip.IP.cache_main_mod(IPython.__dict__,IPython.__file__)
1543 1548
1544 1549 In [12]: IPython.__file__ in _ip.IP._main_ns_cache
1545 1550 Out[12]: True
1546 1551 """
1547 1552 self._main_ns_cache[os.path.abspath(fname)] = ns.copy()
1548 1553
1549 1554 def clear_main_mod_cache(self):
1550 1555 """Clear the cache of main modules.
1551 1556
1552 1557 Mainly for use by utilities like %reset.
1553 1558
1554 1559 Examples
1555 1560 --------
1556 1561
1557 1562 In [15]: import IPython
1558 1563
1559 1564 In [16]: _ip.IP.cache_main_mod(IPython.__dict__,IPython.__file__)
1560 1565
1561 1566 In [17]: len(_ip.IP._main_ns_cache) > 0
1562 1567 Out[17]: True
1563 1568
1564 1569 In [18]: _ip.IP.clear_main_mod_cache()
1565 1570
1566 1571 In [19]: len(_ip.IP._main_ns_cache) == 0
1567 1572 Out[19]: True
1568 1573 """
1569 1574 self._main_ns_cache.clear()
1570 1575
1571 1576 def _should_recompile(self,e):
1572 1577 """Utility routine for edit_syntax_error"""
1573 1578
1574 1579 if e.filename in ('<ipython console>','<input>','<string>',
1575 1580 '<console>','<BackgroundJob compilation>',
1576 1581 None):
1577 1582
1578 1583 return False
1579 1584 try:
1580 1585 if (self.rc.autoedit_syntax and
1581 1586 not self.ask_yes_no('Return to editor to correct syntax error? '
1582 1587 '[Y/n] ','y')):
1583 1588 return False
1584 1589 except EOFError:
1585 1590 return False
1586 1591
1587 1592 def int0(x):
1588 1593 try:
1589 1594 return int(x)
1590 1595 except TypeError:
1591 1596 return 0
1592 1597 # always pass integer line and offset values to editor hook
1593 1598 try:
1594 1599 self.hooks.fix_error_editor(e.filename,
1595 1600 int0(e.lineno),int0(e.offset),e.msg)
1596 1601 except IPython.ipapi.TryNext:
1597 1602 warn('Could not open editor')
1598 1603 return False
1599 1604 return True
1600 1605
1601 1606 def edit_syntax_error(self):
1602 1607 """The bottom half of the syntax error handler called in the main loop.
1603 1608
1604 1609 Loop until syntax error is fixed or user cancels.
1605 1610 """
1606 1611
1607 1612 while self.SyntaxTB.last_syntax_error:
1608 1613 # copy and clear last_syntax_error
1609 1614 err = self.SyntaxTB.clear_err_state()
1610 1615 if not self._should_recompile(err):
1611 1616 return
1612 1617 try:
1613 1618 # may set last_syntax_error again if a SyntaxError is raised
1614 1619 self.safe_execfile(err.filename,self.user_ns)
1615 1620 except:
1616 1621 self.showtraceback()
1617 1622 else:
1618 1623 try:
1619 1624 f = file(err.filename)
1620 1625 try:
1621 1626 sys.displayhook(f.read())
1622 1627 finally:
1623 1628 f.close()
1624 1629 except:
1625 1630 self.showtraceback()
1626 1631
1627 1632 def showsyntaxerror(self, filename=None):
1628 1633 """Display the syntax error that just occurred.
1629 1634
1630 1635 This doesn't display a stack trace because there isn't one.
1631 1636
1632 1637 If a filename is given, it is stuffed in the exception instead
1633 1638 of what was there before (because Python's parser always uses
1634 1639 "<string>" when reading from a string).
1635 1640 """
1636 1641 etype, value, last_traceback = sys.exc_info()
1637 1642
1638 1643 # See note about these variables in showtraceback() below
1639 1644 sys.last_type = etype
1640 1645 sys.last_value = value
1641 1646 sys.last_traceback = last_traceback
1642 1647
1643 1648 if filename and etype is SyntaxError:
1644 1649 # Work hard to stuff the correct filename in the exception
1645 1650 try:
1646 1651 msg, (dummy_filename, lineno, offset, line) = value
1647 1652 except:
1648 1653 # Not the format we expect; leave it alone
1649 1654 pass
1650 1655 else:
1651 1656 # Stuff in the right filename
1652 1657 try:
1653 1658 # Assume SyntaxError is a class exception
1654 1659 value = SyntaxError(msg, (filename, lineno, offset, line))
1655 1660 except:
1656 1661 # If that failed, assume SyntaxError is a string
1657 1662 value = msg, (filename, lineno, offset, line)
1658 1663 self.SyntaxTB(etype,value,[])
1659 1664
1660 1665 def debugger(self,force=False):
1661 1666 """Call the pydb/pdb debugger.
1662 1667
1663 1668 Keywords:
1664 1669
1665 1670 - force(False): by default, this routine checks the instance call_pdb
1666 1671 flag and does not actually invoke the debugger if the flag is false.
1667 1672 The 'force' option forces the debugger to activate even if the flag
1668 1673 is false.
1669 1674 """
1670 1675
1671 1676 if not (force or self.call_pdb):
1672 1677 return
1673 1678
1674 1679 if not hasattr(sys,'last_traceback'):
1675 1680 error('No traceback has been produced, nothing to debug.')
1676 1681 return
1677 1682
1678 1683 # use pydb if available
1679 1684 if Debugger.has_pydb:
1680 1685 from pydb import pm
1681 1686 else:
1682 1687 # fallback to our internal debugger
1683 1688 pm = lambda : self.InteractiveTB.debugger(force=True)
1684 1689 self.history_saving_wrapper(pm)()
1685 1690
1686 1691 def showtraceback(self,exc_tuple = None,filename=None,tb_offset=None):
1687 1692 """Display the exception that just occurred.
1688 1693
1689 1694 If nothing is known about the exception, this is the method which
1690 1695 should be used throughout the code for presenting user tracebacks,
1691 1696 rather than directly invoking the InteractiveTB object.
1692 1697
1693 1698 A specific showsyntaxerror() also exists, but this method can take
1694 1699 care of calling it if needed, so unless you are explicitly catching a
1695 1700 SyntaxError exception, don't try to analyze the stack manually and
1696 1701 simply call this method."""
1697 1702
1698 1703
1699 1704 # Though this won't be called by syntax errors in the input line,
1700 1705 # there may be SyntaxError cases whith imported code.
1701 1706
1702 1707 try:
1703 1708 if exc_tuple is None:
1704 1709 etype, value, tb = sys.exc_info()
1705 1710 else:
1706 1711 etype, value, tb = exc_tuple
1707 1712
1708 1713 if etype is SyntaxError:
1709 1714 self.showsyntaxerror(filename)
1710 1715 elif etype is IPython.ipapi.UsageError:
1711 1716 print "UsageError:", value
1712 1717 else:
1713 1718 # WARNING: these variables are somewhat deprecated and not
1714 1719 # necessarily safe to use in a threaded environment, but tools
1715 1720 # like pdb depend on their existence, so let's set them. If we
1716 1721 # find problems in the field, we'll need to revisit their use.
1717 1722 sys.last_type = etype
1718 1723 sys.last_value = value
1719 1724 sys.last_traceback = tb
1720 1725
1721 1726 if etype in self.custom_exceptions:
1722 1727 self.CustomTB(etype,value,tb)
1723 1728 else:
1724 1729 self.InteractiveTB(etype,value,tb,tb_offset=tb_offset)
1725 1730 if self.InteractiveTB.call_pdb and self.has_readline:
1726 1731 # pdb mucks up readline, fix it back
1727 1732 self.set_completer()
1728 1733 except KeyboardInterrupt:
1729 1734 self.write("\nKeyboardInterrupt\n")
1730 1735
1731 1736 def mainloop(self,banner=None):
1732 1737 """Creates the local namespace and starts the mainloop.
1733 1738
1734 1739 If an optional banner argument is given, it will override the
1735 1740 internally created default banner."""
1736 1741
1737 1742 if self.rc.c: # Emulate Python's -c option
1738 1743 self.exec_init_cmd()
1739 1744 if banner is None:
1740 1745 if not self.rc.banner:
1741 1746 banner = ''
1742 1747 # banner is string? Use it directly!
1743 1748 elif isinstance(self.rc.banner,basestring):
1744 1749 banner = self.rc.banner
1745 1750 else:
1746 1751 banner = self.BANNER+self.banner2
1747 1752
1748 1753 # if you run stuff with -c <cmd>, raw hist is not updated
1749 1754 # ensure that it's in sync
1750 1755 if len(self.input_hist) != len (self.input_hist_raw):
1751 1756 self.input_hist_raw = InputList(self.input_hist)
1752 1757
1753 1758 while 1:
1754 1759 try:
1755 1760 self.interact(banner)
1756 1761 #self.interact_with_readline()
1757 1762
1758 1763 # XXX for testing of a readline-decoupled repl loop, call
1759 1764 # interact_with_readline above
1760 1765
1761 1766 break
1762 1767 except KeyboardInterrupt:
1763 1768 # this should not be necessary, but KeyboardInterrupt
1764 1769 # handling seems rather unpredictable...
1765 1770 self.write("\nKeyboardInterrupt in interact()\n")
1766 1771
1767 1772 def exec_init_cmd(self):
1768 1773 """Execute a command given at the command line.
1769 1774
1770 1775 This emulates Python's -c option."""
1771 1776
1772 1777 #sys.argv = ['-c']
1773 1778 self.push(self.prefilter(self.rc.c, False))
1774 1779 if not self.rc.interact:
1775 1780 self.ask_exit()
1776 1781
1777 1782 def embed_mainloop(self,header='',local_ns=None,global_ns=None,stack_depth=0):
1778 1783 """Embeds IPython into a running python program.
1779 1784
1780 1785 Input:
1781 1786
1782 1787 - header: An optional header message can be specified.
1783 1788
1784 1789 - local_ns, global_ns: working namespaces. If given as None, the
1785 1790 IPython-initialized one is updated with __main__.__dict__, so that
1786 1791 program variables become visible but user-specific configuration
1787 1792 remains possible.
1788 1793
1789 1794 - stack_depth: specifies how many levels in the stack to go to
1790 1795 looking for namespaces (when local_ns and global_ns are None). This
1791 1796 allows an intermediate caller to make sure that this function gets
1792 1797 the namespace from the intended level in the stack. By default (0)
1793 1798 it will get its locals and globals from the immediate caller.
1794 1799
1795 1800 Warning: it's possible to use this in a program which is being run by
1796 1801 IPython itself (via %run), but some funny things will happen (a few
1797 1802 globals get overwritten). In the future this will be cleaned up, as
1798 1803 there is no fundamental reason why it can't work perfectly."""
1799 1804
1800 1805 # Get locals and globals from caller
1801 1806 if local_ns is None or global_ns is None:
1802 1807 call_frame = sys._getframe(stack_depth).f_back
1803 1808
1804 1809 if local_ns is None:
1805 1810 local_ns = call_frame.f_locals
1806 1811 if global_ns is None:
1807 1812 global_ns = call_frame.f_globals
1808 1813
1809 1814 # Update namespaces and fire up interpreter
1810 1815
1811 1816 # The global one is easy, we can just throw it in
1812 1817 self.user_global_ns = global_ns
1813 1818
1814 1819 # but the user/local one is tricky: ipython needs it to store internal
1815 1820 # data, but we also need the locals. We'll copy locals in the user
1816 1821 # one, but will track what got copied so we can delete them at exit.
1817 1822 # This is so that a later embedded call doesn't see locals from a
1818 1823 # previous call (which most likely existed in a separate scope).
1819 1824 local_varnames = local_ns.keys()
1820 1825 self.user_ns.update(local_ns)
1821 1826 #self.user_ns['local_ns'] = local_ns # dbg
1822 1827
1823 1828 # Patch for global embedding to make sure that things don't overwrite
1824 1829 # user globals accidentally. Thanks to Richard <rxe@renre-europe.com>
1825 1830 # FIXME. Test this a bit more carefully (the if.. is new)
1826 1831 if local_ns is None and global_ns is None:
1827 1832 self.user_global_ns.update(__main__.__dict__)
1828 1833
1829 1834 # make sure the tab-completer has the correct frame information, so it
1830 1835 # actually completes using the frame's locals/globals
1831 1836 self.set_completer_frame()
1832 1837
1833 1838 # before activating the interactive mode, we need to make sure that
1834 1839 # all names in the builtin namespace needed by ipython point to
1835 1840 # ourselves, and not to other instances.
1836 1841 self.add_builtins()
1837 1842
1838 1843 self.interact(header)
1839 1844
1840 1845 # now, purge out the user namespace from anything we might have added
1841 1846 # from the caller's local namespace
1842 1847 delvar = self.user_ns.pop
1843 1848 for var in local_varnames:
1844 1849 delvar(var,None)
1845 1850 # and clean builtins we may have overridden
1846 1851 self.clean_builtins()
1847 1852
1848 1853 def interact_prompt(self):
1849 1854 """ Print the prompt (in read-eval-print loop)
1850 1855
1851 1856 Provided for those who want to implement their own read-eval-print loop (e.g. GUIs), not
1852 1857 used in standard IPython flow.
1853 1858 """
1854 1859 if self.more:
1855 1860 try:
1856 1861 prompt = self.hooks.generate_prompt(True)
1857 1862 except:
1858 1863 self.showtraceback()
1859 1864 if self.autoindent:
1860 1865 self.rl_do_indent = True
1861 1866
1862 1867 else:
1863 1868 try:
1864 1869 prompt = self.hooks.generate_prompt(False)
1865 1870 except:
1866 1871 self.showtraceback()
1867 1872 self.write(prompt)
1868 1873
1869 1874 def interact_handle_input(self,line):
1870 1875 """ Handle the input line (in read-eval-print loop)
1871 1876
1872 1877 Provided for those who want to implement their own read-eval-print loop (e.g. GUIs), not
1873 1878 used in standard IPython flow.
1874 1879 """
1875 1880 if line.lstrip() == line:
1876 1881 self.shadowhist.add(line.strip())
1877 1882 lineout = self.prefilter(line,self.more)
1878 1883
1879 1884 if line.strip():
1880 1885 if self.more:
1881 1886 self.input_hist_raw[-1] += '%s\n' % line
1882 1887 else:
1883 1888 self.input_hist_raw.append('%s\n' % line)
1884 1889
1885 1890
1886 1891 self.more = self.push(lineout)
1887 1892 if (self.SyntaxTB.last_syntax_error and
1888 1893 self.rc.autoedit_syntax):
1889 1894 self.edit_syntax_error()
1890 1895
1891 1896 def interact_with_readline(self):
1892 1897 """ Demo of using interact_handle_input, interact_prompt
1893 1898
1894 1899 This is the main read-eval-print loop. If you need to implement your own (e.g. for GUI),
1895 1900 it should work like this.
1896 1901 """
1897 1902 self.readline_startup_hook(self.pre_readline)
1898 1903 while not self.exit_now:
1899 1904 self.interact_prompt()
1900 1905 if self.more:
1901 1906 self.rl_do_indent = True
1902 1907 else:
1903 1908 self.rl_do_indent = False
1904 1909 line = raw_input_original().decode(self.stdin_encoding)
1905 1910 self.interact_handle_input(line)
1906 1911
1907 1912
1908 1913 def interact(self, banner=None):
1909 1914 """Closely emulate the interactive Python console.
1910 1915
1911 1916 The optional banner argument specify the banner to print
1912 1917 before the first interaction; by default it prints a banner
1913 1918 similar to the one printed by the real Python interpreter,
1914 1919 followed by the current class name in parentheses (so as not
1915 1920 to confuse this with the real interpreter -- since it's so
1916 1921 close!).
1917 1922
1918 1923 """
1919 1924
1920 1925 if self.exit_now:
1921 1926 # batch run -> do not interact
1922 1927 return
1923 1928 cprt = 'Type "copyright", "credits" or "license" for more information.'
1924 1929 if banner is None:
1925 1930 self.write("Python %s on %s\n%s\n(%s)\n" %
1926 1931 (sys.version, sys.platform, cprt,
1927 1932 self.__class__.__name__))
1928 1933 else:
1929 1934 self.write(banner)
1930 1935
1931 1936 more = 0
1932 1937
1933 1938 # Mark activity in the builtins
1934 1939 __builtin__.__dict__['__IPYTHON__active'] += 1
1935 1940
1936 1941 if self.has_readline:
1937 1942 self.readline_startup_hook(self.pre_readline)
1938 1943 # exit_now is set by a call to %Exit or %Quit, through the
1939 1944 # ask_exit callback.
1940 1945
1941 1946 while not self.exit_now:
1942 1947 self.hooks.pre_prompt_hook()
1943 1948 if more:
1944 1949 try:
1945 1950 prompt = self.hooks.generate_prompt(True)
1946 1951 except:
1947 1952 self.showtraceback()
1948 1953 if self.autoindent:
1949 1954 self.rl_do_indent = True
1950 1955
1951 1956 else:
1952 1957 try:
1953 1958 prompt = self.hooks.generate_prompt(False)
1954 1959 except:
1955 1960 self.showtraceback()
1956 1961 try:
1957 1962 line = self.raw_input(prompt,more)
1958 1963 if self.exit_now:
1959 1964 # quick exit on sys.std[in|out] close
1960 1965 break
1961 1966 if self.autoindent:
1962 1967 self.rl_do_indent = False
1963 1968
1964 1969 except KeyboardInterrupt:
1965 1970 #double-guard against keyboardinterrupts during kbdint handling
1966 1971 try:
1967 1972 self.write('\nKeyboardInterrupt\n')
1968 1973 self.resetbuffer()
1969 1974 # keep cache in sync with the prompt counter:
1970 1975 self.outputcache.prompt_count -= 1
1971 1976
1972 1977 if self.autoindent:
1973 1978 self.indent_current_nsp = 0
1974 1979 more = 0
1975 1980 except KeyboardInterrupt:
1976 1981 pass
1977 1982 except EOFError:
1978 1983 if self.autoindent:
1979 1984 self.rl_do_indent = False
1980 1985 self.readline_startup_hook(None)
1981 1986 self.write('\n')
1982 1987 self.exit()
1983 1988 except bdb.BdbQuit:
1984 1989 warn('The Python debugger has exited with a BdbQuit exception.\n'
1985 1990 'Because of how pdb handles the stack, it is impossible\n'
1986 1991 'for IPython to properly format this particular exception.\n'
1987 1992 'IPython will resume normal operation.')
1988 1993 except:
1989 1994 # exceptions here are VERY RARE, but they can be triggered
1990 1995 # asynchronously by signal handlers, for example.
1991 1996 self.showtraceback()
1992 1997 else:
1993 1998 more = self.push(line)
1994 1999 if (self.SyntaxTB.last_syntax_error and
1995 2000 self.rc.autoedit_syntax):
1996 2001 self.edit_syntax_error()
1997 2002
1998 2003 # We are off again...
1999 2004 __builtin__.__dict__['__IPYTHON__active'] -= 1
2000 2005
2001 2006 def excepthook(self, etype, value, tb):
2002 2007 """One more defense for GUI apps that call sys.excepthook.
2003 2008
2004 2009 GUI frameworks like wxPython trap exceptions and call
2005 2010 sys.excepthook themselves. I guess this is a feature that
2006 2011 enables them to keep running after exceptions that would
2007 2012 otherwise kill their mainloop. This is a bother for IPython
2008 2013 which excepts to catch all of the program exceptions with a try:
2009 2014 except: statement.
2010 2015
2011 2016 Normally, IPython sets sys.excepthook to a CrashHandler instance, so if
2012 2017 any app directly invokes sys.excepthook, it will look to the user like
2013 2018 IPython crashed. In order to work around this, we can disable the
2014 2019 CrashHandler and replace it with this excepthook instead, which prints a
2015 2020 regular traceback using our InteractiveTB. In this fashion, apps which
2016 2021 call sys.excepthook will generate a regular-looking exception from
2017 2022 IPython, and the CrashHandler will only be triggered by real IPython
2018 2023 crashes.
2019 2024
2020 2025 This hook should be used sparingly, only in places which are not likely
2021 2026 to be true IPython errors.
2022 2027 """
2023 2028 self.showtraceback((etype,value,tb),tb_offset=0)
2024 2029
2025 2030 def expand_aliases(self,fn,rest):
2026 2031 """ Expand multiple levels of aliases:
2027 2032
2028 2033 if:
2029 2034
2030 2035 alias foo bar /tmp
2031 2036 alias baz foo
2032 2037
2033 2038 then:
2034 2039
2035 2040 baz huhhahhei -> bar /tmp huhhahhei
2036 2041
2037 2042 """
2038 2043 line = fn + " " + rest
2039 2044
2040 2045 done = set()
2041 2046 while 1:
2042 2047 pre,fn,rest = prefilter.splitUserInput(line,
2043 2048 prefilter.shell_line_split)
2044 2049 if fn in self.alias_table:
2045 2050 if fn in done:
2046 2051 warn("Cyclic alias definition, repeated '%s'" % fn)
2047 2052 return ""
2048 2053 done.add(fn)
2049 2054
2050 2055 l2 = self.transform_alias(fn,rest)
2051 2056 # dir -> dir
2052 2057 # print "alias",line, "->",l2 #dbg
2053 2058 if l2 == line:
2054 2059 break
2055 2060 # ls -> ls -F should not recurse forever
2056 2061 if l2.split(None,1)[0] == line.split(None,1)[0]:
2057 2062 line = l2
2058 2063 break
2059 2064
2060 2065 line=l2
2061 2066
2062 2067
2063 2068 # print "al expand to",line #dbg
2064 2069 else:
2065 2070 break
2066 2071
2067 2072 return line
2068 2073
2069 2074 def transform_alias(self, alias,rest=''):
2070 2075 """ Transform alias to system command string.
2071 2076 """
2072 2077 trg = self.alias_table[alias]
2073 2078
2074 2079 nargs,cmd = trg
2075 2080 # print trg #dbg
2076 2081 if ' ' in cmd and os.path.isfile(cmd):
2077 2082 cmd = '"%s"' % cmd
2078 2083
2079 2084 # Expand the %l special to be the user's input line
2080 2085 if cmd.find('%l') >= 0:
2081 2086 cmd = cmd.replace('%l',rest)
2082 2087 rest = ''
2083 2088 if nargs==0:
2084 2089 # Simple, argument-less aliases
2085 2090 cmd = '%s %s' % (cmd,rest)
2086 2091 else:
2087 2092 # Handle aliases with positional arguments
2088 2093 args = rest.split(None,nargs)
2089 2094 if len(args)< nargs:
2090 2095 error('Alias <%s> requires %s arguments, %s given.' %
2091 2096 (alias,nargs,len(args)))
2092 2097 return None
2093 2098 cmd = '%s %s' % (cmd % tuple(args[:nargs]),' '.join(args[nargs:]))
2094 2099 # Now call the macro, evaluating in the user's namespace
2095 2100 #print 'new command: <%r>' % cmd # dbg
2096 2101 return cmd
2097 2102
2098 2103 def call_alias(self,alias,rest=''):
2099 2104 """Call an alias given its name and the rest of the line.
2100 2105
2101 2106 This is only used to provide backwards compatibility for users of
2102 2107 ipalias(), use of which is not recommended for anymore."""
2103 2108
2104 2109 # Now call the macro, evaluating in the user's namespace
2105 2110 cmd = self.transform_alias(alias, rest)
2106 2111 try:
2107 2112 self.system(cmd)
2108 2113 except:
2109 2114 self.showtraceback()
2110 2115
2111 2116 def indent_current_str(self):
2112 2117 """return the current level of indentation as a string"""
2113 2118 return self.indent_current_nsp * ' '
2114 2119
2115 2120 def autoindent_update(self,line):
2116 2121 """Keep track of the indent level."""
2117 2122
2118 2123 #debugx('line')
2119 2124 #debugx('self.indent_current_nsp')
2120 2125 if self.autoindent:
2121 2126 if line:
2122 2127 inisp = num_ini_spaces(line)
2123 2128 if inisp < self.indent_current_nsp:
2124 2129 self.indent_current_nsp = inisp
2125 2130
2126 2131 if line[-1] == ':':
2127 2132 self.indent_current_nsp += 4
2128 2133 elif dedent_re.match(line):
2129 2134 self.indent_current_nsp -= 4
2130 2135 else:
2131 2136 self.indent_current_nsp = 0
2132 2137
2133 2138 def runlines(self,lines):
2134 2139 """Run a string of one or more lines of source.
2135 2140
2136 2141 This method is capable of running a string containing multiple source
2137 2142 lines, as if they had been entered at the IPython prompt. Since it
2138 2143 exposes IPython's processing machinery, the given strings can contain
2139 2144 magic calls (%magic), special shell access (!cmd), etc."""
2140 2145
2141 2146 # We must start with a clean buffer, in case this is run from an
2142 2147 # interactive IPython session (via a magic, for example).
2143 2148 self.resetbuffer()
2144 2149 lines = lines.split('\n')
2145 2150 more = 0
2146 2151
2147 2152 for line in lines:
2148 2153 # skip blank lines so we don't mess up the prompt counter, but do
2149 2154 # NOT skip even a blank line if we are in a code block (more is
2150 2155 # true)
2151 2156
2152 2157 if line or more:
2153 2158 # push to raw history, so hist line numbers stay in sync
2154 2159 self.input_hist_raw.append("# " + line + "\n")
2155 2160 more = self.push(self.prefilter(line,more))
2156 2161 # IPython's runsource returns None if there was an error
2157 2162 # compiling the code. This allows us to stop processing right
2158 2163 # away, so the user gets the error message at the right place.
2159 2164 if more is None:
2160 2165 break
2161 2166 else:
2162 2167 self.input_hist_raw.append("\n")
2163 2168 # final newline in case the input didn't have it, so that the code
2164 2169 # actually does get executed
2165 2170 if more:
2166 2171 self.push('\n')
2167 2172
2168 2173 def runsource(self, source, filename='<input>', symbol='single'):
2169 2174 """Compile and run some source in the interpreter.
2170 2175
2171 2176 Arguments are as for compile_command().
2172 2177
2173 2178 One several things can happen:
2174 2179
2175 2180 1) The input is incorrect; compile_command() raised an
2176 2181 exception (SyntaxError or OverflowError). A syntax traceback
2177 2182 will be printed by calling the showsyntaxerror() method.
2178 2183
2179 2184 2) The input is incomplete, and more input is required;
2180 2185 compile_command() returned None. Nothing happens.
2181 2186
2182 2187 3) The input is complete; compile_command() returned a code
2183 2188 object. The code is executed by calling self.runcode() (which
2184 2189 also handles run-time exceptions, except for SystemExit).
2185 2190
2186 2191 The return value is:
2187 2192
2188 2193 - True in case 2
2189 2194
2190 2195 - False in the other cases, unless an exception is raised, where
2191 2196 None is returned instead. This can be used by external callers to
2192 2197 know whether to continue feeding input or not.
2193 2198
2194 2199 The return value can be used to decide whether to use sys.ps1 or
2195 2200 sys.ps2 to prompt the next line."""
2196 2201
2197 2202 # if the source code has leading blanks, add 'if 1:\n' to it
2198 2203 # this allows execution of indented pasted code. It is tempting
2199 2204 # to add '\n' at the end of source to run commands like ' a=1'
2200 2205 # directly, but this fails for more complicated scenarios
2201 2206 source=source.encode(self.stdin_encoding)
2202 2207 if source[:1] in [' ', '\t']:
2203 2208 source = 'if 1:\n%s' % source
2204 2209
2205 2210 try:
2206 2211 code = self.compile(source,filename,symbol)
2207 2212 except (OverflowError, SyntaxError, ValueError, TypeError):
2208 2213 # Case 1
2209 2214 self.showsyntaxerror(filename)
2210 2215 return None
2211 2216
2212 2217 if code is None:
2213 2218 # Case 2
2214 2219 return True
2215 2220
2216 2221 # Case 3
2217 2222 # We store the code object so that threaded shells and
2218 2223 # custom exception handlers can access all this info if needed.
2219 2224 # The source corresponding to this can be obtained from the
2220 2225 # buffer attribute as '\n'.join(self.buffer).
2221 2226 self.code_to_run = code
2222 2227 # now actually execute the code object
2223 2228 if self.runcode(code) == 0:
2224 2229 return False
2225 2230 else:
2226 2231 return None
2227 2232
2228 2233 def runcode(self,code_obj):
2229 2234 """Execute a code object.
2230 2235
2231 2236 When an exception occurs, self.showtraceback() is called to display a
2232 2237 traceback.
2233 2238
2234 2239 Return value: a flag indicating whether the code to be run completed
2235 2240 successfully:
2236 2241
2237 2242 - 0: successful execution.
2238 2243 - 1: an error occurred.
2239 2244 """
2240 2245
2241 2246 # Set our own excepthook in case the user code tries to call it
2242 2247 # directly, so that the IPython crash handler doesn't get triggered
2243 2248 old_excepthook,sys.excepthook = sys.excepthook, self.excepthook
2244 2249
2245 2250 # we save the original sys.excepthook in the instance, in case config
2246 2251 # code (such as magics) needs access to it.
2247 2252 self.sys_excepthook = old_excepthook
2248 2253 outflag = 1 # happens in more places, so it's easier as default
2249 2254 try:
2250 2255 try:
2251 2256 self.hooks.pre_runcode_hook()
2252 2257 exec code_obj in self.user_global_ns, self.user_ns
2253 2258 finally:
2254 2259 # Reset our crash handler in place
2255 2260 sys.excepthook = old_excepthook
2256 2261 except SystemExit:
2257 2262 self.resetbuffer()
2258 2263 self.showtraceback()
2259 2264 warn("Type %exit or %quit to exit IPython "
2260 2265 "(%Exit or %Quit do so unconditionally).",level=1)
2261 2266 except self.custom_exceptions:
2262 2267 etype,value,tb = sys.exc_info()
2263 2268 self.CustomTB(etype,value,tb)
2264 2269 except:
2265 2270 self.showtraceback()
2266 2271 else:
2267 2272 outflag = 0
2268 2273 if softspace(sys.stdout, 0):
2269 2274 print
2270 2275 # Flush out code object which has been run (and source)
2271 2276 self.code_to_run = None
2272 2277 return outflag
2273 2278
2274 2279 def push(self, line):
2275 2280 """Push a line to the interpreter.
2276 2281
2277 2282 The line should not have a trailing newline; it may have
2278 2283 internal newlines. The line is appended to a buffer and the
2279 2284 interpreter's runsource() method is called with the
2280 2285 concatenated contents of the buffer as source. If this
2281 2286 indicates that the command was executed or invalid, the buffer
2282 2287 is reset; otherwise, the command is incomplete, and the buffer
2283 2288 is left as it was after the line was appended. The return
2284 2289 value is 1 if more input is required, 0 if the line was dealt
2285 2290 with in some way (this is the same as runsource()).
2286 2291 """
2287 2292
2288 2293 # autoindent management should be done here, and not in the
2289 2294 # interactive loop, since that one is only seen by keyboard input. We
2290 2295 # need this done correctly even for code run via runlines (which uses
2291 2296 # push).
2292 2297
2293 2298 #print 'push line: <%s>' % line # dbg
2294 2299 for subline in line.splitlines():
2295 2300 self.autoindent_update(subline)
2296 2301 self.buffer.append(line)
2297 2302 more = self.runsource('\n'.join(self.buffer), self.filename)
2298 2303 if not more:
2299 2304 self.resetbuffer()
2300 2305 return more
2301 2306
2302 2307 def split_user_input(self, line):
2303 2308 # This is really a hold-over to support ipapi and some extensions
2304 2309 return prefilter.splitUserInput(line)
2305 2310
2306 2311 def resetbuffer(self):
2307 2312 """Reset the input buffer."""
2308 2313 self.buffer[:] = []
2309 2314
2310 2315 def raw_input(self,prompt='',continue_prompt=False):
2311 2316 """Write a prompt and read a line.
2312 2317
2313 2318 The returned line does not include the trailing newline.
2314 2319 When the user enters the EOF key sequence, EOFError is raised.
2315 2320
2316 2321 Optional inputs:
2317 2322
2318 2323 - prompt(''): a string to be printed to prompt the user.
2319 2324
2320 2325 - continue_prompt(False): whether this line is the first one or a
2321 2326 continuation in a sequence of inputs.
2322 2327 """
2323 2328
2324 2329 # Code run by the user may have modified the readline completer state.
2325 2330 # We must ensure that our completer is back in place.
2326 2331 if self.has_readline:
2327 2332 self.set_completer()
2328 2333
2329 2334 try:
2330 2335 line = raw_input_original(prompt).decode(self.stdin_encoding)
2331 2336 except ValueError:
2332 2337 warn("\n********\nYou or a %run:ed script called sys.stdin.close()"
2333 2338 " or sys.stdout.close()!\nExiting IPython!")
2334 2339 self.ask_exit()
2335 2340 return ""
2336 2341
2337 2342 # Try to be reasonably smart about not re-indenting pasted input more
2338 2343 # than necessary. We do this by trimming out the auto-indent initial
2339 2344 # spaces, if the user's actual input started itself with whitespace.
2340 2345 #debugx('self.buffer[-1]')
2341 2346
2342 2347 if self.autoindent:
2343 2348 if num_ini_spaces(line) > self.indent_current_nsp:
2344 2349 line = line[self.indent_current_nsp:]
2345 2350 self.indent_current_nsp = 0
2346 2351
2347 2352 # store the unfiltered input before the user has any chance to modify
2348 2353 # it.
2349 2354 if line.strip():
2350 2355 if continue_prompt:
2351 2356 self.input_hist_raw[-1] += '%s\n' % line
2352 2357 if self.has_readline: # and some config option is set?
2353 2358 try:
2354 2359 histlen = self.readline.get_current_history_length()
2355 2360 if histlen > 1:
2356 2361 newhist = self.input_hist_raw[-1].rstrip()
2357 2362 self.readline.remove_history_item(histlen-1)
2358 2363 self.readline.replace_history_item(histlen-2,
2359 2364 newhist.encode(self.stdin_encoding))
2360 2365 except AttributeError:
2361 2366 pass # re{move,place}_history_item are new in 2.4.
2362 2367 else:
2363 2368 self.input_hist_raw.append('%s\n' % line)
2364 2369 # only entries starting at first column go to shadow history
2365 2370 if line.lstrip() == line:
2366 2371 self.shadowhist.add(line.strip())
2367 2372 elif not continue_prompt:
2368 2373 self.input_hist_raw.append('\n')
2369 2374 try:
2370 2375 lineout = self.prefilter(line,continue_prompt)
2371 2376 except:
2372 2377 # blanket except, in case a user-defined prefilter crashes, so it
2373 2378 # can't take all of ipython with it.
2374 2379 self.showtraceback()
2375 2380 return ''
2376 2381 else:
2377 2382 return lineout
2378 2383
2379 2384 def _prefilter(self, line, continue_prompt):
2380 2385 """Calls different preprocessors, depending on the form of line."""
2381 2386
2382 2387 # All handlers *must* return a value, even if it's blank ('').
2383 2388
2384 2389 # Lines are NOT logged here. Handlers should process the line as
2385 2390 # needed, update the cache AND log it (so that the input cache array
2386 2391 # stays synced).
2387 2392
2388 2393 #.....................................................................
2389 2394 # Code begins
2390 2395
2391 2396 #if line.startswith('%crash'): raise RuntimeError,'Crash now!' # dbg
2392 2397
2393 2398 # save the line away in case we crash, so the post-mortem handler can
2394 2399 # record it
2395 2400 self._last_input_line = line
2396 2401
2397 2402 #print '***line: <%s>' % line # dbg
2398 2403
2399 2404 if not line:
2400 2405 # Return immediately on purely empty lines, so that if the user
2401 2406 # previously typed some whitespace that started a continuation
2402 2407 # prompt, he can break out of that loop with just an empty line.
2403 2408 # This is how the default python prompt works.
2404 2409
2405 2410 # Only return if the accumulated input buffer was just whitespace!
2406 2411 if ''.join(self.buffer).isspace():
2407 2412 self.buffer[:] = []
2408 2413 return ''
2409 2414
2410 2415 line_info = prefilter.LineInfo(line, continue_prompt)
2411 2416
2412 2417 # the input history needs to track even empty lines
2413 2418 stripped = line.strip()
2414 2419
2415 2420 if not stripped:
2416 2421 if not continue_prompt:
2417 2422 self.outputcache.prompt_count -= 1
2418 2423 return self.handle_normal(line_info)
2419 2424
2420 2425 # print '***cont',continue_prompt # dbg
2421 2426 # special handlers are only allowed for single line statements
2422 2427 if continue_prompt and not self.rc.multi_line_specials:
2423 2428 return self.handle_normal(line_info)
2424 2429
2425 2430
2426 2431 # See whether any pre-existing handler can take care of it
2427 2432 rewritten = self.hooks.input_prefilter(stripped)
2428 2433 if rewritten != stripped: # ok, some prefilter did something
2429 2434 rewritten = line_info.pre + rewritten # add indentation
2430 2435 return self.handle_normal(prefilter.LineInfo(rewritten,
2431 2436 continue_prompt))
2432 2437
2433 2438 #print 'pre <%s> iFun <%s> rest <%s>' % (pre,iFun,theRest) # dbg
2434 2439
2435 2440 return prefilter.prefilter(line_info, self)
2436 2441
2437 2442
2438 2443 def _prefilter_dumb(self, line, continue_prompt):
2439 2444 """simple prefilter function, for debugging"""
2440 2445 return self.handle_normal(line,continue_prompt)
2441 2446
2442 2447
2443 2448 def multiline_prefilter(self, line, continue_prompt):
2444 2449 """ Run _prefilter for each line of input
2445 2450
2446 2451 Covers cases where there are multiple lines in the user entry,
2447 2452 which is the case when the user goes back to a multiline history
2448 2453 entry and presses enter.
2449 2454
2450 2455 """
2451 2456 out = []
2452 2457 for l in line.rstrip('\n').split('\n'):
2453 2458 out.append(self._prefilter(l, continue_prompt))
2454 2459 return '\n'.join(out)
2455 2460
2456 2461 # Set the default prefilter() function (this can be user-overridden)
2457 2462 prefilter = multiline_prefilter
2458 2463
2459 2464 def handle_normal(self,line_info):
2460 2465 """Handle normal input lines. Use as a template for handlers."""
2461 2466
2462 2467 # With autoindent on, we need some way to exit the input loop, and I
2463 2468 # don't want to force the user to have to backspace all the way to
2464 2469 # clear the line. The rule will be in this case, that either two
2465 2470 # lines of pure whitespace in a row, or a line of pure whitespace but
2466 2471 # of a size different to the indent level, will exit the input loop.
2467 2472 line = line_info.line
2468 2473 continue_prompt = line_info.continue_prompt
2469 2474
2470 2475 if (continue_prompt and self.autoindent and line.isspace() and
2471 2476 (0 < abs(len(line) - self.indent_current_nsp) <= 2 or
2472 2477 (self.buffer[-1]).isspace() )):
2473 2478 line = ''
2474 2479
2475 2480 self.log(line,line,continue_prompt)
2476 2481 return line
2477 2482
2478 2483 def handle_alias(self,line_info):
2479 2484 """Handle alias input lines. """
2480 2485 tgt = self.alias_table[line_info.iFun]
2481 2486 # print "=>",tgt #dbg
2482 2487 if callable(tgt):
2483 2488 if '$' in line_info.line:
2484 2489 call_meth = '(_ip, _ip.itpl(%s))'
2485 2490 else:
2486 2491 call_meth = '(_ip,%s)'
2487 2492 line_out = ("%s_sh.%s" + call_meth) % (line_info.preWhitespace,
2488 2493 line_info.iFun,
2489 2494 make_quoted_expr(line_info.line))
2490 2495 else:
2491 2496 transformed = self.expand_aliases(line_info.iFun,line_info.theRest)
2492 2497
2493 2498 # pre is needed, because it carries the leading whitespace. Otherwise
2494 2499 # aliases won't work in indented sections.
2495 2500 line_out = '%s_ip.system(%s)' % (line_info.preWhitespace,
2496 2501 make_quoted_expr( transformed ))
2497 2502
2498 2503 self.log(line_info.line,line_out,line_info.continue_prompt)
2499 2504 #print 'line out:',line_out # dbg
2500 2505 return line_out
2501 2506
2502 2507 def handle_shell_escape(self, line_info):
2503 2508 """Execute the line in a shell, empty return value"""
2504 2509 #print 'line in :', `line` # dbg
2505 2510 line = line_info.line
2506 2511 if line.lstrip().startswith('!!'):
2507 2512 # rewrite LineInfo's line, iFun and theRest to properly hold the
2508 2513 # call to %sx and the actual command to be executed, so
2509 2514 # handle_magic can work correctly. Note that this works even if
2510 2515 # the line is indented, so it handles multi_line_specials
2511 2516 # properly.
2512 2517 new_rest = line.lstrip()[2:]
2513 2518 line_info.line = '%ssx %s' % (self.ESC_MAGIC,new_rest)
2514 2519 line_info.iFun = 'sx'
2515 2520 line_info.theRest = new_rest
2516 2521 return self.handle_magic(line_info)
2517 2522 else:
2518 2523 cmd = line.lstrip().lstrip('!')
2519 2524 line_out = '%s_ip.system(%s)' % (line_info.preWhitespace,
2520 2525 make_quoted_expr(cmd))
2521 2526 # update cache/log and return
2522 2527 self.log(line,line_out,line_info.continue_prompt)
2523 2528 return line_out
2524 2529
2525 2530 def handle_magic(self, line_info):
2526 2531 """Execute magic functions."""
2527 2532 iFun = line_info.iFun
2528 2533 theRest = line_info.theRest
2529 2534 cmd = '%s_ip.magic(%s)' % (line_info.preWhitespace,
2530 2535 make_quoted_expr(iFun + " " + theRest))
2531 2536 self.log(line_info.line,cmd,line_info.continue_prompt)
2532 2537 #print 'in handle_magic, cmd=<%s>' % cmd # dbg
2533 2538 return cmd
2534 2539
2535 2540 def handle_auto(self, line_info):
2536 2541 """Hande lines which can be auto-executed, quoting if requested."""
2537 2542
2538 2543 line = line_info.line
2539 2544 iFun = line_info.iFun
2540 2545 theRest = line_info.theRest
2541 2546 pre = line_info.pre
2542 2547 continue_prompt = line_info.continue_prompt
2543 2548 obj = line_info.ofind(self)['obj']
2544 2549
2545 2550 #print 'pre <%s> iFun <%s> rest <%s>' % (pre,iFun,theRest) # dbg
2546 2551
2547 2552 # This should only be active for single-line input!
2548 2553 if continue_prompt:
2549 2554 self.log(line,line,continue_prompt)
2550 2555 return line
2551 2556
2552 2557 force_auto = isinstance(obj, IPython.ipapi.IPyAutocall)
2553 2558 auto_rewrite = True
2554 2559
2555 2560 if pre == self.ESC_QUOTE:
2556 2561 # Auto-quote splitting on whitespace
2557 2562 newcmd = '%s("%s")' % (iFun,'", "'.join(theRest.split()) )
2558 2563 elif pre == self.ESC_QUOTE2:
2559 2564 # Auto-quote whole string
2560 2565 newcmd = '%s("%s")' % (iFun,theRest)
2561 2566 elif pre == self.ESC_PAREN:
2562 2567 newcmd = '%s(%s)' % (iFun,",".join(theRest.split()))
2563 2568 else:
2564 2569 # Auto-paren.
2565 2570 # We only apply it to argument-less calls if the autocall
2566 2571 # parameter is set to 2. We only need to check that autocall is <
2567 2572 # 2, since this function isn't called unless it's at least 1.
2568 2573 if not theRest and (self.rc.autocall < 2) and not force_auto:
2569 2574 newcmd = '%s %s' % (iFun,theRest)
2570 2575 auto_rewrite = False
2571 2576 else:
2572 2577 if not force_auto and theRest.startswith('['):
2573 2578 if hasattr(obj,'__getitem__'):
2574 2579 # Don't autocall in this case: item access for an object
2575 2580 # which is BOTH callable and implements __getitem__.
2576 2581 newcmd = '%s %s' % (iFun,theRest)
2577 2582 auto_rewrite = False
2578 2583 else:
2579 2584 # if the object doesn't support [] access, go ahead and
2580 2585 # autocall
2581 2586 newcmd = '%s(%s)' % (iFun.rstrip(),theRest)
2582 2587 elif theRest.endswith(';'):
2583 2588 newcmd = '%s(%s);' % (iFun.rstrip(),theRest[:-1])
2584 2589 else:
2585 2590 newcmd = '%s(%s)' % (iFun.rstrip(), theRest)
2586 2591
2587 2592 if auto_rewrite:
2588 2593 rw = self.outputcache.prompt1.auto_rewrite() + newcmd
2589 2594
2590 2595 try:
2591 2596 # plain ascii works better w/ pyreadline, on some machines, so
2592 2597 # we use it and only print uncolored rewrite if we have unicode
2593 2598 rw = str(rw)
2594 2599 print >>Term.cout, rw
2595 2600 except UnicodeEncodeError:
2596 2601 print "-------------->" + newcmd
2597 2602
2598 2603 # log what is now valid Python, not the actual user input (without the
2599 2604 # final newline)
2600 2605 self.log(line,newcmd,continue_prompt)
2601 2606 return newcmd
2602 2607
2603 2608 def handle_help(self, line_info):
2604 2609 """Try to get some help for the object.
2605 2610
2606 2611 obj? or ?obj -> basic information.
2607 2612 obj?? or ??obj -> more details.
2608 2613 """
2609 2614
2610 2615 line = line_info.line
2611 2616 # We need to make sure that we don't process lines which would be
2612 2617 # otherwise valid python, such as "x=1 # what?"
2613 2618 try:
2614 2619 codeop.compile_command(line)
2615 2620 except SyntaxError:
2616 2621 # We should only handle as help stuff which is NOT valid syntax
2617 2622 if line[0]==self.ESC_HELP:
2618 2623 line = line[1:]
2619 2624 elif line[-1]==self.ESC_HELP:
2620 2625 line = line[:-1]
2621 2626 self.log(line,'#?'+line,line_info.continue_prompt)
2622 2627 if line:
2623 2628 #print 'line:<%r>' % line # dbg
2624 2629 self.magic_pinfo(line)
2625 2630 else:
2626 2631 page(self.usage,screen_lines=self.rc.screen_length)
2627 2632 return '' # Empty string is needed here!
2628 2633 except:
2629 2634 # Pass any other exceptions through to the normal handler
2630 2635 return self.handle_normal(line_info)
2631 2636 else:
2632 2637 # If the code compiles ok, we should handle it normally
2633 2638 return self.handle_normal(line_info)
2634 2639
2635 2640 def getapi(self):
2636 2641 """ Get an IPApi object for this shell instance
2637 2642
2638 2643 Getting an IPApi object is always preferable to accessing the shell
2639 2644 directly, but this holds true especially for extensions.
2640 2645
2641 2646 It should always be possible to implement an extension with IPApi
2642 2647 alone. If not, contact maintainer to request an addition.
2643 2648
2644 2649 """
2645 2650 return self.api
2646 2651
2647 2652 def handle_emacs(self, line_info):
2648 2653 """Handle input lines marked by python-mode."""
2649 2654
2650 2655 # Currently, nothing is done. Later more functionality can be added
2651 2656 # here if needed.
2652 2657
2653 2658 # The input cache shouldn't be updated
2654 2659 return line_info.line
2655 2660
2656 2661
2657 2662 def mktempfile(self,data=None):
2658 2663 """Make a new tempfile and return its filename.
2659 2664
2660 2665 This makes a call to tempfile.mktemp, but it registers the created
2661 2666 filename internally so ipython cleans it up at exit time.
2662 2667
2663 2668 Optional inputs:
2664 2669
2665 2670 - data(None): if data is given, it gets written out to the temp file
2666 2671 immediately, and the file is closed again."""
2667 2672
2668 2673 filename = tempfile.mktemp('.py','ipython_edit_')
2669 2674 self.tempfiles.append(filename)
2670 2675
2671 2676 if data:
2672 2677 tmp_file = open(filename,'w')
2673 2678 tmp_file.write(data)
2674 2679 tmp_file.close()
2675 2680 return filename
2676 2681
2677 2682 def write(self,data):
2678 2683 """Write a string to the default output"""
2679 2684 Term.cout.write(data)
2680 2685
2681 2686 def write_err(self,data):
2682 2687 """Write a string to the default error output"""
2683 2688 Term.cerr.write(data)
2684 2689
2685 2690 def ask_exit(self):
2686 2691 """ Call for exiting. Can be overiden and used as a callback. """
2687 2692 self.exit_now = True
2688 2693
2689 2694 def exit(self):
2690 2695 """Handle interactive exit.
2691 2696
2692 2697 This method calls the ask_exit callback."""
2693 2698
2694 2699 if self.rc.confirm_exit:
2695 2700 if self.ask_yes_no('Do you really want to exit ([y]/n)?','y'):
2696 2701 self.ask_exit()
2697 2702 else:
2698 2703 self.ask_exit()
2699 2704
2700 2705 def safe_execfile(self,fname,*where,**kw):
2701 2706 """A safe version of the builtin execfile().
2702 2707
2703 2708 This version will never throw an exception, and knows how to handle
2704 2709 ipython logs as well.
2705 2710
2706 2711 :Parameters:
2707 2712 fname : string
2708 2713 Name of the file to be executed.
2709 2714
2710 2715 where : tuple
2711 2716 One or two namespaces, passed to execfile() as (globals,locals).
2712 2717 If only one is given, it is passed as both.
2713 2718
2714 2719 :Keywords:
2715 2720 islog : boolean (False)
2716 2721
2717 2722 quiet : boolean (True)
2718 2723
2719 2724 exit_ignore : boolean (False)
2720 2725 """
2721 2726
2722 2727 def syspath_cleanup():
2723 2728 """Internal cleanup routine for sys.path."""
2724 2729 if add_dname:
2725 2730 try:
2726 2731 sys.path.remove(dname)
2727 2732 except ValueError:
2728 2733 # For some reason the user has already removed it, ignore.
2729 2734 pass
2730 2735
2731 2736 fname = os.path.expanduser(fname)
2732 2737
2733 2738 # Find things also in current directory. This is needed to mimic the
2734 2739 # behavior of running a script from the system command line, where
2735 2740 # Python inserts the script's directory into sys.path
2736 2741 dname = os.path.dirname(os.path.abspath(fname))
2737 2742 add_dname = False
2738 2743 if dname not in sys.path:
2739 2744 sys.path.insert(0,dname)
2740 2745 add_dname = True
2741 2746
2742 2747 try:
2743 2748 xfile = open(fname)
2744 2749 except:
2745 2750 print >> Term.cerr, \
2746 2751 'Could not open file <%s> for safe execution.' % fname
2747 2752 syspath_cleanup()
2748 2753 return None
2749 2754
2750 2755 kw.setdefault('islog',0)
2751 2756 kw.setdefault('quiet',1)
2752 2757 kw.setdefault('exit_ignore',0)
2753 2758
2754 2759 first = xfile.readline()
2755 2760 loghead = str(self.loghead_tpl).split('\n',1)[0].strip()
2756 2761 xfile.close()
2757 2762 # line by line execution
2758 2763 if first.startswith(loghead) or kw['islog']:
2759 2764 print 'Loading log file <%s> one line at a time...' % fname
2760 2765 if kw['quiet']:
2761 2766 stdout_save = sys.stdout
2762 2767 sys.stdout = StringIO.StringIO()
2763 2768 try:
2764 2769 globs,locs = where[0:2]
2765 2770 except:
2766 2771 try:
2767 2772 globs = locs = where[0]
2768 2773 except:
2769 2774 globs = locs = globals()
2770 2775 badblocks = []
2771 2776
2772 2777 # we also need to identify indented blocks of code when replaying
2773 2778 # logs and put them together before passing them to an exec
2774 2779 # statement. This takes a bit of regexp and look-ahead work in the
2775 2780 # file. It's easiest if we swallow the whole thing in memory
2776 2781 # first, and manually walk through the lines list moving the
2777 2782 # counter ourselves.
2778 2783 indent_re = re.compile('\s+\S')
2779 2784 xfile = open(fname)
2780 2785 filelines = xfile.readlines()
2781 2786 xfile.close()
2782 2787 nlines = len(filelines)
2783 2788 lnum = 0
2784 2789 while lnum < nlines:
2785 2790 line = filelines[lnum]
2786 2791 lnum += 1
2787 2792 # don't re-insert logger status info into cache
2788 2793 if line.startswith('#log#'):
2789 2794 continue
2790 2795 else:
2791 2796 # build a block of code (maybe a single line) for execution
2792 2797 block = line
2793 2798 try:
2794 2799 next = filelines[lnum] # lnum has already incremented
2795 2800 except:
2796 2801 next = None
2797 2802 while next and indent_re.match(next):
2798 2803 block += next
2799 2804 lnum += 1
2800 2805 try:
2801 2806 next = filelines[lnum]
2802 2807 except:
2803 2808 next = None
2804 2809 # now execute the block of one or more lines
2805 2810 try:
2806 2811 exec block in globs,locs
2807 2812 except SystemExit:
2808 2813 pass
2809 2814 except:
2810 2815 badblocks.append(block.rstrip())
2811 2816 if kw['quiet']: # restore stdout
2812 2817 sys.stdout.close()
2813 2818 sys.stdout = stdout_save
2814 2819 print 'Finished replaying log file <%s>' % fname
2815 2820 if badblocks:
2816 2821 print >> sys.stderr, ('\nThe following lines/blocks in file '
2817 2822 '<%s> reported errors:' % fname)
2818 2823
2819 2824 for badline in badblocks:
2820 2825 print >> sys.stderr, badline
2821 2826 else: # regular file execution
2822 2827 try:
2823 2828 if sys.platform == 'win32' and sys.version_info < (2,5,1):
2824 2829 # Work around a bug in Python for Windows. The bug was
2825 2830 # fixed in in Python 2.5 r54159 and 54158, but that's still
2826 2831 # SVN Python as of March/07. For details, see:
2827 2832 # http://projects.scipy.org/ipython/ipython/ticket/123
2828 2833 try:
2829 2834 globs,locs = where[0:2]
2830 2835 except:
2831 2836 try:
2832 2837 globs = locs = where[0]
2833 2838 except:
2834 2839 globs = locs = globals()
2835 2840 exec file(fname) in globs,locs
2836 2841 else:
2837 2842 execfile(fname,*where)
2838 2843 except SyntaxError:
2839 2844 self.showsyntaxerror()
2840 2845 warn('Failure executing file: <%s>' % fname)
2841 2846 except SystemExit,status:
2842 2847 # Code that correctly sets the exit status flag to success (0)
2843 2848 # shouldn't be bothered with a traceback. Note that a plain
2844 2849 # sys.exit() does NOT set the message to 0 (it's empty) so that
2845 2850 # will still get a traceback. Note that the structure of the
2846 2851 # SystemExit exception changed between Python 2.4 and 2.5, so
2847 2852 # the checks must be done in a version-dependent way.
2848 2853 show = False
2849 2854
2850 2855 if sys.version_info[:2] > (2,5):
2851 2856 if status.message!=0 and not kw['exit_ignore']:
2852 2857 show = True
2853 2858 else:
2854 2859 if status.code and not kw['exit_ignore']:
2855 2860 show = True
2856 2861 if show:
2857 2862 self.showtraceback()
2858 2863 warn('Failure executing file: <%s>' % fname)
2859 2864 except:
2860 2865 self.showtraceback()
2861 2866 warn('Failure executing file: <%s>' % fname)
2862 2867
2863 2868 syspath_cleanup()
2864 2869
2865 2870 #************************* end of file <iplib.py> *****************************
@@ -1,773 +1,773 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 IPython -- An enhanced Interactive Python
4 4
5 5 Requires Python 2.1 or better.
6 6
7 7 This file contains the main make_IPython() starter function.
8 8 """
9 9
10 10 #*****************************************************************************
11 11 # Copyright (C) 2008-2009 The IPython Development Team
12 12 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
13 13 #
14 14 # Distributed under the terms of the BSD License. The full license is in
15 15 # the file COPYING, distributed as part of this software.
16 16 #*****************************************************************************
17 17
18 18 try:
19 19 credits._Printer__data = """
20 20 Python: %s
21 21
22 22 IPython: The IPython Development Team.
23 23 See http://ipython.scipy.org for more information.""" \
24 24 % credits._Printer__data
25 25
26 26 copyright._Printer__data += """
27 27
28 28 Copyright (c) 2008-2009 The IPython Development Team.
29 29 Copyright (c) 2001-2007 Fernando Perez, Janko Hauser, Nathan Gray.
30 30 All Rights Reserved."""
31 31 except NameError:
32 32 # Can happen if ipython was started with 'python -S', so that site.py is
33 33 # not loaded
34 34 pass
35 35
36 36 #****************************************************************************
37 37 # Required modules
38 38
39 39 # From the standard library
40 40 import __main__
41 41 import __builtin__
42 42 import os
43 43 import re
44 44 import sys
45 45 import types
46 46 from pprint import pprint,pformat
47 47
48 48 # Our own
49 49 from IPython import DPyGetOpt
50 50 from IPython import Release
51 51 from IPython.ipstruct import Struct
52 52 from IPython.OutputTrap import OutputTrap
53 53 from IPython.ConfigLoader import ConfigLoader
54 54 from IPython.iplib import InteractiveShell
55 55 from IPython.usage import cmd_line_usage,interactive_usage
56 56 from IPython.genutils import *
57 57
58 def force_import(modname):
59 if modname in sys.modules:
60 print "reload",modname
58 def force_import(modname,force_reload=False):
59 if modname in sys.modules and force_reload:
60 info("reloading: %s" % modname)
61 61 reload(sys.modules[modname])
62 62 else:
63 63 __import__(modname)
64 64
65 65
66 66 #-----------------------------------------------------------------------------
67 67 def make_IPython(argv=None,user_ns=None,user_global_ns=None,debug=1,
68 68 rc_override=None,shell_class=InteractiveShell,
69 69 embedded=False,**kw):
70 70 """This is a dump of IPython into a single function.
71 71
72 72 Later it will have to be broken up in a sensible manner.
73 73
74 74 Arguments:
75 75
76 76 - argv: a list similar to sys.argv[1:]. It should NOT contain the desired
77 77 script name, b/c DPyGetOpt strips the first argument only for the real
78 78 sys.argv.
79 79
80 80 - user_ns: a dict to be used as the user's namespace."""
81 81
82 82 #----------------------------------------------------------------------
83 83 # Defaults and initialization
84 84
85 85 # For developer debugging, deactivates crash handler and uses pdb.
86 86 DEVDEBUG = False
87 87
88 88 if argv is None:
89 89 argv = sys.argv
90 90
91 91 # __IP is the main global that lives throughout and represents the whole
92 92 # application. If the user redefines it, all bets are off as to what
93 93 # happens.
94 94
95 95 # __IP is the name of he global which the caller will have accessible as
96 96 # __IP.name. We set its name via the first parameter passed to
97 97 # InteractiveShell:
98 98
99 99 IP = shell_class('__IP',user_ns=user_ns,user_global_ns=user_global_ns,
100 100 embedded=embedded,**kw)
101 101
102 102 # Put 'help' in the user namespace
103 103 try:
104 104 from site import _Helper
105 105 IP.user_ns['help'] = _Helper()
106 106 except ImportError:
107 107 warn('help() not available - check site.py')
108 108
109 109 if DEVDEBUG:
110 110 # For developer debugging only (global flag)
111 111 from IPython import ultraTB
112 112 sys.excepthook = ultraTB.VerboseTB(call_pdb=1)
113 113
114 114 IP.BANNER_PARTS = ['Python %s\n'
115 115 'Type "copyright", "credits" or "license" '
116 116 'for more information.\n'
117 117 % (sys.version.split('\n')[0],),
118 118 "IPython %s -- An enhanced Interactive Python."
119 119 % (Release.version,),
120 120 """\
121 121 ? -> Introduction and overview of IPython's features.
122 122 %quickref -> Quick reference.
123 123 help -> Python's own help system.
124 124 object? -> Details about 'object'. ?object also works, ?? prints more.
125 125 """ ]
126 126
127 127 IP.usage = interactive_usage
128 128
129 129 # Platform-dependent suffix.
130 130 if os.name == 'posix':
131 131 rc_suffix = ''
132 132 else:
133 133 rc_suffix = '.ini'
134 134
135 135 # default directory for configuration
136 136 ipythondir_def = get_ipython_dir()
137 137
138 138 sys.path.insert(0, '') # add . to sys.path. Fix from Prabhu Ramachandran
139 139
140 140 # we need the directory where IPython itself is installed
141 141 import IPython
142 142 IPython_dir = os.path.dirname(IPython.__file__)
143 143 del IPython
144 144
145 145 #-------------------------------------------------------------------------
146 146 # Command line handling
147 147
148 148 # Valid command line options (uses DPyGetOpt syntax, like Perl's
149 149 # GetOpt::Long)
150 150
151 151 # Any key not listed here gets deleted even if in the file (like session
152 152 # or profile). That's deliberate, to maintain the rc namespace clean.
153 153
154 154 # Each set of options appears twice: under _conv only the names are
155 155 # listed, indicating which type they must be converted to when reading the
156 156 # ipythonrc file. And under DPyGetOpt they are listed with the regular
157 157 # DPyGetOpt syntax (=s,=i,:f,etc).
158 158
159 159 # Make sure there's a space before each end of line (they get auto-joined!)
160 160 cmdline_opts = ('autocall=i autoindent! automagic! banner! cache_size|cs=i '
161 161 'c=s classic|cl color_info! colors=s confirm_exit! '
162 162 'debug! deep_reload! editor=s log|l messages! nosep '
163 163 'object_info_string_level=i pdb! '
164 164 'pprint! prompt_in1|pi1=s prompt_in2|pi2=s prompt_out|po=s '
165 165 'pydb! '
166 166 'pylab_import_all! '
167 167 'quick screen_length|sl=i prompts_pad_left=i '
168 168 'logfile|lf=s logplay|lp=s profile|p=s '
169 169 'readline! readline_merge_completions! '
170 170 'readline_omit__names! '
171 171 'rcfile=s separate_in|si=s separate_out|so=s '
172 172 'separate_out2|so2=s xmode=s wildcards_case_sensitive! '
173 173 'magic_docstrings system_verbose! '
174 174 'multi_line_specials! '
175 175 'term_title! wxversion=s '
176 176 'autoedit_syntax!')
177 177
178 178 # Options that can *only* appear at the cmd line (not in rcfiles).
179 179
180 180 cmdline_only = ('help interact|i ipythondir=s Version upgrade '
181 181 'gthread! qthread! q4thread! wthread! tkthread! pylab! tk! '
182 182 # 'twisted!' # disabled for now.
183 183 )
184 184
185 185 # Build the actual name list to be used by DPyGetOpt
186 186 opts_names = qw(cmdline_opts) + qw(cmdline_only)
187 187
188 188 # Set sensible command line defaults.
189 189 # This should have everything from cmdline_opts and cmdline_only
190 190 opts_def = Struct(autocall = 1,
191 191 autoedit_syntax = 0,
192 192 autoindent = 0,
193 193 automagic = 1,
194 194 autoexec = [],
195 195 banner = 1,
196 196 c = '',
197 197 cache_size = 1000,
198 198 classic = 0,
199 199 color_info = 0,
200 200 colors = 'NoColor',
201 201 confirm_exit = 1,
202 202 debug = 0,
203 203 deep_reload = 0,
204 204 editor = '0',
205 205 gthread = 0,
206 206 help = 0,
207 207 interact = 0,
208 208 ipythondir = ipythondir_def,
209 209 log = 0,
210 210 logfile = '',
211 211 logplay = '',
212 212 messages = 1,
213 213 multi_line_specials = 1,
214 214 nosep = 0,
215 215 object_info_string_level = 0,
216 216 pdb = 0,
217 217 pprint = 0,
218 218 profile = '',
219 219 prompt_in1 = 'In [\\#]: ',
220 220 prompt_in2 = ' .\\D.: ',
221 221 prompt_out = 'Out[\\#]: ',
222 222 prompts_pad_left = 1,
223 223 pydb = 0,
224 224 pylab = 0,
225 225 pylab_import_all = 1,
226 226 q4thread = 0,
227 227 qthread = 0,
228 228 quick = 0,
229 229 quiet = 0,
230 230 rcfile = 'ipythonrc' + rc_suffix,
231 231 readline = 1,
232 232 readline_merge_completions = 1,
233 233 readline_omit__names = 0,
234 234 screen_length = 0,
235 235 separate_in = '\n',
236 236 separate_out = '\n',
237 237 separate_out2 = '',
238 238 system_header = 'IPython system call: ',
239 239 system_verbose = 0,
240 240 term_title = 1,
241 241 tk = 0,
242 242 #twisted= 0, # disabled for now
243 243 upgrade = 0,
244 244 Version = 0,
245 245 wildcards_case_sensitive = 1,
246 246 wthread = 0,
247 247 wxversion = '0',
248 248 xmode = 'Context',
249 249 magic_docstrings = 0, # undocumented, for doc generation
250 250 )
251 251
252 252 # Things that will *only* appear in rcfiles (not at the command line).
253 253 # Make sure there's a space before each end of line (they get auto-joined!)
254 254 rcfile_opts = { qwflat: 'include import_mod import_all execfile ',
255 255 qw_lol: 'import_some ',
256 256 # for things with embedded whitespace:
257 257 list_strings:'execute alias readline_parse_and_bind ',
258 258 # Regular strings need no conversion:
259 259 None:'readline_remove_delims ',
260 260 }
261 261 # Default values for these
262 262 rc_def = Struct(include = [],
263 263 import_mod = [],
264 264 import_all = [],
265 265 import_some = [[]],
266 266 execute = [],
267 267 execfile = [],
268 268 alias = [],
269 269 readline_parse_and_bind = [],
270 270 readline_remove_delims = '',
271 271 )
272 272
273 273 # Build the type conversion dictionary from the above tables:
274 274 typeconv = rcfile_opts.copy()
275 275 typeconv.update(optstr2types(cmdline_opts))
276 276
277 277 # FIXME: the None key appears in both, put that back together by hand. Ugly!
278 278 typeconv[None] += ' ' + rcfile_opts[None]
279 279
280 280 # Remove quotes at ends of all strings (used to protect spaces)
281 281 typeconv[unquote_ends] = typeconv[None]
282 282 del typeconv[None]
283 283
284 284 # Build the list we'll use to make all config decisions with defaults:
285 285 opts_all = opts_def.copy()
286 286 opts_all.update(rc_def)
287 287
288 288 # Build conflict resolver for recursive loading of config files:
289 289 # - preserve means the outermost file maintains the value, it is not
290 290 # overwritten if an included file has the same key.
291 291 # - add_flip applies + to the two values, so it better make sense to add
292 292 # those types of keys. But it flips them first so that things loaded
293 293 # deeper in the inclusion chain have lower precedence.
294 294 conflict = {'preserve': ' '.join([ typeconv[int],
295 295 typeconv[unquote_ends] ]),
296 296 'add_flip': ' '.join([ typeconv[qwflat],
297 297 typeconv[qw_lol],
298 298 typeconv[list_strings] ])
299 299 }
300 300
301 301 # Now actually process the command line
302 302 getopt = DPyGetOpt.DPyGetOpt()
303 303 getopt.setIgnoreCase(0)
304 304
305 305 getopt.parseConfiguration(opts_names)
306 306
307 307 try:
308 308 getopt.processArguments(argv)
309 309 except DPyGetOpt.ArgumentError, exc:
310 310 print cmd_line_usage
311 311 warn('\nError in Arguments: "%s"' % exc)
312 312 sys.exit(1)
313 313
314 314 # convert the options dict to a struct for much lighter syntax later
315 315 opts = Struct(getopt.optionValues)
316 316 args = getopt.freeValues
317 317
318 318 # this is the struct (which has default values at this point) with which
319 319 # we make all decisions:
320 320 opts_all.update(opts)
321 321
322 322 # Options that force an immediate exit
323 323 if opts_all.help:
324 324 page(cmd_line_usage)
325 325 sys.exit()
326 326
327 327 if opts_all.Version:
328 328 print Release.version
329 329 sys.exit()
330 330
331 331 if opts_all.magic_docstrings:
332 332 IP.magic_magic('-latex')
333 333 sys.exit()
334 334
335 335 # add personal ipythondir to sys.path so that users can put things in
336 336 # there for customization
337 337 sys.path.append(os.path.abspath(opts_all.ipythondir))
338 338
339 339 # Create user config directory if it doesn't exist. This must be done
340 340 # *after* getting the cmd line options.
341 341 if not os.path.isdir(opts_all.ipythondir):
342 342 IP.user_setup(opts_all.ipythondir,rc_suffix,'install')
343 343
344 344 # upgrade user config files while preserving a copy of the originals
345 345 if opts_all.upgrade:
346 346 IP.user_setup(opts_all.ipythondir,rc_suffix,'upgrade')
347 347
348 348 # check mutually exclusive options in the *original* command line
349 349 mutex_opts(opts,[qw('log logfile'),qw('rcfile profile'),
350 350 qw('classic profile'),qw('classic rcfile')])
351 351
352 352 #---------------------------------------------------------------------------
353 353 # Log replay
354 354
355 355 # if -logplay, we need to 'become' the other session. That basically means
356 356 # replacing the current command line environment with that of the old
357 357 # session and moving on.
358 358
359 359 # this is needed so that later we know we're in session reload mode, as
360 360 # opts_all will get overwritten:
361 361 load_logplay = 0
362 362
363 363 if opts_all.logplay:
364 364 load_logplay = opts_all.logplay
365 365 opts_debug_save = opts_all.debug
366 366 try:
367 367 logplay = open(opts_all.logplay)
368 368 except IOError:
369 369 if opts_all.debug: IP.InteractiveTB()
370 370 warn('Could not open logplay file '+`opts_all.logplay`)
371 371 # restore state as if nothing had happened and move on, but make
372 372 # sure that later we don't try to actually load the session file
373 373 logplay = None
374 374 load_logplay = 0
375 375 del opts_all.logplay
376 376 else:
377 377 try:
378 378 logplay.readline()
379 379 logplay.readline();
380 380 # this reloads that session's command line
381 381 cmd = logplay.readline()[6:]
382 382 exec cmd
383 383 # restore the true debug flag given so that the process of
384 384 # session loading itself can be monitored.
385 385 opts.debug = opts_debug_save
386 386 # save the logplay flag so later we don't overwrite the log
387 387 opts.logplay = load_logplay
388 388 # now we must update our own structure with defaults
389 389 opts_all.update(opts)
390 390 # now load args
391 391 cmd = logplay.readline()[6:]
392 392 exec cmd
393 393 logplay.close()
394 394 except:
395 395 logplay.close()
396 396 if opts_all.debug: IP.InteractiveTB()
397 397 warn("Logplay file lacking full configuration information.\n"
398 398 "I'll try to read it, but some things may not work.")
399 399
400 400 #-------------------------------------------------------------------------
401 401 # set up output traps: catch all output from files, being run, modules
402 402 # loaded, etc. Then give it to the user in a clean form at the end.
403 403
404 404 msg_out = 'Output messages. '
405 405 msg_err = 'Error messages. '
406 406 msg_sep = '\n'
407 407 msg = Struct(config = OutputTrap('Configuration Loader',msg_out,
408 408 msg_err,msg_sep,debug,
409 409 quiet_out=1),
410 410 user_exec = OutputTrap('User File Execution',msg_out,
411 411 msg_err,msg_sep,debug),
412 412 logplay = OutputTrap('Log Loader',msg_out,
413 413 msg_err,msg_sep,debug),
414 414 summary = ''
415 415 )
416 416
417 417 #-------------------------------------------------------------------------
418 418 # Process user ipythonrc-type configuration files
419 419
420 420 # turn on output trapping and log to msg.config
421 421 # remember that with debug on, trapping is actually disabled
422 422 msg.config.trap_all()
423 423
424 424 # look for rcfile in current or default directory
425 425 try:
426 426 opts_all.rcfile = filefind(opts_all.rcfile,opts_all.ipythondir)
427 427 except IOError:
428 428 if opts_all.debug: IP.InteractiveTB()
429 429 warn('Configuration file %s not found. Ignoring request.'
430 430 % (opts_all.rcfile) )
431 431
432 432 # 'profiles' are a shorthand notation for config filenames
433 433 profile_handled_by_legacy = False
434 434 if opts_all.profile:
435 435
436 436 try:
437 437 opts_all.rcfile = filefind('ipythonrc-' + opts_all.profile
438 438 + rc_suffix,
439 439 opts_all.ipythondir)
440 440 profile_handled_by_legacy = True
441 441 except IOError:
442 442 if opts_all.debug: IP.InteractiveTB()
443 443 opts.profile = '' # remove profile from options if invalid
444 444 # We won't warn anymore, primary method is ipy_profile_PROFNAME
445 445 # which does trigger a warning.
446 446
447 447 # load the config file
448 448 rcfiledata = None
449 449 if opts_all.quick:
450 450 print 'Launching IPython in quick mode. No config file read.'
451 451 elif opts_all.rcfile:
452 452 try:
453 453 cfg_loader = ConfigLoader(conflict)
454 454 rcfiledata = cfg_loader.load(opts_all.rcfile,typeconv,
455 455 'include',opts_all.ipythondir,
456 456 purge = 1,
457 457 unique = conflict['preserve'])
458 458 except:
459 459 IP.InteractiveTB()
460 460 warn('Problems loading configuration file '+
461 461 `opts_all.rcfile`+
462 462 '\nStarting with default -bare bones- configuration.')
463 463 else:
464 464 warn('No valid configuration file found in either currrent directory\n'+
465 465 'or in the IPython config. directory: '+`opts_all.ipythondir`+
466 466 '\nProceeding with internal defaults.')
467 467
468 468 #------------------------------------------------------------------------
469 469 # Set exception handlers in mode requested by user.
470 470 otrap = OutputTrap(trap_out=1) # trap messages from magic_xmode
471 471 IP.magic_xmode(opts_all.xmode)
472 472 otrap.release_out()
473 473
474 474 #------------------------------------------------------------------------
475 475 # Execute user config
476 476
477 477 # Create a valid config structure with the right precedence order:
478 478 # defaults < rcfile < command line. This needs to be in the instance, so
479 479 # that method calls below that rely on it find it.
480 480 IP.rc = rc_def.copy()
481 481
482 482 # Work with a local alias inside this routine to avoid unnecessary
483 483 # attribute lookups.
484 484 IP_rc = IP.rc
485 485
486 486 IP_rc.update(opts_def)
487 487 if rcfiledata:
488 488 # now we can update
489 489 IP_rc.update(rcfiledata)
490 490 IP_rc.update(opts)
491 491 IP_rc.update(rc_override)
492 492
493 493 # Store the original cmd line for reference:
494 494 IP_rc.opts = opts
495 495 IP_rc.args = args
496 496
497 497 # create a *runtime* Struct like rc for holding parameters which may be
498 498 # created and/or modified by runtime user extensions.
499 499 IP.runtime_rc = Struct()
500 500
501 501 # from this point on, all config should be handled through IP_rc,
502 502 # opts* shouldn't be used anymore.
503 503
504 504
505 505 # update IP_rc with some special things that need manual
506 506 # tweaks. Basically options which affect other options. I guess this
507 507 # should just be written so that options are fully orthogonal and we
508 508 # wouldn't worry about this stuff!
509 509
510 510 if IP_rc.classic:
511 511 IP_rc.quick = 1
512 512 IP_rc.cache_size = 0
513 513 IP_rc.pprint = 0
514 514 IP_rc.prompt_in1 = '>>> '
515 515 IP_rc.prompt_in2 = '... '
516 516 IP_rc.prompt_out = ''
517 517 IP_rc.separate_in = IP_rc.separate_out = IP_rc.separate_out2 = '0'
518 518 IP_rc.colors = 'NoColor'
519 519 IP_rc.xmode = 'Plain'
520 520
521 521 IP.pre_config_initialization()
522 522 # configure readline
523 523
524 524 # update exception handlers with rc file status
525 525 otrap.trap_out() # I don't want these messages ever.
526 526 IP.magic_xmode(IP_rc.xmode)
527 527 otrap.release_out()
528 528
529 529 # activate logging if requested and not reloading a log
530 530 if IP_rc.logplay:
531 531 IP.magic_logstart(IP_rc.logplay + ' append')
532 532 elif IP_rc.logfile:
533 533 IP.magic_logstart(IP_rc.logfile)
534 534 elif IP_rc.log:
535 535 IP.magic_logstart()
536 536
537 537 # find user editor so that it we don't have to look it up constantly
538 538 if IP_rc.editor.strip()=='0':
539 539 try:
540 540 ed = os.environ['EDITOR']
541 541 except KeyError:
542 542 if os.name == 'posix':
543 543 ed = 'vi' # the only one guaranteed to be there!
544 544 else:
545 545 ed = 'notepad' # same in Windows!
546 546 IP_rc.editor = ed
547 547
548 548 # Keep track of whether this is an embedded instance or not (useful for
549 549 # post-mortems).
550 550 IP_rc.embedded = IP.embedded
551 551
552 552 # Recursive reload
553 553 try:
554 554 from IPython import deep_reload
555 555 if IP_rc.deep_reload:
556 556 __builtin__.reload = deep_reload.reload
557 557 else:
558 558 __builtin__.dreload = deep_reload.reload
559 559 del deep_reload
560 560 except ImportError:
561 561 pass
562 562
563 563 # Save the current state of our namespace so that the interactive shell
564 564 # can later know which variables have been created by us from config files
565 565 # and loading. This way, loading a file (in any way) is treated just like
566 566 # defining things on the command line, and %who works as expected.
567 567
568 568 # DON'T do anything that affects the namespace beyond this point!
569 569 IP.internal_ns.update(__main__.__dict__)
570 570
571 571 #IP.internal_ns.update(locals()) # so our stuff doesn't show up in %who
572 572
573 573 # Now run through the different sections of the users's config
574 574 if IP_rc.debug:
575 575 print 'Trying to execute the following configuration structure:'
576 576 print '(Things listed first are deeper in the inclusion tree and get'
577 577 print 'loaded first).\n'
578 578 pprint(IP_rc.__dict__)
579 579
580 580 for mod in IP_rc.import_mod:
581 581 try:
582 582 exec 'import '+mod in IP.user_ns
583 583 except :
584 584 IP.InteractiveTB()
585 585 import_fail_info(mod)
586 586
587 587 for mod_fn in IP_rc.import_some:
588 588 if not mod_fn == []:
589 589 mod,fn = mod_fn[0],','.join(mod_fn[1:])
590 590 try:
591 591 exec 'from '+mod+' import '+fn in IP.user_ns
592 592 except :
593 593 IP.InteractiveTB()
594 594 import_fail_info(mod,fn)
595 595
596 596 for mod in IP_rc.import_all:
597 597 try:
598 598 exec 'from '+mod+' import *' in IP.user_ns
599 599 except :
600 600 IP.InteractiveTB()
601 601 import_fail_info(mod)
602 602
603 603 for code in IP_rc.execute:
604 604 try:
605 605 exec code in IP.user_ns
606 606 except:
607 607 IP.InteractiveTB()
608 608 warn('Failure executing code: ' + `code`)
609 609
610 610 # Execute the files the user wants in ipythonrc
611 611 for file in IP_rc.execfile:
612 612 try:
613 613 file = filefind(file,sys.path+[IPython_dir])
614 614 except IOError:
615 615 warn(itpl('File $file not found. Skipping it.'))
616 616 else:
617 617 IP.safe_execfile(os.path.expanduser(file),IP.user_ns)
618 618
619 619 # finally, try importing ipy_*_conf for final configuration
620 620 try:
621 621 import ipy_system_conf
622 622 except ImportError:
623 623 if opts_all.debug: IP.InteractiveTB()
624 624 warn("Could not import 'ipy_system_conf'")
625 625 except:
626 626 IP.InteractiveTB()
627 627 import_fail_info('ipy_system_conf')
628
628
629 629 # only import prof module if ipythonrc-PROF was not found
630 630 if opts_all.profile and not profile_handled_by_legacy:
631 631 profmodname = 'ipy_profile_' + opts_all.profile
632 632 try:
633
634 633 force_import(profmodname)
635 634 except:
636 635 IP.InteractiveTB()
637 print "Error importing",profmodname,"- perhaps you should run %upgrade?"
636 print "Error importing",profmodname,\
637 "- perhaps you should run %upgrade?"
638 638 import_fail_info(profmodname)
639 639 else:
640 640 opts.profile = opts_all.profile
641 641 else:
642 642 force_import('ipy_profile_none')
643 # XXX - this is wrong: ipy_user_conf should not be loaded unconditionally,
644 # since the user could have specified a config file path by hand.
643 645 try:
644
645 646 force_import('ipy_user_conf')
646
647 647 except:
648 648 conf = opts_all.ipythondir + "/ipy_user_conf.py"
649 649 IP.InteractiveTB()
650 650 if not os.path.isfile(conf):
651 651 warn(conf + ' does not exist, please run %upgrade!')
652 652
653 653 import_fail_info("ipy_user_conf")
654 654
655 655 # Define the history file for saving commands in between sessions
656 656 try:
657 657 histfname = 'history-%s' % opts.profile
658 658 except AttributeError:
659 659 histfname = 'history'
660 660 IP.histfile = os.path.join(opts_all.ipythondir,histfname)
661 661
662 662 # finally, push the argv to options again to ensure highest priority
663 663 IP_rc.update(opts)
664 664
665 665 # release stdout and stderr and save config log into a global summary
666 666 msg.config.release_all()
667 667 if IP_rc.messages:
668 668 msg.summary += msg.config.summary_all()
669 669
670 670 #------------------------------------------------------------------------
671 671 # Setup interactive session
672 672
673 673 # Now we should be fully configured. We can then execute files or load
674 674 # things only needed for interactive use. Then we'll open the shell.
675 675
676 676 # Take a snapshot of the user namespace before opening the shell. That way
677 677 # we'll be able to identify which things were interactively defined and
678 678 # which were defined through config files.
679 679 IP.user_config_ns.update(IP.user_ns)
680 680
681 681 # Force reading a file as if it were a session log. Slower but safer.
682 682 if load_logplay:
683 683 print 'Replaying log...'
684 684 try:
685 685 if IP_rc.debug:
686 686 logplay_quiet = 0
687 687 else:
688 688 logplay_quiet = 1
689 689
690 690 msg.logplay.trap_all()
691 691 IP.safe_execfile(load_logplay,IP.user_ns,
692 692 islog = 1, quiet = logplay_quiet)
693 693 msg.logplay.release_all()
694 694 if IP_rc.messages:
695 695 msg.summary += msg.logplay.summary_all()
696 696 except:
697 697 warn('Problems replaying logfile %s.' % load_logplay)
698 698 IP.InteractiveTB()
699 699
700 700 # Load remaining files in command line
701 701 msg.user_exec.trap_all()
702 702
703 703 # Do NOT execute files named in the command line as scripts to be loaded
704 704 # by embedded instances. Doing so has the potential for an infinite
705 705 # recursion if there are exceptions thrown in the process.
706 706
707 707 # XXX FIXME: the execution of user files should be moved out to after
708 708 # ipython is fully initialized, just as if they were run via %run at the
709 709 # ipython prompt. This would also give them the benefit of ipython's
710 710 # nice tracebacks.
711 711
712 712 if (not embedded and IP_rc.args and
713 713 not IP_rc.args[0].lower().endswith('.ipy')):
714 714 name_save = IP.user_ns['__name__']
715 715 IP.user_ns['__name__'] = '__main__'
716 716 # Set our own excepthook in case the user code tries to call it
717 717 # directly. This prevents triggering the IPython crash handler.
718 718 old_excepthook,sys.excepthook = sys.excepthook, IP.excepthook
719 719
720 720 save_argv = sys.argv[1:] # save it for later restoring
721 721
722 722 sys.argv = args
723 723
724 724 try:
725 725 IP.safe_execfile(args[0], IP.user_ns)
726 726 finally:
727 727 # Reset our crash handler in place
728 728 sys.excepthook = old_excepthook
729 729 sys.argv[:] = save_argv
730 730 IP.user_ns['__name__'] = name_save
731 731
732 732 msg.user_exec.release_all()
733 733
734 734 if IP_rc.messages:
735 735 msg.summary += msg.user_exec.summary_all()
736 736
737 737 # since we can't specify a null string on the cmd line, 0 is the equivalent:
738 738 if IP_rc.nosep:
739 739 IP_rc.separate_in = IP_rc.separate_out = IP_rc.separate_out2 = '0'
740 740 if IP_rc.separate_in == '0': IP_rc.separate_in = ''
741 741 if IP_rc.separate_out == '0': IP_rc.separate_out = ''
742 742 if IP_rc.separate_out2 == '0': IP_rc.separate_out2 = ''
743 743 IP_rc.separate_in = IP_rc.separate_in.replace('\\n','\n')
744 744 IP_rc.separate_out = IP_rc.separate_out.replace('\\n','\n')
745 745 IP_rc.separate_out2 = IP_rc.separate_out2.replace('\\n','\n')
746 746
747 747 # Determine how many lines at the bottom of the screen are needed for
748 748 # showing prompts, so we can know wheter long strings are to be printed or
749 749 # paged:
750 750 num_lines_bot = IP_rc.separate_in.count('\n')+1
751 751 IP_rc.screen_length = IP_rc.screen_length - num_lines_bot
752 752
753 753 # configure startup banner
754 754 if IP_rc.c: # regular python doesn't print the banner with -c
755 755 IP_rc.banner = 0
756 756 if IP_rc.banner:
757 757 BANN_P = IP.BANNER_PARTS
758 758 else:
759 759 BANN_P = []
760 760
761 761 if IP_rc.profile: BANN_P.append('IPython profile: %s\n' % IP_rc.profile)
762 762
763 763 # add message log (possibly empty)
764 764 if msg.summary: BANN_P.append(msg.summary)
765 765 # Final banner is a string
766 766 IP.BANNER = '\n'.join(BANN_P)
767 767
768 768 # Finalize the IPython instance. This assumes the rc structure is fully
769 769 # in place.
770 770 IP.post_config_initialization()
771 771
772 772 return IP
773 773 #************************ end of file <ipmaker.py> **************************
@@ -1,24 +1,25 b''
1 1 # encoding: utf-8
2 2 """The IPython1 kernel.
3 3
4 4 The IPython kernel actually refers to three things:
5 5
6 6 * The IPython Engine
7 7 * The IPython Controller
8 8 * Clients to the IPython Controller
9 9
10 10 The kernel module implements the engine, controller and client and all the
11 11 network protocols needed for the various entities to talk to each other.
12 12
13 13 An end user should probably begin by looking at the `client.py` module
14 14 if they need blocking clients or in `asyncclient.py` if they want asynchronous,
15 15 deferred/Twisted using clients.
16 16 """
17 17 __docformat__ = "restructuredtext en"
18 #-------------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
19 19 # Copyright (C) 2008 The IPython Development Team
20 20 #
21 21 # Distributed under the terms of the BSD License. The full license is in
22 22 # the file COPYING, distributed as part of this software.
23 #-------------------------------------------------------------------------------
24 No newline at end of file
23 #-----------------------------------------------------------------------------
24
25 from IPython.kernel.error import TaskRejectError No newline at end of file
@@ -1,124 +1,126 b''
1 1 # encoding: utf-8
2 2
3 3 """Default kernel configuration."""
4 4
5 5 __docformat__ = "restructuredtext en"
6 6
7 7 #-------------------------------------------------------------------------------
8 8 # Copyright (C) 2008 The IPython Development Team
9 9 #
10 10 # Distributed under the terms of the BSD License. The full license is in
11 11 # the file COPYING, distributed as part of this software.
12 12 #-------------------------------------------------------------------------------
13 13
14 14 #-------------------------------------------------------------------------------
15 15 # Imports
16 16 #-------------------------------------------------------------------------------
17 17
18 import os, sys
18 19 from os.path import join as pjoin
19 20
20 21 from IPython.external.configobj import ConfigObj
21 22 from IPython.config.api import ConfigObjManager
22 23 from IPython.genutils import get_ipython_dir, get_security_dir
23 24
24 25 default_kernel_config = ConfigObj()
25 26
27 # This will raise OSError if ipythondir doesn't exist.
26 28 security_dir = get_security_dir()
27 29
28 30 #-------------------------------------------------------------------------------
29 31 # Engine Configuration
30 32 #-------------------------------------------------------------------------------
31 33
32 34 engine_config = dict(
33 35 logfile = '', # Empty means log to stdout
34 36 furl_file = pjoin(security_dir, 'ipcontroller-engine.furl')
35 37 )
36 38
37 39 #-------------------------------------------------------------------------------
38 40 # MPI Configuration
39 41 #-------------------------------------------------------------------------------
40 42
41 43 mpi_config = dict(
42 44 mpi4py = """from mpi4py import MPI as mpi
43 45 mpi.size = mpi.COMM_WORLD.Get_size()
44 46 mpi.rank = mpi.COMM_WORLD.Get_rank()
45 47 """,
46 48 pytrilinos = """from PyTrilinos import Epetra
47 49 class SimpleStruct:
48 50 pass
49 51 mpi = SimpleStruct()
50 52 mpi.rank = 0
51 53 mpi.size = 0
52 54 """,
53 55 default = ''
54 56 )
55 57
56 58 #-------------------------------------------------------------------------------
57 59 # Controller Configuration
58 60 #-------------------------------------------------------------------------------
59 61
60 62 controller_config = dict(
61 63
62 64 logfile = '', # Empty means log to stdout
63 65 import_statement = '',
64 66 reuse_furls = False, # If False, old furl files are deleted
65 67
66 68 engine_tub = dict(
67 69 ip = '', # Empty string means all interfaces
68 70 port = 0, # 0 means pick a port for me
69 71 location = '', # Empty string means try to set automatically
70 72 secure = True,
71 73 cert_file = pjoin(security_dir, 'ipcontroller-engine.pem'),
72 74 ),
73 75 engine_fc_interface = 'IPython.kernel.enginefc.IFCControllerBase',
74 76 engine_furl_file = pjoin(security_dir, 'ipcontroller-engine.furl'),
75 77
76 78 controller_interfaces = dict(
77 79 # multiengine = dict(
78 80 # controller_interface = 'IPython.kernel.multiengine.IMultiEngine',
79 81 # fc_interface = 'IPython.kernel.multienginefc.IFCMultiEngine',
80 82 # furl_file = 'ipcontroller-mec.furl'
81 83 # ),
82 84 task = dict(
83 85 controller_interface = 'IPython.kernel.task.ITaskController',
84 86 fc_interface = 'IPython.kernel.taskfc.IFCTaskController',
85 87 furl_file = pjoin(security_dir, 'ipcontroller-tc.furl')
86 88 ),
87 89 multiengine = dict(
88 90 controller_interface = 'IPython.kernel.multiengine.IMultiEngine',
89 91 fc_interface = 'IPython.kernel.multienginefc.IFCSynchronousMultiEngine',
90 92 furl_file = pjoin(security_dir, 'ipcontroller-mec.furl')
91 93 )
92 94 ),
93 95
94 96 client_tub = dict(
95 97 ip = '', # Empty string means all interfaces
96 98 port = 0, # 0 means pick a port for me
97 99 location = '', # Empty string means try to set automatically
98 100 secure = True,
99 101 cert_file = pjoin(security_dir, 'ipcontroller-client.pem')
100 102 )
101 103 )
102 104
103 105 #-------------------------------------------------------------------------------
104 106 # Client Configuration
105 107 #-------------------------------------------------------------------------------
106 108
107 109 client_config = dict(
108 110 client_interfaces = dict(
109 111 task = dict(
110 112 furl_file = pjoin(security_dir, 'ipcontroller-tc.furl')
111 113 ),
112 114 multiengine = dict(
113 115 furl_file = pjoin(security_dir, 'ipcontroller-mec.furl')
114 116 )
115 117 )
116 118 )
117 119
118 120 default_kernel_config['engine'] = engine_config
119 121 default_kernel_config['mpi'] = mpi_config
120 122 default_kernel_config['controller'] = controller_config
121 123 default_kernel_config['client'] = client_config
122 124
123 125
124 126 config_manager = ConfigObjManager(default_kernel_config, 'IPython.kernel.ini') No newline at end of file
@@ -1,754 +1,761 b''
1 1 # encoding: utf-8
2 2
3 3 """Central interpreter object for an IPython engine.
4 4
5 5 The interpreter is the object whose job is to process lines of user input and
6 6 actually execute them in the user's namespace.
7 7 """
8 8
9 9 __docformat__ = "restructuredtext en"
10 10
11 11 #-------------------------------------------------------------------------------
12 12 # Copyright (C) 2008 The IPython Development Team
13 13 #
14 14 # Distributed under the terms of the BSD License. The full license is in
15 15 # the file COPYING, distributed as part of this software.
16 16 #-------------------------------------------------------------------------------
17 17
18 18 #-------------------------------------------------------------------------------
19 19 # Imports
20 20 #-------------------------------------------------------------------------------
21 21
22 22 # Standard library imports.
23 23 from types import FunctionType
24 24
25 25 import __builtin__
26 26 import codeop
27 27 import compiler
28 28 import sys
29 29 import traceback
30 30
31 31 # Local imports.
32 32 from IPython.kernel.core import ultraTB
33 33 from IPython.kernel.core.display_trap import DisplayTrap
34 34 from IPython.kernel.core.macro import Macro
35 35 from IPython.kernel.core.prompts import CachedOutput
36 36 from IPython.kernel.core.traceback_trap import TracebackTrap
37 37 from IPython.kernel.core.util import Bunch, system_shell
38 38 from IPython.external.Itpl import ItplNS
39 39
40 40 # Global constants
41 41 COMPILER_ERROR = 'error'
42 42 INCOMPLETE_INPUT = 'incomplete'
43 43 COMPLETE_INPUT = 'complete'
44 44
45 45 ##############################################################################
46 46 # TEMPORARY!!! fake configuration, while we decide whether to use tconfig or
47 47 # not
48 48
49 49 rc = Bunch()
50 50 rc.cache_size = 100
51 51 rc.pprint = True
52 52 rc.separate_in = '\n'
53 53 rc.separate_out = '\n'
54 54 rc.separate_out2 = ''
55 55 rc.prompt_in1 = r'In [\#]: '
56 56 rc.prompt_in2 = r' .\\D.: '
57 57 rc.prompt_out = ''
58 58 rc.prompts_pad_left = False
59 59
60 60 ##############################################################################
61 61
62 62 # Top-level utilities
63 63 def default_display_formatters():
64 64 """ Return a list of default display formatters.
65 65 """
66 66
67 67 from display_formatter import PPrintDisplayFormatter, ReprDisplayFormatter
68 68 return [PPrintDisplayFormatter(), ReprDisplayFormatter()]
69 69
70 70 def default_traceback_formatters():
71 71 """ Return a list of default traceback formatters.
72 72 """
73 73
74 74 from traceback_formatter import PlainTracebackFormatter
75 75 return [PlainTracebackFormatter()]
76 76
77 77 # Top-level classes
78 78 class NotDefined(object): pass
79 79
80 80 class Interpreter(object):
81 81 """ An interpreter object.
82 82
83 83 fixme: needs to negotiate available formatters with frontends.
84 84
85 85 Important: the interpeter should be built so that it exposes a method
86 86 for each attribute/method of its sub-object. This way it can be
87 87 replaced by a network adapter.
88 88 """
89 89
90 90 def __init__(self, user_ns=None, global_ns=None,translator=None,
91 91 magic=None, display_formatters=None,
92 92 traceback_formatters=None, output_trap=None, history=None,
93 93 message_cache=None, filename='<string>', config=None):
94 94
95 95 # The local/global namespaces for code execution
96 96 local_ns = user_ns # compatibility name
97 97 if local_ns is None:
98 98 local_ns = {}
99 99 self.user_ns = local_ns
100 100 # The local namespace
101 101 if global_ns is None:
102 102 global_ns = {}
103 103 self.user_global_ns = global_ns
104 104
105 105 # An object that will translate commands into executable Python.
106 106 # The current translator does not work properly so for now we are going
107 107 # without!
108 108 # if translator is None:
109 109 # from IPython.kernel.core.translator import IPythonTranslator
110 110 # translator = IPythonTranslator()
111 111 self.translator = translator
112 112
113 113 # An object that maintains magic commands.
114 114 if magic is None:
115 115 from IPython.kernel.core.magic import Magic
116 116 magic = Magic(self)
117 117 self.magic = magic
118 118
119 119 # A list of formatters for the displayhook.
120 120 if display_formatters is None:
121 121 display_formatters = default_display_formatters()
122 122 self.display_formatters = display_formatters
123 123
124 124 # A list of formatters for tracebacks.
125 125 if traceback_formatters is None:
126 126 traceback_formatters = default_traceback_formatters()
127 127 self.traceback_formatters = traceback_formatters
128 128
129 129 # The object trapping stdout/stderr.
130 130 if output_trap is None:
131 131 from IPython.kernel.core.output_trap import OutputTrap
132 132 output_trap = OutputTrap()
133 133 self.output_trap = output_trap
134 134
135 135 # An object that manages the history.
136 136 if history is None:
137 137 from IPython.kernel.core.history import InterpreterHistory
138 138 history = InterpreterHistory()
139 139 self.history = history
140 140 self.get_history_item = history.get_history_item
141 141 self.get_history_input_cache = history.get_input_cache
142 142 self.get_history_input_after = history.get_input_after
143 143
144 144 # An object that caches all of the return messages.
145 145 if message_cache is None:
146 146 from IPython.kernel.core.message_cache import SimpleMessageCache
147 147 message_cache = SimpleMessageCache()
148 148 self.message_cache = message_cache
149 149
150 150 # The "filename" of the code that is executed in this interpreter.
151 151 self.filename = filename
152 152
153 153 # An object that contains much configuration information.
154 154 if config is None:
155 155 # fixme: Move this constant elsewhere!
156 156 config = Bunch(ESC_MAGIC='%')
157 157 self.config = config
158 158
159 159 # Hook managers.
160 160 # fixme: make the display callbacks configurable. In the meantime,
161 161 # enable macros.
162 162 self.display_trap = DisplayTrap(
163 163 formatters=self.display_formatters,
164 164 callbacks=[self._possible_macro],
165 165 )
166 166 self.traceback_trap = TracebackTrap(
167 167 formatters=self.traceback_formatters)
168 168
169 169 # This is used temporarily for reformating exceptions in certain
170 170 # cases. It will go away once the ultraTB stuff is ported
171 171 # to ipython1
172 172 self.tbHandler = ultraTB.FormattedTB(color_scheme='NoColor',
173 173 mode='Context',
174 174 tb_offset=2)
175 175
176 176 # An object that can compile commands and remember __future__
177 177 # statements.
178 178 self.command_compiler = codeop.CommandCompiler()
179 179
180 180 # A replacement for the raw_input() and input() builtins. Change these
181 181 # attributes later to configure them.
182 182 self.raw_input_builtin = raw_input
183 183 self.input_builtin = input
184 184
185 185 # The number of the current cell.
186 186 self.current_cell_number = 1
187 187
188 188 # Initialize cache, set in/out prompts and printing system
189 189 self.outputcache = CachedOutput(self,
190 190 rc.cache_size,
191 191 rc.pprint,
192 192 input_sep = rc.separate_in,
193 193 output_sep = rc.separate_out,
194 194 output_sep2 = rc.separate_out2,
195 195 ps1 = rc.prompt_in1,
196 196 ps2 = rc.prompt_in2,
197 197 ps_out = rc.prompt_out,
198 198 pad_left = rc.prompts_pad_left)
199 199
200 200 # Need to decide later if this is the right approach, but clients
201 201 # commonly use sys.ps1/2, so it may be best to just set them here
202 202 sys.ps1 = self.outputcache.prompt1.p_str
203 203 sys.ps2 = self.outputcache.prompt2.p_str
204 204
205 205 # This is the message dictionary assigned temporarily when running the
206 206 # code.
207 207 self.message = None
208 208
209 209 self.setup_namespace()
210 210
211 211
212 212 #### Public 'Interpreter' interface ########################################
213 213
214 214 def formatTraceback(self, et, ev, tb, message=''):
215 215 """Put a formatted version of the traceback into value and reraise.
216 216
217 217 When exceptions have to be sent over the network, the traceback
218 218 needs to be put into the value of the exception in a nicely
219 219 formatted way. The method takes the type, value and tb of an
220 220 exception and puts a string representation of the tb into the
221 221 value of the exception and reraises it.
222 222
223 223 Currently this method uses the ultraTb formatter from IPython trunk.
224 224 Eventually it should simply use the traceback formatters in core
225 225 that are loaded into self.tracback_trap.formatters.
226 226 """
227 227 tbinfo = self.tbHandler.text(et,ev,tb)
228 228 ev._ipython_traceback_text = tbinfo
229 229 return et, ev, tb
230 230
231 231 def execute(self, commands, raiseException=True):
232 232 """ Execute some IPython commands.
233 233
234 234 1. Translate them into Python.
235 235 2. Run them.
236 236 3. Trap stdout/stderr.
237 237 4. Trap sys.displayhook().
238 238 5. Trap exceptions.
239 239 6. Return a message object.
240 240
241 241 Parameters
242 242 ----------
243 243 commands : str
244 244 The raw commands that the user typed into the prompt.
245 245
246 246 Returns
247 247 -------
248 248 message : dict
249 249 The dictionary of responses. See the README.txt in this directory
250 250 for an explanation of the format.
251 251 """
252 252
253 253 # Create a message dictionary with all of the information we will be
254 254 # returning to the frontend and other listeners.
255 255 message = self.setup_message()
256 256
257 257 # Massage the input and store the raw and translated commands into
258 258 # a dict.
259 259 user_input = dict(raw=commands)
260 260 if self.translator is not None:
261 261 python = self.translator(commands, message)
262 262 if python is None:
263 263 # Something went wrong with the translation. The translator
264 264 # should have added an appropriate entry to the message object.
265 265 return message
266 266 else:
267 267 python = commands
268 268 user_input['translated'] = python
269 269 message['input'] = user_input
270 270
271 271 # Set the message object so that any magics executed in the code have
272 272 # access.
273 273 self.message = message
274 274
275 275 # Set all of the output/exception traps.
276 276 self.set_traps()
277 277
278 278 # Actually execute the Python code.
279 279 status = self.execute_python(python)
280 280
281 281 # Unset all of the traps.
282 282 self.unset_traps()
283 283
284 284 # Unset the message object.
285 285 self.message = None
286 286
287 287 # Update the history variables in the namespace.
288 288 # E.g. In, Out, _, __, ___
289 289 if self.history is not None:
290 290 self.history.update_history(self, python)
291 291
292 292 # Let all of the traps contribute to the message and then clear their
293 293 # stored information.
294 294 self.output_trap.add_to_message(message)
295 295 self.output_trap.clear()
296 296 self.display_trap.add_to_message(message)
297 297 self.display_trap.clear()
298 298 self.traceback_trap.add_to_message(message)
299 299 # Pull out the type, value and tb of the current exception
300 300 # before clearing it.
301 301 einfo = self.traceback_trap.args
302 302 self.traceback_trap.clear()
303 303
304 304 # Cache the message.
305 305 self.message_cache.add_message(self.current_cell_number, message)
306 306
307 307 # Bump the number.
308 308 self.current_cell_number += 1
309 309
310 310 # This conditional lets the execute method either raise any
311 311 # exception that has occured in user code OR return the message
312 312 # dict containing the traceback and other useful info.
313 313 if raiseException and einfo:
314 314 raise einfo[0],einfo[1],einfo[2]
315 315 else:
316 316 return message
317 317
318 318 def generate_prompt(self, is_continuation):
319 319 """Calculate and return a string with the prompt to display.
320 320
321 321 :Parameters:
322 322 is_continuation : bool
323 323 Whether the input line is continuing multiline input or not, so
324 324 that a proper continuation prompt can be computed."""
325 325
326 326 if is_continuation:
327 327 return str(self.outputcache.prompt2)
328 328 else:
329 329 return str(self.outputcache.prompt1)
330 330
331 331 def execute_python(self, python):
332 332 """ Actually run the Python code in the namespace.
333 333
334 334 :Parameters:
335 335
336 336 python : str
337 337 Pure, exec'able Python code. Special IPython commands should have
338 338 already been translated into pure Python.
339 339 """
340 340
341 341 # We use a CommandCompiler instance to compile the code so as to keep
342 342 # track of __future__ imports.
343 343 try:
344 344 commands = self.split_commands(python)
345 345 except (SyntaxError, IndentationError), e:
346 346 # Save the exc_info so compilation related exceptions can be
347 347 # reraised
348 348 self.traceback_trap.args = sys.exc_info()
349 349 self.pack_exception(self.message,e)
350 350 return None
351 351
352 352 for cmd in commands:
353 353 try:
354 354 code = self.command_compiler(cmd, self.filename, 'single')
355 355 except (SyntaxError, OverflowError, ValueError), e:
356 356 self.traceback_trap.args = sys.exc_info()
357 357 self.pack_exception(self.message,e)
358 358 # No point in continuing if one block raised
359 359 return None
360 360 else:
361 361 self.execute_block(code)
362 362
363 363 def execute_block(self,code):
364 364 """Execute a single block of code in the user namespace.
365 365
366 366 Return value: a flag indicating whether the code to be run completed
367 367 successfully:
368 368
369 369 - 0: successful execution.
370 370 - 1: an error occurred.
371 371 """
372 372
373 373 outflag = 1 # start by assuming error, success will reset it
374 374 try:
375 375 exec code in self.user_ns
376 376 outflag = 0
377 377 except SystemExit:
378 378 self.resetbuffer()
379 379 self.traceback_trap.args = sys.exc_info()
380 380 except:
381 381 self.traceback_trap.args = sys.exc_info()
382 382
383 383 return outflag
384 384
385 385 def execute_macro(self, macro):
386 386 """ Execute the value of a macro.
387 387
388 388 Parameters
389 389 ----------
390 390 macro : Macro
391 391 """
392 392
393 393 python = macro.value
394 394 if self.translator is not None:
395 395 python = self.translator(python)
396 396 self.execute_python(python)
397 397
398 398 def getCommand(self, i=None):
399 399 """Gets the ith message in the message_cache.
400 400
401 401 This is implemented here for compatibility with the old ipython1 shell
402 402 I am not sure we need this though. I even seem to remember that we
403 403 were going to get rid of it.
404 404 """
405 405 return self.message_cache.get_message(i)
406 406
407 407 def reset(self):
408 408 """Reset the interpreter.
409 409
410 410 Currently this only resets the users variables in the namespace.
411 411 In the future we might want to also reset the other stateful
412 412 things like that the Interpreter has, like In, Out, etc.
413 413 """
414 414 self.user_ns.clear()
415 415 self.setup_namespace()
416 416
417 417 def complete(self,line,text=None, pos=None):
418 418 """Complete the given text.
419 419
420 420 :Parameters:
421 421
422 422 text : str
423 423 Text fragment to be completed on. Typically this is
424 424 """
425 425 # fixme: implement
426 426 raise NotImplementedError
427 427
428 428 def push(self, ns):
429 429 """ Put value into the namespace with name key.
430 430
431 431 Parameters
432 432 ----------
433 433 **kwds
434 434 """
435 435
436 436 self.user_ns.update(ns)
437 437
438 438 def push_function(self, ns):
439 439 # First set the func_globals for all functions to self.user_ns
440 440 new_kwds = {}
441 441 for k, v in ns.iteritems():
442 442 if not isinstance(v, FunctionType):
443 443 raise TypeError("function object expected")
444 444 new_kwds[k] = FunctionType(v.func_code, self.user_ns)
445 445 self.user_ns.update(new_kwds)
446 446
447 447 def pack_exception(self,message,exc):
448 448 message['exception'] = exc.__class__
449 449 message['exception_value'] = \
450 450 traceback.format_exception_only(exc.__class__, exc)
451 451
452 452 def feed_block(self, source, filename='<input>', symbol='single'):
453 453 """Compile some source in the interpreter.
454 454
455 455 One several things can happen:
456 456
457 457 1) The input is incorrect; compile_command() raised an
458 458 exception (SyntaxError or OverflowError).
459 459
460 460 2) The input is incomplete, and more input is required;
461 461 compile_command() returned None. Nothing happens.
462 462
463 463 3) The input is complete; compile_command() returned a code
464 464 object. The code is executed by calling self.runcode() (which
465 465 also handles run-time exceptions, except for SystemExit).
466 466
467 467 The return value is:
468 468
469 469 - True in case 2
470 470
471 471 - False in the other cases, unless an exception is raised, where
472 472 None is returned instead. This can be used by external callers to
473 473 know whether to continue feeding input or not.
474 474
475 475 The return value can be used to decide whether to use sys.ps1 or
476 476 sys.ps2 to prompt the next line."""
477 477
478 478 self.message = self.setup_message()
479 479
480 480 try:
481 481 code = self.command_compiler(source,filename,symbol)
482 482 except (OverflowError, SyntaxError, IndentationError, ValueError ), e:
483 483 # Case 1
484 484 self.traceback_trap.args = sys.exc_info()
485 485 self.pack_exception(self.message,e)
486 486 return COMPILER_ERROR,False
487 487
488 488 if code is None:
489 489 # Case 2: incomplete input. This means that the input can span
490 490 # multiple lines. But we still need to decide when to actually
491 491 # stop taking user input. Later we'll add auto-indentation support
492 492 # somehow. In the meantime, we'll just stop if there are two lines
493 493 # of pure whitespace at the end.
494 494 last_two = source.rsplit('\n',2)[-2:]
495 495 print 'last two:',last_two # dbg
496 496 if len(last_two)==2 and all(s.isspace() for s in last_two):
497 497 return COMPLETE_INPUT,False
498 498 else:
499 499 return INCOMPLETE_INPUT, True
500 500 else:
501 501 # Case 3
502 502 return COMPLETE_INPUT, False
503 503
504 504 def pull(self, keys):
505 505 """ Get an item out of the namespace by key.
506 506
507 507 Parameters
508 508 ----------
509 509 key : str
510 510
511 511 Returns
512 512 -------
513 513 value : object
514 514
515 515 Raises
516 516 ------
517 517 TypeError if the key is not a string.
518 518 NameError if the object doesn't exist.
519 519 """
520 520
521 521 if isinstance(keys, str):
522 522 result = self.user_ns.get(keys, NotDefined())
523 523 if isinstance(result, NotDefined):
524 524 raise NameError('name %s is not defined' % keys)
525 525 elif isinstance(keys, (list, tuple)):
526 526 result = []
527 527 for key in keys:
528 528 if not isinstance(key, str):
529 529 raise TypeError("objects must be keyed by strings.")
530 530 else:
531 531 r = self.user_ns.get(key, NotDefined())
532 532 if isinstance(r, NotDefined):
533 533 raise NameError('name %s is not defined' % key)
534 534 else:
535 535 result.append(r)
536 536 if len(keys)==1:
537 537 result = result[0]
538 538 else:
539 539 raise TypeError("keys must be a strong or a list/tuple of strings")
540 540 return result
541 541
542 542 def pull_function(self, keys):
543 543 return self.pull(keys)
544 544
545 545 #### Interactive user API ##################################################
546 546
547 547 def ipsystem(self, command):
548 548 """ Execute a command in a system shell while expanding variables in the
549 549 current namespace.
550 550
551 551 Parameters
552 552 ----------
553 553 command : str
554 554 """
555 555
556 556 # Expand $variables.
557 557 command = self.var_expand(command)
558 558
559 559 system_shell(command,
560 560 header='IPython system call: ',
561 561 verbose=self.rc.system_verbose,
562 562 )
563 563
564 564 def ipmagic(self, arg_string):
565 565 """ Call a magic function by name.
566 566
567 567 ipmagic('name -opt foo bar') is equivalent to typing at the ipython
568 568 prompt:
569 569
570 570 In[1]: %name -opt foo bar
571 571
572 572 To call a magic without arguments, simply use ipmagic('name').
573 573
574 574 This provides a proper Python function to call IPython's magics in any
575 575 valid Python code you can type at the interpreter, including loops and
576 576 compound statements. It is added by IPython to the Python builtin
577 577 namespace upon initialization.
578 578
579 579 Parameters
580 580 ----------
581 581 arg_string : str
582 582 A string containing the name of the magic function to call and any
583 583 additional arguments to be passed to the magic.
584 584
585 585 Returns
586 586 -------
587 587 something : object
588 588 The return value of the actual object.
589 589 """
590 590
591 591 # Taken from IPython.
592 592 raise NotImplementedError('Not ported yet')
593 593
594 594 args = arg_string.split(' ', 1)
595 595 magic_name = args[0]
596 596 magic_name = magic_name.lstrip(self.config.ESC_MAGIC)
597 597
598 598 try:
599 599 magic_args = args[1]
600 600 except IndexError:
601 601 magic_args = ''
602 602 fn = getattr(self.magic, 'magic_'+magic_name, None)
603 603 if fn is None:
604 604 self.error("Magic function `%s` not found." % magic_name)
605 605 else:
606 606 magic_args = self.var_expand(magic_args)
607 607 return fn(magic_args)
608 608
609 609
610 610 #### Private 'Interpreter' interface #######################################
611 611
612 612 def setup_message(self):
613 613 """Return a message object.
614 614
615 615 This method prepares and returns a message dictionary. This dict
616 616 contains the various fields that are used to transfer information about
617 617 execution, results, tracebacks, etc, to clients (either in or out of
618 618 process ones). Because of the need to work with possibly out of
619 619 process clients, this dict MUST contain strictly pickle-safe values.
620 620 """
621 621
622 622 return dict(number=self.current_cell_number)
623 623
624 624 def setup_namespace(self):
625 625 """ Add things to the namespace.
626 626 """
627 627
628 628 self.user_ns.setdefault('__name__', '__main__')
629 629 self.user_ns.setdefault('__builtins__', __builtin__)
630 630 self.user_ns['__IP'] = self
631 631 if self.raw_input_builtin is not None:
632 632 self.user_ns['raw_input'] = self.raw_input_builtin
633 633 if self.input_builtin is not None:
634 634 self.user_ns['input'] = self.input_builtin
635 635
636 636 builtin_additions = dict(
637 637 ipmagic=self.ipmagic,
638 638 )
639 639 __builtin__.__dict__.update(builtin_additions)
640 640
641 641 if self.history is not None:
642 642 self.history.setup_namespace(self.user_ns)
643 643
644 644 def set_traps(self):
645 645 """ Set all of the output, display, and traceback traps.
646 646 """
647 647
648 648 self.output_trap.set()
649 649 self.display_trap.set()
650 650 self.traceback_trap.set()
651 651
652 652 def unset_traps(self):
653 653 """ Unset all of the output, display, and traceback traps.
654 654 """
655 655
656 656 self.output_trap.unset()
657 657 self.display_trap.unset()
658 658 self.traceback_trap.unset()
659 659
660 660 def split_commands(self, python):
661 661 """ Split multiple lines of code into discrete commands that can be
662 662 executed singly.
663 663
664 664 Parameters
665 665 ----------
666 666 python : str
667 667 Pure, exec'able Python code.
668 668
669 669 Returns
670 670 -------
671 671 commands : list of str
672 672 Separate commands that can be exec'ed independently.
673 673 """
674 674
675 675 # compiler.parse treats trailing spaces after a newline as a
676 676 # SyntaxError. This is different than codeop.CommandCompiler, which
677 677 # will compile the trailng spaces just fine. We simply strip any
678 678 # trailing whitespace off. Passing a string with trailing whitespace
679 679 # to exec will fail however. There seems to be some inconsistency in
680 680 # how trailing whitespace is handled, but this seems to work.
681 681 python = python.strip()
682
682
683 683 # The compiler module does not like unicode. We need to convert
684 684 # it encode it:
685 685 if isinstance(python, unicode):
686 686 # Use the utf-8-sig BOM so the compiler detects this a UTF-8
687 687 # encode string.
688 688 python = '\xef\xbb\xbf' + python.encode('utf-8')
689
689
690 690 # The compiler module will parse the code into an abstract syntax tree.
691 # This has a bug with str("a\nb"), but not str("""a\nb""")!!!
691 692 ast = compiler.parse(python)
692
693
693 694 # Uncomment to help debug the ast tree
694 695 # for n in ast.node:
695 696 # print n.lineno,'->',n
696
697
697 698 # Each separate command is available by iterating over ast.node. The
698 699 # lineno attribute is the line number (1-indexed) beginning the commands
699 700 # suite.
700 701 # lines ending with ";" yield a Discard Node that doesn't have a lineno
701 702 # attribute. These nodes can and should be discarded. But there are
702 703 # other situations that cause Discard nodes that shouldn't be discarded.
703 704 # We might eventually discover other cases where lineno is None and have
704 705 # to put in a more sophisticated test.
705 706 linenos = [x.lineno-1 for x in ast.node if x.lineno is not None]
706
707
707 708 # When we finally get the slices, we will need to slice all the way to
708 709 # the end even though we don't have a line number for it. Fortunately,
709 710 # None does the job nicely.
710 711 linenos.append(None)
712
713 # Same problem at the other end: sometimes the ast tree has its
714 # first complete statement not starting on line 0. In this case
715 # we might miss part of it. This fixes ticket 266993. Thanks Gael!
716 linenos[0] = 0
717
711 718 lines = python.splitlines()
712
719
713 720 # Create a list of atomic commands.
714 721 cmds = []
715 722 for i, j in zip(linenos[:-1], linenos[1:]):
716 723 cmd = lines[i:j]
717 724 if cmd:
718 725 cmds.append('\n'.join(cmd)+'\n')
719
726
720 727 return cmds
721 728
722 729 def error(self, text):
723 730 """ Pass an error message back to the shell.
724 731
725 732 Preconditions
726 733 -------------
727 734 This should only be called when self.message is set. In other words,
728 735 when code is being executed.
729 736
730 737 Parameters
731 738 ----------
732 739 text : str
733 740 """
734 741
735 742 errors = self.message.get('IPYTHON_ERROR', [])
736 743 errors.append(text)
737 744
738 745 def var_expand(self, template):
739 746 """ Expand $variables in the current namespace using Itpl.
740 747
741 748 Parameters
742 749 ----------
743 750 template : str
744 751 """
745 752
746 753 return str(ItplNS(template, self.user_ns))
747 754
748 755 def _possible_macro(self, obj):
749 756 """ If the object is a macro, execute it.
750 757 """
751 758
752 759 if isinstance(obj, Macro):
753 760 self.execute_macro(obj)
754 761
@@ -1,123 +1,125 b''
1 1 # encoding: utf-8
2 2
3 3 """The IPython Core Notification Center.
4 4
5 5 See docs/source/development/notification_blueprint.txt for an overview of the
6 6 notification module.
7 7 """
8 8
9 9 __docformat__ = "restructuredtext en"
10 10
11 11 #-----------------------------------------------------------------------------
12 12 # Copyright (C) 2008 The IPython Development Team
13 13 #
14 14 # Distributed under the terms of the BSD License. The full license is in
15 15 # the file COPYING, distributed as part of this software.
16 16 #-----------------------------------------------------------------------------
17 17
18 # Tell nose to skip the testing of this module
19 __test__ = {}
18 20
19 21 class NotificationCenter(object):
20 22 """Synchronous notification center
21 23
22 24 Example
23 25 -------
24 26 >>> import IPython.kernel.core.notification as notification
25 27 >>> def callback(theType, theSender, args={}):
26 28 ... print theType,theSender,args
27 29 ...
28 30 >>> notification.sharedCenter.add_observer(callback, 'NOTIFICATION_TYPE', None)
29 31 >>> notification.sharedCenter.post_notification('NOTIFICATION_TYPE', object()) # doctest:+ELLIPSIS
30 32 NOTIFICATION_TYPE ...
31 33
32 34 """
33 35 def __init__(self):
34 36 super(NotificationCenter, self).__init__()
35 37 self._init_observers()
36 38
37 39
38 40 def _init_observers(self):
39 41 """Initialize observer storage"""
40 42
41 43 self.registered_types = set() #set of types that are observed
42 44 self.registered_senders = set() #set of senders that are observed
43 45 self.observers = {} #map (type,sender) => callback (callable)
44 46
45 47
46 48 def post_notification(self, theType, sender, **kwargs):
47 49 """Post notification (type,sender,**kwargs) to all registered
48 50 observers.
49 51
50 52 Implementation
51 53 --------------
52 54 * If no registered observers, performance is O(1).
53 55 * Notificaiton order is undefined.
54 56 * Notifications are posted synchronously.
55 57 """
56 58
57 59 if(theType==None or sender==None):
58 60 raise Exception("NotificationCenter.post_notification requires \
59 61 type and sender.")
60 62
61 63 # If there are no registered observers for the type/sender pair
62 64 if((theType not in self.registered_types and
63 65 None not in self.registered_types) or
64 66 (sender not in self.registered_senders and
65 67 None not in self.registered_senders)):
66 68 return
67 69
68 70 for o in self._observers_for_notification(theType, sender):
69 71 o(theType, sender, args=kwargs)
70 72
71 73
72 74 def _observers_for_notification(self, theType, sender):
73 75 """Find all registered observers that should recieve notification"""
74 76
75 77 keys = (
76 78 (theType,sender),
77 79 (theType, None),
78 80 (None, sender),
79 81 (None,None)
80 82 )
81 83
82 84
83 85 obs = set()
84 86 for k in keys:
85 87 obs.update(self.observers.get(k, set()))
86 88
87 89 return obs
88 90
89 91
90 92 def add_observer(self, callback, theType, sender):
91 93 """Add an observer callback to this notification center.
92 94
93 95 The given callback will be called upon posting of notifications of
94 96 the given type/sender and will receive any additional kwargs passed
95 97 to post_notification.
96 98
97 99 Parameters
98 100 ----------
99 101 observerCallback : callable
100 102 Callable. Must take at least two arguments::
101 103 observerCallback(type, sender, args={})
102 104
103 105 theType : hashable
104 106 The notification type. If None, all notifications from sender
105 107 will be posted.
106 108
107 109 sender : hashable
108 110 The notification sender. If None, all notifications of theType
109 111 will be posted.
110 112 """
111 113 assert(callback != None)
112 114 self.registered_types.add(theType)
113 115 self.registered_senders.add(sender)
114 116 self.observers.setdefault((theType,sender), set()).add(callback)
115 117
116 118 def remove_all_observers(self):
117 119 """Removes all observers from this notification center"""
118 120
119 121 self._init_observers()
120 122
121 123
122 124
123 125 sharedCenter = NotificationCenter() No newline at end of file
@@ -1,26 +1,62 b''
1 1 # encoding: utf-8
2 2
3 3 """This file contains unittests for the interpreter.py module."""
4 4
5 __docformat__ = "restructuredtext en"
6
7 5 #-----------------------------------------------------------------------------
8 # Copyright (C) 2008 The IPython Development Team
9 #
10 # Distributed under the terms of the BSD License. The full license is in
11 # the file COPYING, distributed as part of this software.
6 # Copyright (C) 2008-2009 The IPython Development Team
7 #
8 # Distributed under the terms of the BSD License. The full license is
9 # in the file COPYING, distributed as part of this software.
12 10 #-----------------------------------------------------------------------------
13
11
14 12 #-----------------------------------------------------------------------------
15 # Imports
13 # Imports
16 14 #-----------------------------------------------------------------------------
17 15
16 # Tell nose to skip this module
17 __test__ = {}
18
19 from twisted.trial import unittest
18 20 from IPython.kernel.core.interpreter import Interpreter
19 21
20 def test_unicode():
21 """ Test unicode handling with the interpreter.
22 """
23 i = Interpreter()
24 i.execute_python(u'print "ù"')
25 i.execute_python('print "ù"')
22 #-----------------------------------------------------------------------------
23 # Tests
24 #-----------------------------------------------------------------------------
25
26 class TestInterpreter(unittest.TestCase):
27
28 def test_unicode(self):
29 """ Test unicode handling with the interpreter."""
30 i = Interpreter()
31 i.execute_python(u'print "ù"')
32 i.execute_python('print "ù"')
33
34 def test_ticket266993(self):
35 """ Test for ticket 266993."""
36 i = Interpreter()
37 i.execute('str("""a\nb""")')
38
39 def test_ticket364347(self):
40 """Test for ticket 364347."""
41 i = Interpreter()
42 i.split_commands('str("a\\nb")')
43
44 def test_split_commands(self):
45 """ Test that commands are indeed individually split."""
46 i = Interpreter()
47 test_atoms = [('(1\n + 1)', ),
48 ('1', '1', ),
49 ]
50 for atoms in test_atoms:
51 atoms = [atom.rstrip() + '\n' for atom in atoms]
52 self.assertEquals(i.split_commands(''.join(atoms)),atoms)
53
54 def test_long_lines(self):
55 """ Test for spurious syntax error created by the interpreter."""
56 test_strings = [u'( 1 +\n 1\n )\n\n',
57 u'(1 \n + 1\n )\n\n',
58 ]
59 i = Interpreter()
60 for s in test_strings:
61 i.execute(s)
26 62
@@ -1,171 +1,161 b''
1 1 # encoding: utf-8
2 2
3 3 """This file contains unittests for the notification.py module."""
4 4
5 __docformat__ = "restructuredtext en"
6
7 5 #-----------------------------------------------------------------------------
8 # Copyright (C) 2008 The IPython Development Team
9 #
10 # Distributed under the terms of the BSD License. The full license is in
11 # the file COPYING, distributed as part of this software.
6 # Copyright (C) 2008-2009 The IPython Development Team
7 #
8 # Distributed under the terms of the BSD License. The full license is
9 # in the file COPYING, distributed as part of this software.
12 10 #-----------------------------------------------------------------------------
13
11
14 12 #-----------------------------------------------------------------------------
15 # Imports
13 # Imports
16 14 #-----------------------------------------------------------------------------
17 15
18 import unittest
16 # Tell nose to skip this module
17 __test__ = {}
18
19 from twisted.trial import unittest
19 20 import IPython.kernel.core.notification as notification
20 from nose.tools import timed
21 21
22 #
23 # Supporting test classes
24 #
22 #-----------------------------------------------------------------------------
23 # Support Classes
24 #-----------------------------------------------------------------------------
25 25
26 26 class Observer(object):
27 27 """docstring for Observer"""
28 28 def __init__(self, expectedType, expectedSender,
29 29 center=notification.sharedCenter, **kwargs):
30 30 super(Observer, self).__init__()
31 31 self.expectedType = expectedType
32 32 self.expectedSender = expectedSender
33 33 self.expectedKwArgs = kwargs
34 34 self.recieved = False
35 35 center.add_observer(self.callback,
36 36 self.expectedType,
37 37 self.expectedSender)
38 38
39
40 39 def callback(self, theType, sender, args={}):
41 40 """callback"""
42 41
43 42 assert(theType == self.expectedType or
44 43 self.expectedType == None)
45 44 assert(sender == self.expectedSender or
46 45 self.expectedSender == None)
47 46 assert(args == self.expectedKwArgs)
48 47 self.recieved = True
49 48
50
51 49 def verify(self):
52 50 """verify"""
53 51
54 52 assert(self.recieved)
55 53
56 54 def reset(self):
57 55 """reset"""
58 56
59 57 self.recieved = False
60
61 58
62 59
63 60 class Notifier(object):
64 61 """docstring for Notifier"""
65 62 def __init__(self, theType, **kwargs):
66 63 super(Notifier, self).__init__()
67 64 self.theType = theType
68 65 self.kwargs = kwargs
69 66
70 67 def post(self, center=notification.sharedCenter):
71 68 """fire"""
72 69
73 70 center.post_notification(self.theType, self,
74 71 **self.kwargs)
75
76 72
77 #
78 # Test Cases
79 #
73 #-----------------------------------------------------------------------------
74 # Tests
75 #-----------------------------------------------------------------------------
80 76
81 77 class NotificationTests(unittest.TestCase):
82 78 """docstring for NotificationTests"""
83 79
84 80 def tearDown(self):
85 81 notification.sharedCenter.remove_all_observers()
86 82
87 83 def test_notification_delivered(self):
88 84 """Test that notifications are delivered"""
89 85 expectedType = 'EXPECTED_TYPE'
90 86 sender = Notifier(expectedType)
91 87 observer = Observer(expectedType, sender)
92 88
93 89 sender.post()
94 90
95 91 observer.verify()
96 92
97
98 93 def test_type_specificity(self):
99 94 """Test that observers are registered by type"""
100 95
101 96 expectedType = 1
102 97 unexpectedType = "UNEXPECTED_TYPE"
103 98 sender = Notifier(expectedType)
104 99 unexpectedSender = Notifier(unexpectedType)
105 100 observer = Observer(expectedType, sender)
106 101
107 102 sender.post()
108 103 unexpectedSender.post()
109 104
110 105 observer.verify()
111 106
112
113 107 def test_sender_specificity(self):
114 108 """Test that observers are registered by sender"""
115 109
116 110 expectedType = "EXPECTED_TYPE"
117 111 sender1 = Notifier(expectedType)
118 112 sender2 = Notifier(expectedType)
119 113 observer = Observer(expectedType, sender1)
120 114
121 115 sender1.post()
122 116 sender2.post()
123 117
124 118 observer.verify()
125 119
126
127 120 def test_remove_all_observers(self):
128 121 """White-box test for remove_all_observers"""
129 122
130 123 for i in xrange(10):
131 124 Observer('TYPE', None, center=notification.sharedCenter)
132 125
133 126 self.assert_(len(notification.sharedCenter.observers[('TYPE',None)]) >= 10,
134 127 "observers registered")
135 128
136 129 notification.sharedCenter.remove_all_observers()
137 130
138 131 self.assert_(len(notification.sharedCenter.observers) == 0, "observers removed")
139
140
132
141 133 def test_any_sender(self):
142 134 """test_any_sender"""
143 135
144 136 expectedType = "EXPECTED_TYPE"
145 137 sender1 = Notifier(expectedType)
146 138 sender2 = Notifier(expectedType)
147 139 observer = Observer(expectedType, None)
148 140
149 141
150 142 sender1.post()
151 143 observer.verify()
152 144
153 145 observer.reset()
154 146 sender2.post()
155 147 observer.verify()
156
157
158 @timed(.01)
148
159 149 def test_post_performance(self):
160 150 """Test that post_notification, even with many registered irrelevant
161 151 observers is fast"""
162 152
163 153 for i in xrange(10):
164 154 Observer("UNRELATED_TYPE", None)
165 155
166 156 o = Observer('EXPECTED_TYPE', None)
167 157
168 158 notification.sharedCenter.post_notification('EXPECTED_TYPE', self)
169 159
170 160 o.verify()
171
161
@@ -1,70 +1,78 b''
1 1 # encoding: utf-8
2 2 """
3 3 Test the output capture at the OS level, using file descriptors.
4 4 """
5
6 __docformat__ = "restructuredtext en"
7
8 #-------------------------------------------------------------------------------
9 # Copyright (C) 2008 The IPython Development Team
5 #-----------------------------------------------------------------------------
6 # Copyright (C) 2008-2009 The IPython Development Team
10 7 #
11 8 # Distributed under the terms of the BSD License. The full license is
12 9 # in the file COPYING, distributed as part of this software.
13 #-------------------------------------------------------------------------------
10 #-----------------------------------------------------------------------------
14 11
12 #-----------------------------------------------------------------------------
13 # Imports
14 #-----------------------------------------------------------------------------
15
16 # Tell nose to skip this module
17 __test__ = {}
15 18
16 # Stdlib imports
17 import os
18 19 from cStringIO import StringIO
20 import os
21
22 from twisted.trial import unittest
19 23
20 # Our own imports
21 from IPython.testing import decorators as dec
24 from IPython.testing import decorators_trial as dec
22 25
23 26 #-----------------------------------------------------------------------------
24 # Test functions
27 # Tests
28 #-----------------------------------------------------------------------------
25 29
26 @dec.skip_win32
27 def test_redirector():
28 """ Checks that the redirector can be used to do synchronous capture.
29 """
30 from IPython.kernel.core.fd_redirector import FDRedirector
31 r = FDRedirector()
32 out = StringIO()
33 try:
34 r.start()
35 for i in range(10):
36 os.system('echo %ic' % i)
37 print >>out, r.getvalue(),
38 print >>out, i
39 except:
40 r.stop()
41 raise
42 r.stop()
43 result1 = out.getvalue()
44 result2 = "".join("%ic\n%i\n" %(i, i) for i in range(10))
45 assert result1 == result2
46 30
31 class TestRedirector(unittest.TestCase):
47 32
48 @dec.skip_win32
49 def test_redirector_output_trap():
50 """ This test check not only that the redirector_output_trap does
33 @dec.skip_win32
34 def test_redirector(self):
35 """Checks that the redirector can be used to do synchronous capture.
36 """
37 from IPython.kernel.core.fd_redirector import FDRedirector
38 r = FDRedirector()
39 out = StringIO()
40 try:
41 r.start()
42 for i in range(10):
43 os.system('echo %ic' % i)
44 print >>out, r.getvalue(),
45 print >>out, i
46 except:
47 r.stop()
48 raise
49 r.stop()
50 result1 = out.getvalue()
51 result2 = "".join("%ic\n%i\n" %(i, i) for i in range(10))
52 self.assertEquals(result1, result2)
53
54 @dec.skip_win32
55 def test_redirector_output_trap(self):
56 """Check the greedy trapping behavior of the traps.
57
58 This test check not only that the redirector_output_trap does
51 59 trap the output, but also that it does it in a gready way, that
52 60 is by calling the callback ASAP.
53 """
54 from IPython.kernel.core.redirector_output_trap import RedirectorOutputTrap
55 out = StringIO()
56 trap = RedirectorOutputTrap(out.write, out.write)
57 try:
58 trap.set()
59 for i in range(10):
60 os.system('echo %ic' % i)
61 print "%ip" % i
62 print >>out, i
63 except:
61 """
62 from IPython.kernel.core.redirector_output_trap import RedirectorOutputTrap
63 out = StringIO()
64 trap = RedirectorOutputTrap(out.write, out.write)
65 try:
66 trap.set()
67 for i in range(10):
68 os.system('echo %ic' % i)
69 print "%ip" % i
70 print >>out, i
71 except:
72 trap.unset()
73 raise
64 74 trap.unset()
65 raise
66 trap.unset()
67 result1 = out.getvalue()
68 result2 = "".join("%ic\n%ip\n%i\n" %(i, i, i) for i in range(10))
69 assert result1 == result2
70
75 result1 = out.getvalue()
76 result2 = "".join("%ic\n%ip\n%i\n" %(i, i, i) for i in range(10))
77 self.assertEquals(result1, result2)
78
@@ -1,1056 +1,1066 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 ultraTB.py -- Spice up your tracebacks!
4 4
5 5 * ColorTB
6 6 I've always found it a bit hard to visually parse tracebacks in Python. The
7 7 ColorTB class is a solution to that problem. It colors the different parts of a
8 8 traceback in a manner similar to what you would expect from a syntax-highlighting
9 9 text editor.
10 10
11 11 Installation instructions for ColorTB:
12 12 import sys,ultraTB
13 13 sys.excepthook = ultraTB.ColorTB()
14 14
15 15 * VerboseTB
16 16 I've also included a port of Ka-Ping Yee's "cgitb.py" that produces all kinds
17 17 of useful info when a traceback occurs. Ping originally had it spit out HTML
18 18 and intended it for CGI programmers, but why should they have all the fun? I
19 19 altered it to spit out colored text to the terminal. It's a bit overwhelming,
20 20 but kind of neat, and maybe useful for long-running programs that you believe
21 21 are bug-free. If a crash *does* occur in that type of program you want details.
22 22 Give it a shot--you'll love it or you'll hate it.
23 23
24 24 Note:
25 25
26 26 The Verbose mode prints the variables currently visible where the exception
27 27 happened (shortening their strings if too long). This can potentially be
28 28 very slow, if you happen to have a huge data structure whose string
29 29 representation is complex to compute. Your computer may appear to freeze for
30 30 a while with cpu usage at 100%. If this occurs, you can cancel the traceback
31 31 with Ctrl-C (maybe hitting it more than once).
32 32
33 33 If you encounter this kind of situation often, you may want to use the
34 34 Verbose_novars mode instead of the regular Verbose, which avoids formatting
35 35 variables (but otherwise includes the information and context given by
36 36 Verbose).
37 37
38 38
39 39 Installation instructions for ColorTB:
40 40 import sys,ultraTB
41 41 sys.excepthook = ultraTB.VerboseTB()
42 42
43 43 Note: Much of the code in this module was lifted verbatim from the standard
44 44 library module 'traceback.py' and Ka-Ping Yee's 'cgitb.py'.
45 45
46 46 * Color schemes
47 47 The colors are defined in the class TBTools through the use of the
48 48 ColorSchemeTable class. Currently the following exist:
49 49
50 50 - NoColor: allows all of this module to be used in any terminal (the color
51 51 escapes are just dummy blank strings).
52 52
53 53 - Linux: is meant to look good in a terminal like the Linux console (black
54 54 or very dark background).
55 55
56 56 - LightBG: similar to Linux but swaps dark/light colors to be more readable
57 57 in light background terminals.
58 58
59 59 You can implement other color schemes easily, the syntax is fairly
60 60 self-explanatory. Please send back new schemes you develop to the author for
61 61 possible inclusion in future releases.
62 62 """
63 63
64 64 #*****************************************************************************
65 65 # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu>
66 66 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
67 67 #
68 68 # Distributed under the terms of the BSD License. The full license is in
69 69 # the file COPYING, distributed as part of this software.
70 70 #*****************************************************************************
71 71
72 72 # Required modules
73 73 import inspect
74 74 import keyword
75 75 import linecache
76 76 import os
77 77 import pydoc
78 78 import re
79 79 import string
80 80 import sys
81 81 import time
82 82 import tokenize
83 83 import traceback
84 84 import types
85 85
86 86 # For purposes of monkeypatching inspect to fix a bug in it.
87 87 from inspect import getsourcefile, getfile, getmodule,\
88 88 ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode
89 89
90 90
91 91 # IPython's own modules
92 92 # Modified pdb which doesn't damage IPython's readline handling
93 93 from IPython import Debugger, PyColorize
94 94 from IPython.ipstruct import Struct
95 95 from IPython.excolors import exception_colors
96 96 from IPython.genutils import Term,uniq_stable,error,info
97 97
98 98 # Globals
99 99 # amount of space to put line numbers before verbose tracebacks
100 100 INDENT_SIZE = 8
101 101
102 102 # Default color scheme. This is used, for example, by the traceback
103 103 # formatter. When running in an actual IPython instance, the user's rc.colors
104 104 # value is used, but havinga module global makes this functionality available
105 105 # to users of ultraTB who are NOT running inside ipython.
106 106 DEFAULT_SCHEME = 'NoColor'
107 107
108 108 #---------------------------------------------------------------------------
109 109 # Code begins
110 110
111 111 # Utility functions
112 112 def inspect_error():
113 113 """Print a message about internal inspect errors.
114 114
115 115 These are unfortunately quite common."""
116 116
117 117 error('Internal Python error in the inspect module.\n'
118 118 'Below is the traceback from this internal error.\n')
119 119
120 120
121 121 def findsource(object):
122 122 """Return the entire source file and starting line number for an object.
123 123
124 124 The argument may be a module, class, method, function, traceback, frame,
125 125 or code object. The source code is returned as a list of all the lines
126 126 in the file and the line number indexes a line in that list. An IOError
127 127 is raised if the source code cannot be retrieved.
128 128
129 129 FIXED version with which we monkeypatch the stdlib to work around a bug."""
130 130
131 131 file = getsourcefile(object) or getfile(object)
132 132 # If the object is a frame, then trying to get the globals dict from its
133 133 # module won't work. Instead, the frame object itself has the globals
134 134 # dictionary.
135 135 globals_dict = None
136 136 if inspect.isframe(object):
137 137 # XXX: can this ever be false?
138 138 globals_dict = object.f_globals
139 139 else:
140 140 module = getmodule(object, file)
141 141 if module:
142 142 globals_dict = module.__dict__
143 143 lines = linecache.getlines(file, globals_dict)
144 144 if not lines:
145 145 raise IOError('could not get source code')
146 146
147 147 if ismodule(object):
148 148 return lines, 0
149 149
150 150 if isclass(object):
151 151 name = object.__name__
152 152 pat = re.compile(r'^(\s*)class\s*' + name + r'\b')
153 153 # make some effort to find the best matching class definition:
154 154 # use the one with the least indentation, which is the one
155 155 # that's most probably not inside a function definition.
156 156 candidates = []
157 157 for i in range(len(lines)):
158 158 match = pat.match(lines[i])
159 159 if match:
160 160 # if it's at toplevel, it's already the best one
161 161 if lines[i][0] == 'c':
162 162 return lines, i
163 163 # else add whitespace to candidate list
164 164 candidates.append((match.group(1), i))
165 165 if candidates:
166 166 # this will sort by whitespace, and by line number,
167 167 # less whitespace first
168 168 candidates.sort()
169 169 return lines, candidates[0][1]
170 170 else:
171 171 raise IOError('could not find class definition')
172 172
173 173 if ismethod(object):
174 174 object = object.im_func
175 175 if isfunction(object):
176 176 object = object.func_code
177 177 if istraceback(object):
178 178 object = object.tb_frame
179 179 if isframe(object):
180 180 object = object.f_code
181 181 if iscode(object):
182 182 if not hasattr(object, 'co_firstlineno'):
183 183 raise IOError('could not find function definition')
184 184 pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)')
185 185 pmatch = pat.match
186 186 # fperez - fix: sometimes, co_firstlineno can give a number larger than
187 187 # the length of lines, which causes an error. Safeguard against that.
188 188 lnum = min(object.co_firstlineno,len(lines))-1
189 189 while lnum > 0:
190 190 if pmatch(lines[lnum]): break
191 191 lnum -= 1
192 192
193 193 return lines, lnum
194 194 raise IOError('could not find code object')
195 195
196 196 # Monkeypatch inspect to apply our bugfix. This code only works with py25
197 197 if sys.version_info[:2] >= (2,5):
198 198 inspect.findsource = findsource
199 199
200 200 def fix_frame_records_filenames(records):
201 201 """Try to fix the filenames in each record from inspect.getinnerframes().
202 202
203 203 Particularly, modules loaded from within zip files have useless filenames
204 204 attached to their code object, and inspect.getinnerframes() just uses it.
205 205 """
206 206 fixed_records = []
207 207 for frame, filename, line_no, func_name, lines, index in records:
208 208 # Look inside the frame's globals dictionary for __file__, which should
209 209 # be better.
210 210 better_fn = frame.f_globals.get('__file__', None)
211 211 if isinstance(better_fn, str):
212 212 # Check the type just in case someone did something weird with
213 213 # __file__. It might also be None if the error occurred during
214 214 # import.
215 215 filename = better_fn
216 216 fixed_records.append((frame, filename, line_no, func_name, lines, index))
217 217 return fixed_records
218 218
219 219
220 220 def _fixed_getinnerframes(etb, context=1,tb_offset=0):
221 221 import linecache
222 222 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
223 223
224 224 records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))
225 225
226 226 # If the error is at the console, don't build any context, since it would
227 227 # otherwise produce 5 blank lines printed out (there is no file at the
228 228 # console)
229 229 rec_check = records[tb_offset:]
230 230 try:
231 231 rname = rec_check[0][1]
232 232 if rname == '<ipython console>' or rname.endswith('<string>'):
233 233 return rec_check
234 234 except IndexError:
235 235 pass
236 236
237 237 aux = traceback.extract_tb(etb)
238 238 assert len(records) == len(aux)
239 239 for i, (file, lnum, _, _) in zip(range(len(records)), aux):
240 240 maybeStart = lnum-1 - context//2
241 241 start = max(maybeStart, 0)
242 242 end = start + context
243 243 lines = linecache.getlines(file)[start:end]
244 244 # pad with empty lines if necessary
245 245 if maybeStart < 0:
246 246 lines = (['\n'] * -maybeStart) + lines
247 247 if len(lines) < context:
248 248 lines += ['\n'] * (context - len(lines))
249 249 buf = list(records[i])
250 250 buf[LNUM_POS] = lnum
251 251 buf[INDEX_POS] = lnum - 1 - start
252 252 buf[LINES_POS] = lines
253 253 records[i] = tuple(buf)
254 254 return records[tb_offset:]
255 255
256 256 # Helper function -- largely belongs to VerboseTB, but we need the same
257 257 # functionality to produce a pseudo verbose TB for SyntaxErrors, so that they
258 258 # can be recognized properly by ipython.el's py-traceback-line-re
259 259 # (SyntaxErrors have to be treated specially because they have no traceback)
260 260
261 261 _parser = PyColorize.Parser()
262 262
263 263 def _formatTracebackLines(lnum, index, lines, Colors, lvals=None,scheme=None):
264 264 numbers_width = INDENT_SIZE - 1
265 265 res = []
266 266 i = lnum - index
267 267
268 268 # This lets us get fully syntax-highlighted tracebacks.
269 269 if scheme is None:
270 270 try:
271 # Again, reference to a global __IPYTHON__ that doesn't exist.
272 # XXX
271 273 scheme = __IPYTHON__.rc.colors
272 274 except:
273 275 scheme = DEFAULT_SCHEME
274 276 _line_format = _parser.format2
275 277
276 278 for line in lines:
277 279 new_line, err = _line_format(line,'str',scheme)
278 280 if not err: line = new_line
279 281
280 282 if i == lnum:
281 283 # This is the line with the error
282 284 pad = numbers_width - len(str(i))
283 285 if pad >= 3:
284 286 marker = '-'*(pad-3) + '-> '
285 287 elif pad == 2:
286 288 marker = '> '
287 289 elif pad == 1:
288 290 marker = '>'
289 291 else:
290 292 marker = ''
291 293 num = marker + str(i)
292 294 line = '%s%s%s %s%s' %(Colors.linenoEm, num,
293 295 Colors.line, line, Colors.Normal)
294 296 else:
295 297 num = '%*s' % (numbers_width,i)
296 298 line = '%s%s%s %s' %(Colors.lineno, num,
297 299 Colors.Normal, line)
298 300
299 301 res.append(line)
300 302 if lvals and i == lnum:
301 303 res.append(lvals + '\n')
302 304 i = i + 1
303 305 return res
304 306
305 307
306 308 #---------------------------------------------------------------------------
307 309 # Module classes
308 310 class TBTools:
309 311 """Basic tools used by all traceback printer classes."""
310 312
311 313 def __init__(self,color_scheme = 'NoColor',call_pdb=False):
312 314 # Whether to call the interactive pdb debugger after printing
313 315 # tracebacks or not
314 316 self.call_pdb = call_pdb
315 317
316 318 # Create color table
317 319 self.color_scheme_table = exception_colors()
318 320
319 321 self.set_colors(color_scheme)
320 322 self.old_scheme = color_scheme # save initial value for toggles
321 323
322 324 if call_pdb:
323 325 self.pdb = Debugger.Pdb(self.color_scheme_table.active_scheme_name)
324 326 else:
325 327 self.pdb = None
326 328
327 329 def set_colors(self,*args,**kw):
328 330 """Shorthand access to the color table scheme selector method."""
329 331
330 332 # Set own color table
331 333 self.color_scheme_table.set_active_scheme(*args,**kw)
332 334 # for convenience, set Colors to the active scheme
333 335 self.Colors = self.color_scheme_table.active_colors
334 336 # Also set colors of debugger
335 337 if hasattr(self,'pdb') and self.pdb is not None:
336 338 self.pdb.set_colors(*args,**kw)
337 339
338 340 def color_toggle(self):
339 341 """Toggle between the currently active color scheme and NoColor."""
340 342
341 343 if self.color_scheme_table.active_scheme_name == 'NoColor':
342 344 self.color_scheme_table.set_active_scheme(self.old_scheme)
343 345 self.Colors = self.color_scheme_table.active_colors
344 346 else:
345 347 self.old_scheme = self.color_scheme_table.active_scheme_name
346 348 self.color_scheme_table.set_active_scheme('NoColor')
347 349 self.Colors = self.color_scheme_table.active_colors
348 350
349 351 #---------------------------------------------------------------------------
350 352 class ListTB(TBTools):
351 353 """Print traceback information from a traceback list, with optional color.
352 354
353 355 Calling: requires 3 arguments:
354 356 (etype, evalue, elist)
355 357 as would be obtained by:
356 358 etype, evalue, tb = sys.exc_info()
357 359 if tb:
358 360 elist = traceback.extract_tb(tb)
359 361 else:
360 362 elist = None
361 363
362 364 It can thus be used by programs which need to process the traceback before
363 365 printing (such as console replacements based on the code module from the
364 366 standard library).
365 367
366 368 Because they are meant to be called without a full traceback (only a
367 369 list), instances of this class can't call the interactive pdb debugger."""
368 370
369 371 def __init__(self,color_scheme = 'NoColor'):
370 372 TBTools.__init__(self,color_scheme = color_scheme,call_pdb=0)
371 373
372 374 def __call__(self, etype, value, elist):
373 375 Term.cout.flush()
374 376 print >> Term.cerr, self.text(etype,value,elist)
375 377 Term.cerr.flush()
376 378
377 379 def text(self,etype, value, elist,context=5):
378 380 """Return a color formatted string with the traceback info."""
379 381
380 382 Colors = self.Colors
381 383 out_string = ['%s%s%s\n' % (Colors.topline,'-'*60,Colors.Normal)]
382 384 if elist:
383 385 out_string.append('Traceback %s(most recent call last)%s:' % \
384 386 (Colors.normalEm, Colors.Normal) + '\n')
385 387 out_string.extend(self._format_list(elist))
386 388 lines = self._format_exception_only(etype, value)
387 389 for line in lines[:-1]:
388 390 out_string.append(" "+line)
389 391 out_string.append(lines[-1])
390 392 return ''.join(out_string)
391 393
392 394 def _format_list(self, extracted_list):
393 395 """Format a list of traceback entry tuples for printing.
394 396
395 397 Given a list of tuples as returned by extract_tb() or
396 398 extract_stack(), return a list of strings ready for printing.
397 399 Each string in the resulting list corresponds to the item with the
398 400 same index in the argument list. Each string ends in a newline;
399 401 the strings may contain internal newlines as well, for those items
400 402 whose source text line is not None.
401 403
402 404 Lifted almost verbatim from traceback.py
403 405 """
404 406
405 407 Colors = self.Colors
406 408 list = []
407 409 for filename, lineno, name, line in extracted_list[:-1]:
408 410 item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \
409 411 (Colors.filename, filename, Colors.Normal,
410 412 Colors.lineno, lineno, Colors.Normal,
411 413 Colors.name, name, Colors.Normal)
412 414 if line:
413 415 item = item + ' %s\n' % line.strip()
414 416 list.append(item)
415 417 # Emphasize the last entry
416 418 filename, lineno, name, line = extracted_list[-1]
417 419 item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \
418 420 (Colors.normalEm,
419 421 Colors.filenameEm, filename, Colors.normalEm,
420 422 Colors.linenoEm, lineno, Colors.normalEm,
421 423 Colors.nameEm, name, Colors.normalEm,
422 424 Colors.Normal)
423 425 if line:
424 426 item = item + '%s %s%s\n' % (Colors.line, line.strip(),
425 427 Colors.Normal)
426 428 list.append(item)
427 429 return list
428 430
429 431 def _format_exception_only(self, etype, value):
430 432 """Format the exception part of a traceback.
431 433
432 434 The arguments are the exception type and value such as given by
433 435 sys.exc_info()[:2]. The return value is a list of strings, each ending
434 436 in a newline. Normally, the list contains a single string; however,
435 437 for SyntaxError exceptions, it contains several lines that (when
436 438 printed) display detailed information about where the syntax error
437 439 occurred. The message indicating which exception occurred is the
438 440 always last string in the list.
439 441
440 442 Also lifted nearly verbatim from traceback.py
441 443 """
442 444
443 445 have_filedata = False
444 446 Colors = self.Colors
445 447 list = []
446 448 try:
447 449 stype = Colors.excName + etype.__name__ + Colors.Normal
448 450 except AttributeError:
449 451 stype = etype # String exceptions don't get special coloring
450 452 if value is None:
451 453 list.append( str(stype) + '\n')
452 454 else:
453 455 if etype is SyntaxError:
454 456 try:
455 457 msg, (filename, lineno, offset, line) = value
456 458 except:
457 459 have_filedata = False
458 460 else:
459 461 have_filedata = True
460 462 #print 'filename is',filename # dbg
461 463 if not filename: filename = "<string>"
462 464 list.append('%s File %s"%s"%s, line %s%d%s\n' % \
463 465 (Colors.normalEm,
464 466 Colors.filenameEm, filename, Colors.normalEm,
465 467 Colors.linenoEm, lineno, Colors.Normal ))
466 468 if line is not None:
467 469 i = 0
468 470 while i < len(line) and line[i].isspace():
469 471 i = i+1
470 472 list.append('%s %s%s\n' % (Colors.line,
471 473 line.strip(),
472 474 Colors.Normal))
473 475 if offset is not None:
474 476 s = ' '
475 477 for c in line[i:offset-1]:
476 478 if c.isspace():
477 479 s = s + c
478 480 else:
479 481 s = s + ' '
480 482 list.append('%s%s^%s\n' % (Colors.caret, s,
481 483 Colors.Normal) )
482 484 value = msg
483 485 s = self._some_str(value)
484 486 if s:
485 487 list.append('%s%s:%s %s\n' % (str(stype), Colors.excName,
486 488 Colors.Normal, s))
487 489 else:
488 490 list.append('%s\n' % str(stype))
489 491
490 # vds:>>
491 if have_filedata:
492 __IPYTHON__.hooks.synchronize_with_editor(filename, lineno, 0)
493 # vds:<<
492 # This is being commented out for now as the __IPYTHON__ variable
493 # referenced here is not resolved and causes massive test failures
494 # and errors. B. Granger, 04/2009. XXX
495 # See https://bugs.launchpad.net/bugs/362137
496 # # vds:>>
497 # if have_filedata:
498 # __IPYTHON__.hooks.synchronize_with_editor(filename, lineno, 0)
499 # # vds:<<
494 500
495 501 return list
496 502
497 503 def _some_str(self, value):
498 504 # Lifted from traceback.py
499 505 try:
500 506 return str(value)
501 507 except:
502 508 return '<unprintable %s object>' % type(value).__name__
503 509
504 510 #----------------------------------------------------------------------------
505 511 class VerboseTB(TBTools):
506 512 """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead
507 513 of HTML. Requires inspect and pydoc. Crazy, man.
508 514
509 515 Modified version which optionally strips the topmost entries from the
510 516 traceback, to be used with alternate interpreters (because their own code
511 517 would appear in the traceback)."""
512 518
513 519 def __init__(self,color_scheme = 'Linux',tb_offset=0,long_header=0,
514 520 call_pdb = 0, include_vars=1):
515 521 """Specify traceback offset, headers and color scheme.
516 522
517 523 Define how many frames to drop from the tracebacks. Calling it with
518 524 tb_offset=1 allows use of this handler in interpreters which will have
519 525 their own code at the top of the traceback (VerboseTB will first
520 526 remove that frame before printing the traceback info)."""
521 527 TBTools.__init__(self,color_scheme=color_scheme,call_pdb=call_pdb)
522 528 self.tb_offset = tb_offset
523 529 self.long_header = long_header
524 530 self.include_vars = include_vars
525 531
526 532 def text(self, etype, evalue, etb, context=5):
527 533 """Return a nice text document describing the traceback."""
528 534
529 535 # some locals
530 536 try:
531 537 etype = etype.__name__
532 538 except AttributeError:
533 539 pass
534 540 Colors = self.Colors # just a shorthand + quicker name lookup
535 541 ColorsNormal = Colors.Normal # used a lot
536 542 col_scheme = self.color_scheme_table.active_scheme_name
537 543 indent = ' '*INDENT_SIZE
538 544 em_normal = '%s\n%s%s' % (Colors.valEm, indent,ColorsNormal)
539 545 undefined = '%sundefined%s' % (Colors.em, ColorsNormal)
540 546 exc = '%s%s%s' % (Colors.excName,etype,ColorsNormal)
541 547
542 548 # some internal-use functions
543 549 def text_repr(value):
544 550 """Hopefully pretty robust repr equivalent."""
545 551 # this is pretty horrible but should always return *something*
546 552 try:
547 553 return pydoc.text.repr(value)
548 554 except KeyboardInterrupt:
549 555 raise
550 556 except:
551 557 try:
552 558 return repr(value)
553 559 except KeyboardInterrupt:
554 560 raise
555 561 except:
556 562 try:
557 563 # all still in an except block so we catch
558 564 # getattr raising
559 565 name = getattr(value, '__name__', None)
560 566 if name:
561 567 # ick, recursion
562 568 return text_repr(name)
563 569 klass = getattr(value, '__class__', None)
564 570 if klass:
565 571 return '%s instance' % text_repr(klass)
566 572 except KeyboardInterrupt:
567 573 raise
568 574 except:
569 575 return 'UNRECOVERABLE REPR FAILURE'
570 576 def eqrepr(value, repr=text_repr): return '=%s' % repr(value)
571 577 def nullrepr(value, repr=text_repr): return ''
572 578
573 579 # meat of the code begins
574 580 try:
575 581 etype = etype.__name__
576 582 except AttributeError:
577 583 pass
578 584
579 585 if self.long_header:
580 586 # Header with the exception type, python version, and date
581 587 pyver = 'Python ' + string.split(sys.version)[0] + ': ' + sys.executable
582 588 date = time.ctime(time.time())
583 589
584 590 head = '%s%s%s\n%s%s%s\n%s' % (Colors.topline, '-'*75, ColorsNormal,
585 591 exc, ' '*(75-len(str(etype))-len(pyver)),
586 592 pyver, string.rjust(date, 75) )
587 593 head += "\nA problem occured executing Python code. Here is the sequence of function"\
588 594 "\ncalls leading up to the error, with the most recent (innermost) call last."
589 595 else:
590 596 # Simplified header
591 597 head = '%s%s%s\n%s%s' % (Colors.topline, '-'*75, ColorsNormal,exc,
592 598 string.rjust('Traceback (most recent call last)',
593 599 75 - len(str(etype)) ) )
594 600 frames = []
595 601 # Flush cache before calling inspect. This helps alleviate some of the
596 602 # problems with python 2.3's inspect.py.
597 603 linecache.checkcache()
598 604 # Drop topmost frames if requested
599 605 try:
600 606 # Try the default getinnerframes and Alex's: Alex's fixes some
601 607 # problems, but it generates empty tracebacks for console errors
602 608 # (5 blanks lines) where none should be returned.
603 609 #records = inspect.getinnerframes(etb, context)[self.tb_offset:]
604 610 #print 'python records:', records # dbg
605 611 records = _fixed_getinnerframes(etb, context,self.tb_offset)
606 612 #print 'alex records:', records # dbg
607 613 except:
608 614
609 615 # FIXME: I've been getting many crash reports from python 2.3
610 616 # users, traceable to inspect.py. If I can find a small test-case
611 617 # to reproduce this, I should either write a better workaround or
612 618 # file a bug report against inspect (if that's the real problem).
613 619 # So far, I haven't been able to find an isolated example to
614 620 # reproduce the problem.
615 621 inspect_error()
616 622 traceback.print_exc(file=Term.cerr)
617 623 info('\nUnfortunately, your original traceback can not be constructed.\n')
618 624 return ''
619 625
620 626 # build some color string templates outside these nested loops
621 627 tpl_link = '%s%%s%s' % (Colors.filenameEm,ColorsNormal)
622 628 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
623 629 ColorsNormal)
624 630 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
625 631 (Colors.vName, Colors.valEm, ColorsNormal)
626 632 tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal)
627 633 tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal,
628 634 Colors.vName, ColorsNormal)
629 635 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
630 636 tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal)
631 637 tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm,Colors.line,
632 638 ColorsNormal)
633 639
634 640 # now, loop over all records printing context and info
635 641 abspath = os.path.abspath
636 642 for frame, file, lnum, func, lines, index in records:
637 643 #print '*** record:',file,lnum,func,lines,index # dbg
638 644 try:
639 645 file = file and abspath(file) or '?'
640 646 except OSError:
641 647 # if file is '<console>' or something not in the filesystem,
642 648 # the abspath call will throw an OSError. Just ignore it and
643 649 # keep the original file string.
644 650 pass
645 651 link = tpl_link % file
646 652 try:
647 653 args, varargs, varkw, locals = inspect.getargvalues(frame)
648 654 except:
649 655 # This can happen due to a bug in python2.3. We should be
650 656 # able to remove this try/except when 2.4 becomes a
651 657 # requirement. Bug details at http://python.org/sf/1005466
652 658 inspect_error()
653 659 traceback.print_exc(file=Term.cerr)
654 660 info("\nIPython's exception reporting continues...\n")
655 661
656 662 if func == '?':
657 663 call = ''
658 664 else:
659 665 # Decide whether to include variable details or not
660 666 var_repr = self.include_vars and eqrepr or nullrepr
661 667 try:
662 668 call = tpl_call % (func,inspect.formatargvalues(args,
663 669 varargs, varkw,
664 670 locals,formatvalue=var_repr))
665 671 except KeyError:
666 672 # Very odd crash from inspect.formatargvalues(). The
667 673 # scenario under which it appeared was a call to
668 674 # view(array,scale) in NumTut.view.view(), where scale had
669 675 # been defined as a scalar (it should be a tuple). Somehow
670 676 # inspect messes up resolving the argument list of view()
671 677 # and barfs out. At some point I should dig into this one
672 678 # and file a bug report about it.
673 679 inspect_error()
674 680 traceback.print_exc(file=Term.cerr)
675 681 info("\nIPython's exception reporting continues...\n")
676 682 call = tpl_call_fail % func
677 683
678 684 # Initialize a list of names on the current line, which the
679 685 # tokenizer below will populate.
680 686 names = []
681 687
682 688 def tokeneater(token_type, token, start, end, line):
683 689 """Stateful tokeneater which builds dotted names.
684 690
685 691 The list of names it appends to (from the enclosing scope) can
686 692 contain repeated composite names. This is unavoidable, since
687 693 there is no way to disambguate partial dotted structures until
688 694 the full list is known. The caller is responsible for pruning
689 695 the final list of duplicates before using it."""
690 696
691 697 # build composite names
692 698 if token == '.':
693 699 try:
694 700 names[-1] += '.'
695 701 # store state so the next token is added for x.y.z names
696 702 tokeneater.name_cont = True
697 703 return
698 704 except IndexError:
699 705 pass
700 706 if token_type == tokenize.NAME and token not in keyword.kwlist:
701 707 if tokeneater.name_cont:
702 708 # Dotted names
703 709 names[-1] += token
704 710 tokeneater.name_cont = False
705 711 else:
706 712 # Regular new names. We append everything, the caller
707 713 # will be responsible for pruning the list later. It's
708 714 # very tricky to try to prune as we go, b/c composite
709 715 # names can fool us. The pruning at the end is easy
710 716 # to do (or the caller can print a list with repeated
711 717 # names if so desired.
712 718 names.append(token)
713 719 elif token_type == tokenize.NEWLINE:
714 720 raise IndexError
715 721 # we need to store a bit of state in the tokenizer to build
716 722 # dotted names
717 723 tokeneater.name_cont = False
718 724
719 725 def linereader(file=file, lnum=[lnum], getline=linecache.getline):
720 726 line = getline(file, lnum[0])
721 727 lnum[0] += 1
722 728 return line
723 729
724 730 # Build the list of names on this line of code where the exception
725 731 # occurred.
726 732 try:
727 733 # This builds the names list in-place by capturing it from the
728 734 # enclosing scope.
729 735 tokenize.tokenize(linereader, tokeneater)
730 736 except IndexError:
731 737 # signals exit of tokenizer
732 738 pass
733 739 except tokenize.TokenError,msg:
734 740 _m = ("An unexpected error occurred while tokenizing input\n"
735 741 "The following traceback may be corrupted or invalid\n"
736 742 "The error message is: %s\n" % msg)
737 743 error(_m)
738 744
739 745 # prune names list of duplicates, but keep the right order
740 746 unique_names = uniq_stable(names)
741 747
742 748 # Start loop over vars
743 749 lvals = []
744 750 if self.include_vars:
745 751 for name_full in unique_names:
746 752 name_base = name_full.split('.',1)[0]
747 753 if name_base in frame.f_code.co_varnames:
748 754 if locals.has_key(name_base):
749 755 try:
750 756 value = repr(eval(name_full,locals))
751 757 except:
752 758 value = undefined
753 759 else:
754 760 value = undefined
755 761 name = tpl_local_var % name_full
756 762 else:
757 763 if frame.f_globals.has_key(name_base):
758 764 try:
759 765 value = repr(eval(name_full,frame.f_globals))
760 766 except:
761 767 value = undefined
762 768 else:
763 769 value = undefined
764 770 name = tpl_global_var % name_full
765 771 lvals.append(tpl_name_val % (name,value))
766 772 if lvals:
767 773 lvals = '%s%s' % (indent,em_normal.join(lvals))
768 774 else:
769 775 lvals = ''
770 776
771 777 level = '%s %s\n' % (link,call)
772 778
773 779 if index is None:
774 780 frames.append(level)
775 781 else:
776 782 frames.append('%s%s' % (level,''.join(
777 783 _formatTracebackLines(lnum,index,lines,Colors,lvals,
778 784 col_scheme))))
779 785
780 786 # Get (safely) a string form of the exception info
781 787 try:
782 788 etype_str,evalue_str = map(str,(etype,evalue))
783 789 except:
784 790 # User exception is improperly defined.
785 791 etype,evalue = str,sys.exc_info()[:2]
786 792 etype_str,evalue_str = map(str,(etype,evalue))
787 793 # ... and format it
788 794 exception = ['%s%s%s: %s' % (Colors.excName, etype_str,
789 795 ColorsNormal, evalue_str)]
790 796 if type(evalue) is types.InstanceType:
791 797 try:
792 798 names = [w for w in dir(evalue) if isinstance(w, basestring)]
793 799 except:
794 800 # Every now and then, an object with funny inernals blows up
795 801 # when dir() is called on it. We do the best we can to report
796 802 # the problem and continue
797 803 _m = '%sException reporting error (object with broken dir())%s:'
798 804 exception.append(_m % (Colors.excName,ColorsNormal))
799 805 etype_str,evalue_str = map(str,sys.exc_info()[:2])
800 806 exception.append('%s%s%s: %s' % (Colors.excName,etype_str,
801 807 ColorsNormal, evalue_str))
802 808 names = []
803 809 for name in names:
804 810 value = text_repr(getattr(evalue, name))
805 811 exception.append('\n%s%s = %s' % (indent, name, value))
806 812
807 # vds: >>
808 if records:
809 filepath, lnum = records[-1][1:3]
810 #print "file:", str(file), "linenb", str(lnum) # dbg
811 filepath = os.path.abspath(filepath)
812 __IPYTHON__.hooks.synchronize_with_editor(filepath, lnum, 0)
813 # vds: <<
813 # This is being commented out for now as the __IPYTHON__ variable
814 # referenced here is not resolved and causes massive test failures
815 # and errors. B. Granger, 04/2009. XXX
816 # See https://bugs.launchpad.net/bugs/362137
817 # # vds: >>
818 # if records:
819 # filepath, lnum = records[-1][1:3]
820 # #print "file:", str(file), "linenb", str(lnum) # dbg
821 # filepath = os.path.abspath(filepath)
822 # __IPYTHON__.hooks.synchronize_with_editor(filepath, lnum, 0)
823 # # vds: <<
814 824
815 825 # return all our info assembled as a single string
816 826 return '%s\n\n%s\n%s' % (head,'\n'.join(frames),''.join(exception[0]) )
817 827
818 828 def debugger(self,force=False):
819 829 """Call up the pdb debugger if desired, always clean up the tb
820 830 reference.
821 831
822 832 Keywords:
823 833
824 834 - force(False): by default, this routine checks the instance call_pdb
825 835 flag and does not actually invoke the debugger if the flag is false.
826 836 The 'force' option forces the debugger to activate even if the flag
827 837 is false.
828 838
829 839 If the call_pdb flag is set, the pdb interactive debugger is
830 840 invoked. In all cases, the self.tb reference to the current traceback
831 841 is deleted to prevent lingering references which hamper memory
832 842 management.
833 843
834 844 Note that each call to pdb() does an 'import readline', so if your app
835 845 requires a special setup for the readline completers, you'll have to
836 846 fix that by hand after invoking the exception handler."""
837 847
838 848 if force or self.call_pdb:
839 849 if self.pdb is None:
840 850 self.pdb = Debugger.Pdb(
841 851 self.color_scheme_table.active_scheme_name)
842 852 # the system displayhook may have changed, restore the original
843 853 # for pdb
844 854 dhook = sys.displayhook
845 855 sys.displayhook = sys.__displayhook__
846 856 self.pdb.reset()
847 857 # Find the right frame so we don't pop up inside ipython itself
848 858 if hasattr(self,'tb'):
849 859 etb = self.tb
850 860 else:
851 861 etb = self.tb = sys.last_traceback
852 862 while self.tb.tb_next is not None:
853 863 self.tb = self.tb.tb_next
854 864 try:
855 865 if etb and etb.tb_next:
856 866 etb = etb.tb_next
857 867 self.pdb.botframe = etb.tb_frame
858 868 self.pdb.interaction(self.tb.tb_frame, self.tb)
859 869 finally:
860 870 sys.displayhook = dhook
861 871
862 872 if hasattr(self,'tb'):
863 873 del self.tb
864 874
865 875 def handler(self, info=None):
866 876 (etype, evalue, etb) = info or sys.exc_info()
867 877 self.tb = etb
868 878 Term.cout.flush()
869 879 print >> Term.cerr, self.text(etype, evalue, etb)
870 880 Term.cerr.flush()
871 881
872 882 # Changed so an instance can just be called as VerboseTB_inst() and print
873 883 # out the right info on its own.
874 884 def __call__(self, etype=None, evalue=None, etb=None):
875 885 """This hook can replace sys.excepthook (for Python 2.1 or higher)."""
876 886 if etb is None:
877 887 self.handler()
878 888 else:
879 889 self.handler((etype, evalue, etb))
880 890 try:
881 891 self.debugger()
882 892 except KeyboardInterrupt:
883 893 print "\nKeyboardInterrupt"
884 894
885 895 #----------------------------------------------------------------------------
886 896 class FormattedTB(VerboseTB,ListTB):
887 897 """Subclass ListTB but allow calling with a traceback.
888 898
889 899 It can thus be used as a sys.excepthook for Python > 2.1.
890 900
891 901 Also adds 'Context' and 'Verbose' modes, not available in ListTB.
892 902
893 903 Allows a tb_offset to be specified. This is useful for situations where
894 904 one needs to remove a number of topmost frames from the traceback (such as
895 905 occurs with python programs that themselves execute other python code,
896 906 like Python shells). """
897 907
898 908 def __init__(self, mode = 'Plain', color_scheme='Linux',
899 909 tb_offset = 0,long_header=0,call_pdb=0,include_vars=0):
900 910
901 911 # NEVER change the order of this list. Put new modes at the end:
902 912 self.valid_modes = ['Plain','Context','Verbose']
903 913 self.verbose_modes = self.valid_modes[1:3]
904 914
905 915 VerboseTB.__init__(self,color_scheme,tb_offset,long_header,
906 916 call_pdb=call_pdb,include_vars=include_vars)
907 917 self.set_mode(mode)
908 918
909 919 def _extract_tb(self,tb):
910 920 if tb:
911 921 return traceback.extract_tb(tb)
912 922 else:
913 923 return None
914 924
915 925 def text(self, etype, value, tb,context=5,mode=None):
916 926 """Return formatted traceback.
917 927
918 928 If the optional mode parameter is given, it overrides the current
919 929 mode."""
920 930
921 931 if mode is None:
922 932 mode = self.mode
923 933 if mode in self.verbose_modes:
924 934 # verbose modes need a full traceback
925 935 return VerboseTB.text(self,etype, value, tb,context=5)
926 936 else:
927 937 # We must check the source cache because otherwise we can print
928 938 # out-of-date source code.
929 939 linecache.checkcache()
930 940 # Now we can extract and format the exception
931 941 elist = self._extract_tb(tb)
932 942 if len(elist) > self.tb_offset:
933 943 del elist[:self.tb_offset]
934 944 return ListTB.text(self,etype,value,elist)
935 945
936 946 def set_mode(self,mode=None):
937 947 """Switch to the desired mode.
938 948
939 949 If mode is not specified, cycles through the available modes."""
940 950
941 951 if not mode:
942 952 new_idx = ( self.valid_modes.index(self.mode) + 1 ) % \
943 953 len(self.valid_modes)
944 954 self.mode = self.valid_modes[new_idx]
945 955 elif mode not in self.valid_modes:
946 956 raise ValueError, 'Unrecognized mode in FormattedTB: <'+mode+'>\n'\
947 957 'Valid modes: '+str(self.valid_modes)
948 958 else:
949 959 self.mode = mode
950 960 # include variable details only in 'Verbose' mode
951 961 self.include_vars = (self.mode == self.valid_modes[2])
952 962
953 963 # some convenient shorcuts
954 964 def plain(self):
955 965 self.set_mode(self.valid_modes[0])
956 966
957 967 def context(self):
958 968 self.set_mode(self.valid_modes[1])
959 969
960 970 def verbose(self):
961 971 self.set_mode(self.valid_modes[2])
962 972
963 973 #----------------------------------------------------------------------------
964 974 class AutoFormattedTB(FormattedTB):
965 975 """A traceback printer which can be called on the fly.
966 976
967 977 It will find out about exceptions by itself.
968 978
969 979 A brief example:
970 980
971 981 AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux')
972 982 try:
973 983 ...
974 984 except:
975 985 AutoTB() # or AutoTB(out=logfile) where logfile is an open file object
976 986 """
977 987 def __call__(self,etype=None,evalue=None,etb=None,
978 988 out=None,tb_offset=None):
979 989 """Print out a formatted exception traceback.
980 990
981 991 Optional arguments:
982 992 - out: an open file-like object to direct output to.
983 993
984 994 - tb_offset: the number of frames to skip over in the stack, on a
985 995 per-call basis (this overrides temporarily the instance's tb_offset
986 996 given at initialization time. """
987 997
988 998 if out is None:
989 999 out = Term.cerr
990 1000 Term.cout.flush()
991 1001 if tb_offset is not None:
992 1002 tb_offset, self.tb_offset = self.tb_offset, tb_offset
993 1003 print >> out, self.text(etype, evalue, etb)
994 1004 self.tb_offset = tb_offset
995 1005 else:
996 1006 print >> out, self.text(etype, evalue, etb)
997 1007 out.flush()
998 1008 try:
999 1009 self.debugger()
1000 1010 except KeyboardInterrupt:
1001 1011 print "\nKeyboardInterrupt"
1002 1012
1003 1013 def text(self,etype=None,value=None,tb=None,context=5,mode=None):
1004 1014 if etype is None:
1005 1015 etype,value,tb = sys.exc_info()
1006 1016 self.tb = tb
1007 1017 return FormattedTB.text(self,etype,value,tb,context=5,mode=mode)
1008 1018
1009 1019 #---------------------------------------------------------------------------
1010 1020 # A simple class to preserve Nathan's original functionality.
1011 1021 class ColorTB(FormattedTB):
1012 1022 """Shorthand to initialize a FormattedTB in Linux colors mode."""
1013 1023 def __init__(self,color_scheme='Linux',call_pdb=0):
1014 1024 FormattedTB.__init__(self,color_scheme=color_scheme,
1015 1025 call_pdb=call_pdb)
1016 1026
1017 1027 #----------------------------------------------------------------------------
1018 1028 # module testing (minimal)
1019 1029 if __name__ == "__main__":
1020 1030 def spam(c, (d, e)):
1021 1031 x = c + d
1022 1032 y = c * d
1023 1033 foo(x, y)
1024 1034
1025 1035 def foo(a, b, bar=1):
1026 1036 eggs(a, b + bar)
1027 1037
1028 1038 def eggs(f, g, z=globals()):
1029 1039 h = f + g
1030 1040 i = f - g
1031 1041 return h / i
1032 1042
1033 1043 print ''
1034 1044 print '*** Before ***'
1035 1045 try:
1036 1046 print spam(1, (2, 3))
1037 1047 except:
1038 1048 traceback.print_exc()
1039 1049 print ''
1040 1050
1041 1051 handler = ColorTB()
1042 1052 print '*** ColorTB ***'
1043 1053 try:
1044 1054 print spam(1, (2, 3))
1045 1055 except:
1046 1056 apply(handler, sys.exc_info() )
1047 1057 print ''
1048 1058
1049 1059 handler = VerboseTB()
1050 1060 print '*** VerboseTB ***'
1051 1061 try:
1052 1062 print spam(1, (2, 3))
1053 1063 except:
1054 1064 apply(handler, sys.exc_info() )
1055 1065 print ''
1056 1066
@@ -1,92 +1,92 b''
1 1 # encoding: utf-8
2 2
3 3 """A class that manages the engines connection to the controller."""
4 4
5 5 __docformat__ = "restructuredtext en"
6 6
7 7 #-------------------------------------------------------------------------------
8 8 # Copyright (C) 2008 The IPython Development Team
9 9 #
10 10 # Distributed under the terms of the BSD License. The full license is in
11 11 # the file COPYING, distributed as part of this software.
12 12 #-------------------------------------------------------------------------------
13 13
14 14 #-------------------------------------------------------------------------------
15 15 # Imports
16 16 #-------------------------------------------------------------------------------
17 17
18 18 import os
19 19 import cPickle as pickle
20 20
21 21 from twisted.python import log, failure
22 22 from twisted.internet import defer
23 23
24 24 from IPython.kernel.fcutil import find_furl
25 25 from IPython.kernel.enginefc import IFCEngine
26 26
27 27 #-------------------------------------------------------------------------------
28 28 # The ClientConnector class
29 29 #-------------------------------------------------------------------------------
30 30
31 31 class EngineConnector(object):
32 32 """Manage an engines connection to a controller.
33 33
34 34 This class takes a foolscap `Tub` and provides a `connect_to_controller`
35 35 method that will use the `Tub` to connect to a controller and register
36 36 the engine with the controller.
37 37 """
38 38
39 39 def __init__(self, tub):
40 40 self.tub = tub
41 41
42 42 def connect_to_controller(self, engine_service, furl_or_file):
43 43 """
44 44 Make a connection to a controller specified by a furl.
45 45
46 46 This method takes an `IEngineBase` instance and a foolcap URL and uses
47 47 the `tub` attribute to make a connection to the controller. The
48 48 foolscap URL contains all the information needed to connect to the
49 49 controller, including the ip and port as well as any encryption and
50 50 authentication information needed for the connection.
51 51
52 52 After getting a reference to the controller, this method calls the
53 53 `register_engine` method of the controller to actually register the
54 54 engine.
55 55
56 56 :Parameters:
57 57 engine_service : IEngineBase
58 58 An instance of an `IEngineBase` implementer
59 59 furl_or_file : str
60 60 A furl or a filename containing a furl
61 61 """
62 62 if not self.tub.running:
63 63 self.tub.startService()
64 64 self.engine_service = engine_service
65 65 self.engine_reference = IFCEngine(self.engine_service)
66 66 try:
67 67 self.furl = find_furl(furl_or_file)
68 68 except ValueError:
69 69 return defer.fail(failure.Failure())
70 # return defer.fail(failure.Failure(ValueError('not a valid furl or furl file: %r' % furl_or_file)))
71 d = self.tub.getReference(self.furl)
72 d.addCallbacks(self._register, self._log_failure)
73 return d
70 else:
71 d = self.tub.getReference(self.furl)
72 d.addCallbacks(self._register, self._log_failure)
73 return d
74 74
75 75 def _log_failure(self, reason):
76 76 log.err('EngineConnector: engine registration failed:')
77 77 log.err(reason)
78 78 return reason
79 79
80 80 def _register(self, rr):
81 81 self.remote_ref = rr
82 82 # Now register myself with the controller
83 83 desired_id = self.engine_service.id
84 84 d = self.remote_ref.callRemote('register_engine', self.engine_reference,
85 85 desired_id, os.getpid(), pickle.dumps(self.engine_service.properties,2))
86 86 return d.addCallbacks(self._reference_sent, self._log_failure)
87 87
88 88 def _reference_sent(self, registration_dict):
89 89 self.engine_service.id = registration_dict['id']
90 90 log.msg("engine registration succeeded, got id: %r" % self.engine_service.id)
91 91 return self.engine_service.id
92 92
@@ -1,903 +1,906 b''
1 1 # encoding: utf-8
2 2 # -*- test-case-name: IPython.kernel.tests.test_engineservice -*-
3 3
4 4 """A Twisted Service Representation of the IPython core.
5 5
6 6 The IPython Core exposed to the network is called the Engine. Its
7 7 representation in Twisted in the EngineService. Interfaces and adapters
8 8 are used to abstract out the details of the actual network protocol used.
9 9 The EngineService is an Engine that knows nothing about the actual protocol
10 10 used.
11 11
12 12 The EngineService is exposed with various network protocols in modules like:
13 13
14 14 enginepb.py
15 15 enginevanilla.py
16 16
17 17 As of 12/12/06 the classes in this module have been simplified greatly. It was
18 18 felt that we had over-engineered things. To improve the maintainability of the
19 19 code we have taken out the ICompleteEngine interface and the completeEngine
20 20 method that automatically added methods to engines.
21 21
22 22 """
23 23
24 24 __docformat__ = "restructuredtext en"
25 25
26 26 #-------------------------------------------------------------------------------
27 27 # Copyright (C) 2008 The IPython Development Team
28 28 #
29 29 # Distributed under the terms of the BSD License. The full license is in
30 30 # the file COPYING, distributed as part of this software.
31 31 #-------------------------------------------------------------------------------
32 32
33 33 #-------------------------------------------------------------------------------
34 34 # Imports
35 35 #-------------------------------------------------------------------------------
36 36
37 # Tell nose to skip the testing of this module
38 __test__ = {}
39
37 40 import os, sys, copy
38 41 import cPickle as pickle
39 42 from new import instancemethod
40 43
41 44 from twisted.application import service
42 45 from twisted.internet import defer, reactor
43 46 from twisted.python import log, failure, components
44 47 import zope.interface as zi
45 48
46 49 from IPython.kernel.core.interpreter import Interpreter
47 50 from IPython.kernel import newserialized, error, util
48 51 from IPython.kernel.util import printer
49 52 from IPython.kernel.twistedutil import gatherBoth, DeferredList
50 53 from IPython.kernel import codeutil
51 54
52 55
53 56 #-------------------------------------------------------------------------------
54 57 # Interface specification for the Engine
55 58 #-------------------------------------------------------------------------------
56 59
57 60 class IEngineCore(zi.Interface):
58 61 """The minimal required interface for the IPython Engine.
59 62
60 63 This interface provides a formal specification of the IPython core.
61 64 All these methods should return deferreds regardless of what side of a
62 65 network connection they are on.
63 66
64 67 In general, this class simply wraps a shell class and wraps its return
65 68 values as Deferred objects. If the underlying shell class method raises
66 69 an exception, this class should convert it to a twisted.failure.Failure
67 70 that will be propagated along the Deferred's errback chain.
68 71
69 72 In addition, Failures are aggressive. By this, we mean that if a method
70 73 is performing multiple actions (like pulling multiple object) if any
71 74 single one fails, the entire method will fail with that Failure. It is
72 75 all or nothing.
73 76 """
74 77
75 78 id = zi.interface.Attribute("the id of the Engine object")
76 79 properties = zi.interface.Attribute("A dict of properties of the Engine")
77 80
78 81 def execute(lines):
79 82 """Execute lines of Python code.
80 83
81 84 Returns a dictionary with keys (id, number, stdin, stdout, stderr)
82 85 upon success.
83 86
84 87 Returns a failure object if the execution of lines raises an exception.
85 88 """
86 89
87 90 def push(namespace):
88 91 """Push dict namespace into the user's namespace.
89 92
90 93 Returns a deferred to None or a failure.
91 94 """
92 95
93 96 def pull(keys):
94 97 """Pulls values out of the user's namespace by keys.
95 98
96 99 Returns a deferred to a tuple objects or a single object.
97 100
98 101 Raises NameError if any one of objects doess not exist.
99 102 """
100 103
101 104 def push_function(namespace):
102 105 """Push a dict of key, function pairs into the user's namespace.
103 106
104 107 Returns a deferred to None or a failure."""
105 108
106 109 def pull_function(keys):
107 110 """Pulls functions out of the user's namespace by keys.
108 111
109 112 Returns a deferred to a tuple of functions or a single function.
110 113
111 114 Raises NameError if any one of the functions does not exist.
112 115 """
113 116
114 117 def get_result(i=None):
115 118 """Get the stdin/stdout/stderr of command i.
116 119
117 120 Returns a deferred to a dict with keys
118 121 (id, number, stdin, stdout, stderr).
119 122
120 123 Raises IndexError if command i does not exist.
121 124 Raises TypeError if i in not an int.
122 125 """
123 126
124 127 def reset():
125 128 """Reset the shell.
126 129
127 130 This clears the users namespace. Won't cause modules to be
128 131 reloaded. Should also re-initialize certain variables like id.
129 132 """
130 133
131 134 def kill():
132 135 """Kill the engine by stopping the reactor."""
133 136
134 137 def keys():
135 138 """Return the top level variables in the users namspace.
136 139
137 140 Returns a deferred to a dict."""
138 141
139 142
140 143 class IEngineSerialized(zi.Interface):
141 144 """Push/Pull methods that take Serialized objects.
142 145
143 146 All methods should return deferreds.
144 147 """
145 148
146 149 def push_serialized(namespace):
147 150 """Push a dict of keys and Serialized objects into the user's namespace."""
148 151
149 152 def pull_serialized(keys):
150 153 """Pull objects by key from the user's namespace as Serialized.
151 154
152 155 Returns a list of or one Serialized.
153 156
154 157 Raises NameError is any one of the objects does not exist.
155 158 """
156 159
157 160
158 161 class IEngineProperties(zi.Interface):
159 162 """Methods for access to the properties object of an Engine"""
160 163
161 164 properties = zi.Attribute("A StrictDict object, containing the properties")
162 165
163 166 def set_properties(properties):
164 167 """set properties by key and value"""
165 168
166 169 def get_properties(keys=None):
167 170 """get a list of properties by `keys`, if no keys specified, get all"""
168 171
169 172 def del_properties(keys):
170 173 """delete properties by `keys`"""
171 174
172 175 def has_properties(keys):
173 176 """get a list of bool values for whether `properties` has `keys`"""
174 177
175 178 def clear_properties():
176 179 """clear the properties dict"""
177 180
178 181 class IEngineBase(IEngineCore, IEngineSerialized, IEngineProperties):
179 182 """The basic engine interface that EngineService will implement.
180 183
181 184 This exists so it is easy to specify adapters that adapt to and from the
182 185 API that the basic EngineService implements.
183 186 """
184 187 pass
185 188
186 189 class IEngineQueued(IEngineBase):
187 190 """Interface for adding a queue to an IEngineBase.
188 191
189 192 This interface extends the IEngineBase interface to add methods for managing
190 193 the engine's queue. The implicit details of this interface are that the
191 194 execution of all methods declared in IEngineBase should appropriately be
192 195 put through a queue before execution.
193 196
194 197 All methods should return deferreds.
195 198 """
196 199
197 200 def clear_queue():
198 201 """Clear the queue."""
199 202
200 203 def queue_status():
201 204 """Get the queued and pending commands in the queue."""
202 205
203 206 def register_failure_observer(obs):
204 207 """Register an observer of pending Failures.
205 208
206 209 The observer must implement IFailureObserver.
207 210 """
208 211
209 212 def unregister_failure_observer(obs):
210 213 """Unregister an observer of pending Failures."""
211 214
212 215
213 216 class IEngineThreaded(zi.Interface):
214 217 """A place holder for threaded commands.
215 218
216 219 All methods should return deferreds.
217 220 """
218 221 pass
219 222
220 223
221 224 #-------------------------------------------------------------------------------
222 225 # Functions and classes to implement the EngineService
223 226 #-------------------------------------------------------------------------------
224 227
225 228
226 229 class StrictDict(dict):
227 230 """This is a strict copying dictionary for use as the interface to the
228 231 properties of an Engine.
229 232
230 233 :IMPORTANT:
231 234 This object copies the values you set to it, and returns copies to you
232 235 when you request them. The only way to change properties os explicitly
233 236 through the setitem and getitem of the dictionary interface.
234 237
235 238 Example:
236 239 >>> e = get_engine(id)
237 240 >>> L = [1,2,3]
238 241 >>> e.properties['L'] = L
239 242 >>> L == e.properties['L']
240 243 True
241 244 >>> L.append(99)
242 245 >>> L == e.properties['L']
243 246 False
244 247
245 248 Note that getitem copies, so calls to methods of objects do not affect
246 249 the properties, as seen here:
247 250
248 251 >>> e.properties[1] = range(2)
249 252 >>> print e.properties[1]
250 253 [0, 1]
251 254 >>> e.properties[1].append(2)
252 255 >>> print e.properties[1]
253 256 [0, 1]
254 257 """
255 258 def __init__(self, *args, **kwargs):
256 259 dict.__init__(self, *args, **kwargs)
257 260 self.modified = True
258 261
259 262 def __getitem__(self, key):
260 263 return copy.deepcopy(dict.__getitem__(self, key))
261 264
262 265 def __setitem__(self, key, value):
263 266 # check if this entry is valid for transport around the network
264 267 # and copying
265 268 try:
266 269 pickle.dumps(key, 2)
267 270 pickle.dumps(value, 2)
268 271 newvalue = copy.deepcopy(value)
269 except:
270 raise error.InvalidProperty(value)
272 except Exception, e:
273 raise error.InvalidProperty("can't be a value: %r" % value)
271 274 dict.__setitem__(self, key, newvalue)
272 275 self.modified = True
273 276
274 277 def __delitem__(self, key):
275 278 dict.__delitem__(self, key)
276 279 self.modified = True
277 280
278 281 def update(self, dikt):
279 282 for k,v in dikt.iteritems():
280 283 self[k] = v
281 284
282 285 def pop(self, key):
283 286 self.modified = True
284 287 return dict.pop(self, key)
285 288
286 289 def popitem(self):
287 290 self.modified = True
288 291 return dict.popitem(self)
289 292
290 293 def clear(self):
291 294 self.modified = True
292 295 dict.clear(self)
293 296
294 297 def subDict(self, *keys):
295 298 d = {}
296 299 for key in keys:
297 300 d[key] = self[key]
298 301 return d
299 302
300 303
301 304
302 305 class EngineAPI(object):
303 306 """This is the object through which the user can edit the `properties`
304 307 attribute of an Engine.
305 308 The Engine Properties object copies all object in and out of itself.
306 309 See the EngineProperties object for details.
307 310 """
308 311 _fix=False
309 312 def __init__(self, id):
310 313 self.id = id
311 314 self.properties = StrictDict()
312 315 self._fix=True
313 316
314 317 def __setattr__(self, k,v):
315 318 if self._fix:
316 319 raise error.KernelError("I am protected!")
317 320 else:
318 321 object.__setattr__(self, k, v)
319 322
320 323 def __delattr__(self, key):
321 324 raise error.KernelError("I am protected!")
322 325
323 326
324 327 _apiDict = {}
325 328
326 329 def get_engine(id):
327 330 """Get the Engine API object, whcih currently just provides the properties
328 331 object, by ID"""
329 332 global _apiDict
330 333 if not _apiDict.get(id):
331 334 _apiDict[id] = EngineAPI(id)
332 335 return _apiDict[id]
333 336
334 337 def drop_engine(id):
335 338 """remove an engine"""
336 339 global _apiDict
337 340 if _apiDict.has_key(id):
338 341 del _apiDict[id]
339 342
340 343 class EngineService(object, service.Service):
341 344 """Adapt a IPython shell into a IEngine implementing Twisted Service."""
342 345
343 346 zi.implements(IEngineBase)
344 347 name = 'EngineService'
345 348
346 349 def __init__(self, shellClass=Interpreter, mpi=None):
347 350 """Create an EngineService.
348 351
349 352 shellClass: something that implements IInterpreter or core1
350 353 mpi: an mpi module that has rank and size attributes
351 354 """
352 355 self.shellClass = shellClass
353 356 self.shell = self.shellClass()
354 357 self.mpi = mpi
355 358 self.id = None
356 359 self.properties = get_engine(self.id).properties
357 360 if self.mpi is not None:
358 361 log.msg("MPI started with rank = %i and size = %i" %
359 362 (self.mpi.rank, self.mpi.size))
360 363 self.id = self.mpi.rank
361 364 self._seedNamespace()
362 365
363 366 # Make id a property so that the shell can get the updated id
364 367
365 368 def _setID(self, id):
366 369 self._id = id
367 370 self.properties = get_engine(id).properties
368 371 self.shell.push({'id': id})
369 372
370 373 def _getID(self):
371 374 return self._id
372 375
373 376 id = property(_getID, _setID)
374 377
375 378 def _seedNamespace(self):
376 379 self.shell.push({'mpi': self.mpi, 'id' : self.id})
377 380
378 381 def executeAndRaise(self, msg, callable, *args, **kwargs):
379 382 """Call a method of self.shell and wrap any exception."""
380 383 d = defer.Deferred()
381 384 try:
382 385 result = callable(*args, **kwargs)
383 386 except:
384 387 # This gives the following:
385 388 # et=exception class
386 389 # ev=exception class instance
387 390 # tb=traceback object
388 391 et,ev,tb = sys.exc_info()
389 392 # This call adds attributes to the exception value
390 393 et,ev,tb = self.shell.formatTraceback(et,ev,tb,msg)
391 394 # Add another attribute
392 395 ev._ipython_engine_info = msg
393 396 f = failure.Failure(ev,et,None)
394 397 d.errback(f)
395 398 else:
396 399 d.callback(result)
397 400
398 401 return d
399 402
400 403
401 404 # The IEngine methods. See the interface for documentation.
402 405
403 406 def execute(self, lines):
404 407 msg = {'engineid':self.id,
405 408 'method':'execute',
406 409 'args':[lines]}
407 410 d = self.executeAndRaise(msg, self.shell.execute, lines)
408 411 d.addCallback(self.addIDToResult)
409 412 return d
410 413
411 414 def addIDToResult(self, result):
412 415 result['id'] = self.id
413 416 return result
414 417
415 418 def push(self, namespace):
416 419 msg = {'engineid':self.id,
417 420 'method':'push',
418 421 'args':[repr(namespace.keys())]}
419 422 d = self.executeAndRaise(msg, self.shell.push, namespace)
420 423 return d
421 424
422 425 def pull(self, keys):
423 426 msg = {'engineid':self.id,
424 427 'method':'pull',
425 428 'args':[repr(keys)]}
426 429 d = self.executeAndRaise(msg, self.shell.pull, keys)
427 430 return d
428 431
429 432 def push_function(self, namespace):
430 433 msg = {'engineid':self.id,
431 434 'method':'push_function',
432 435 'args':[repr(namespace.keys())]}
433 436 d = self.executeAndRaise(msg, self.shell.push_function, namespace)
434 437 return d
435 438
436 439 def pull_function(self, keys):
437 440 msg = {'engineid':self.id,
438 441 'method':'pull_function',
439 442 'args':[repr(keys)]}
440 443 d = self.executeAndRaise(msg, self.shell.pull_function, keys)
441 444 return d
442 445
443 446 def get_result(self, i=None):
444 447 msg = {'engineid':self.id,
445 448 'method':'get_result',
446 449 'args':[repr(i)]}
447 450 d = self.executeAndRaise(msg, self.shell.getCommand, i)
448 451 d.addCallback(self.addIDToResult)
449 452 return d
450 453
451 454 def reset(self):
452 455 msg = {'engineid':self.id,
453 456 'method':'reset',
454 457 'args':[]}
455 458 del self.shell
456 459 self.shell = self.shellClass()
457 460 self.properties.clear()
458 461 d = self.executeAndRaise(msg, self._seedNamespace)
459 462 return d
460 463
461 464 def kill(self):
462 465 drop_engine(self.id)
463 466 try:
464 467 reactor.stop()
465 468 except RuntimeError:
466 469 log.msg('The reactor was not running apparently.')
467 470 return defer.fail()
468 471 else:
469 472 return defer.succeed(None)
470 473
471 474 def keys(self):
472 475 """Return a list of variables names in the users top level namespace.
473 476
474 477 This used to return a dict of all the keys/repr(values) in the
475 478 user's namespace. This was too much info for the ControllerService
476 479 to handle so it is now just a list of keys.
477 480 """
478 481
479 482 remotes = []
480 483 for k in self.shell.user_ns.iterkeys():
481 484 if k not in ['__name__', '_ih', '_oh', '__builtins__',
482 485 'In', 'Out', '_', '__', '___', '__IP', 'input', 'raw_input']:
483 486 remotes.append(k)
484 487 return defer.succeed(remotes)
485 488
486 489 def set_properties(self, properties):
487 490 msg = {'engineid':self.id,
488 491 'method':'set_properties',
489 492 'args':[repr(properties.keys())]}
490 493 return self.executeAndRaise(msg, self.properties.update, properties)
491 494
492 495 def get_properties(self, keys=None):
493 496 msg = {'engineid':self.id,
494 497 'method':'get_properties',
495 498 'args':[repr(keys)]}
496 499 if keys is None:
497 500 keys = self.properties.keys()
498 501 return self.executeAndRaise(msg, self.properties.subDict, *keys)
499 502
500 503 def _doDel(self, keys):
501 504 for key in keys:
502 505 del self.properties[key]
503 506
504 507 def del_properties(self, keys):
505 508 msg = {'engineid':self.id,
506 509 'method':'del_properties',
507 510 'args':[repr(keys)]}
508 511 return self.executeAndRaise(msg, self._doDel, keys)
509 512
510 513 def _doHas(self, keys):
511 514 return [self.properties.has_key(key) for key in keys]
512 515
513 516 def has_properties(self, keys):
514 517 msg = {'engineid':self.id,
515 518 'method':'has_properties',
516 519 'args':[repr(keys)]}
517 520 return self.executeAndRaise(msg, self._doHas, keys)
518 521
519 522 def clear_properties(self):
520 523 msg = {'engineid':self.id,
521 524 'method':'clear_properties',
522 525 'args':[]}
523 526 return self.executeAndRaise(msg, self.properties.clear)
524 527
525 528 def push_serialized(self, sNamespace):
526 529 msg = {'engineid':self.id,
527 530 'method':'push_serialized',
528 531 'args':[repr(sNamespace.keys())]}
529 532 ns = {}
530 533 for k,v in sNamespace.iteritems():
531 534 try:
532 535 unserialized = newserialized.IUnSerialized(v)
533 536 ns[k] = unserialized.getObject()
534 537 except:
535 538 return defer.fail()
536 539 return self.executeAndRaise(msg, self.shell.push, ns)
537 540
538 541 def pull_serialized(self, keys):
539 542 msg = {'engineid':self.id,
540 543 'method':'pull_serialized',
541 544 'args':[repr(keys)]}
542 545 if isinstance(keys, str):
543 546 keys = [keys]
544 547 if len(keys)==1:
545 548 d = self.executeAndRaise(msg, self.shell.pull, keys)
546 549 d.addCallback(newserialized.serialize)
547 550 return d
548 551 elif len(keys)>1:
549 552 d = self.executeAndRaise(msg, self.shell.pull, keys)
550 553 @d.addCallback
551 554 def packThemUp(values):
552 555 serials = []
553 556 for v in values:
554 557 try:
555 558 serials.append(newserialized.serialize(v))
556 559 except:
557 560 return defer.fail(failure.Failure())
558 561 return serials
559 562 return packThemUp
560 563
561 564
562 565 def queue(methodToQueue):
563 566 def queuedMethod(this, *args, **kwargs):
564 567 name = methodToQueue.__name__
565 568 return this.submitCommand(Command(name, *args, **kwargs))
566 569 return queuedMethod
567 570
568 571 class QueuedEngine(object):
569 572 """Adapt an IEngineBase to an IEngineQueued by wrapping it.
570 573
571 574 The resulting object will implement IEngineQueued which extends
572 575 IEngineCore which extends (IEngineBase, IEngineSerialized).
573 576
574 577 This seems like the best way of handling it, but I am not sure. The
575 578 other option is to have the various base interfaces be used like
576 579 mix-in intefaces. The problem I have with this is adpatation is
577 580 more difficult and complicated because there can be can multiple
578 581 original and final Interfaces.
579 582 """
580 583
581 584 zi.implements(IEngineQueued)
582 585
583 586 def __init__(self, engine):
584 587 """Create a QueuedEngine object from an engine
585 588
586 589 engine: An implementor of IEngineCore and IEngineSerialized
587 590 keepUpToDate: whether to update the remote status when the
588 591 queue is empty. Defaults to False.
589 592 """
590 593
591 594 # This is the right way to do these tests rather than
592 595 # IEngineCore in list(zi.providedBy(engine)) which will only
593 596 # picks of the interfaces that are directly declared by engine.
594 597 assert IEngineBase.providedBy(engine), \
595 598 "engine passed to QueuedEngine doesn't provide IEngineBase"
596 599
597 600 self.engine = engine
598 601 self.id = engine.id
599 602 self.queued = []
600 603 self.history = {}
601 604 self.engineStatus = {}
602 605 self.currentCommand = None
603 606 self.failureObservers = []
604 607
605 608 def _get_properties(self):
606 609 return self.engine.properties
607 610
608 611 properties = property(_get_properties, lambda self, _: None)
609 612 # Queue management methods. You should not call these directly
610 613
611 614 def submitCommand(self, cmd):
612 615 """Submit command to queue."""
613 616
614 617 d = defer.Deferred()
615 618 cmd.setDeferred(d)
616 619 if self.currentCommand is not None:
617 620 if self.currentCommand.finished:
618 621 # log.msg("Running command immediately: %r" % cmd)
619 622 self.currentCommand = cmd
620 623 self.runCurrentCommand()
621 624 else: # command is still running
622 625 # log.msg("Command is running: %r" % self.currentCommand)
623 626 # log.msg("Queueing: %r" % cmd)
624 627 self.queued.append(cmd)
625 628 else:
626 629 # log.msg("No current commands, running: %r" % cmd)
627 630 self.currentCommand = cmd
628 631 self.runCurrentCommand()
629 632 return d
630 633
631 634 def runCurrentCommand(self):
632 635 """Run current command."""
633 636
634 637 cmd = self.currentCommand
635 638 f = getattr(self.engine, cmd.remoteMethod, None)
636 639 if f:
637 640 d = f(*cmd.args, **cmd.kwargs)
638 641 if cmd.remoteMethod is 'execute':
639 642 d.addCallback(self.saveResult)
640 643 d.addCallback(self.finishCommand)
641 644 d.addErrback(self.abortCommand)
642 645 else:
643 646 return defer.fail(AttributeError(cmd.remoteMethod))
644 647
645 648 def _flushQueue(self):
646 649 """Pop next command in queue and run it."""
647 650
648 651 if len(self.queued) > 0:
649 652 self.currentCommand = self.queued.pop(0)
650 653 self.runCurrentCommand()
651 654
652 655 def saveResult(self, result):
653 656 """Put the result in the history."""
654 657 self.history[result['number']] = result
655 658 return result
656 659
657 660 def finishCommand(self, result):
658 661 """Finish currrent command."""
659 662
660 663 # The order of these commands is absolutely critical.
661 664 self.currentCommand.handleResult(result)
662 665 self.currentCommand.finished = True
663 666 self._flushQueue()
664 667 return result
665 668
666 669 def abortCommand(self, reason):
667 670 """Abort current command.
668 671
669 672 This eats the Failure but first passes it onto the Deferred that the
670 673 user has.
671 674
672 675 It also clear out the queue so subsequence commands don't run.
673 676 """
674 677
675 678 # The order of these 3 commands is absolutely critical. The currentCommand
676 679 # must first be marked as finished BEFORE the queue is cleared and before
677 680 # the current command is sent the failure.
678 681 # Also, the queue must be cleared BEFORE the current command is sent the Failure
679 682 # otherwise the errback chain could trigger new commands to be added to the
680 683 # queue before we clear it. We should clear ONLY the commands that were in
681 684 # the queue when the error occured.
682 685 self.currentCommand.finished = True
683 686 s = "%r %r %r" % (self.currentCommand.remoteMethod, self.currentCommand.args, self.currentCommand.kwargs)
684 687 self.clear_queue(msg=s)
685 688 self.currentCommand.handleError(reason)
686 689
687 690 return None
688 691
689 692 #---------------------------------------------------------------------------
690 693 # IEngineCore methods
691 694 #---------------------------------------------------------------------------
692 695
693 696 @queue
694 697 def execute(self, lines):
695 698 pass
696 699
697 700 @queue
698 701 def push(self, namespace):
699 702 pass
700 703
701 704 @queue
702 705 def pull(self, keys):
703 706 pass
704 707
705 708 @queue
706 709 def push_function(self, namespace):
707 710 pass
708 711
709 712 @queue
710 713 def pull_function(self, keys):
711 714 pass
712 715
713 716 def get_result(self, i=None):
714 717 if i is None:
715 718 i = max(self.history.keys()+[None])
716 719
717 720 cmd = self.history.get(i, None)
718 721 # Uncomment this line to disable chaching of results
719 722 #cmd = None
720 723 if cmd is None:
721 724 return self.submitCommand(Command('get_result', i))
722 725 else:
723 726 return defer.succeed(cmd)
724 727
725 728 def reset(self):
726 729 self.clear_queue()
727 730 self.history = {} # reset the cache - I am not sure we should do this
728 731 return self.submitCommand(Command('reset'))
729 732
730 733 def kill(self):
731 734 self.clear_queue()
732 735 return self.submitCommand(Command('kill'))
733 736
734 737 @queue
735 738 def keys(self):
736 739 pass
737 740
738 741 #---------------------------------------------------------------------------
739 742 # IEngineSerialized methods
740 743 #---------------------------------------------------------------------------
741 744
742 745 @queue
743 746 def push_serialized(self, namespace):
744 747 pass
745 748
746 749 @queue
747 750 def pull_serialized(self, keys):
748 751 pass
749 752
750 753 #---------------------------------------------------------------------------
751 754 # IEngineProperties methods
752 755 #---------------------------------------------------------------------------
753 756
754 757 @queue
755 758 def set_properties(self, namespace):
756 759 pass
757 760
758 761 @queue
759 762 def get_properties(self, keys=None):
760 763 pass
761 764
762 765 @queue
763 766 def del_properties(self, keys):
764 767 pass
765 768
766 769 @queue
767 770 def has_properties(self, keys):
768 771 pass
769 772
770 773 @queue
771 774 def clear_properties(self):
772 775 pass
773 776
774 777 #---------------------------------------------------------------------------
775 778 # IQueuedEngine methods
776 779 #---------------------------------------------------------------------------
777 780
778 781 def clear_queue(self, msg=''):
779 782 """Clear the queue, but doesn't cancel the currently running commmand."""
780 783
781 784 for cmd in self.queued:
782 785 cmd.deferred.errback(failure.Failure(error.QueueCleared(msg)))
783 786 self.queued = []
784 787 return defer.succeed(None)
785 788
786 789 def queue_status(self):
787 790 if self.currentCommand is not None:
788 791 if self.currentCommand.finished:
789 792 pending = repr(None)
790 793 else:
791 794 pending = repr(self.currentCommand)
792 795 else:
793 796 pending = repr(None)
794 797 dikt = {'queue':map(repr,self.queued), 'pending':pending}
795 798 return defer.succeed(dikt)
796 799
797 800 def register_failure_observer(self, obs):
798 801 self.failureObservers.append(obs)
799 802
800 803 def unregister_failure_observer(self, obs):
801 804 self.failureObservers.remove(obs)
802 805
803 806
804 807 # Now register QueuedEngine as an adpater class that makes an IEngineBase into a
805 808 # IEngineQueued.
806 809 components.registerAdapter(QueuedEngine, IEngineBase, IEngineQueued)
807 810
808 811
809 812 class Command(object):
810 813 """A command object that encapslates queued commands.
811 814
812 815 This class basically keeps track of a command that has been queued
813 816 in a QueuedEngine. It manages the deferreds and hold the method to be called
814 817 and the arguments to that method.
815 818 """
816 819
817 820
818 821 def __init__(self, remoteMethod, *args, **kwargs):
819 822 """Build a new Command object."""
820 823
821 824 self.remoteMethod = remoteMethod
822 825 self.args = args
823 826 self.kwargs = kwargs
824 827 self.finished = False
825 828
826 829 def setDeferred(self, d):
827 830 """Sets the deferred attribute of the Command."""
828 831
829 832 self.deferred = d
830 833
831 834 def __repr__(self):
832 835 if not self.args:
833 836 args = ''
834 837 else:
835 838 args = str(self.args)[1:-2] #cut off (...,)
836 839 for k,v in self.kwargs.iteritems():
837 840 if args:
838 841 args += ', '
839 842 args += '%s=%r' %(k,v)
840 843 return "%s(%s)" %(self.remoteMethod, args)
841 844
842 845 def handleResult(self, result):
843 846 """When the result is ready, relay it to self.deferred."""
844 847
845 848 self.deferred.callback(result)
846 849
847 850 def handleError(self, reason):
848 851 """When an error has occured, relay it to self.deferred."""
849 852
850 853 self.deferred.errback(reason)
851 854
852 855 class ThreadedEngineService(EngineService):
853 856 """An EngineService subclass that defers execute commands to a separate
854 857 thread.
855 858
856 859 ThreadedEngineService uses twisted.internet.threads.deferToThread to
857 860 defer execute requests to a separate thread. GUI frontends may want to
858 861 use ThreadedEngineService as the engine in an
859 862 IPython.frontend.frontendbase.FrontEndBase subclass to prevent
860 863 block execution from blocking the GUI thread.
861 864 """
862 865
863 866 zi.implements(IEngineBase)
864 867
865 868 def __init__(self, shellClass=Interpreter, mpi=None):
866 869 EngineService.__init__(self, shellClass, mpi)
867 870
868 871 def wrapped_execute(self, msg, lines):
869 872 """Wrap self.shell.execute to add extra information to tracebacks"""
870 873
871 874 try:
872 875 result = self.shell.execute(lines)
873 876 except Exception,e:
874 877 # This gives the following:
875 878 # et=exception class
876 879 # ev=exception class instance
877 880 # tb=traceback object
878 881 et,ev,tb = sys.exc_info()
879 882 # This call adds attributes to the exception value
880 883 et,ev,tb = self.shell.formatTraceback(et,ev,tb,msg)
881 884 # Add another attribute
882 885
883 886 # Create a new exception with the new attributes
884 887 e = et(ev._ipython_traceback_text)
885 888 e._ipython_engine_info = msg
886 889
887 890 # Re-raise
888 891 raise e
889 892
890 893 return result
891 894
892 895
893 896 def execute(self, lines):
894 897 # Only import this if we are going to use this class
895 898 from twisted.internet import threads
896 899
897 900 msg = {'engineid':self.id,
898 901 'method':'execute',
899 902 'args':[lines]}
900 903
901 904 d = threads.deferToThread(self.wrapped_execute, msg, lines)
902 905 d.addCallback(self.addIDToResult)
903 906 return d
@@ -1,185 +1,202 b''
1 1 # encoding: utf-8
2 2
3 3 """Classes and functions for kernel related errors and exceptions."""
4 4
5 5 __docformat__ = "restructuredtext en"
6 6
7 7 #-------------------------------------------------------------------------------
8 8 # Copyright (C) 2008 The IPython Development Team
9 9 #
10 10 # Distributed under the terms of the BSD License. The full license is in
11 11 # the file COPYING, distributed as part of this software.
12 12 #-------------------------------------------------------------------------------
13 13
14 14 #-------------------------------------------------------------------------------
15 15 # Imports
16 16 #-------------------------------------------------------------------------------
17 17
18 18 from IPython.kernel.core import error
19 19 from twisted.python import failure
20 20
21 21 #-------------------------------------------------------------------------------
22 22 # Error classes
23 23 #-------------------------------------------------------------------------------
24 24
25 25 class KernelError(error.IPythonError):
26 26 pass
27 27
28 28 class NotDefined(KernelError):
29 29 def __init__(self, name):
30 30 self.name = name
31 31 self.args = (name,)
32 32
33 33 def __repr__(self):
34 34 return '<NotDefined: %s>' % self.name
35 35
36 36 __str__ = __repr__
37 37
38 38 class QueueCleared(KernelError):
39 39 pass
40 40
41 41 class IdInUse(KernelError):
42 42 pass
43 43
44 44 class ProtocolError(KernelError):
45 45 pass
46 46
47 47 class ConnectionError(KernelError):
48 48 pass
49 49
50 50 class InvalidEngineID(KernelError):
51 51 pass
52 52
53 53 class NoEnginesRegistered(KernelError):
54 54 pass
55 55
56 56 class InvalidClientID(KernelError):
57 57 pass
58 58
59 59 class InvalidDeferredID(KernelError):
60 60 pass
61 61
62 62 class SerializationError(KernelError):
63 63 pass
64 64
65 65 class MessageSizeError(KernelError):
66 66 pass
67 67
68 68 class PBMessageSizeError(MessageSizeError):
69 69 pass
70 70
71 71 class ResultNotCompleted(KernelError):
72 72 pass
73 73
74 74 class ResultAlreadyRetrieved(KernelError):
75 75 pass
76 76
77 77 class ClientError(KernelError):
78 78 pass
79 79
80 80 class TaskAborted(KernelError):
81 81 pass
82 82
83 83 class TaskTimeout(KernelError):
84 84 pass
85 85
86 86 class NotAPendingResult(KernelError):
87 87 pass
88 88
89 89 class UnpickleableException(KernelError):
90 90 pass
91 91
92 92 class AbortedPendingDeferredError(KernelError):
93 93 pass
94 94
95 95 class InvalidProperty(KernelError):
96 96 pass
97 97
98 98 class MissingBlockArgument(KernelError):
99 99 pass
100 100
101 101 class StopLocalExecution(KernelError):
102 102 pass
103 103
104 104 class SecurityError(KernelError):
105 105 pass
106 106
107 class FileTimeoutError(KernelError):
108 pass
109
110 class TaskRejectError(KernelError):
111 """Exception to raise when a task should be rejected by an engine.
112
113 This exception can be used to allow a task running on an engine to test
114 if the engine (or the user's namespace on the engine) has the needed
115 task dependencies. If not, the task should raise this exception. For
116 the task to be retried on another engine, the task should be created
117 with the `retries` argument > 1.
118
119 The advantage of this approach over our older properties system is that
120 tasks have full access to the user's namespace on the engines and the
121 properties don't have to be managed or tested by the controller.
122 """
123
107 124 class CompositeError(KernelError):
108 125 def __init__(self, message, elist):
109 126 Exception.__init__(self, *(message, elist))
110 127 self.message = message
111 128 self.elist = elist
112 129
113 130 def _get_engine_str(self, ev):
114 131 try:
115 132 ei = ev._ipython_engine_info
116 133 except AttributeError:
117 134 return '[Engine Exception]'
118 135 else:
119 136 return '[%i:%s]: ' % (ei['engineid'], ei['method'])
120 137
121 138 def _get_traceback(self, ev):
122 139 try:
123 140 tb = ev._ipython_traceback_text
124 141 except AttributeError:
125 142 return 'No traceback available'
126 143 else:
127 144 return tb
128 145
129 146 def __str__(self):
130 147 s = str(self.message)
131 148 for et, ev, etb in self.elist:
132 149 engine_str = self._get_engine_str(ev)
133 150 s = s + '\n' + engine_str + str(et.__name__) + ': ' + str(ev)
134 151 return s
135 152
136 153 def print_tracebacks(self, excid=None):
137 154 if excid is None:
138 155 for (et,ev,etb) in self.elist:
139 156 print self._get_engine_str(ev)
140 157 print self._get_traceback(ev)
141 158 print
142 159 else:
143 160 try:
144 161 et,ev,etb = self.elist[excid]
145 162 except:
146 163 raise IndexError("an exception with index %i does not exist"%excid)
147 164 else:
148 165 print self._get_engine_str(ev)
149 166 print self._get_traceback(ev)
150 167
151 168 def raise_exception(self, excid=0):
152 169 try:
153 170 et,ev,etb = self.elist[excid]
154 171 except:
155 172 raise IndexError("an exception with index %i does not exist"%excid)
156 173 else:
157 174 raise et, ev, etb
158 175
159 176 def collect_exceptions(rlist, method):
160 177 elist = []
161 178 for r in rlist:
162 179 if isinstance(r, failure.Failure):
163 180 r.cleanFailure()
164 181 et, ev, etb = r.type, r.value, r.tb
165 182 # Sometimes we could have CompositeError in our list. Just take
166 183 # the errors out of them and put them in our new list. This
167 184 # has the effect of flattening lists of CompositeErrors into one
168 185 # CompositeError
169 186 if et==CompositeError:
170 187 for e in ev.elist:
171 188 elist.append(e)
172 189 else:
173 190 elist.append((et, ev, etb))
174 191 if len(elist)==0:
175 192 return rlist
176 193 else:
177 194 msg = "one or more exceptions from call to method: %s" % (method)
178 195 # This silliness is needed so the debugger has access to the exception
179 196 # instance (e in this case)
180 197 try:
181 198 raise CompositeError(msg, elist)
182 199 except CompositeError, e:
183 200 raise e
184 201
185 202
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
General Comments 0
You need to be logged in to leave comments. Login now