##// END OF EJS Templates
Merging upstream work, and fixing installation docs....
Brian Granger -
r1675:2cbe8d0b merge
parent child Browse files
Show More
@@ -1,436 +1,436 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 A Wx widget to act as a console and input commands.
3 A Wx widget to act as a console and input commands.
4
4
5 This widget deals with prompts and provides an edit buffer
5 This widget deals with prompts and provides an edit buffer
6 restricted to after the last prompt.
6 restricted to after the last prompt.
7 """
7 """
8
8
9 __docformat__ = "restructuredtext en"
9 __docformat__ = "restructuredtext en"
10
10
11 #-------------------------------------------------------------------------------
11 #-------------------------------------------------------------------------------
12 # Copyright (C) 2008 The IPython Development Team
12 # Copyright (C) 2008 The IPython Development Team
13 #
13 #
14 # Distributed under the terms of the BSD License. The full license is
14 # Distributed under the terms of the BSD License. The full license is
15 # in the file COPYING, distributed as part of this software.
15 # in the file COPYING, distributed as part of this software.
16 #-------------------------------------------------------------------------------
16 #-------------------------------------------------------------------------------
17
17
18 #-------------------------------------------------------------------------------
18 #-------------------------------------------------------------------------------
19 # Imports
19 # Imports
20 #-------------------------------------------------------------------------------
20 #-------------------------------------------------------------------------------
21
21
22 import wx
22 import wx
23 import wx.stc as stc
23 import wx.stc as stc
24
24
25 from wx.py import editwindow
25 from wx.py import editwindow
26 import time
26 import time
27 import sys
27 import sys
28 LINESEP = '\n'
28 LINESEP = '\n'
29 if sys.platform == 'win32':
29 if sys.platform == 'win32':
30 LINESEP = '\n\r'
30 LINESEP = '\n\r'
31
31
32 import re
32 import re
33
33
34 # FIXME: Need to provide an API for non user-generated display on the
34 # FIXME: Need to provide an API for non user-generated display on the
35 # screen: this should not be editable by the user.
35 # screen: this should not be editable by the user.
36
36
37 _DEFAULT_SIZE = 10
37 _DEFAULT_SIZE = 10
38 if sys.platform == 'darwin':
38 if sys.platform == 'darwin':
39 _DEFAULT_STYLE = 12
39 _DEFAULT_SIZE = 12
40
40
41 _DEFAULT_STYLE = {
41 _DEFAULT_STYLE = {
42 'stdout' : 'fore:#0000FF',
42 'stdout' : 'fore:#0000FF',
43 'stderr' : 'fore:#007f00',
43 'stderr' : 'fore:#007f00',
44 'trace' : 'fore:#FF0000',
44 'trace' : 'fore:#FF0000',
45
45
46 'default' : 'size:%d' % _DEFAULT_SIZE,
46 'default' : 'size:%d' % _DEFAULT_SIZE,
47 'bracegood' : 'fore:#00AA00,back:#000000,bold',
47 'bracegood' : 'fore:#00AA00,back:#000000,bold',
48 'bracebad' : 'fore:#FF0000,back:#000000,bold',
48 'bracebad' : 'fore:#FF0000,back:#000000,bold',
49
49
50 # properties for the various Python lexer styles
50 # properties for the various Python lexer styles
51 'comment' : 'fore:#007F00',
51 'comment' : 'fore:#007F00',
52 'number' : 'fore:#007F7F',
52 'number' : 'fore:#007F7F',
53 'string' : 'fore:#7F007F,italic',
53 'string' : 'fore:#7F007F,italic',
54 'char' : 'fore:#7F007F,italic',
54 'char' : 'fore:#7F007F,italic',
55 'keyword' : 'fore:#00007F,bold',
55 'keyword' : 'fore:#00007F,bold',
56 'triple' : 'fore:#7F0000',
56 'triple' : 'fore:#7F0000',
57 'tripledouble' : 'fore:#7F0000',
57 'tripledouble' : 'fore:#7F0000',
58 'class' : 'fore:#0000FF,bold,underline',
58 'class' : 'fore:#0000FF,bold,underline',
59 'def' : 'fore:#007F7F,bold',
59 'def' : 'fore:#007F7F,bold',
60 'operator' : 'bold'
60 'operator' : 'bold'
61 }
61 }
62
62
63 # new style numbers
63 # new style numbers
64 _STDOUT_STYLE = 15
64 _STDOUT_STYLE = 15
65 _STDERR_STYLE = 16
65 _STDERR_STYLE = 16
66 _TRACE_STYLE = 17
66 _TRACE_STYLE = 17
67
67
68
68
69 # system colors
69 # system colors
70 #SYS_COLOUR_BACKGROUND = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BACKGROUND)
70 #SYS_COLOUR_BACKGROUND = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BACKGROUND)
71
71
72 #-------------------------------------------------------------------------------
72 #-------------------------------------------------------------------------------
73 # The console widget class
73 # The console widget class
74 #-------------------------------------------------------------------------------
74 #-------------------------------------------------------------------------------
75 class ConsoleWidget(editwindow.EditWindow):
75 class ConsoleWidget(editwindow.EditWindow):
76 """ Specialized styled text control view for console-like workflow.
76 """ Specialized styled text control view for console-like workflow.
77
77
78 This widget is mainly interested in dealing with the prompt and
78 This widget is mainly interested in dealing with the prompt and
79 keeping the cursor inside the editing line.
79 keeping the cursor inside the editing line.
80 """
80 """
81
81
82 # This is where the title captured from the ANSI escape sequences are
82 # This is where the title captured from the ANSI escape sequences are
83 # stored.
83 # stored.
84 title = 'Console'
84 title = 'Console'
85
85
86 # The buffer being edited.
86 # The buffer being edited.
87 def _set_input_buffer(self, string):
87 def _set_input_buffer(self, string):
88 self.SetSelection(self.current_prompt_pos, self.GetLength())
88 self.SetSelection(self.current_prompt_pos, self.GetLength())
89 self.ReplaceSelection(string)
89 self.ReplaceSelection(string)
90 self.GotoPos(self.GetLength())
90 self.GotoPos(self.GetLength())
91
91
92 def _get_input_buffer(self):
92 def _get_input_buffer(self):
93 """ Returns the text in current edit buffer.
93 """ Returns the text in current edit buffer.
94 """
94 """
95 input_buffer = self.GetTextRange(self.current_prompt_pos,
95 input_buffer = self.GetTextRange(self.current_prompt_pos,
96 self.GetLength())
96 self.GetLength())
97 input_buffer = input_buffer.replace(LINESEP, '\n')
97 input_buffer = input_buffer.replace(LINESEP, '\n')
98 return input_buffer
98 return input_buffer
99
99
100 input_buffer = property(_get_input_buffer, _set_input_buffer)
100 input_buffer = property(_get_input_buffer, _set_input_buffer)
101
101
102 style = _DEFAULT_STYLE.copy()
102 style = _DEFAULT_STYLE.copy()
103
103
104 # Translation table from ANSI escape sequences to color. Override
104 # Translation table from ANSI escape sequences to color. Override
105 # this to specify your colors.
105 # this to specify your colors.
106 ANSI_STYLES = {'0;30': [0, 'BLACK'], '0;31': [1, 'RED'],
106 ANSI_STYLES = {'0;30': [0, 'BLACK'], '0;31': [1, 'RED'],
107 '0;32': [2, 'GREEN'], '0;33': [3, 'BROWN'],
107 '0;32': [2, 'GREEN'], '0;33': [3, 'BROWN'],
108 '0;34': [4, 'BLUE'], '0;35': [5, 'PURPLE'],
108 '0;34': [4, 'BLUE'], '0;35': [5, 'PURPLE'],
109 '0;36': [6, 'CYAN'], '0;37': [7, 'LIGHT GREY'],
109 '0;36': [6, 'CYAN'], '0;37': [7, 'LIGHT GREY'],
110 '1;30': [8, 'DARK GREY'], '1;31': [9, 'RED'],
110 '1;30': [8, 'DARK GREY'], '1;31': [9, 'RED'],
111 '1;32': [10, 'SEA GREEN'], '1;33': [11, 'YELLOW'],
111 '1;32': [10, 'SEA GREEN'], '1;33': [11, 'YELLOW'],
112 '1;34': [12, 'LIGHT BLUE'], '1;35':
112 '1;34': [12, 'LIGHT BLUE'], '1;35':
113 [13, 'MEDIUM VIOLET RED'],
113 [13, 'MEDIUM VIOLET RED'],
114 '1;36': [14, 'LIGHT STEEL BLUE'], '1;37': [15, 'YELLOW']}
114 '1;36': [14, 'LIGHT STEEL BLUE'], '1;37': [15, 'YELLOW']}
115
115
116 # The color of the carret (call _apply_style() after setting)
116 # The color of the carret (call _apply_style() after setting)
117 carret_color = 'BLACK'
117 carret_color = 'BLACK'
118
118
119 # Store the last time a refresh was done
119 # Store the last time a refresh was done
120 _last_refresh_time = 0
120 _last_refresh_time = 0
121
121
122 #--------------------------------------------------------------------------
122 #--------------------------------------------------------------------------
123 # Public API
123 # Public API
124 #--------------------------------------------------------------------------
124 #--------------------------------------------------------------------------
125
125
126 def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
126 def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
127 size=wx.DefaultSize, style=wx.WANTS_CHARS, ):
127 size=wx.DefaultSize, style=wx.WANTS_CHARS, ):
128 editwindow.EditWindow.__init__(self, parent, id, pos, size, style)
128 editwindow.EditWindow.__init__(self, parent, id, pos, size, style)
129 self._configure_scintilla()
129 self._configure_scintilla()
130
130
131 self.Bind(wx.EVT_KEY_DOWN, self._on_key_down)
131 self.Bind(wx.EVT_KEY_DOWN, self._on_key_down)
132 self.Bind(wx.EVT_KEY_UP, self._on_key_up)
132 self.Bind(wx.EVT_KEY_UP, self._on_key_up)
133
133
134
134
135 def write(self, text, refresh=True):
135 def write(self, text, refresh=True):
136 """ Write given text to buffer, while translating the ansi escape
136 """ Write given text to buffer, while translating the ansi escape
137 sequences.
137 sequences.
138 """
138 """
139 # XXX: do not put print statements to sys.stdout/sys.stderr in
139 # XXX: do not put print statements to sys.stdout/sys.stderr in
140 # this method, the print statements will call this method, as
140 # this method, the print statements will call this method, as
141 # you will end up with an infinit loop
141 # you will end up with an infinit loop
142 title = self.title_pat.split(text)
142 title = self.title_pat.split(text)
143 if len(title)>1:
143 if len(title)>1:
144 self.title = title[-2]
144 self.title = title[-2]
145
145
146 text = self.title_pat.sub('', text)
146 text = self.title_pat.sub('', text)
147 segments = self.color_pat.split(text)
147 segments = self.color_pat.split(text)
148 segment = segments.pop(0)
148 segment = segments.pop(0)
149 self.GotoPos(self.GetLength())
149 self.GotoPos(self.GetLength())
150 self.StartStyling(self.GetLength(), 0xFF)
150 self.StartStyling(self.GetLength(), 0xFF)
151 try:
151 try:
152 self.AppendText(segment)
152 self.AppendText(segment)
153 except UnicodeDecodeError:
153 except UnicodeDecodeError:
154 # XXX: Do I really want to skip the exception?
154 # XXX: Do I really want to skip the exception?
155 pass
155 pass
156
156
157 if segments:
157 if segments:
158 for ansi_tag, text in zip(segments[::2], segments[1::2]):
158 for ansi_tag, text in zip(segments[::2], segments[1::2]):
159 self.StartStyling(self.GetLength(), 0xFF)
159 self.StartStyling(self.GetLength(), 0xFF)
160 try:
160 try:
161 self.AppendText(text)
161 self.AppendText(text)
162 except UnicodeDecodeError:
162 except UnicodeDecodeError:
163 # XXX: Do I really want to skip the exception?
163 # XXX: Do I really want to skip the exception?
164 pass
164 pass
165
165
166 if ansi_tag not in self.ANSI_STYLES:
166 if ansi_tag not in self.ANSI_STYLES:
167 style = 0
167 style = 0
168 else:
168 else:
169 style = self.ANSI_STYLES[ansi_tag][0]
169 style = self.ANSI_STYLES[ansi_tag][0]
170
170
171 self.SetStyling(len(text), style)
171 self.SetStyling(len(text), style)
172
172
173 self.GotoPos(self.GetLength())
173 self.GotoPos(self.GetLength())
174 if refresh:
174 if refresh:
175 current_time = time.time()
175 current_time = time.time()
176 if current_time - self._last_refresh_time > 0.03:
176 if current_time - self._last_refresh_time > 0.03:
177 if sys.platform == 'win32':
177 if sys.platform == 'win32':
178 wx.SafeYield()
178 wx.SafeYield()
179 else:
179 else:
180 wx.Yield()
180 wx.Yield()
181 # self.ProcessEvent(wx.PaintEvent())
181 # self.ProcessEvent(wx.PaintEvent())
182 self._last_refresh_time = current_time
182 self._last_refresh_time = current_time
183
183
184
184
185 def new_prompt(self, prompt):
185 def new_prompt(self, prompt):
186 """ Prints a prompt at start of line, and move the start of the
186 """ Prints a prompt at start of line, and move the start of the
187 current block there.
187 current block there.
188
188
189 The prompt can be given with ascii escape sequences.
189 The prompt can be given with ascii escape sequences.
190 """
190 """
191 self.write(prompt, refresh=False)
191 self.write(prompt, refresh=False)
192 # now we update our cursor giving end of prompt
192 # now we update our cursor giving end of prompt
193 self.current_prompt_pos = self.GetLength()
193 self.current_prompt_pos = self.GetLength()
194 self.current_prompt_line = self.GetCurrentLine()
194 self.current_prompt_line = self.GetCurrentLine()
195 self.EnsureCaretVisible()
195 self.EnsureCaretVisible()
196
196
197
197
198 def scroll_to_bottom(self):
198 def scroll_to_bottom(self):
199 maxrange = self.GetScrollRange(wx.VERTICAL)
199 maxrange = self.GetScrollRange(wx.VERTICAL)
200 self.ScrollLines(maxrange)
200 self.ScrollLines(maxrange)
201
201
202
202
203 def pop_completion(self, possibilities, offset=0):
203 def pop_completion(self, possibilities, offset=0):
204 """ Pops up an autocompletion menu. Offset is the offset
204 """ Pops up an autocompletion menu. Offset is the offset
205 in characters of the position at which the menu should
205 in characters of the position at which the menu should
206 appear, relativ to the cursor.
206 appear, relativ to the cursor.
207 """
207 """
208 self.AutoCompSetIgnoreCase(False)
208 self.AutoCompSetIgnoreCase(False)
209 self.AutoCompSetAutoHide(False)
209 self.AutoCompSetAutoHide(False)
210 self.AutoCompSetMaxHeight(len(possibilities))
210 self.AutoCompSetMaxHeight(len(possibilities))
211 self.AutoCompShow(offset, " ".join(possibilities))
211 self.AutoCompShow(offset, " ".join(possibilities))
212
212
213
213
214 def get_line_width(self):
214 def get_line_width(self):
215 """ Return the width of the line in characters.
215 """ Return the width of the line in characters.
216 """
216 """
217 return self.GetSize()[0]/self.GetCharWidth()
217 return self.GetSize()[0]/self.GetCharWidth()
218
218
219 #--------------------------------------------------------------------------
219 #--------------------------------------------------------------------------
220 # EditWindow API
220 # EditWindow API
221 #--------------------------------------------------------------------------
221 #--------------------------------------------------------------------------
222
222
223 def OnUpdateUI(self, event):
223 def OnUpdateUI(self, event):
224 """ Override the OnUpdateUI of the EditWindow class, to prevent
224 """ Override the OnUpdateUI of the EditWindow class, to prevent
225 syntax highlighting both for faster redraw, and for more
225 syntax highlighting both for faster redraw, and for more
226 consistent look and feel.
226 consistent look and feel.
227 """
227 """
228
228
229 #--------------------------------------------------------------------------
229 #--------------------------------------------------------------------------
230 # Private API
230 # Private API
231 #--------------------------------------------------------------------------
231 #--------------------------------------------------------------------------
232
232
233 def _apply_style(self):
233 def _apply_style(self):
234 """ Applies the colors for the different text elements and the
234 """ Applies the colors for the different text elements and the
235 carret.
235 carret.
236 """
236 """
237 self.SetCaretForeground(self.carret_color)
237 self.SetCaretForeground(self.carret_color)
238
238
239 #self.StyleClearAll()
239 #self.StyleClearAll()
240 self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT,
240 self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT,
241 "fore:#FF0000,back:#0000FF,bold")
241 "fore:#FF0000,back:#0000FF,bold")
242 self.StyleSetSpec(stc.STC_STYLE_BRACEBAD,
242 self.StyleSetSpec(stc.STC_STYLE_BRACEBAD,
243 "fore:#000000,back:#FF0000,bold")
243 "fore:#000000,back:#FF0000,bold")
244
244
245 for style in self.ANSI_STYLES.values():
245 for style in self.ANSI_STYLES.values():
246 self.StyleSetSpec(style[0], "bold,fore:%s" % style[1])
246 self.StyleSetSpec(style[0], "bold,fore:%s" % style[1])
247
247
248
248
249 def _configure_scintilla(self):
249 def _configure_scintilla(self):
250 self.SetEOLMode(stc.STC_EOL_LF)
250 self.SetEOLMode(stc.STC_EOL_LF)
251
251
252 # Ctrl"+" or Ctrl "-" can be used to zoomin/zoomout the text inside
252 # Ctrl"+" or Ctrl "-" can be used to zoomin/zoomout the text inside
253 # the widget
253 # the widget
254 self.CmdKeyAssign(ord('+'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN)
254 self.CmdKeyAssign(ord('+'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN)
255 self.CmdKeyAssign(ord('-'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT)
255 self.CmdKeyAssign(ord('-'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT)
256 # Also allow Ctrl Shift "=" for poor non US keyboard users.
256 # Also allow Ctrl Shift "=" for poor non US keyboard users.
257 self.CmdKeyAssign(ord('='), stc.STC_SCMOD_CTRL|stc.STC_SCMOD_SHIFT,
257 self.CmdKeyAssign(ord('='), stc.STC_SCMOD_CTRL|stc.STC_SCMOD_SHIFT,
258 stc.STC_CMD_ZOOMIN)
258 stc.STC_CMD_ZOOMIN)
259
259
260 # Keys: we need to clear some of the keys the that don't play
260 # Keys: we need to clear some of the keys the that don't play
261 # well with a console.
261 # well with a console.
262 self.CmdKeyClear(ord('D'), stc.STC_SCMOD_CTRL)
262 self.CmdKeyClear(ord('D'), stc.STC_SCMOD_CTRL)
263 self.CmdKeyClear(ord('L'), stc.STC_SCMOD_CTRL)
263 self.CmdKeyClear(ord('L'), stc.STC_SCMOD_CTRL)
264 self.CmdKeyClear(ord('T'), stc.STC_SCMOD_CTRL)
264 self.CmdKeyClear(ord('T'), stc.STC_SCMOD_CTRL)
265 self.CmdKeyClear(ord('A'), stc.STC_SCMOD_CTRL)
265 self.CmdKeyClear(ord('A'), stc.STC_SCMOD_CTRL)
266
266
267 self.SetEOLMode(stc.STC_EOL_CRLF)
267 self.SetEOLMode(stc.STC_EOL_CRLF)
268 self.SetWrapMode(stc.STC_WRAP_CHAR)
268 self.SetWrapMode(stc.STC_WRAP_CHAR)
269 self.SetWrapMode(stc.STC_WRAP_WORD)
269 self.SetWrapMode(stc.STC_WRAP_WORD)
270 self.SetBufferedDraw(True)
270 self.SetBufferedDraw(True)
271 self.SetUseAntiAliasing(True)
271 self.SetUseAntiAliasing(True)
272 self.SetLayoutCache(stc.STC_CACHE_PAGE)
272 self.SetLayoutCache(stc.STC_CACHE_PAGE)
273 self.SetUndoCollection(False)
273 self.SetUndoCollection(False)
274 self.SetUseTabs(True)
274 self.SetUseTabs(True)
275 self.SetIndent(4)
275 self.SetIndent(4)
276 self.SetTabWidth(4)
276 self.SetTabWidth(4)
277
277
278 # we don't want scintilla's autocompletion to choose
278 # we don't want scintilla's autocompletion to choose
279 # automaticaly out of a single choice list, as we pop it up
279 # automaticaly out of a single choice list, as we pop it up
280 # automaticaly
280 # automaticaly
281 self.AutoCompSetChooseSingle(False)
281 self.AutoCompSetChooseSingle(False)
282 self.AutoCompSetMaxHeight(10)
282 self.AutoCompSetMaxHeight(10)
283 # XXX: this doesn't seem to have an effect.
283 # XXX: this doesn't seem to have an effect.
284 self.AutoCompSetFillUps('\n')
284 self.AutoCompSetFillUps('\n')
285
285
286 self.SetMargins(3, 3) #text is moved away from border with 3px
286 self.SetMargins(3, 3) #text is moved away from border with 3px
287 # Suppressing Scintilla margins
287 # Suppressing Scintilla margins
288 self.SetMarginWidth(0, 0)
288 self.SetMarginWidth(0, 0)
289 self.SetMarginWidth(1, 0)
289 self.SetMarginWidth(1, 0)
290 self.SetMarginWidth(2, 0)
290 self.SetMarginWidth(2, 0)
291
291
292 self._apply_style()
292 self._apply_style()
293
293
294 # Xterm escape sequences
294 # Xterm escape sequences
295 self.color_pat = re.compile('\x01?\x1b\[(.*?)m\x02?')
295 self.color_pat = re.compile('\x01?\x1b\[(.*?)m\x02?')
296 self.title_pat = re.compile('\x1b]0;(.*?)\x07')
296 self.title_pat = re.compile('\x1b]0;(.*?)\x07')
297
297
298 #self.SetEdgeMode(stc.STC_EDGE_LINE)
298 #self.SetEdgeMode(stc.STC_EDGE_LINE)
299 #self.SetEdgeColumn(80)
299 #self.SetEdgeColumn(80)
300
300
301 # styles
301 # styles
302 p = self.style
302 p = self.style
303 self.StyleSetSpec(stc.STC_STYLE_DEFAULT, p['default'])
303 self.StyleSetSpec(stc.STC_STYLE_DEFAULT, p['default'])
304 self.StyleClearAll()
304 self.StyleClearAll()
305 self.StyleSetSpec(_STDOUT_STYLE, p['stdout'])
305 self.StyleSetSpec(_STDOUT_STYLE, p['stdout'])
306 self.StyleSetSpec(_STDERR_STYLE, p['stderr'])
306 self.StyleSetSpec(_STDERR_STYLE, p['stderr'])
307 self.StyleSetSpec(_TRACE_STYLE, p['trace'])
307 self.StyleSetSpec(_TRACE_STYLE, p['trace'])
308
308
309 self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT, p['bracegood'])
309 self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT, p['bracegood'])
310 self.StyleSetSpec(stc.STC_STYLE_BRACEBAD, p['bracebad'])
310 self.StyleSetSpec(stc.STC_STYLE_BRACEBAD, p['bracebad'])
311 self.StyleSetSpec(stc.STC_P_COMMENTLINE, p['comment'])
311 self.StyleSetSpec(stc.STC_P_COMMENTLINE, p['comment'])
312 self.StyleSetSpec(stc.STC_P_NUMBER, p['number'])
312 self.StyleSetSpec(stc.STC_P_NUMBER, p['number'])
313 self.StyleSetSpec(stc.STC_P_STRING, p['string'])
313 self.StyleSetSpec(stc.STC_P_STRING, p['string'])
314 self.StyleSetSpec(stc.STC_P_CHARACTER, p['char'])
314 self.StyleSetSpec(stc.STC_P_CHARACTER, p['char'])
315 self.StyleSetSpec(stc.STC_P_WORD, p['keyword'])
315 self.StyleSetSpec(stc.STC_P_WORD, p['keyword'])
316 self.StyleSetSpec(stc.STC_P_WORD2, p['keyword'])
316 self.StyleSetSpec(stc.STC_P_WORD2, p['keyword'])
317 self.StyleSetSpec(stc.STC_P_TRIPLE, p['triple'])
317 self.StyleSetSpec(stc.STC_P_TRIPLE, p['triple'])
318 self.StyleSetSpec(stc.STC_P_TRIPLEDOUBLE, p['tripledouble'])
318 self.StyleSetSpec(stc.STC_P_TRIPLEDOUBLE, p['tripledouble'])
319 self.StyleSetSpec(stc.STC_P_CLASSNAME, p['class'])
319 self.StyleSetSpec(stc.STC_P_CLASSNAME, p['class'])
320 self.StyleSetSpec(stc.STC_P_DEFNAME, p['def'])
320 self.StyleSetSpec(stc.STC_P_DEFNAME, p['def'])
321 self.StyleSetSpec(stc.STC_P_OPERATOR, p['operator'])
321 self.StyleSetSpec(stc.STC_P_OPERATOR, p['operator'])
322 self.StyleSetSpec(stc.STC_P_COMMENTBLOCK, p['comment'])
322 self.StyleSetSpec(stc.STC_P_COMMENTBLOCK, p['comment'])
323
323
324 def _on_key_down(self, event, skip=True):
324 def _on_key_down(self, event, skip=True):
325 """ Key press callback used for correcting behavior for
325 """ Key press callback used for correcting behavior for
326 console-like interfaces: the cursor is constraint to be after
326 console-like interfaces: the cursor is constraint to be after
327 the last prompt.
327 the last prompt.
328
328
329 Return True if event as been catched.
329 Return True if event as been catched.
330 """
330 """
331 catched = True
331 catched = True
332 # Intercept some specific keys.
332 # Intercept some specific keys.
333 if event.KeyCode == ord('L') and event.ControlDown() :
333 if event.KeyCode == ord('L') and event.ControlDown() :
334 self.scroll_to_bottom()
334 self.scroll_to_bottom()
335 elif event.KeyCode == ord('K') and event.ControlDown() :
335 elif event.KeyCode == ord('K') and event.ControlDown() :
336 self.input_buffer = ''
336 self.input_buffer = ''
337 elif event.KeyCode == ord('A') and event.ControlDown() :
337 elif event.KeyCode == ord('A') and event.ControlDown() :
338 self.GotoPos(self.GetLength())
338 self.GotoPos(self.GetLength())
339 self.SetSelectionStart(self.current_prompt_pos)
339 self.SetSelectionStart(self.current_prompt_pos)
340 self.SetSelectionEnd(self.GetCurrentPos())
340 self.SetSelectionEnd(self.GetCurrentPos())
341 catched = True
341 catched = True
342 elif event.KeyCode == ord('E') and event.ControlDown() :
342 elif event.KeyCode == ord('E') and event.ControlDown() :
343 self.GotoPos(self.GetLength())
343 self.GotoPos(self.GetLength())
344 catched = True
344 catched = True
345 elif event.KeyCode == wx.WXK_PAGEUP:
345 elif event.KeyCode == wx.WXK_PAGEUP:
346 self.ScrollPages(-1)
346 self.ScrollPages(-1)
347 elif event.KeyCode == wx.WXK_PAGEDOWN:
347 elif event.KeyCode == wx.WXK_PAGEDOWN:
348 self.ScrollPages(1)
348 self.ScrollPages(1)
349 elif event.KeyCode == wx.WXK_UP and event.ShiftDown():
349 elif event.KeyCode == wx.WXK_UP and event.ShiftDown():
350 self.ScrollLines(-1)
350 self.ScrollLines(-1)
351 elif event.KeyCode == wx.WXK_DOWN and event.ShiftDown():
351 elif event.KeyCode == wx.WXK_DOWN and event.ShiftDown():
352 self.ScrollLines(1)
352 self.ScrollLines(1)
353 else:
353 else:
354 catched = False
354 catched = False
355
355
356 if self.AutoCompActive():
356 if self.AutoCompActive():
357 event.Skip()
357 event.Skip()
358 else:
358 else:
359 if event.KeyCode in (13, wx.WXK_NUMPAD_ENTER) and \
359 if event.KeyCode in (13, wx.WXK_NUMPAD_ENTER) and \
360 event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN):
360 event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN):
361 catched = True
361 catched = True
362 self.CallTipCancel()
362 self.CallTipCancel()
363 self.write('\n', refresh=False)
363 self.write('\n', refresh=False)
364 # Under windows scintilla seems to be doing funny stuff to the
364 # Under windows scintilla seems to be doing funny stuff to the
365 # line returns here, but the getter for input_buffer filters
365 # line returns here, but the getter for input_buffer filters
366 # this out.
366 # this out.
367 if sys.platform == 'win32':
367 if sys.platform == 'win32':
368 self.input_buffer = self.input_buffer
368 self.input_buffer = self.input_buffer
369 self._on_enter()
369 self._on_enter()
370
370
371 elif event.KeyCode == wx.WXK_HOME:
371 elif event.KeyCode == wx.WXK_HOME:
372 if event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN):
372 if event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN):
373 self.GotoPos(self.current_prompt_pos)
373 self.GotoPos(self.current_prompt_pos)
374 catched = True
374 catched = True
375
375
376 elif event.Modifiers == wx.MOD_SHIFT:
376 elif event.Modifiers == wx.MOD_SHIFT:
377 # FIXME: This behavior is not ideal: if the selection
377 # FIXME: This behavior is not ideal: if the selection
378 # is already started, it will jump.
378 # is already started, it will jump.
379 self.SetSelectionStart(self.current_prompt_pos)
379 self.SetSelectionStart(self.current_prompt_pos)
380 self.SetSelectionEnd(self.GetCurrentPos())
380 self.SetSelectionEnd(self.GetCurrentPos())
381 catched = True
381 catched = True
382
382
383 elif event.KeyCode == wx.WXK_UP:
383 elif event.KeyCode == wx.WXK_UP:
384 if self.GetCurrentLine() > self.current_prompt_line:
384 if self.GetCurrentLine() > self.current_prompt_line:
385 if self.GetCurrentLine() == self.current_prompt_line + 1 \
385 if self.GetCurrentLine() == self.current_prompt_line + 1 \
386 and self.GetColumn(self.GetCurrentPos()) < \
386 and self.GetColumn(self.GetCurrentPos()) < \
387 self.GetColumn(self.current_prompt_pos):
387 self.GetColumn(self.current_prompt_pos):
388 self.GotoPos(self.current_prompt_pos)
388 self.GotoPos(self.current_prompt_pos)
389 else:
389 else:
390 event.Skip()
390 event.Skip()
391 catched = True
391 catched = True
392
392
393 elif event.KeyCode in (wx.WXK_LEFT, wx.WXK_BACK):
393 elif event.KeyCode in (wx.WXK_LEFT, wx.WXK_BACK):
394 if self.GetCurrentPos() > self.current_prompt_pos:
394 if self.GetCurrentPos() > self.current_prompt_pos:
395 event.Skip()
395 event.Skip()
396 catched = True
396 catched = True
397
397
398 if skip and not catched:
398 if skip and not catched:
399 # Put the cursor back in the edit region
399 # Put the cursor back in the edit region
400 if self.GetCurrentPos() < self.current_prompt_pos:
400 if self.GetCurrentPos() < self.current_prompt_pos:
401 self.GotoPos(self.current_prompt_pos)
401 self.GotoPos(self.current_prompt_pos)
402 else:
402 else:
403 event.Skip()
403 event.Skip()
404
404
405 return catched
405 return catched
406
406
407
407
408 def _on_key_up(self, event, skip=True):
408 def _on_key_up(self, event, skip=True):
409 """ If cursor is outside the editing region, put it back.
409 """ If cursor is outside the editing region, put it back.
410 """
410 """
411 event.Skip()
411 event.Skip()
412 if self.GetCurrentPos() < self.current_prompt_pos:
412 if self.GetCurrentPos() < self.current_prompt_pos:
413 self.GotoPos(self.current_prompt_pos)
413 self.GotoPos(self.current_prompt_pos)
414
414
415
415
416
416
417 if __name__ == '__main__':
417 if __name__ == '__main__':
418 # Some simple code to test the console widget.
418 # Some simple code to test the console widget.
419 class MainWindow(wx.Frame):
419 class MainWindow(wx.Frame):
420 def __init__(self, parent, id, title):
420 def __init__(self, parent, id, title):
421 wx.Frame.__init__(self, parent, id, title, size=(300,250))
421 wx.Frame.__init__(self, parent, id, title, size=(300,250))
422 self._sizer = wx.BoxSizer(wx.VERTICAL)
422 self._sizer = wx.BoxSizer(wx.VERTICAL)
423 self.console_widget = ConsoleWidget(self)
423 self.console_widget = ConsoleWidget(self)
424 self._sizer.Add(self.console_widget, 1, wx.EXPAND)
424 self._sizer.Add(self.console_widget, 1, wx.EXPAND)
425 self.SetSizer(self._sizer)
425 self.SetSizer(self._sizer)
426 self.SetAutoLayout(1)
426 self.SetAutoLayout(1)
427 self.Show(True)
427 self.Show(True)
428
428
429 app = wx.PySimpleApp()
429 app = wx.PySimpleApp()
430 w = MainWindow(None, wx.ID_ANY, 'ConsoleWidget')
430 w = MainWindow(None, wx.ID_ANY, 'ConsoleWidget')
431 w.SetSize((780, 460))
431 w.SetSize((780, 460))
432 w.Show()
432 w.Show()
433
433
434 app.MainLoop()
434 app.MainLoop()
435
435
436
436
@@ -1,252 +1,296 b''
1 .. _changes:
1 .. _changes:
2
2
3 ==========
3 ==========
4 What's new
4 What's new
5 ==========
5 ==========
6
6
7 .. contents::
7 .. contents::
8 ..
8 ..
9 1 Release 0.9
9 1 Release 0.9
10 1.1 New features
10 1.1 New features
11 1.2 Bug fixes
11 1.2 Bug fixes
12 1.3 Backwards incompatible changes
12 1.3 Backwards incompatible changes
13 1.4 Changes merged in from IPython1
13 1.4 Changes merged in from IPython1
14 1.4.1 New features
14 1.4.1 New features
15 1.4.2 Bug fixes
15 1.4.2 Bug fixes
16 1.4.3 Backwards incompatible changes
16 1.4.3 Backwards incompatible changes
17 2 Release 0.8.4
17 2 Release 0.8.4
18 3 Release 0.8.2
18 3 Release 0.8.2
19 4 Release 0.8.3
19 4 Release 0.8.3
20 5 Older releases
20 5 Older releases
21 ..
21 ..
22
22
23
23
24 Release 0.9
24 Release 0.9
25 ===========
25 ===========
26
26
27 New features
27 New features
28 ------------
28 ------------
29
29
30 * Laurent's WX application has been given a top-level script called ipython-wx,
30 * Laurent's WX application has been given a top-level script called ipython-wx,
31 and it has received numerous fixes. We expect this code to be
31 and it has received numerous fixes. We expect this code to be
32 architecturally better integrated with Gael's WX 'ipython widget' over the
32 architecturally better integrated with Gael's WX 'ipython widget' over the
33 next few releases.
33 next few releases.
34
34
35 * The Editor synchronization work by Vivian De Smedt has been merged in. This
35 * The Editor synchronization work by Vivian De Smedt has been merged in. This
36 code adds a number of new editor hooks to synchronize with editors under
36 code adds a number of new editor hooks to synchronize with editors under
37 Windows.
37 Windows.
38
38
39 * A new, still experimental but highly functional, WX shell by Gael Varoquaux.
39 * A new, still experimental but highly functional, WX shell by Gael Varoquaux.
40 This work was sponsored by Enthought, and while it's still very new, it is
40 This work was sponsored by Enthought, and while it's still very new, it is
41 based on a more cleanly organized arhictecture of the various IPython
41 based on a more cleanly organized arhictecture of the various IPython
42 components. We will continue to develop this over the next few releases as a
42 components. We will continue to develop this over the next few releases as a
43 model for GUI components that use IPython.
43 model for GUI components that use IPython.
44
44
45 * Another GUI frontend, Cocoa based (Cocoa is the OSX native GUI framework),
45 * Another GUI frontend, Cocoa based (Cocoa is the OSX native GUI framework),
46 authored by Barry Wark. Currently the WX and the Cocoa ones have slightly
46 authored by Barry Wark. Currently the WX and the Cocoa ones have slightly
47 different internal organizations, but the whole team is working on finding
47 different internal organizations, but the whole team is working on finding
48 what the right abstraction points are for a unified codebase.
48 what the right abstraction points are for a unified codebase.
49
49
50 * As part of the frontend work, Barry Wark also implemented an experimental
50 * As part of the frontend work, Barry Wark also implemented an experimental
51 event notification system that various ipython components can use. In the
51 event notification system that various ipython components can use. In the
52 next release the implications and use patterns of this system regarding the
52 next release the implications and use patterns of this system regarding the
53 various GUI options will be worked out.
53 various GUI options will be worked out.
54
54
55 * IPython finally has a full test system, that can test docstrings with
55 * IPython finally has a full test system, that can test docstrings with
56 IPython-specific functionality. There are still a few pieces missing for it
56 IPython-specific functionality. There are still a few pieces missing for it
57 to be widely accessible to all users (so they can run the test suite at any
57 to be widely accessible to all users (so they can run the test suite at any
58 time and report problems), but it now works for the developers. We are
58 time and report problems), but it now works for the developers. We are
59 working hard on continuing to improve it, as this was probably IPython's
59 working hard on continuing to improve it, as this was probably IPython's
60 major Achilles heel (the lack of proper test coverage made it effectively
60 major Achilles heel (the lack of proper test coverage made it effectively
61 impossible to do large-scale refactoring).
61 impossible to do large-scale refactoring).
62
62
63 * The notion of a task has been completely reworked. An `ITask` interface has
63 * The notion of a task has been completely reworked. An `ITask` interface has
64 been created. This interface defines the methods that tasks need to implement.
64 been created. This interface defines the methods that tasks need to implement.
65 These methods are now responsible for things like submitting tasks and processing
65 These methods are now responsible for things like submitting tasks and processing
66 results. There are two basic task types: :class:`IPython.kernel.task.StringTask`
66 results. There are two basic task types: :class:`IPython.kernel.task.StringTask`
67 (this is the old `Task` object, but renamed) and the new
67 (this is the old `Task` object, but renamed) and the new
68 :class:`IPython.kernel.task.MapTask`, which is based on a function.
68 :class:`IPython.kernel.task.MapTask`, which is based on a function.
69 * A new interface, :class:`IPython.kernel.mapper.IMapper` has been defined to
69
70 standardize the idea of a `map` method. This interface has a single
70 * A new interface, :class:`IPython.kernel.mapper.IMapper` has been defined to
71 `map` method that has the same syntax as the built-in `map`. We have also defined
71 standardize the idea of a `map` method. This interface has a single
72 a `mapper` factory interface that creates objects that implement
72 `map` method that has the same syntax as the built-in `map`. We have also defined
73 :class:`IPython.kernel.mapper.IMapper` for different controllers. Both
73 a `mapper` factory interface that creates objects that implement
74 the multiengine and task controller now have mapping capabilties.
74 :class:`IPython.kernel.mapper.IMapper` for different controllers. Both
75 * The parallel function capabilities have been reworks. The major changes are that
75 the multiengine and task controller now have mapping capabilties.
76 i) there is now an `@parallel` magic that creates parallel functions, ii)
76
77 the syntax for mulitple variable follows that of `map`, iii) both the
77 * The parallel function capabilities have been reworks. The major changes are that
78 multiengine and task controller now have a parallel function implementation.
78 i) there is now an `@parallel` magic that creates parallel functions, ii)
79 * All of the parallel computing capabilities from `ipython1-dev` have been merged into
79 the syntax for mulitple variable follows that of `map`, iii) both the
80 IPython proper. This resulted in the following new subpackages:
80 multiengine and task controller now have a parallel function implementation.
81 :mod:`IPython.kernel`, :mod:`IPython.kernel.core`, :mod:`IPython.config`,
81
82 :mod:`IPython.tools` and :mod:`IPython.testing`.
82 * All of the parallel computing capabilities from `ipython1-dev` have been merged into
83 * As part of merging in the `ipython1-dev` stuff, the `setup.py` script and friends
83 IPython proper. This resulted in the following new subpackages:
84 have been completely refactored. Now we are checking for dependencies using
84 :mod:`IPython.kernel`, :mod:`IPython.kernel.core`, :mod:`IPython.config`,
85 the approach that matplotlib uses.
85 :mod:`IPython.tools` and :mod:`IPython.testing`.
86 * The documentation has been completely reorganized to accept the documentation
86
87 from `ipython1-dev`.
87 * As part of merging in the `ipython1-dev` stuff, the `setup.py` script and friends
88 * We have switched to using Foolscap for all of our network protocols in
88 have been completely refactored. Now we are checking for dependencies using
89 :mod:`IPython.kernel`. This gives us secure connections that are both encrypted
89 the approach that matplotlib uses.
90 and authenticated.
90
91 * We have a brand new `COPYING.txt` files that describes the IPython license
91 * The documentation has been completely reorganized to accept the documentation
92 and copyright. The biggest change is that we are putting "The IPython
92 from `ipython1-dev`.
93 Development Team" as the copyright holder. We give more details about exactly
93
94 what this means in this file. All developer should read this and use the new
94 * We have switched to using Foolscap for all of our network protocols in
95 banner in all IPython source code files.
95 :mod:`IPython.kernel`. This gives us secure connections that are both encrypted
96 * sh profile: ./foo runs foo as system command, no need to do !./foo anymore
96 and authenticated.
97 * String lists now support 'sort(field, nums = True)' method (to easily
97
98 sort system command output). Try it with 'a = !ls -l ; a.sort(1, nums=1)'
98 * We have a brand new `COPYING.txt` files that describes the IPython license
99 * '%cpaste foo' now assigns the pasted block as string list, instead of string
99 and copyright. The biggest change is that we are putting "The IPython
100 * The ipcluster script now run by default with no security. This is done because
100 Development Team" as the copyright holder. We give more details about exactly
101 the main usage of the script is for starting things on localhost. Eventually
101 what this means in this file. All developer should read this and use the new
102 when ipcluster is able to start things on other hosts, we will put security
102 banner in all IPython source code files.
103 back.
103
104 * 'cd --foo' searches directory history for string foo, and jumps to that dir.
104 * sh profile: ./foo runs foo as system command, no need to do !./foo anymore
105 Last part of dir name is checked first. If no matches for that are found,
105
106 look at the whole path.
106 * String lists now support 'sort(field, nums = True)' method (to easily
107 sort system command output). Try it with 'a = !ls -l ; a.sort(1, nums=1)'
108
109 * '%cpaste foo' now assigns the pasted block as string list, instead of string
110
111 * The ipcluster script now run by default with no security. This is done because
112 the main usage of the script is for starting things on localhost. Eventually
113 when ipcluster is able to start things on other hosts, we will put security
114 back.
115
116 * 'cd --foo' searches directory history for string foo, and jumps to that dir.
117 Last part of dir name is checked first. If no matches for that are found,
118 look at the whole path.
107
119
108 Bug fixes
120 Bug fixes
109 ---------
121 ---------
110
122
111 * The colors escapes in the multiengine client are now turned off on win32 as they
123 * The colors escapes in the multiengine client are now turned off on win32 as they
112 don't print correctly.
124 don't print correctly.
113 * The :mod:`IPython.kernel.scripts.ipengine` script was exec'ing mpi_import_statement
125
114 incorrectly, which was leading the engine to crash when mpi was enabled.
126 * The :mod:`IPython.kernel.scripts.ipengine` script was exec'ing mpi_import_statement
115 * A few subpackages has missing `__init__.py` files.
127 incorrectly, which was leading the engine to crash when mpi was enabled.
116 * The documentation is only created is Sphinx is found. Previously, the `setup.py`
128
117 script would fail if it was missing.
129 * A few subpackages has missing `__init__.py` files.
118 * Greedy 'cd' completion has been disabled again (it was enabled in 0.8.4)
130
131 * The documentation is only created is Sphinx is found. Previously, the `setup.py`
132 script would fail if it was missing.
133
134 * Greedy 'cd' completion has been disabled again (it was enabled in 0.8.4)
119
135
120
136
121 Backwards incompatible changes
137 Backwards incompatible changes
122 ------------------------------
138 ------------------------------
123
139
124 * In ipapi, the :func:`make_user_ns` function has been replaced with
140 * In ipapi, the :func:`make_user_ns` function has been replaced with
125 :func:`make_user_namespaces`, to support dict subclasses in namespace
141 :func:`make_user_namespaces`, to support dict subclasses in namespace
126 creation.
142 creation.
127
143
128 * :class:`IPython.kernel.client.Task` has been renamed
144 * :class:`IPython.kernel.client.Task` has been renamed
129 :class:`IPython.kernel.client.StringTask` to make way for new task types.
145 :class:`IPython.kernel.client.StringTask` to make way for new task types.
130 * The keyword argument `style` has been renamed `dist` in `scatter`, `gather`
146
131 and `map`.
147 * The keyword argument `style` has been renamed `dist` in `scatter`, `gather`
132 * Renamed the values that the rename `dist` keyword argument can have from
148 and `map`.
133 `'basic'` to `'b'`.
149
134 * IPython has a larger set of dependencies if you want all of its capabilities.
150 * Renamed the values that the rename `dist` keyword argument can have from
135 See the `setup.py` script for details.
151 `'basic'` to `'b'`.
136 * The constructors for :class:`IPython.kernel.client.MultiEngineClient` and
152
137 :class:`IPython.kernel.client.TaskClient` no longer take the (ip,port) tuple.
153 * IPython has a larger set of dependencies if you want all of its capabilities.
138 Instead they take the filename of a file that contains the FURL for that
154 See the `setup.py` script for details.
139 client. If the FURL file is in your IPYTHONDIR, it will be found automatically
155
140 and the constructor can be left empty.
156 * The constructors for :class:`IPython.kernel.client.MultiEngineClient` and
141 * The asynchronous clients in :mod:`IPython.kernel.asyncclient` are now created
157 :class:`IPython.kernel.client.TaskClient` no longer take the (ip,port) tuple.
142 using the factory functions :func:`get_multiengine_client` and
158 Instead they take the filename of a file that contains the FURL for that
143 :func:`get_task_client`. These return a `Deferred` to the actual client.
159 client. If the FURL file is in your IPYTHONDIR, it will be found automatically
144 * The command line options to `ipcontroller` and `ipengine` have changed to
160 and the constructor can be left empty.
145 reflect the new Foolscap network protocol and the FURL files. Please see the
161
146 help for these scripts for details.
162 * The asynchronous clients in :mod:`IPython.kernel.asyncclient` are now created
147 * The configuration files for the kernel have changed because of the Foolscap stuff.
163 using the factory functions :func:`get_multiengine_client` and
148 If you were using custom config files before, you should delete them and regenerate
164 :func:`get_task_client`. These return a `Deferred` to the actual client.
149 new ones.
165
166 * The command line options to `ipcontroller` and `ipengine` have changed to
167 reflect the new Foolscap network protocol and the FURL files. Please see the
168 help for these scripts for details.
169
170 * The configuration files for the kernel have changed because of the Foolscap stuff.
171 If you were using custom config files before, you should delete them and regenerate
172 new ones.
150
173
151 Changes merged in from IPython1
174 Changes merged in from IPython1
152 -------------------------------
175 -------------------------------
153
176
154 New features
177 New features
155 ............
178 ............
156
179
157 * Much improved ``setup.py`` and ``setupegg.py`` scripts. Because Twisted
180 * Much improved ``setup.py`` and ``setupegg.py`` scripts. Because Twisted
158 and zope.interface are now easy installable, we can declare them as dependencies
181 and zope.interface are now easy installable, we can declare them as dependencies
159 in our setupegg.py script.
182 in our setupegg.py script.
160 * IPython is now compatible with Twisted 2.5.0 and 8.x.
183
161 * Added a new example of how to use :mod:`ipython1.kernel.asynclient`.
184 * IPython is now compatible with Twisted 2.5.0 and 8.x.
162 * Initial draft of a process daemon in :mod:`ipython1.daemon`. This has not
185
163 been merged into IPython and is still in `ipython1-dev`.
186 * Added a new example of how to use :mod:`ipython1.kernel.asynclient`.
164 * The ``TaskController`` now has methods for getting the queue status.
187
165 * The ``TaskResult`` objects not have information about how long the task
188 * Initial draft of a process daemon in :mod:`ipython1.daemon`. This has not
166 took to run.
189 been merged into IPython and is still in `ipython1-dev`.
167 * We are attaching additional attributes to exceptions ``(_ipython_*)`` that
190
168 we use to carry additional info around.
191 * The ``TaskController`` now has methods for getting the queue status.
169 * New top-level module :mod:`asyncclient` that has asynchronous versions (that
192
170 return deferreds) of the client classes. This is designed to users who want
193 * The ``TaskResult`` objects not have information about how long the task
171 to run their own Twisted reactor
194 took to run.
172 * All the clients in :mod:`client` are now based on Twisted. This is done by
195
173 running the Twisted reactor in a separate thread and using the
196 * We are attaching additional attributes to exceptions ``(_ipython_*)`` that
174 :func:`blockingCallFromThread` function that is in recent versions of Twisted.
197 we use to carry additional info around.
175 * Functions can now be pushed/pulled to/from engines using
198
176 :meth:`MultiEngineClient.push_function` and :meth:`MultiEngineClient.pull_function`.
199 * New top-level module :mod:`asyncclient` that has asynchronous versions (that
177 * Gather/scatter are now implemented in the client to reduce the work load
200 return deferreds) of the client classes. This is designed to users who want
178 of the controller and improve performance.
201 to run their own Twisted reactor.
179 * Complete rewrite of the IPython docuementation. All of the documentation
202
180 from the IPython website has been moved into docs/source as restructured
203 * All the clients in :mod:`client` are now based on Twisted. This is done by
181 text documents. PDF and HTML documentation are being generated using
204 running the Twisted reactor in a separate thread and using the
182 Sphinx.
205 :func:`blockingCallFromThread` function that is in recent versions of Twisted.
183 * New developer oriented documentation: development guidelines and roadmap.
206
184 * Traditional ``ChangeLog`` has been changed to a more useful ``changes.txt`` file
207 * Functions can now be pushed/pulled to/from engines using
185 that is organized by release and is meant to provide something more relevant
208 :meth:`MultiEngineClient.push_function` and :meth:`MultiEngineClient.pull_function`.
186 for users.
209
210 * Gather/scatter are now implemented in the client to reduce the work load
211 of the controller and improve performance.
212
213 * Complete rewrite of the IPython docuementation. All of the documentation
214 from the IPython website has been moved into docs/source as restructured
215 text documents. PDF and HTML documentation are being generated using
216 Sphinx.
217
218 * New developer oriented documentation: development guidelines and roadmap.
219
220 * Traditional ``ChangeLog`` has been changed to a more useful ``changes.txt`` file
221 that is organized by release and is meant to provide something more relevant
222 for users.
187
223
188 Bug fixes
224 Bug fixes
189 .........
225 .........
190
226
191 * Created a proper ``MANIFEST.in`` file to create source distributions.
227 * Created a proper ``MANIFEST.in`` file to create source distributions.
192 * Fixed a bug in the ``MultiEngine`` interface. Previously, multi-engine
228
193 actions were being collected with a :class:`DeferredList` with
229 * Fixed a bug in the ``MultiEngine`` interface. Previously, multi-engine
194 ``fireononeerrback=1``. This meant that methods were returning
230 actions were being collected with a :class:`DeferredList` with
195 before all engines had given their results. This was causing extremely odd
231 ``fireononeerrback=1``. This meant that methods were returning
196 bugs in certain cases. To fix this problem, we have 1) set
232 before all engines had given their results. This was causing extremely odd
197 ``fireononeerrback=0`` to make sure all results (or exceptions) are in
233 bugs in certain cases. To fix this problem, we have 1) set
198 before returning and 2) introduced a :exc:`CompositeError` exception
234 ``fireononeerrback=0`` to make sure all results (or exceptions) are in
199 that wraps all of the engine exceptions. This is a huge change as it means
235 before returning and 2) introduced a :exc:`CompositeError` exception
200 that users will have to catch :exc:`CompositeError` rather than the actual
236 that wraps all of the engine exceptions. This is a huge change as it means
201 exception.
237 that users will have to catch :exc:`CompositeError` rather than the actual
238 exception.
202
239
203 Backwards incompatible changes
240 Backwards incompatible changes
204 ..............................
241 ..............................
205
242
206 * All names have been renamed to conform to the lowercase_with_underscore
243 * All names have been renamed to conform to the lowercase_with_underscore
207 convention. This will require users to change references to all names like
244 convention. This will require users to change references to all names like
208 ``queueStatus`` to ``queue_status``.
245 ``queueStatus`` to ``queue_status``.
209 * Previously, methods like :meth:`MultiEngineClient.push` and
246
210 :meth:`MultiEngineClient.push` used ``*args`` and ``**kwargs``. This was
247 * Previously, methods like :meth:`MultiEngineClient.push` and
211 becoming a problem as we weren't able to introduce new keyword arguments into
248 :meth:`MultiEngineClient.push` used ``*args`` and ``**kwargs``. This was
212 the API. Now these methods simple take a dict or sequence. This has also allowed
249 becoming a problem as we weren't able to introduce new keyword arguments into
213 us to get rid of the ``*All`` methods like :meth:`pushAll` and :meth:`pullAll`.
250 the API. Now these methods simple take a dict or sequence. This has also allowed
214 These things are now handled with the ``targets`` keyword argument that defaults
251 us to get rid of the ``*All`` methods like :meth:`pushAll` and :meth:`pullAll`.
215 to ``'all'``.
252 These things are now handled with the ``targets`` keyword argument that defaults
216 * The :attr:`MultiEngineClient.magicTargets` has been renamed to
253 to ``'all'``.
217 :attr:`MultiEngineClient.targets`.
254
218 * All methods in the MultiEngine interface now accept the optional keyword argument
255 * The :attr:`MultiEngineClient.magicTargets` has been renamed to
219 ``block``.
256 :attr:`MultiEngineClient.targets`.
220 * Renamed :class:`RemoteController` to :class:`MultiEngineClient` and
257
221 :class:`TaskController` to :class:`TaskClient`.
258 * All methods in the MultiEngine interface now accept the optional keyword argument
222 * Renamed the top-level module from :mod:`api` to :mod:`client`.
259 ``block``.
223 * Most methods in the multiengine interface now raise a :exc:`CompositeError` exception
260
224 that wraps the user's exceptions, rather than just raising the raw user's exception.
261 * Renamed :class:`RemoteController` to :class:`MultiEngineClient` and
225 * Changed the ``setupNS`` and ``resultNames`` in the ``Task`` class to ``push``
262 :class:`TaskController` to :class:`TaskClient`.
226 and ``pull``.
263
264 * Renamed the top-level module from :mod:`api` to :mod:`client`.
265
266 * Most methods in the multiengine interface now raise a :exc:`CompositeError` exception
267 that wraps the user's exceptions, rather than just raising the raw user's exception.
268
269 * Changed the ``setupNS`` and ``resultNames`` in the ``Task`` class to ``push``
270 and ``pull``.
227
271
228 Release 0.8.4
272 Release 0.8.4
229 =============
273 =============
230
274
231 Someone needs to describe what went into 0.8.4.
275 Someone needs to describe what went into 0.8.4.
232
276
233 Release 0.8.2
277 Release 0.8.2
234 =============
278 =============
235
279
236 * %pushd/%popd behave differently; now "pushd /foo" pushes CURRENT directory
280 * %pushd/%popd behave differently; now "pushd /foo" pushes CURRENT directory
237 and jumps to /foo. The current behaviour is closer to the documented
281 and jumps to /foo. The current behaviour is closer to the documented
238 behaviour, and should not trip anyone.
282 behaviour, and should not trip anyone.
239
283
240 Release 0.8.3
284 Release 0.8.3
241 =============
285 =============
242
286
243 * pydb is now disabled by default (due to %run -d problems). You can enable
287 * pydb is now disabled by default (due to %run -d problems). You can enable
244 it by passing -pydb command line argument to IPython. Note that setting
288 it by passing -pydb command line argument to IPython. Note that setting
245 it in config file won't work.
289 it in config file won't work.
246
290
247 Older releases
291 Older releases
248 ==============
292 ==============
249
293
250 Changes in earlier releases of IPython are described in the older file ``ChangeLog``.
294 Changes in earlier releases of IPython are described in the older file ``ChangeLog``.
251 Please refer to this document for details.
295 Please refer to this document for details.
252
296
@@ -1,28 +1,32 b''
1 =====================
1 =====================
2 IPython Documentation
2 IPython Documentation
3 =====================
3 =====================
4
4
5 Contents
5 .. htmlonly::
6 ========
6
7 :Release: |version|
8 :Date: |today|
9
10 Contents:
7
11
8 .. toctree::
12 .. toctree::
9 :maxdepth: 1
13 :maxdepth: 2
10
14
11 overview.txt
15 overview.txt
12 install/index.txt
16 install/index.txt
13 interactive/index.txt
17 interactive/index.txt
14 parallel/index.txt
18 parallel/index.txt
15 config/index.txt
19 config/index.txt
16 changes.txt
20 changes.txt
17 development/index.txt
21 development/index.txt
18 faq.txt
22 faq.txt
19 history.txt
23 history.txt
20 license_and_copyright.txt
24 license_and_copyright.txt
21 credits.txt
25 credits.txt
22
26
23 Indices and tables
24 ==================
25
27
26 * :ref:`genindex`
28 .. htmlonly::
27 * :ref:`modindex`
29
28 * :ref:`search` No newline at end of file
30 * :ref:`genindex`
31 * :ref:`modindex`
32 * :ref:`search`
@@ -1,11 +1,10 b''
1 .. _install_index:
1 .. _install_index:
2
2
3 ==================
3 ==================
4 Installation
4 Installation
5 ==================
5 ==================
6
6
7 .. toctree::
7 .. toctree::
8 :maxdepth: 2
8 :maxdepth: 2
9
9
10 basic.txt
10 install.txt
11 advanced.txt
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now