Show More
@@ -1,1267 +1,1267 b'' | |||||
1 | # encoding: utf-8 |
|
1 | # encoding: utf-8 | |
2 | """Word completion for IPython. |
|
2 | """Word completion for IPython. | |
3 |
|
3 | |||
4 | This module is a fork of the rlcompleter module in the Python standard |
|
4 | This module is a fork of the rlcompleter module in the Python standard | |
5 | library. The original enhancements made to rlcompleter have been sent |
|
5 | library. The original enhancements made to rlcompleter have been sent | |
6 | upstream and were accepted as of Python 2.3, but we need a lot more |
|
6 | upstream and were accepted as of Python 2.3, but we need a lot more | |
7 | functionality specific to IPython, so this module will continue to live as an |
|
7 | functionality specific to IPython, so this module will continue to live as an | |
8 | IPython-specific utility. |
|
8 | IPython-specific utility. | |
9 |
|
9 | |||
10 | Original rlcompleter documentation: |
|
10 | Original rlcompleter documentation: | |
11 |
|
11 | |||
12 | This requires the latest extension to the readline module (the |
|
12 | This requires the latest extension to the readline module (the | |
13 | completes keywords, built-ins and globals in __main__; when completing |
|
13 | completes keywords, built-ins and globals in __main__; when completing | |
14 | NAME.NAME..., it evaluates (!) the expression up to the last dot and |
|
14 | NAME.NAME..., it evaluates (!) the expression up to the last dot and | |
15 | completes its attributes. |
|
15 | completes its attributes. | |
16 |
|
16 | |||
17 | It's very cool to do "import string" type "string.", hit the |
|
17 | It's very cool to do "import string" type "string.", hit the | |
18 | completion key (twice), and see the list of names defined by the |
|
18 | completion key (twice), and see the list of names defined by the | |
19 | string module! |
|
19 | string module! | |
20 |
|
20 | |||
21 | Tip: to use the tab key as the completion key, call |
|
21 | Tip: to use the tab key as the completion key, call | |
22 |
|
22 | |||
23 | readline.parse_and_bind("tab: complete") |
|
23 | readline.parse_and_bind("tab: complete") | |
24 |
|
24 | |||
25 | Notes: |
|
25 | Notes: | |
26 |
|
26 | |||
27 | - Exceptions raised by the completer function are *ignored* (and |
|
27 | - Exceptions raised by the completer function are *ignored* (and | |
28 | generally cause the completion to fail). This is a feature -- since |
|
28 | generally cause the completion to fail). This is a feature -- since | |
29 | readline sets the tty device in raw (or cbreak) mode, printing a |
|
29 | readline sets the tty device in raw (or cbreak) mode, printing a | |
30 | traceback wouldn't work well without some complicated hoopla to save, |
|
30 | traceback wouldn't work well without some complicated hoopla to save, | |
31 | reset and restore the tty state. |
|
31 | reset and restore the tty state. | |
32 |
|
32 | |||
33 | - The evaluation of the NAME.NAME... form may cause arbitrary |
|
33 | - The evaluation of the NAME.NAME... form may cause arbitrary | |
34 | application defined code to be executed if an object with a |
|
34 | application defined code to be executed if an object with a | |
35 | ``__getattr__`` hook is found. Since it is the responsibility of the |
|
35 | ``__getattr__`` hook is found. Since it is the responsibility of the | |
36 | application (or the user) to enable this feature, I consider this an |
|
36 | application (or the user) to enable this feature, I consider this an | |
37 | acceptable risk. More complicated expressions (e.g. function calls or |
|
37 | acceptable risk. More complicated expressions (e.g. function calls or | |
38 | indexing operations) are *not* evaluated. |
|
38 | indexing operations) are *not* evaluated. | |
39 |
|
39 | |||
40 | - GNU readline is also used by the built-in functions input() and |
|
40 | - GNU readline is also used by the built-in functions input() and | |
41 | raw_input(), and thus these also benefit/suffer from the completer |
|
41 | raw_input(), and thus these also benefit/suffer from the completer | |
42 | features. Clearly an interactive application can benefit by |
|
42 | features. Clearly an interactive application can benefit by | |
43 | specifying its own completer function and using raw_input() for all |
|
43 | specifying its own completer function and using raw_input() for all | |
44 | its input. |
|
44 | its input. | |
45 |
|
45 | |||
46 | - When the original stdin is not a tty device, GNU readline is never |
|
46 | - When the original stdin is not a tty device, GNU readline is never | |
47 | used, and this module (and the readline module) are silently inactive. |
|
47 | used, and this module (and the readline module) are silently inactive. | |
48 | """ |
|
48 | """ | |
49 |
|
49 | |||
50 | # Copyright (c) IPython Development Team. |
|
50 | # Copyright (c) IPython Development Team. | |
51 | # Distributed under the terms of the Modified BSD License. |
|
51 | # Distributed under the terms of the Modified BSD License. | |
52 | # |
|
52 | # | |
53 | # Some of this code originated from rlcompleter in the Python standard library |
|
53 | # Some of this code originated from rlcompleter in the Python standard library | |
54 | # Copyright (C) 2001 Python Software Foundation, www.python.org |
|
54 | # Copyright (C) 2001 Python Software Foundation, www.python.org | |
55 |
|
55 | |||
56 | import __main__ |
|
56 | import __main__ | |
57 | import glob |
|
57 | import glob | |
58 | import inspect |
|
58 | import inspect | |
59 | import itertools |
|
59 | import itertools | |
60 | import keyword |
|
60 | import keyword | |
61 | import os |
|
61 | import os | |
62 | import re |
|
62 | import re | |
63 | import sys |
|
63 | import sys | |
64 | import unicodedata |
|
64 | import unicodedata | |
65 | import string |
|
65 | import string | |
66 |
|
66 | |||
67 | from traitlets.config.configurable import Configurable |
|
67 | from traitlets.config.configurable import Configurable | |
68 | from IPython.core.error import TryNext |
|
68 | from IPython.core.error import TryNext | |
69 | from IPython.core.inputsplitter import ESC_MAGIC |
|
69 | from IPython.core.inputsplitter import ESC_MAGIC | |
70 | from IPython.core.latex_symbols import latex_symbols, reverse_latex_symbol |
|
70 | from IPython.core.latex_symbols import latex_symbols, reverse_latex_symbol | |
71 | from IPython.utils import generics |
|
71 | from IPython.utils import generics | |
72 | from IPython.utils import io |
|
72 | from IPython.utils import io | |
73 | from IPython.utils.decorators import undoc |
|
73 | from IPython.utils.decorators import undoc | |
74 | from IPython.utils.dir2 import dir2 |
|
74 | from IPython.utils.dir2 import dir2 | |
75 | from IPython.utils.process import arg_split |
|
75 | from IPython.utils.process import arg_split | |
76 | from IPython.utils.py3compat import builtin_mod, string_types, PY3 |
|
76 | from IPython.utils.py3compat import builtin_mod, string_types, PY3 | |
77 | from traitlets import CBool, Enum |
|
77 | from traitlets import CBool, Enum | |
78 |
|
78 | |||
79 | #----------------------------------------------------------------------------- |
|
79 | #----------------------------------------------------------------------------- | |
80 | # Globals |
|
80 | # Globals | |
81 | #----------------------------------------------------------------------------- |
|
81 | #----------------------------------------------------------------------------- | |
82 |
|
82 | |||
83 | # Public API |
|
83 | # Public API | |
84 | __all__ = ['Completer','IPCompleter'] |
|
84 | __all__ = ['Completer','IPCompleter'] | |
85 |
|
85 | |||
86 | if sys.platform == 'win32': |
|
86 | if sys.platform == 'win32': | |
87 | PROTECTABLES = ' ' |
|
87 | PROTECTABLES = ' ' | |
88 | else: |
|
88 | else: | |
89 | PROTECTABLES = ' ()[]{}?=\\|;:\'#*"^&' |
|
89 | PROTECTABLES = ' ()[]{}?=\\|;:\'#*"^&' | |
90 |
|
90 | |||
91 |
|
91 | |||
92 | #----------------------------------------------------------------------------- |
|
92 | #----------------------------------------------------------------------------- | |
93 | # Main functions and classes |
|
93 | # Main functions and classes | |
94 | #----------------------------------------------------------------------------- |
|
94 | #----------------------------------------------------------------------------- | |
95 |
|
95 | |||
96 | def has_open_quotes(s): |
|
96 | def has_open_quotes(s): | |
97 | """Return whether a string has open quotes. |
|
97 | """Return whether a string has open quotes. | |
98 |
|
98 | |||
99 | This simply counts whether the number of quote characters of either type in |
|
99 | This simply counts whether the number of quote characters of either type in | |
100 | the string is odd. |
|
100 | the string is odd. | |
101 |
|
101 | |||
102 | Returns |
|
102 | Returns | |
103 | ------- |
|
103 | ------- | |
104 | If there is an open quote, the quote character is returned. Else, return |
|
104 | If there is an open quote, the quote character is returned. Else, return | |
105 | False. |
|
105 | False. | |
106 | """ |
|
106 | """ | |
107 | # We check " first, then ', so complex cases with nested quotes will get |
|
107 | # We check " first, then ', so complex cases with nested quotes will get | |
108 | # the " to take precedence. |
|
108 | # the " to take precedence. | |
109 | if s.count('"') % 2: |
|
109 | if s.count('"') % 2: | |
110 | return '"' |
|
110 | return '"' | |
111 | elif s.count("'") % 2: |
|
111 | elif s.count("'") % 2: | |
112 | return "'" |
|
112 | return "'" | |
113 | else: |
|
113 | else: | |
114 | return False |
|
114 | return False | |
115 |
|
115 | |||
116 |
|
116 | |||
117 | def protect_filename(s): |
|
117 | def protect_filename(s): | |
118 | """Escape a string to protect certain characters.""" |
|
118 | """Escape a string to protect certain characters.""" | |
119 |
|
119 | |||
120 | return "".join([(ch in PROTECTABLES and '\\' + ch or ch) |
|
120 | return "".join([(ch in PROTECTABLES and '\\' + ch or ch) | |
121 | for ch in s]) |
|
121 | for ch in s]) | |
122 |
|
122 | |||
123 | def expand_user(path): |
|
123 | def expand_user(path): | |
124 | """Expand '~'-style usernames in strings. |
|
124 | """Expand '~'-style usernames in strings. | |
125 |
|
125 | |||
126 | This is similar to :func:`os.path.expanduser`, but it computes and returns |
|
126 | This is similar to :func:`os.path.expanduser`, but it computes and returns | |
127 | extra information that will be useful if the input was being used in |
|
127 | extra information that will be useful if the input was being used in | |
128 | computing completions, and you wish to return the completions with the |
|
128 | computing completions, and you wish to return the completions with the | |
129 | original '~' instead of its expanded value. |
|
129 | original '~' instead of its expanded value. | |
130 |
|
130 | |||
131 | Parameters |
|
131 | Parameters | |
132 | ---------- |
|
132 | ---------- | |
133 | path : str |
|
133 | path : str | |
134 | String to be expanded. If no ~ is present, the output is the same as the |
|
134 | String to be expanded. If no ~ is present, the output is the same as the | |
135 | input. |
|
135 | input. | |
136 |
|
136 | |||
137 | Returns |
|
137 | Returns | |
138 | ------- |
|
138 | ------- | |
139 | newpath : str |
|
139 | newpath : str | |
140 | Result of ~ expansion in the input path. |
|
140 | Result of ~ expansion in the input path. | |
141 | tilde_expand : bool |
|
141 | tilde_expand : bool | |
142 | Whether any expansion was performed or not. |
|
142 | Whether any expansion was performed or not. | |
143 | tilde_val : str |
|
143 | tilde_val : str | |
144 | The value that ~ was replaced with. |
|
144 | The value that ~ was replaced with. | |
145 | """ |
|
145 | """ | |
146 | # Default values |
|
146 | # Default values | |
147 | tilde_expand = False |
|
147 | tilde_expand = False | |
148 | tilde_val = '' |
|
148 | tilde_val = '' | |
149 | newpath = path |
|
149 | newpath = path | |
150 |
|
150 | |||
151 | if path.startswith('~'): |
|
151 | if path.startswith('~'): | |
152 | tilde_expand = True |
|
152 | tilde_expand = True | |
153 | rest = len(path)-1 |
|
153 | rest = len(path)-1 | |
154 | newpath = os.path.expanduser(path) |
|
154 | newpath = os.path.expanduser(path) | |
155 | if rest: |
|
155 | if rest: | |
156 | tilde_val = newpath[:-rest] |
|
156 | tilde_val = newpath[:-rest] | |
157 | else: |
|
157 | else: | |
158 | tilde_val = newpath |
|
158 | tilde_val = newpath | |
159 |
|
159 | |||
160 | return newpath, tilde_expand, tilde_val |
|
160 | return newpath, tilde_expand, tilde_val | |
161 |
|
161 | |||
162 |
|
162 | |||
163 | def compress_user(path, tilde_expand, tilde_val): |
|
163 | def compress_user(path, tilde_expand, tilde_val): | |
164 | """Does the opposite of expand_user, with its outputs. |
|
164 | """Does the opposite of expand_user, with its outputs. | |
165 | """ |
|
165 | """ | |
166 | if tilde_expand: |
|
166 | if tilde_expand: | |
167 | return path.replace(tilde_val, '~') |
|
167 | return path.replace(tilde_val, '~') | |
168 | else: |
|
168 | else: | |
169 | return path |
|
169 | return path | |
170 |
|
170 | |||
171 |
|
171 | |||
172 |
|
172 | |||
173 | def penalize_magics_key(word): |
|
173 | def penalize_magics_key(word): | |
174 | """key for sorting that penalizes magic commands in the ordering |
|
174 | """key for sorting that penalizes magic commands in the ordering | |
175 |
|
175 | |||
176 | Normal words are left alone. |
|
176 | Normal words are left alone. | |
177 |
|
177 | |||
178 | Magic commands have the initial % moved to the end, e.g. |
|
178 | Magic commands have the initial % moved to the end, e.g. | |
179 | %matplotlib is transformed as follows: |
|
179 | %matplotlib is transformed as follows: | |
180 |
|
180 | |||
181 | %matplotlib -> matplotlib% |
|
181 | %matplotlib -> matplotlib% | |
182 |
|
182 | |||
183 | [The choice of the final % is arbitrary.] |
|
183 | [The choice of the final % is arbitrary.] | |
184 |
|
184 | |||
185 | Since "matplotlib" < "matplotlib%" as strings, |
|
185 | Since "matplotlib" < "matplotlib%" as strings, | |
186 | "timeit" will appear before the magic "%timeit" in the ordering |
|
186 | "timeit" will appear before the magic "%timeit" in the ordering | |
187 |
|
187 | |||
188 | For consistency, move "%%" to the end, so cell magics appear *after* |
|
188 | For consistency, move "%%" to the end, so cell magics appear *after* | |
189 | line magics with the same name. |
|
189 | line magics with the same name. | |
190 |
|
190 | |||
191 | A check is performed that there are no other "%" in the string; |
|
191 | A check is performed that there are no other "%" in the string; | |
192 | if there are, then the string is not a magic command and is left unchanged. |
|
192 | if there are, then the string is not a magic command and is left unchanged. | |
193 |
|
193 | |||
194 | """ |
|
194 | """ | |
195 |
|
195 | |||
196 | # Move any % signs from start to end of the key |
|
196 | # Move any % signs from start to end of the key | |
197 | # provided there are no others elsewhere in the string |
|
197 | # provided there are no others elsewhere in the string | |
198 |
|
198 | |||
199 | if word[:2] == "%%": |
|
199 | if word[:2] == "%%": | |
200 | if not "%" in word[2:]: |
|
200 | if not "%" in word[2:]: | |
201 | return word[2:] + "%%" |
|
201 | return word[2:] + "%%" | |
202 |
|
202 | |||
203 | if word[:1] == "%": |
|
203 | if word[:1] == "%": | |
204 | if not "%" in word[1:]: |
|
204 | if not "%" in word[1:]: | |
205 | return word[1:] + "%" |
|
205 | return word[1:] + "%" | |
206 |
|
206 | |||
207 | return word |
|
207 | return word | |
208 |
|
208 | |||
209 |
|
209 | |||
210 | @undoc |
|
210 | @undoc | |
211 | class Bunch(object): pass |
|
211 | class Bunch(object): pass | |
212 |
|
212 | |||
213 |
|
213 | |||
214 | DELIMS = ' \t\n`!@#$^&*()=+[{]}\\|;:\'",<>?' |
|
214 | DELIMS = ' \t\n`!@#$^&*()=+[{]}\\|;:\'",<>?' | |
215 | GREEDY_DELIMS = ' =\r\n' |
|
215 | GREEDY_DELIMS = ' =\r\n' | |
216 |
|
216 | |||
217 |
|
217 | |||
218 | class CompletionSplitter(object): |
|
218 | class CompletionSplitter(object): | |
219 | """An object to split an input line in a manner similar to readline. |
|
219 | """An object to split an input line in a manner similar to readline. | |
220 |
|
220 | |||
221 | By having our own implementation, we can expose readline-like completion in |
|
221 | By having our own implementation, we can expose readline-like completion in | |
222 | a uniform manner to all frontends. This object only needs to be given the |
|
222 | a uniform manner to all frontends. This object only needs to be given the | |
223 | line of text to be split and the cursor position on said line, and it |
|
223 | line of text to be split and the cursor position on said line, and it | |
224 | returns the 'word' to be completed on at the cursor after splitting the |
|
224 | returns the 'word' to be completed on at the cursor after splitting the | |
225 | entire line. |
|
225 | entire line. | |
226 |
|
226 | |||
227 | What characters are used as splitting delimiters can be controlled by |
|
227 | What characters are used as splitting delimiters can be controlled by | |
228 | setting the `delims` attribute (this is a property that internally |
|
228 | setting the `delims` attribute (this is a property that internally | |
229 | automatically builds the necessary regular expression)""" |
|
229 | automatically builds the necessary regular expression)""" | |
230 |
|
230 | |||
231 | # Private interface |
|
231 | # Private interface | |
232 |
|
232 | |||
233 | # A string of delimiter characters. The default value makes sense for |
|
233 | # A string of delimiter characters. The default value makes sense for | |
234 | # IPython's most typical usage patterns. |
|
234 | # IPython's most typical usage patterns. | |
235 | _delims = DELIMS |
|
235 | _delims = DELIMS | |
236 |
|
236 | |||
237 | # The expression (a normal string) to be compiled into a regular expression |
|
237 | # The expression (a normal string) to be compiled into a regular expression | |
238 | # for actual splitting. We store it as an attribute mostly for ease of |
|
238 | # for actual splitting. We store it as an attribute mostly for ease of | |
239 | # debugging, since this type of code can be so tricky to debug. |
|
239 | # debugging, since this type of code can be so tricky to debug. | |
240 | _delim_expr = None |
|
240 | _delim_expr = None | |
241 |
|
241 | |||
242 | # The regular expression that does the actual splitting |
|
242 | # The regular expression that does the actual splitting | |
243 | _delim_re = None |
|
243 | _delim_re = None | |
244 |
|
244 | |||
245 | def __init__(self, delims=None): |
|
245 | def __init__(self, delims=None): | |
246 | delims = CompletionSplitter._delims if delims is None else delims |
|
246 | delims = CompletionSplitter._delims if delims is None else delims | |
247 | self.delims = delims |
|
247 | self.delims = delims | |
248 |
|
248 | |||
249 | @property |
|
249 | @property | |
250 | def delims(self): |
|
250 | def delims(self): | |
251 | """Return the string of delimiter characters.""" |
|
251 | """Return the string of delimiter characters.""" | |
252 | return self._delims |
|
252 | return self._delims | |
253 |
|
253 | |||
254 | @delims.setter |
|
254 | @delims.setter | |
255 | def delims(self, delims): |
|
255 | def delims(self, delims): | |
256 | """Set the delimiters for line splitting.""" |
|
256 | """Set the delimiters for line splitting.""" | |
257 | expr = '[' + ''.join('\\'+ c for c in delims) + ']' |
|
257 | expr = '[' + ''.join('\\'+ c for c in delims) + ']' | |
258 | self._delim_re = re.compile(expr) |
|
258 | self._delim_re = re.compile(expr) | |
259 | self._delims = delims |
|
259 | self._delims = delims | |
260 | self._delim_expr = expr |
|
260 | self._delim_expr = expr | |
261 |
|
261 | |||
262 | def split_line(self, line, cursor_pos=None): |
|
262 | def split_line(self, line, cursor_pos=None): | |
263 | """Split a line of text with a cursor at the given position. |
|
263 | """Split a line of text with a cursor at the given position. | |
264 | """ |
|
264 | """ | |
265 | l = line if cursor_pos is None else line[:cursor_pos] |
|
265 | l = line if cursor_pos is None else line[:cursor_pos] | |
266 | return self._delim_re.split(l)[-1] |
|
266 | return self._delim_re.split(l)[-1] | |
267 |
|
267 | |||
268 |
|
268 | |||
269 | class Completer(Configurable): |
|
269 | class Completer(Configurable): | |
270 |
|
270 | |||
271 | greedy = CBool(False, config=True, |
|
271 | greedy = CBool(False, config=True, | |
272 | help="""Activate greedy completion |
|
272 | help="""Activate greedy completion | |
273 |
|
273 | |||
274 | This will enable completion on elements of lists, results of function calls, etc., |
|
274 | This will enable completion on elements of lists, results of function calls, etc., | |
275 | but can be unsafe because the code is actually evaluated on TAB. |
|
275 | but can be unsafe because the code is actually evaluated on TAB. | |
276 | """ |
|
276 | """ | |
277 | ) |
|
277 | ) | |
278 |
|
278 | |||
279 |
|
279 | |||
280 | def __init__(self, namespace=None, global_namespace=None, **kwargs): |
|
280 | def __init__(self, namespace=None, global_namespace=None, **kwargs): | |
281 | """Create a new completer for the command line. |
|
281 | """Create a new completer for the command line. | |
282 |
|
282 | |||
283 | Completer(namespace=ns,global_namespace=ns2) -> completer instance. |
|
283 | Completer(namespace=ns,global_namespace=ns2) -> completer instance. | |
284 |
|
284 | |||
285 | If unspecified, the default namespace where completions are performed |
|
285 | If unspecified, the default namespace where completions are performed | |
286 | is __main__ (technically, __main__.__dict__). Namespaces should be |
|
286 | is __main__ (technically, __main__.__dict__). Namespaces should be | |
287 | given as dictionaries. |
|
287 | given as dictionaries. | |
288 |
|
288 | |||
289 | An optional second namespace can be given. This allows the completer |
|
289 | An optional second namespace can be given. This allows the completer | |
290 | to handle cases where both the local and global scopes need to be |
|
290 | to handle cases where both the local and global scopes need to be | |
291 | distinguished. |
|
291 | distinguished. | |
292 |
|
292 | |||
293 | Completer instances should be used as the completion mechanism of |
|
293 | Completer instances should be used as the completion mechanism of | |
294 | readline via the set_completer() call: |
|
294 | readline via the set_completer() call: | |
295 |
|
295 | |||
296 | readline.set_completer(Completer(my_namespace).complete) |
|
296 | readline.set_completer(Completer(my_namespace).complete) | |
297 | """ |
|
297 | """ | |
298 |
|
298 | |||
299 | # Don't bind to namespace quite yet, but flag whether the user wants a |
|
299 | # Don't bind to namespace quite yet, but flag whether the user wants a | |
300 | # specific namespace or to use __main__.__dict__. This will allow us |
|
300 | # specific namespace or to use __main__.__dict__. This will allow us | |
301 | # to bind to __main__.__dict__ at completion time, not now. |
|
301 | # to bind to __main__.__dict__ at completion time, not now. | |
302 | if namespace is None: |
|
302 | if namespace is None: | |
303 | self.use_main_ns = 1 |
|
303 | self.use_main_ns = 1 | |
304 | else: |
|
304 | else: | |
305 | self.use_main_ns = 0 |
|
305 | self.use_main_ns = 0 | |
306 | self.namespace = namespace |
|
306 | self.namespace = namespace | |
307 |
|
307 | |||
308 | # The global namespace, if given, can be bound directly |
|
308 | # The global namespace, if given, can be bound directly | |
309 | if global_namespace is None: |
|
309 | if global_namespace is None: | |
310 | self.global_namespace = {} |
|
310 | self.global_namespace = {} | |
311 | else: |
|
311 | else: | |
312 | self.global_namespace = global_namespace |
|
312 | self.global_namespace = global_namespace | |
313 |
|
313 | |||
314 | super(Completer, self).__init__(**kwargs) |
|
314 | super(Completer, self).__init__(**kwargs) | |
315 |
|
315 | |||
316 | def complete(self, text, state): |
|
316 | def complete(self, text, state): | |
317 | """Return the next possible completion for 'text'. |
|
317 | """Return the next possible completion for 'text'. | |
318 |
|
318 | |||
319 | This is called successively with state == 0, 1, 2, ... until it |
|
319 | This is called successively with state == 0, 1, 2, ... until it | |
320 | returns None. The completion should begin with 'text'. |
|
320 | returns None. The completion should begin with 'text'. | |
321 |
|
321 | |||
322 | """ |
|
322 | """ | |
323 | if self.use_main_ns: |
|
323 | if self.use_main_ns: | |
324 | self.namespace = __main__.__dict__ |
|
324 | self.namespace = __main__.__dict__ | |
325 |
|
325 | |||
326 | if state == 0: |
|
326 | if state == 0: | |
327 | if "." in text: |
|
327 | if "." in text: | |
328 | self.matches = self.attr_matches(text) |
|
328 | self.matches = self.attr_matches(text) | |
329 | else: |
|
329 | else: | |
330 | self.matches = self.global_matches(text) |
|
330 | self.matches = self.global_matches(text) | |
331 | try: |
|
331 | try: | |
332 | return self.matches[state] |
|
332 | return self.matches[state] | |
333 | except IndexError: |
|
333 | except IndexError: | |
334 | return None |
|
334 | return None | |
335 |
|
335 | |||
336 | def global_matches(self, text): |
|
336 | def global_matches(self, text): | |
337 | """Compute matches when text is a simple name. |
|
337 | """Compute matches when text is a simple name. | |
338 |
|
338 | |||
339 | Return a list of all keywords, built-in functions and names currently |
|
339 | Return a list of all keywords, built-in functions and names currently | |
340 | defined in self.namespace or self.global_namespace that match. |
|
340 | defined in self.namespace or self.global_namespace that match. | |
341 |
|
341 | |||
342 | """ |
|
342 | """ | |
343 | #print 'Completer->global_matches, txt=%r' % text # dbg |
|
343 | #print 'Completer->global_matches, txt=%r' % text # dbg | |
344 | matches = [] |
|
344 | matches = [] | |
345 | match_append = matches.append |
|
345 | match_append = matches.append | |
346 | n = len(text) |
|
346 | n = len(text) | |
347 | for lst in [keyword.kwlist, |
|
347 | for lst in [keyword.kwlist, | |
348 | builtin_mod.__dict__.keys(), |
|
348 | builtin_mod.__dict__.keys(), | |
349 | self.namespace.keys(), |
|
349 | self.namespace.keys(), | |
350 | self.global_namespace.keys()]: |
|
350 | self.global_namespace.keys()]: | |
351 | for word in lst: |
|
351 | for word in lst: | |
352 | if word[:n] == text and word != "__builtins__": |
|
352 | if word[:n] == text and word != "__builtins__": | |
353 | match_append(word) |
|
353 | match_append(word) | |
354 | return matches |
|
354 | return matches | |
355 |
|
355 | |||
356 | def attr_matches(self, text): |
|
356 | def attr_matches(self, text): | |
357 | """Compute matches when text contains a dot. |
|
357 | """Compute matches when text contains a dot. | |
358 |
|
358 | |||
359 | Assuming the text is of the form NAME.NAME....[NAME], and is |
|
359 | Assuming the text is of the form NAME.NAME....[NAME], and is | |
360 | evaluatable in self.namespace or self.global_namespace, it will be |
|
360 | evaluatable in self.namespace or self.global_namespace, it will be | |
361 | evaluated and its attributes (as revealed by dir()) are used as |
|
361 | evaluated and its attributes (as revealed by dir()) are used as | |
362 | possible completions. (For class instances, class members are are |
|
362 | possible completions. (For class instances, class members are are | |
363 | also considered.) |
|
363 | also considered.) | |
364 |
|
364 | |||
365 | WARNING: this can still invoke arbitrary C code, if an object |
|
365 | WARNING: this can still invoke arbitrary C code, if an object | |
366 | with a __getattr__ hook is evaluated. |
|
366 | with a __getattr__ hook is evaluated. | |
367 |
|
367 | |||
368 | """ |
|
368 | """ | |
369 |
|
369 | |||
370 | #io.rprint('Completer->attr_matches, txt=%r' % text) # dbg |
|
370 | #io.rprint('Completer->attr_matches, txt=%r' % text) # dbg | |
371 | # Another option, seems to work great. Catches things like ''.<tab> |
|
371 | # Another option, seems to work great. Catches things like ''.<tab> | |
372 | m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text) |
|
372 | m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text) | |
373 |
|
373 | |||
374 | if m: |
|
374 | if m: | |
375 | expr, attr = m.group(1, 3) |
|
375 | expr, attr = m.group(1, 3) | |
376 | elif self.greedy: |
|
376 | elif self.greedy: | |
377 | m2 = re.match(r"(.+)\.(\w*)$", self.line_buffer) |
|
377 | m2 = re.match(r"(.+)\.(\w*)$", self.line_buffer) | |
378 | if not m2: |
|
378 | if not m2: | |
379 | return [] |
|
379 | return [] | |
380 | expr, attr = m2.group(1,2) |
|
380 | expr, attr = m2.group(1,2) | |
381 | else: |
|
381 | else: | |
382 | return [] |
|
382 | return [] | |
383 |
|
383 | |||
384 | try: |
|
384 | try: | |
385 | obj = eval(expr, self.namespace) |
|
385 | obj = eval(expr, self.namespace) | |
386 | except: |
|
386 | except: | |
387 | try: |
|
387 | try: | |
388 | obj = eval(expr, self.global_namespace) |
|
388 | obj = eval(expr, self.global_namespace) | |
389 | except: |
|
389 | except: | |
390 | return [] |
|
390 | return [] | |
391 |
|
391 | |||
392 | if self.limit_to__all__ and hasattr(obj, '__all__'): |
|
392 | if self.limit_to__all__ and hasattr(obj, '__all__'): | |
393 | words = get__all__entries(obj) |
|
393 | words = get__all__entries(obj) | |
394 | else: |
|
394 | else: | |
395 | words = dir2(obj) |
|
395 | words = dir2(obj) | |
396 |
|
396 | |||
397 | try: |
|
397 | try: | |
398 | words = generics.complete_object(obj, words) |
|
398 | words = generics.complete_object(obj, words) | |
399 | except TryNext: |
|
399 | except TryNext: | |
400 | pass |
|
400 | pass | |
401 | except Exception: |
|
401 | except Exception: | |
402 | # Silence errors from completion function |
|
402 | # Silence errors from completion function | |
403 | #raise # dbg |
|
403 | #raise # dbg | |
404 | pass |
|
404 | pass | |
405 | # Build match list to return |
|
405 | # Build match list to return | |
406 | n = len(attr) |
|
406 | n = len(attr) | |
407 | res = ["%s.%s" % (expr, w) for w in words if w[:n] == attr ] |
|
407 | res = ["%s.%s" % (expr, w) for w in words if w[:n] == attr ] | |
408 | return res |
|
408 | return res | |
409 |
|
409 | |||
410 |
|
410 | |||
411 | def get__all__entries(obj): |
|
411 | def get__all__entries(obj): | |
412 | """returns the strings in the __all__ attribute""" |
|
412 | """returns the strings in the __all__ attribute""" | |
413 | try: |
|
413 | try: | |
414 | words = getattr(obj, '__all__') |
|
414 | words = getattr(obj, '__all__') | |
415 | except: |
|
415 | except: | |
416 | return [] |
|
416 | return [] | |
417 |
|
417 | |||
418 | return [w for w in words if isinstance(w, string_types)] |
|
418 | return [w for w in words if isinstance(w, string_types)] | |
419 |
|
419 | |||
420 |
|
420 | |||
421 | def match_dict_keys(keys, prefix, delims): |
|
421 | def match_dict_keys(keys, prefix, delims): | |
422 | """Used by dict_key_matches, matching the prefix to a list of keys""" |
|
422 | """Used by dict_key_matches, matching the prefix to a list of keys""" | |
423 | if not prefix: |
|
423 | if not prefix: | |
424 | return None, 0, [repr(k) for k in keys |
|
424 | return None, 0, [repr(k) for k in keys | |
425 | if isinstance(k, (string_types, bytes))] |
|
425 | if isinstance(k, (string_types, bytes))] | |
426 | quote_match = re.search('["\']', prefix) |
|
426 | quote_match = re.search('["\']', prefix) | |
427 | quote = quote_match.group() |
|
427 | quote = quote_match.group() | |
428 | try: |
|
428 | try: | |
429 | prefix_str = eval(prefix + quote, {}) |
|
429 | prefix_str = eval(prefix + quote, {}) | |
430 | except Exception: |
|
430 | except Exception: | |
431 | return None, 0, [] |
|
431 | return None, 0, [] | |
432 |
|
432 | |||
433 | pattern = '[^' + ''.join('\\' + c for c in delims) + ']*$' |
|
433 | pattern = '[^' + ''.join('\\' + c for c in delims) + ']*$' | |
434 | token_match = re.search(pattern, prefix, re.UNICODE) |
|
434 | token_match = re.search(pattern, prefix, re.UNICODE) | |
435 | token_start = token_match.start() |
|
435 | token_start = token_match.start() | |
436 | token_prefix = token_match.group() |
|
436 | token_prefix = token_match.group() | |
437 |
|
437 | |||
438 | # TODO: support bytes in Py3k |
|
438 | # TODO: support bytes in Py3k | |
439 | matched = [] |
|
439 | matched = [] | |
440 | for key in keys: |
|
440 | for key in keys: | |
441 | try: |
|
441 | try: | |
442 | if not key.startswith(prefix_str): |
|
442 | if not key.startswith(prefix_str): | |
443 | continue |
|
443 | continue | |
444 | except (AttributeError, TypeError, UnicodeError): |
|
444 | except (AttributeError, TypeError, UnicodeError): | |
445 | # Python 3+ TypeError on b'a'.startswith('a') or vice-versa |
|
445 | # Python 3+ TypeError on b'a'.startswith('a') or vice-versa | |
446 | continue |
|
446 | continue | |
447 |
|
447 | |||
448 | # reformat remainder of key to begin with prefix |
|
448 | # reformat remainder of key to begin with prefix | |
449 | rem = key[len(prefix_str):] |
|
449 | rem = key[len(prefix_str):] | |
450 | # force repr wrapped in ' |
|
450 | # force repr wrapped in ' | |
451 | rem_repr = repr(rem + '"') |
|
451 | rem_repr = repr(rem + '"') | |
452 | if rem_repr.startswith('u') and prefix[0] not in 'uU': |
|
452 | if rem_repr.startswith('u') and prefix[0] not in 'uU': | |
453 | # Found key is unicode, but prefix is Py2 string. |
|
453 | # Found key is unicode, but prefix is Py2 string. | |
454 | # Therefore attempt to interpret key as string. |
|
454 | # Therefore attempt to interpret key as string. | |
455 | try: |
|
455 | try: | |
456 | rem_repr = repr(rem.encode('ascii') + '"') |
|
456 | rem_repr = repr(rem.encode('ascii') + '"') | |
457 | except UnicodeEncodeError: |
|
457 | except UnicodeEncodeError: | |
458 | continue |
|
458 | continue | |
459 |
|
459 | |||
460 | rem_repr = rem_repr[1 + rem_repr.index("'"):-2] |
|
460 | rem_repr = rem_repr[1 + rem_repr.index("'"):-2] | |
461 | if quote == '"': |
|
461 | if quote == '"': | |
462 | # The entered prefix is quoted with ", |
|
462 | # The entered prefix is quoted with ", | |
463 | # but the match is quoted with '. |
|
463 | # but the match is quoted with '. | |
464 | # A contained " hence needs escaping for comparison: |
|
464 | # A contained " hence needs escaping for comparison: | |
465 | rem_repr = rem_repr.replace('"', '\\"') |
|
465 | rem_repr = rem_repr.replace('"', '\\"') | |
466 |
|
466 | |||
467 | # then reinsert prefix from start of token |
|
467 | # then reinsert prefix from start of token | |
468 | matched.append('%s%s' % (token_prefix, rem_repr)) |
|
468 | matched.append('%s%s' % (token_prefix, rem_repr)) | |
469 | return quote, token_start, matched |
|
469 | return quote, token_start, matched | |
470 |
|
470 | |||
471 |
|
471 | |||
472 | def _safe_isinstance(obj, module, class_name): |
|
472 | def _safe_isinstance(obj, module, class_name): | |
473 | """Checks if obj is an instance of module.class_name if loaded |
|
473 | """Checks if obj is an instance of module.class_name if loaded | |
474 | """ |
|
474 | """ | |
475 | return (module in sys.modules and |
|
475 | return (module in sys.modules and | |
476 | isinstance(obj, getattr(__import__(module), class_name))) |
|
476 | isinstance(obj, getattr(__import__(module), class_name))) | |
477 |
|
477 | |||
478 |
|
478 | |||
479 |
|
479 | |||
480 | def back_unicode_name_matches(text): |
|
480 | def back_unicode_name_matches(text): | |
481 | u"""Match unicode characters back to unicode name |
|
481 | u"""Match unicode characters back to unicode name | |
482 |
|
482 | |||
483 | This does β -> \\snowman |
|
483 | This does β -> \\snowman | |
484 |
|
484 | |||
485 | Note that snowman is not a valid python3 combining character but will be expanded. |
|
485 | Note that snowman is not a valid python3 combining character but will be expanded. | |
486 | Though it will not recombine back to the snowman character by the completion machinery. |
|
486 | Though it will not recombine back to the snowman character by the completion machinery. | |
487 |
|
487 | |||
488 | This will not either back-complete standard sequences like \n, \b ... |
|
488 | This will not either back-complete standard sequences like \\n, \\b ... | |
489 |
|
489 | |||
490 | Used on Python 3 only. |
|
490 | Used on Python 3 only. | |
491 | """ |
|
491 | """ | |
492 | if len(text)<2: |
|
492 | if len(text)<2: | |
493 | return u'', () |
|
493 | return u'', () | |
494 | maybe_slash = text[-2] |
|
494 | maybe_slash = text[-2] | |
495 | if maybe_slash != '\\': |
|
495 | if maybe_slash != '\\': | |
496 | return u'', () |
|
496 | return u'', () | |
497 |
|
497 | |||
498 | char = text[-1] |
|
498 | char = text[-1] | |
499 | # no expand on quote for completion in strings. |
|
499 | # no expand on quote for completion in strings. | |
500 | # nor backcomplete standard ascii keys |
|
500 | # nor backcomplete standard ascii keys | |
501 | if char in string.ascii_letters or char in ['"',"'"]: |
|
501 | if char in string.ascii_letters or char in ['"',"'"]: | |
502 | return u'', () |
|
502 | return u'', () | |
503 | try : |
|
503 | try : | |
504 | unic = unicodedata.name(char) |
|
504 | unic = unicodedata.name(char) | |
505 | return '\\'+char,['\\'+unic] |
|
505 | return '\\'+char,['\\'+unic] | |
506 | except KeyError as e: |
|
506 | except KeyError as e: | |
507 | pass |
|
507 | pass | |
508 | return u'', () |
|
508 | return u'', () | |
509 |
|
509 | |||
510 | def back_latex_name_matches(text): |
|
510 | def back_latex_name_matches(text): | |
511 | u"""Match latex characters back to unicode name |
|
511 | u"""Match latex characters back to unicode name | |
512 |
|
512 | |||
513 | This does ->\\sqrt |
|
513 | This does ->\\sqrt | |
514 |
|
514 | |||
515 | Used on Python 3 only. |
|
515 | Used on Python 3 only. | |
516 | """ |
|
516 | """ | |
517 | if len(text)<2: |
|
517 | if len(text)<2: | |
518 | return u'', () |
|
518 | return u'', () | |
519 | maybe_slash = text[-2] |
|
519 | maybe_slash = text[-2] | |
520 | if maybe_slash != '\\': |
|
520 | if maybe_slash != '\\': | |
521 | return u'', () |
|
521 | return u'', () | |
522 |
|
522 | |||
523 |
|
523 | |||
524 | char = text[-1] |
|
524 | char = text[-1] | |
525 | # no expand on quote for completion in strings. |
|
525 | # no expand on quote for completion in strings. | |
526 | # nor backcomplete standard ascii keys |
|
526 | # nor backcomplete standard ascii keys | |
527 | if char in string.ascii_letters or char in ['"',"'"]: |
|
527 | if char in string.ascii_letters or char in ['"',"'"]: | |
528 | return u'', () |
|
528 | return u'', () | |
529 | try : |
|
529 | try : | |
530 | latex = reverse_latex_symbol[char] |
|
530 | latex = reverse_latex_symbol[char] | |
531 | # '\\' replace the \ as well |
|
531 | # '\\' replace the \ as well | |
532 | return '\\'+char,[latex] |
|
532 | return '\\'+char,[latex] | |
533 | except KeyError as e: |
|
533 | except KeyError as e: | |
534 | pass |
|
534 | pass | |
535 | return u'', () |
|
535 | return u'', () | |
536 |
|
536 | |||
537 |
|
537 | |||
538 | class IPCompleter(Completer): |
|
538 | class IPCompleter(Completer): | |
539 | """Extension of the completer class with IPython-specific features""" |
|
539 | """Extension of the completer class with IPython-specific features""" | |
540 |
|
540 | |||
541 | def _greedy_changed(self, name, old, new): |
|
541 | def _greedy_changed(self, name, old, new): | |
542 | """update the splitter and readline delims when greedy is changed""" |
|
542 | """update the splitter and readline delims when greedy is changed""" | |
543 | if new: |
|
543 | if new: | |
544 | self.splitter.delims = GREEDY_DELIMS |
|
544 | self.splitter.delims = GREEDY_DELIMS | |
545 | else: |
|
545 | else: | |
546 | self.splitter.delims = DELIMS |
|
546 | self.splitter.delims = DELIMS | |
547 |
|
547 | |||
548 | if self.readline: |
|
548 | if self.readline: | |
549 | self.readline.set_completer_delims(self.splitter.delims) |
|
549 | self.readline.set_completer_delims(self.splitter.delims) | |
550 |
|
550 | |||
551 | merge_completions = CBool(True, config=True, |
|
551 | merge_completions = CBool(True, config=True, | |
552 | help="""Whether to merge completion results into a single list |
|
552 | help="""Whether to merge completion results into a single list | |
553 |
|
553 | |||
554 | If False, only the completion results from the first non-empty |
|
554 | If False, only the completion results from the first non-empty | |
555 | completer will be returned. |
|
555 | completer will be returned. | |
556 | """ |
|
556 | """ | |
557 | ) |
|
557 | ) | |
558 | omit__names = Enum((0,1,2), default_value=2, config=True, |
|
558 | omit__names = Enum((0,1,2), default_value=2, config=True, | |
559 | help="""Instruct the completer to omit private method names |
|
559 | help="""Instruct the completer to omit private method names | |
560 |
|
560 | |||
561 | Specifically, when completing on ``object.<tab>``. |
|
561 | Specifically, when completing on ``object.<tab>``. | |
562 |
|
562 | |||
563 | When 2 [default]: all names that start with '_' will be excluded. |
|
563 | When 2 [default]: all names that start with '_' will be excluded. | |
564 |
|
564 | |||
565 | When 1: all 'magic' names (``__foo__``) will be excluded. |
|
565 | When 1: all 'magic' names (``__foo__``) will be excluded. | |
566 |
|
566 | |||
567 | When 0: nothing will be excluded. |
|
567 | When 0: nothing will be excluded. | |
568 | """ |
|
568 | """ | |
569 | ) |
|
569 | ) | |
570 | limit_to__all__ = CBool(default_value=False, config=True, |
|
570 | limit_to__all__ = CBool(default_value=False, config=True, | |
571 | help="""Instruct the completer to use __all__ for the completion |
|
571 | help="""Instruct the completer to use __all__ for the completion | |
572 |
|
572 | |||
573 | Specifically, when completing on ``object.<tab>``. |
|
573 | Specifically, when completing on ``object.<tab>``. | |
574 |
|
574 | |||
575 | When True: only those names in obj.__all__ will be included. |
|
575 | When True: only those names in obj.__all__ will be included. | |
576 |
|
576 | |||
577 | When False [default]: the __all__ attribute is ignored |
|
577 | When False [default]: the __all__ attribute is ignored | |
578 | """ |
|
578 | """ | |
579 | ) |
|
579 | ) | |
580 |
|
580 | |||
581 | def __init__(self, shell=None, namespace=None, global_namespace=None, |
|
581 | def __init__(self, shell=None, namespace=None, global_namespace=None, | |
582 | use_readline=True, config=None, **kwargs): |
|
582 | use_readline=True, config=None, **kwargs): | |
583 | """IPCompleter() -> completer |
|
583 | """IPCompleter() -> completer | |
584 |
|
584 | |||
585 | Return a completer object suitable for use by the readline library |
|
585 | Return a completer object suitable for use by the readline library | |
586 | via readline.set_completer(). |
|
586 | via readline.set_completer(). | |
587 |
|
587 | |||
588 | Inputs: |
|
588 | Inputs: | |
589 |
|
589 | |||
590 | - shell: a pointer to the ipython shell itself. This is needed |
|
590 | - shell: a pointer to the ipython shell itself. This is needed | |
591 | because this completer knows about magic functions, and those can |
|
591 | because this completer knows about magic functions, and those can | |
592 | only be accessed via the ipython instance. |
|
592 | only be accessed via the ipython instance. | |
593 |
|
593 | |||
594 | - namespace: an optional dict where completions are performed. |
|
594 | - namespace: an optional dict where completions are performed. | |
595 |
|
595 | |||
596 | - global_namespace: secondary optional dict for completions, to |
|
596 | - global_namespace: secondary optional dict for completions, to | |
597 | handle cases (such as IPython embedded inside functions) where |
|
597 | handle cases (such as IPython embedded inside functions) where | |
598 | both Python scopes are visible. |
|
598 | both Python scopes are visible. | |
599 |
|
599 | |||
600 | use_readline : bool, optional |
|
600 | use_readline : bool, optional | |
601 | If true, use the readline library. This completer can still function |
|
601 | If true, use the readline library. This completer can still function | |
602 | without readline, though in that case callers must provide some extra |
|
602 | without readline, though in that case callers must provide some extra | |
603 | information on each call about the current line.""" |
|
603 | information on each call about the current line.""" | |
604 |
|
604 | |||
605 | self.magic_escape = ESC_MAGIC |
|
605 | self.magic_escape = ESC_MAGIC | |
606 | self.splitter = CompletionSplitter() |
|
606 | self.splitter = CompletionSplitter() | |
607 |
|
607 | |||
608 | # Readline configuration, only used by the rlcompleter method. |
|
608 | # Readline configuration, only used by the rlcompleter method. | |
609 | if use_readline: |
|
609 | if use_readline: | |
610 | # We store the right version of readline so that later code |
|
610 | # We store the right version of readline so that later code | |
611 | import IPython.utils.rlineimpl as readline |
|
611 | import IPython.utils.rlineimpl as readline | |
612 | self.readline = readline |
|
612 | self.readline = readline | |
613 | else: |
|
613 | else: | |
614 | self.readline = None |
|
614 | self.readline = None | |
615 |
|
615 | |||
616 | # _greedy_changed() depends on splitter and readline being defined: |
|
616 | # _greedy_changed() depends on splitter and readline being defined: | |
617 | Completer.__init__(self, namespace=namespace, global_namespace=global_namespace, |
|
617 | Completer.__init__(self, namespace=namespace, global_namespace=global_namespace, | |
618 | config=config, **kwargs) |
|
618 | config=config, **kwargs) | |
619 |
|
619 | |||
620 | # List where completion matches will be stored |
|
620 | # List where completion matches will be stored | |
621 | self.matches = [] |
|
621 | self.matches = [] | |
622 | self.shell = shell |
|
622 | self.shell = shell | |
623 | # Regexp to split filenames with spaces in them |
|
623 | # Regexp to split filenames with spaces in them | |
624 | self.space_name_re = re.compile(r'([^\\] )') |
|
624 | self.space_name_re = re.compile(r'([^\\] )') | |
625 | # Hold a local ref. to glob.glob for speed |
|
625 | # Hold a local ref. to glob.glob for speed | |
626 | self.glob = glob.glob |
|
626 | self.glob = glob.glob | |
627 |
|
627 | |||
628 | # Determine if we are running on 'dumb' terminals, like (X)Emacs |
|
628 | # Determine if we are running on 'dumb' terminals, like (X)Emacs | |
629 | # buffers, to avoid completion problems. |
|
629 | # buffers, to avoid completion problems. | |
630 | term = os.environ.get('TERM','xterm') |
|
630 | term = os.environ.get('TERM','xterm') | |
631 | self.dumb_terminal = term in ['dumb','emacs'] |
|
631 | self.dumb_terminal = term in ['dumb','emacs'] | |
632 |
|
632 | |||
633 | # Special handling of backslashes needed in win32 platforms |
|
633 | # Special handling of backslashes needed in win32 platforms | |
634 | if sys.platform == "win32": |
|
634 | if sys.platform == "win32": | |
635 | self.clean_glob = self._clean_glob_win32 |
|
635 | self.clean_glob = self._clean_glob_win32 | |
636 | else: |
|
636 | else: | |
637 | self.clean_glob = self._clean_glob |
|
637 | self.clean_glob = self._clean_glob | |
638 |
|
638 | |||
639 | #regexp to parse docstring for function signature |
|
639 | #regexp to parse docstring for function signature | |
640 | self.docstring_sig_re = re.compile(r'^[\w|\s.]+\(([^)]*)\).*') |
|
640 | self.docstring_sig_re = re.compile(r'^[\w|\s.]+\(([^)]*)\).*') | |
641 | self.docstring_kwd_re = re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)') |
|
641 | self.docstring_kwd_re = re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)') | |
642 | #use this if positional argument name is also needed |
|
642 | #use this if positional argument name is also needed | |
643 | #= re.compile(r'[\s|\[]*(\w+)(?:\s*=?\s*.*)') |
|
643 | #= re.compile(r'[\s|\[]*(\w+)(?:\s*=?\s*.*)') | |
644 |
|
644 | |||
645 | # All active matcher routines for completion |
|
645 | # All active matcher routines for completion | |
646 | self.matchers = [self.python_matches, |
|
646 | self.matchers = [self.python_matches, | |
647 | self.file_matches, |
|
647 | self.file_matches, | |
648 | self.magic_matches, |
|
648 | self.magic_matches, | |
649 | self.python_func_kw_matches, |
|
649 | self.python_func_kw_matches, | |
650 | self.dict_key_matches, |
|
650 | self.dict_key_matches, | |
651 | ] |
|
651 | ] | |
652 |
|
652 | |||
653 | def all_completions(self, text): |
|
653 | def all_completions(self, text): | |
654 | """ |
|
654 | """ | |
655 | Wrapper around the complete method for the benefit of emacs |
|
655 | Wrapper around the complete method for the benefit of emacs | |
656 | and pydb. |
|
656 | and pydb. | |
657 | """ |
|
657 | """ | |
658 | return self.complete(text)[1] |
|
658 | return self.complete(text)[1] | |
659 |
|
659 | |||
660 | def _clean_glob(self,text): |
|
660 | def _clean_glob(self,text): | |
661 | return self.glob("%s*" % text) |
|
661 | return self.glob("%s*" % text) | |
662 |
|
662 | |||
663 | def _clean_glob_win32(self,text): |
|
663 | def _clean_glob_win32(self,text): | |
664 | return [f.replace("\\","/") |
|
664 | return [f.replace("\\","/") | |
665 | for f in self.glob("%s*" % text)] |
|
665 | for f in self.glob("%s*" % text)] | |
666 |
|
666 | |||
667 | def file_matches(self, text): |
|
667 | def file_matches(self, text): | |
668 | """Match filenames, expanding ~USER type strings. |
|
668 | """Match filenames, expanding ~USER type strings. | |
669 |
|
669 | |||
670 | Most of the seemingly convoluted logic in this completer is an |
|
670 | Most of the seemingly convoluted logic in this completer is an | |
671 | attempt to handle filenames with spaces in them. And yet it's not |
|
671 | attempt to handle filenames with spaces in them. And yet it's not | |
672 | quite perfect, because Python's readline doesn't expose all of the |
|
672 | quite perfect, because Python's readline doesn't expose all of the | |
673 | GNU readline details needed for this to be done correctly. |
|
673 | GNU readline details needed for this to be done correctly. | |
674 |
|
674 | |||
675 | For a filename with a space in it, the printed completions will be |
|
675 | For a filename with a space in it, the printed completions will be | |
676 | only the parts after what's already been typed (instead of the |
|
676 | only the parts after what's already been typed (instead of the | |
677 | full completions, as is normally done). I don't think with the |
|
677 | full completions, as is normally done). I don't think with the | |
678 | current (as of Python 2.3) Python readline it's possible to do |
|
678 | current (as of Python 2.3) Python readline it's possible to do | |
679 | better.""" |
|
679 | better.""" | |
680 |
|
680 | |||
681 | #io.rprint('Completer->file_matches: <%r>' % text) # dbg |
|
681 | #io.rprint('Completer->file_matches: <%r>' % text) # dbg | |
682 |
|
682 | |||
683 | # chars that require escaping with backslash - i.e. chars |
|
683 | # chars that require escaping with backslash - i.e. chars | |
684 | # that readline treats incorrectly as delimiters, but we |
|
684 | # that readline treats incorrectly as delimiters, but we | |
685 | # don't want to treat as delimiters in filename matching |
|
685 | # don't want to treat as delimiters in filename matching | |
686 | # when escaped with backslash |
|
686 | # when escaped with backslash | |
687 | if text.startswith('!'): |
|
687 | if text.startswith('!'): | |
688 | text = text[1:] |
|
688 | text = text[1:] | |
689 | text_prefix = '!' |
|
689 | text_prefix = '!' | |
690 | else: |
|
690 | else: | |
691 | text_prefix = '' |
|
691 | text_prefix = '' | |
692 |
|
692 | |||
693 | text_until_cursor = self.text_until_cursor |
|
693 | text_until_cursor = self.text_until_cursor | |
694 | # track strings with open quotes |
|
694 | # track strings with open quotes | |
695 | open_quotes = has_open_quotes(text_until_cursor) |
|
695 | open_quotes = has_open_quotes(text_until_cursor) | |
696 |
|
696 | |||
697 | if '(' in text_until_cursor or '[' in text_until_cursor: |
|
697 | if '(' in text_until_cursor or '[' in text_until_cursor: | |
698 | lsplit = text |
|
698 | lsplit = text | |
699 | else: |
|
699 | else: | |
700 | try: |
|
700 | try: | |
701 | # arg_split ~ shlex.split, but with unicode bugs fixed by us |
|
701 | # arg_split ~ shlex.split, but with unicode bugs fixed by us | |
702 | lsplit = arg_split(text_until_cursor)[-1] |
|
702 | lsplit = arg_split(text_until_cursor)[-1] | |
703 | except ValueError: |
|
703 | except ValueError: | |
704 | # typically an unmatched ", or backslash without escaped char. |
|
704 | # typically an unmatched ", or backslash without escaped char. | |
705 | if open_quotes: |
|
705 | if open_quotes: | |
706 | lsplit = text_until_cursor.split(open_quotes)[-1] |
|
706 | lsplit = text_until_cursor.split(open_quotes)[-1] | |
707 | else: |
|
707 | else: | |
708 | return [] |
|
708 | return [] | |
709 | except IndexError: |
|
709 | except IndexError: | |
710 | # tab pressed on empty line |
|
710 | # tab pressed on empty line | |
711 | lsplit = "" |
|
711 | lsplit = "" | |
712 |
|
712 | |||
713 | if not open_quotes and lsplit != protect_filename(lsplit): |
|
713 | if not open_quotes and lsplit != protect_filename(lsplit): | |
714 | # if protectables are found, do matching on the whole escaped name |
|
714 | # if protectables are found, do matching on the whole escaped name | |
715 | has_protectables = True |
|
715 | has_protectables = True | |
716 | text0,text = text,lsplit |
|
716 | text0,text = text,lsplit | |
717 | else: |
|
717 | else: | |
718 | has_protectables = False |
|
718 | has_protectables = False | |
719 | text = os.path.expanduser(text) |
|
719 | text = os.path.expanduser(text) | |
720 |
|
720 | |||
721 | if text == "": |
|
721 | if text == "": | |
722 | return [text_prefix + protect_filename(f) for f in self.glob("*")] |
|
722 | return [text_prefix + protect_filename(f) for f in self.glob("*")] | |
723 |
|
723 | |||
724 | # Compute the matches from the filesystem |
|
724 | # Compute the matches from the filesystem | |
725 | m0 = self.clean_glob(text.replace('\\','')) |
|
725 | m0 = self.clean_glob(text.replace('\\','')) | |
726 |
|
726 | |||
727 | if has_protectables: |
|
727 | if has_protectables: | |
728 | # If we had protectables, we need to revert our changes to the |
|
728 | # If we had protectables, we need to revert our changes to the | |
729 | # beginning of filename so that we don't double-write the part |
|
729 | # beginning of filename so that we don't double-write the part | |
730 | # of the filename we have so far |
|
730 | # of the filename we have so far | |
731 | len_lsplit = len(lsplit) |
|
731 | len_lsplit = len(lsplit) | |
732 | matches = [text_prefix + text0 + |
|
732 | matches = [text_prefix + text0 + | |
733 | protect_filename(f[len_lsplit:]) for f in m0] |
|
733 | protect_filename(f[len_lsplit:]) for f in m0] | |
734 | else: |
|
734 | else: | |
735 | if open_quotes: |
|
735 | if open_quotes: | |
736 | # if we have a string with an open quote, we don't need to |
|
736 | # if we have a string with an open quote, we don't need to | |
737 | # protect the names at all (and we _shouldn't_, as it |
|
737 | # protect the names at all (and we _shouldn't_, as it | |
738 | # would cause bugs when the filesystem call is made). |
|
738 | # would cause bugs when the filesystem call is made). | |
739 | matches = m0 |
|
739 | matches = m0 | |
740 | else: |
|
740 | else: | |
741 | matches = [text_prefix + |
|
741 | matches = [text_prefix + | |
742 | protect_filename(f) for f in m0] |
|
742 | protect_filename(f) for f in m0] | |
743 |
|
743 | |||
744 | #io.rprint('mm', matches) # dbg |
|
744 | #io.rprint('mm', matches) # dbg | |
745 |
|
745 | |||
746 | # Mark directories in input list by appending '/' to their names. |
|
746 | # Mark directories in input list by appending '/' to their names. | |
747 | matches = [x+'/' if os.path.isdir(x) else x for x in matches] |
|
747 | matches = [x+'/' if os.path.isdir(x) else x for x in matches] | |
748 | return matches |
|
748 | return matches | |
749 |
|
749 | |||
750 | def magic_matches(self, text): |
|
750 | def magic_matches(self, text): | |
751 | """Match magics""" |
|
751 | """Match magics""" | |
752 | #print 'Completer->magic_matches:',text,'lb',self.text_until_cursor # dbg |
|
752 | #print 'Completer->magic_matches:',text,'lb',self.text_until_cursor # dbg | |
753 | # Get all shell magics now rather than statically, so magics loaded at |
|
753 | # Get all shell magics now rather than statically, so magics loaded at | |
754 | # runtime show up too. |
|
754 | # runtime show up too. | |
755 | lsm = self.shell.magics_manager.lsmagic() |
|
755 | lsm = self.shell.magics_manager.lsmagic() | |
756 | line_magics = lsm['line'] |
|
756 | line_magics = lsm['line'] | |
757 | cell_magics = lsm['cell'] |
|
757 | cell_magics = lsm['cell'] | |
758 | pre = self.magic_escape |
|
758 | pre = self.magic_escape | |
759 | pre2 = pre+pre |
|
759 | pre2 = pre+pre | |
760 |
|
760 | |||
761 | # Completion logic: |
|
761 | # Completion logic: | |
762 | # - user gives %%: only do cell magics |
|
762 | # - user gives %%: only do cell magics | |
763 | # - user gives %: do both line and cell magics |
|
763 | # - user gives %: do both line and cell magics | |
764 | # - no prefix: do both |
|
764 | # - no prefix: do both | |
765 | # In other words, line magics are skipped if the user gives %% explicitly |
|
765 | # In other words, line magics are skipped if the user gives %% explicitly | |
766 | bare_text = text.lstrip(pre) |
|
766 | bare_text = text.lstrip(pre) | |
767 | comp = [ pre2+m for m in cell_magics if m.startswith(bare_text)] |
|
767 | comp = [ pre2+m for m in cell_magics if m.startswith(bare_text)] | |
768 | if not text.startswith(pre2): |
|
768 | if not text.startswith(pre2): | |
769 | comp += [ pre+m for m in line_magics if m.startswith(bare_text)] |
|
769 | comp += [ pre+m for m in line_magics if m.startswith(bare_text)] | |
770 | return comp |
|
770 | return comp | |
771 |
|
771 | |||
772 | def python_matches(self,text): |
|
772 | def python_matches(self,text): | |
773 | """Match attributes or global python names""" |
|
773 | """Match attributes or global python names""" | |
774 |
|
774 | |||
775 | #io.rprint('Completer->python_matches, txt=%r' % text) # dbg |
|
775 | #io.rprint('Completer->python_matches, txt=%r' % text) # dbg | |
776 | if "." in text: |
|
776 | if "." in text: | |
777 | try: |
|
777 | try: | |
778 | matches = self.attr_matches(text) |
|
778 | matches = self.attr_matches(text) | |
779 | if text.endswith('.') and self.omit__names: |
|
779 | if text.endswith('.') and self.omit__names: | |
780 | if self.omit__names == 1: |
|
780 | if self.omit__names == 1: | |
781 | # true if txt is _not_ a __ name, false otherwise: |
|
781 | # true if txt is _not_ a __ name, false otherwise: | |
782 | no__name = (lambda txt: |
|
782 | no__name = (lambda txt: | |
783 | re.match(r'.*\.__.*?__',txt) is None) |
|
783 | re.match(r'.*\.__.*?__',txt) is None) | |
784 | else: |
|
784 | else: | |
785 | # true if txt is _not_ a _ name, false otherwise: |
|
785 | # true if txt is _not_ a _ name, false otherwise: | |
786 | no__name = (lambda txt: |
|
786 | no__name = (lambda txt: | |
787 | re.match(r'\._.*?',txt[txt.rindex('.'):]) is None) |
|
787 | re.match(r'\._.*?',txt[txt.rindex('.'):]) is None) | |
788 | matches = filter(no__name, matches) |
|
788 | matches = filter(no__name, matches) | |
789 | except NameError: |
|
789 | except NameError: | |
790 | # catches <undefined attributes>.<tab> |
|
790 | # catches <undefined attributes>.<tab> | |
791 | matches = [] |
|
791 | matches = [] | |
792 | else: |
|
792 | else: | |
793 | matches = self.global_matches(text) |
|
793 | matches = self.global_matches(text) | |
794 |
|
794 | |||
795 | return matches |
|
795 | return matches | |
796 |
|
796 | |||
797 | def _default_arguments_from_docstring(self, doc): |
|
797 | def _default_arguments_from_docstring(self, doc): | |
798 | """Parse the first line of docstring for call signature. |
|
798 | """Parse the first line of docstring for call signature. | |
799 |
|
799 | |||
800 | Docstring should be of the form 'min(iterable[, key=func])\n'. |
|
800 | Docstring should be of the form 'min(iterable[, key=func])\n'. | |
801 | It can also parse cython docstring of the form |
|
801 | It can also parse cython docstring of the form | |
802 | 'Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)'. |
|
802 | 'Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)'. | |
803 | """ |
|
803 | """ | |
804 | if doc is None: |
|
804 | if doc is None: | |
805 | return [] |
|
805 | return [] | |
806 |
|
806 | |||
807 | #care only the firstline |
|
807 | #care only the firstline | |
808 | line = doc.lstrip().splitlines()[0] |
|
808 | line = doc.lstrip().splitlines()[0] | |
809 |
|
809 | |||
810 | #p = re.compile(r'^[\w|\s.]+\(([^)]*)\).*') |
|
810 | #p = re.compile(r'^[\w|\s.]+\(([^)]*)\).*') | |
811 | #'min(iterable[, key=func])\n' -> 'iterable[, key=func]' |
|
811 | #'min(iterable[, key=func])\n' -> 'iterable[, key=func]' | |
812 | sig = self.docstring_sig_re.search(line) |
|
812 | sig = self.docstring_sig_re.search(line) | |
813 | if sig is None: |
|
813 | if sig is None: | |
814 | return [] |
|
814 | return [] | |
815 | # iterable[, key=func]' -> ['iterable[' ,' key=func]'] |
|
815 | # iterable[, key=func]' -> ['iterable[' ,' key=func]'] | |
816 | sig = sig.groups()[0].split(',') |
|
816 | sig = sig.groups()[0].split(',') | |
817 | ret = [] |
|
817 | ret = [] | |
818 | for s in sig: |
|
818 | for s in sig: | |
819 | #re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)') |
|
819 | #re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)') | |
820 | ret += self.docstring_kwd_re.findall(s) |
|
820 | ret += self.docstring_kwd_re.findall(s) | |
821 | return ret |
|
821 | return ret | |
822 |
|
822 | |||
823 | def _default_arguments(self, obj): |
|
823 | def _default_arguments(self, obj): | |
824 | """Return the list of default arguments of obj if it is callable, |
|
824 | """Return the list of default arguments of obj if it is callable, | |
825 | or empty list otherwise.""" |
|
825 | or empty list otherwise.""" | |
826 | call_obj = obj |
|
826 | call_obj = obj | |
827 | ret = [] |
|
827 | ret = [] | |
828 | if inspect.isbuiltin(obj): |
|
828 | if inspect.isbuiltin(obj): | |
829 | pass |
|
829 | pass | |
830 | elif not (inspect.isfunction(obj) or inspect.ismethod(obj)): |
|
830 | elif not (inspect.isfunction(obj) or inspect.ismethod(obj)): | |
831 | if inspect.isclass(obj): |
|
831 | if inspect.isclass(obj): | |
832 | #for cython embededsignature=True the constructor docstring |
|
832 | #for cython embededsignature=True the constructor docstring | |
833 | #belongs to the object itself not __init__ |
|
833 | #belongs to the object itself not __init__ | |
834 | ret += self._default_arguments_from_docstring( |
|
834 | ret += self._default_arguments_from_docstring( | |
835 | getattr(obj, '__doc__', '')) |
|
835 | getattr(obj, '__doc__', '')) | |
836 | # for classes, check for __init__,__new__ |
|
836 | # for classes, check for __init__,__new__ | |
837 | call_obj = (getattr(obj, '__init__', None) or |
|
837 | call_obj = (getattr(obj, '__init__', None) or | |
838 | getattr(obj, '__new__', None)) |
|
838 | getattr(obj, '__new__', None)) | |
839 | # for all others, check if they are __call__able |
|
839 | # for all others, check if they are __call__able | |
840 | elif hasattr(obj, '__call__'): |
|
840 | elif hasattr(obj, '__call__'): | |
841 | call_obj = obj.__call__ |
|
841 | call_obj = obj.__call__ | |
842 |
|
842 | |||
843 | ret += self._default_arguments_from_docstring( |
|
843 | ret += self._default_arguments_from_docstring( | |
844 | getattr(call_obj, '__doc__', '')) |
|
844 | getattr(call_obj, '__doc__', '')) | |
845 |
|
845 | |||
846 | try: |
|
846 | try: | |
847 | args,_,_1,defaults = inspect.getargspec(call_obj) |
|
847 | args,_,_1,defaults = inspect.getargspec(call_obj) | |
848 | if defaults: |
|
848 | if defaults: | |
849 | ret+=args[-len(defaults):] |
|
849 | ret+=args[-len(defaults):] | |
850 | except TypeError: |
|
850 | except TypeError: | |
851 | pass |
|
851 | pass | |
852 |
|
852 | |||
853 | return list(set(ret)) |
|
853 | return list(set(ret)) | |
854 |
|
854 | |||
855 | def python_func_kw_matches(self,text): |
|
855 | def python_func_kw_matches(self,text): | |
856 | """Match named parameters (kwargs) of the last open function""" |
|
856 | """Match named parameters (kwargs) of the last open function""" | |
857 |
|
857 | |||
858 | if "." in text: # a parameter cannot be dotted |
|
858 | if "." in text: # a parameter cannot be dotted | |
859 | return [] |
|
859 | return [] | |
860 | try: regexp = self.__funcParamsRegex |
|
860 | try: regexp = self.__funcParamsRegex | |
861 | except AttributeError: |
|
861 | except AttributeError: | |
862 | regexp = self.__funcParamsRegex = re.compile(r''' |
|
862 | regexp = self.__funcParamsRegex = re.compile(r''' | |
863 | '.*?(?<!\\)' | # single quoted strings or |
|
863 | '.*?(?<!\\)' | # single quoted strings or | |
864 | ".*?(?<!\\)" | # double quoted strings or |
|
864 | ".*?(?<!\\)" | # double quoted strings or | |
865 | \w+ | # identifier |
|
865 | \w+ | # identifier | |
866 | \S # other characters |
|
866 | \S # other characters | |
867 | ''', re.VERBOSE | re.DOTALL) |
|
867 | ''', re.VERBOSE | re.DOTALL) | |
868 | # 1. find the nearest identifier that comes before an unclosed |
|
868 | # 1. find the nearest identifier that comes before an unclosed | |
869 | # parenthesis before the cursor |
|
869 | # parenthesis before the cursor | |
870 | # e.g. for "foo (1+bar(x), pa<cursor>,a=1)", the candidate is "foo" |
|
870 | # e.g. for "foo (1+bar(x), pa<cursor>,a=1)", the candidate is "foo" | |
871 | tokens = regexp.findall(self.text_until_cursor) |
|
871 | tokens = regexp.findall(self.text_until_cursor) | |
872 | tokens.reverse() |
|
872 | tokens.reverse() | |
873 | iterTokens = iter(tokens); openPar = 0 |
|
873 | iterTokens = iter(tokens); openPar = 0 | |
874 |
|
874 | |||
875 | for token in iterTokens: |
|
875 | for token in iterTokens: | |
876 | if token == ')': |
|
876 | if token == ')': | |
877 | openPar -= 1 |
|
877 | openPar -= 1 | |
878 | elif token == '(': |
|
878 | elif token == '(': | |
879 | openPar += 1 |
|
879 | openPar += 1 | |
880 | if openPar > 0: |
|
880 | if openPar > 0: | |
881 | # found the last unclosed parenthesis |
|
881 | # found the last unclosed parenthesis | |
882 | break |
|
882 | break | |
883 | else: |
|
883 | else: | |
884 | return [] |
|
884 | return [] | |
885 | # 2. Concatenate dotted names ("foo.bar" for "foo.bar(x, pa" ) |
|
885 | # 2. Concatenate dotted names ("foo.bar" for "foo.bar(x, pa" ) | |
886 | ids = [] |
|
886 | ids = [] | |
887 | isId = re.compile(r'\w+$').match |
|
887 | isId = re.compile(r'\w+$').match | |
888 |
|
888 | |||
889 | while True: |
|
889 | while True: | |
890 | try: |
|
890 | try: | |
891 | ids.append(next(iterTokens)) |
|
891 | ids.append(next(iterTokens)) | |
892 | if not isId(ids[-1]): |
|
892 | if not isId(ids[-1]): | |
893 | ids.pop(); break |
|
893 | ids.pop(); break | |
894 | if not next(iterTokens) == '.': |
|
894 | if not next(iterTokens) == '.': | |
895 | break |
|
895 | break | |
896 | except StopIteration: |
|
896 | except StopIteration: | |
897 | break |
|
897 | break | |
898 | # lookup the candidate callable matches either using global_matches |
|
898 | # lookup the candidate callable matches either using global_matches | |
899 | # or attr_matches for dotted names |
|
899 | # or attr_matches for dotted names | |
900 | if len(ids) == 1: |
|
900 | if len(ids) == 1: | |
901 | callableMatches = self.global_matches(ids[0]) |
|
901 | callableMatches = self.global_matches(ids[0]) | |
902 | else: |
|
902 | else: | |
903 | callableMatches = self.attr_matches('.'.join(ids[::-1])) |
|
903 | callableMatches = self.attr_matches('.'.join(ids[::-1])) | |
904 | argMatches = [] |
|
904 | argMatches = [] | |
905 | for callableMatch in callableMatches: |
|
905 | for callableMatch in callableMatches: | |
906 | try: |
|
906 | try: | |
907 | namedArgs = self._default_arguments(eval(callableMatch, |
|
907 | namedArgs = self._default_arguments(eval(callableMatch, | |
908 | self.namespace)) |
|
908 | self.namespace)) | |
909 | except: |
|
909 | except: | |
910 | continue |
|
910 | continue | |
911 |
|
911 | |||
912 | for namedArg in namedArgs: |
|
912 | for namedArg in namedArgs: | |
913 | if namedArg.startswith(text): |
|
913 | if namedArg.startswith(text): | |
914 | argMatches.append("%s=" %namedArg) |
|
914 | argMatches.append("%s=" %namedArg) | |
915 | return argMatches |
|
915 | return argMatches | |
916 |
|
916 | |||
917 | def dict_key_matches(self, text): |
|
917 | def dict_key_matches(self, text): | |
918 | "Match string keys in a dictionary, after e.g. 'foo[' " |
|
918 | "Match string keys in a dictionary, after e.g. 'foo[' " | |
919 | def get_keys(obj): |
|
919 | def get_keys(obj): | |
920 | # Only allow completion for known in-memory dict-like types |
|
920 | # Only allow completion for known in-memory dict-like types | |
921 | if isinstance(obj, dict) or\ |
|
921 | if isinstance(obj, dict) or\ | |
922 | _safe_isinstance(obj, 'pandas', 'DataFrame'): |
|
922 | _safe_isinstance(obj, 'pandas', 'DataFrame'): | |
923 | try: |
|
923 | try: | |
924 | return list(obj.keys()) |
|
924 | return list(obj.keys()) | |
925 | except Exception: |
|
925 | except Exception: | |
926 | return [] |
|
926 | return [] | |
927 | elif _safe_isinstance(obj, 'numpy', 'ndarray') or\ |
|
927 | elif _safe_isinstance(obj, 'numpy', 'ndarray') or\ | |
928 | _safe_isinstance(obj, 'numpy', 'void'): |
|
928 | _safe_isinstance(obj, 'numpy', 'void'): | |
929 | return obj.dtype.names or [] |
|
929 | return obj.dtype.names or [] | |
930 | return [] |
|
930 | return [] | |
931 |
|
931 | |||
932 | try: |
|
932 | try: | |
933 | regexps = self.__dict_key_regexps |
|
933 | regexps = self.__dict_key_regexps | |
934 | except AttributeError: |
|
934 | except AttributeError: | |
935 | dict_key_re_fmt = r'''(?x) |
|
935 | dict_key_re_fmt = r'''(?x) | |
936 | ( # match dict-referring expression wrt greedy setting |
|
936 | ( # match dict-referring expression wrt greedy setting | |
937 | %s |
|
937 | %s | |
938 | ) |
|
938 | ) | |
939 | \[ # open bracket |
|
939 | \[ # open bracket | |
940 | \s* # and optional whitespace |
|
940 | \s* # and optional whitespace | |
941 | ([uUbB]? # string prefix (r not handled) |
|
941 | ([uUbB]? # string prefix (r not handled) | |
942 | (?: # unclosed string |
|
942 | (?: # unclosed string | |
943 | '(?:[^']|(?<!\\)\\')* |
|
943 | '(?:[^']|(?<!\\)\\')* | |
944 | | |
|
944 | | | |
945 | "(?:[^"]|(?<!\\)\\")* |
|
945 | "(?:[^"]|(?<!\\)\\")* | |
946 | ) |
|
946 | ) | |
947 | )? |
|
947 | )? | |
948 | $ |
|
948 | $ | |
949 | ''' |
|
949 | ''' | |
950 | regexps = self.__dict_key_regexps = { |
|
950 | regexps = self.__dict_key_regexps = { | |
951 | False: re.compile(dict_key_re_fmt % ''' |
|
951 | False: re.compile(dict_key_re_fmt % ''' | |
952 | # identifiers separated by . |
|
952 | # identifiers separated by . | |
953 | (?!\d)\w+ |
|
953 | (?!\d)\w+ | |
954 | (?:\.(?!\d)\w+)* |
|
954 | (?:\.(?!\d)\w+)* | |
955 | '''), |
|
955 | '''), | |
956 | True: re.compile(dict_key_re_fmt % ''' |
|
956 | True: re.compile(dict_key_re_fmt % ''' | |
957 | .+ |
|
957 | .+ | |
958 | ''') |
|
958 | ''') | |
959 | } |
|
959 | } | |
960 |
|
960 | |||
961 | match = regexps[self.greedy].search(self.text_until_cursor) |
|
961 | match = regexps[self.greedy].search(self.text_until_cursor) | |
962 | if match is None: |
|
962 | if match is None: | |
963 | return [] |
|
963 | return [] | |
964 |
|
964 | |||
965 | expr, prefix = match.groups() |
|
965 | expr, prefix = match.groups() | |
966 | try: |
|
966 | try: | |
967 | obj = eval(expr, self.namespace) |
|
967 | obj = eval(expr, self.namespace) | |
968 | except Exception: |
|
968 | except Exception: | |
969 | try: |
|
969 | try: | |
970 | obj = eval(expr, self.global_namespace) |
|
970 | obj = eval(expr, self.global_namespace) | |
971 | except Exception: |
|
971 | except Exception: | |
972 | return [] |
|
972 | return [] | |
973 |
|
973 | |||
974 | keys = get_keys(obj) |
|
974 | keys = get_keys(obj) | |
975 | if not keys: |
|
975 | if not keys: | |
976 | return keys |
|
976 | return keys | |
977 | closing_quote, token_offset, matches = match_dict_keys(keys, prefix, self.splitter.delims) |
|
977 | closing_quote, token_offset, matches = match_dict_keys(keys, prefix, self.splitter.delims) | |
978 | if not matches: |
|
978 | if not matches: | |
979 | return matches |
|
979 | return matches | |
980 |
|
980 | |||
981 | # get the cursor position of |
|
981 | # get the cursor position of | |
982 | # - the text being completed |
|
982 | # - the text being completed | |
983 | # - the start of the key text |
|
983 | # - the start of the key text | |
984 | # - the start of the completion |
|
984 | # - the start of the completion | |
985 | text_start = len(self.text_until_cursor) - len(text) |
|
985 | text_start = len(self.text_until_cursor) - len(text) | |
986 | if prefix: |
|
986 | if prefix: | |
987 | key_start = match.start(2) |
|
987 | key_start = match.start(2) | |
988 | completion_start = key_start + token_offset |
|
988 | completion_start = key_start + token_offset | |
989 | else: |
|
989 | else: | |
990 | key_start = completion_start = match.end() |
|
990 | key_start = completion_start = match.end() | |
991 |
|
991 | |||
992 | # grab the leading prefix, to make sure all completions start with `text` |
|
992 | # grab the leading prefix, to make sure all completions start with `text` | |
993 | if text_start > key_start: |
|
993 | if text_start > key_start: | |
994 | leading = '' |
|
994 | leading = '' | |
995 | else: |
|
995 | else: | |
996 | leading = text[text_start:completion_start] |
|
996 | leading = text[text_start:completion_start] | |
997 |
|
997 | |||
998 | # the index of the `[` character |
|
998 | # the index of the `[` character | |
999 | bracket_idx = match.end(1) |
|
999 | bracket_idx = match.end(1) | |
1000 |
|
1000 | |||
1001 | # append closing quote and bracket as appropriate |
|
1001 | # append closing quote and bracket as appropriate | |
1002 | # this is *not* appropriate if the opening quote or bracket is outside |
|
1002 | # this is *not* appropriate if the opening quote or bracket is outside | |
1003 | # the text given to this method |
|
1003 | # the text given to this method | |
1004 | suf = '' |
|
1004 | suf = '' | |
1005 | continuation = self.line_buffer[len(self.text_until_cursor):] |
|
1005 | continuation = self.line_buffer[len(self.text_until_cursor):] | |
1006 | if key_start > text_start and closing_quote: |
|
1006 | if key_start > text_start and closing_quote: | |
1007 | # quotes were opened inside text, maybe close them |
|
1007 | # quotes were opened inside text, maybe close them | |
1008 | if continuation.startswith(closing_quote): |
|
1008 | if continuation.startswith(closing_quote): | |
1009 | continuation = continuation[len(closing_quote):] |
|
1009 | continuation = continuation[len(closing_quote):] | |
1010 | else: |
|
1010 | else: | |
1011 | suf += closing_quote |
|
1011 | suf += closing_quote | |
1012 | if bracket_idx > text_start: |
|
1012 | if bracket_idx > text_start: | |
1013 | # brackets were opened inside text, maybe close them |
|
1013 | # brackets were opened inside text, maybe close them | |
1014 | if not continuation.startswith(']'): |
|
1014 | if not continuation.startswith(']'): | |
1015 | suf += ']' |
|
1015 | suf += ']' | |
1016 |
|
1016 | |||
1017 | return [leading + k + suf for k in matches] |
|
1017 | return [leading + k + suf for k in matches] | |
1018 |
|
1018 | |||
1019 | def unicode_name_matches(self, text): |
|
1019 | def unicode_name_matches(self, text): | |
1020 | u"""Match Latex-like syntax for unicode characters base |
|
1020 | u"""Match Latex-like syntax for unicode characters base | |
1021 | on the name of the character. |
|
1021 | on the name of the character. | |
1022 |
|
1022 | |||
1023 | This does \\GREEK SMALL LETTER ETA -> Ξ· |
|
1023 | This does \\GREEK SMALL LETTER ETA -> Ξ· | |
1024 |
|
1024 | |||
1025 | Works only on valid python 3 identifier, or on combining characters that |
|
1025 | Works only on valid python 3 identifier, or on combining characters that | |
1026 | will combine to form a valid identifier. |
|
1026 | will combine to form a valid identifier. | |
1027 |
|
1027 | |||
1028 | Used on Python 3 only. |
|
1028 | Used on Python 3 only. | |
1029 | """ |
|
1029 | """ | |
1030 | slashpos = text.rfind('\\') |
|
1030 | slashpos = text.rfind('\\') | |
1031 | if slashpos > -1: |
|
1031 | if slashpos > -1: | |
1032 | s = text[slashpos+1:] |
|
1032 | s = text[slashpos+1:] | |
1033 | try : |
|
1033 | try : | |
1034 | unic = unicodedata.lookup(s) |
|
1034 | unic = unicodedata.lookup(s) | |
1035 | # allow combining chars |
|
1035 | # allow combining chars | |
1036 | if ('a'+unic).isidentifier(): |
|
1036 | if ('a'+unic).isidentifier(): | |
1037 | return '\\'+s,[unic] |
|
1037 | return '\\'+s,[unic] | |
1038 | except KeyError as e: |
|
1038 | except KeyError as e: | |
1039 | pass |
|
1039 | pass | |
1040 | return u'', [] |
|
1040 | return u'', [] | |
1041 |
|
1041 | |||
1042 |
|
1042 | |||
1043 |
|
1043 | |||
1044 |
|
1044 | |||
1045 | def latex_matches(self, text): |
|
1045 | def latex_matches(self, text): | |
1046 | u"""Match Latex syntax for unicode characters. |
|
1046 | u"""Match Latex syntax for unicode characters. | |
1047 |
|
1047 | |||
1048 | This does both \\alp -> \\alpha and \\alpha -> Ξ± |
|
1048 | This does both \\alp -> \\alpha and \\alpha -> Ξ± | |
1049 |
|
1049 | |||
1050 | Used on Python 3 only. |
|
1050 | Used on Python 3 only. | |
1051 | """ |
|
1051 | """ | |
1052 | slashpos = text.rfind('\\') |
|
1052 | slashpos = text.rfind('\\') | |
1053 | if slashpos > -1: |
|
1053 | if slashpos > -1: | |
1054 | s = text[slashpos:] |
|
1054 | s = text[slashpos:] | |
1055 | if s in latex_symbols: |
|
1055 | if s in latex_symbols: | |
1056 | # Try to complete a full latex symbol to unicode |
|
1056 | # Try to complete a full latex symbol to unicode | |
1057 | # \\alpha -> Ξ± |
|
1057 | # \\alpha -> Ξ± | |
1058 | return s, [latex_symbols[s]] |
|
1058 | return s, [latex_symbols[s]] | |
1059 | else: |
|
1059 | else: | |
1060 | # If a user has partially typed a latex symbol, give them |
|
1060 | # If a user has partially typed a latex symbol, give them | |
1061 | # a full list of options \al -> [\aleph, \alpha] |
|
1061 | # a full list of options \al -> [\aleph, \alpha] | |
1062 | matches = [k for k in latex_symbols if k.startswith(s)] |
|
1062 | matches = [k for k in latex_symbols if k.startswith(s)] | |
1063 | return s, matches |
|
1063 | return s, matches | |
1064 | return u'', [] |
|
1064 | return u'', [] | |
1065 |
|
1065 | |||
1066 | def dispatch_custom_completer(self, text): |
|
1066 | def dispatch_custom_completer(self, text): | |
1067 | #io.rprint("Custom! '%s' %s" % (text, self.custom_completers)) # dbg |
|
1067 | #io.rprint("Custom! '%s' %s" % (text, self.custom_completers)) # dbg | |
1068 | line = self.line_buffer |
|
1068 | line = self.line_buffer | |
1069 | if not line.strip(): |
|
1069 | if not line.strip(): | |
1070 | return None |
|
1070 | return None | |
1071 |
|
1071 | |||
1072 | # Create a little structure to pass all the relevant information about |
|
1072 | # Create a little structure to pass all the relevant information about | |
1073 | # the current completion to any custom completer. |
|
1073 | # the current completion to any custom completer. | |
1074 | event = Bunch() |
|
1074 | event = Bunch() | |
1075 | event.line = line |
|
1075 | event.line = line | |
1076 | event.symbol = text |
|
1076 | event.symbol = text | |
1077 | cmd = line.split(None,1)[0] |
|
1077 | cmd = line.split(None,1)[0] | |
1078 | event.command = cmd |
|
1078 | event.command = cmd | |
1079 | event.text_until_cursor = self.text_until_cursor |
|
1079 | event.text_until_cursor = self.text_until_cursor | |
1080 |
|
1080 | |||
1081 | #print "\ncustom:{%s]\n" % event # dbg |
|
1081 | #print "\ncustom:{%s]\n" % event # dbg | |
1082 |
|
1082 | |||
1083 | # for foo etc, try also to find completer for %foo |
|
1083 | # for foo etc, try also to find completer for %foo | |
1084 | if not cmd.startswith(self.magic_escape): |
|
1084 | if not cmd.startswith(self.magic_escape): | |
1085 | try_magic = self.custom_completers.s_matches( |
|
1085 | try_magic = self.custom_completers.s_matches( | |
1086 | self.magic_escape + cmd) |
|
1086 | self.magic_escape + cmd) | |
1087 | else: |
|
1087 | else: | |
1088 | try_magic = [] |
|
1088 | try_magic = [] | |
1089 |
|
1089 | |||
1090 | for c in itertools.chain(self.custom_completers.s_matches(cmd), |
|
1090 | for c in itertools.chain(self.custom_completers.s_matches(cmd), | |
1091 | try_magic, |
|
1091 | try_magic, | |
1092 | self.custom_completers.flat_matches(self.text_until_cursor)): |
|
1092 | self.custom_completers.flat_matches(self.text_until_cursor)): | |
1093 | #print "try",c # dbg |
|
1093 | #print "try",c # dbg | |
1094 | try: |
|
1094 | try: | |
1095 | res = c(event) |
|
1095 | res = c(event) | |
1096 | if res: |
|
1096 | if res: | |
1097 | # first, try case sensitive match |
|
1097 | # first, try case sensitive match | |
1098 | withcase = [r for r in res if r.startswith(text)] |
|
1098 | withcase = [r for r in res if r.startswith(text)] | |
1099 | if withcase: |
|
1099 | if withcase: | |
1100 | return withcase |
|
1100 | return withcase | |
1101 | # if none, then case insensitive ones are ok too |
|
1101 | # if none, then case insensitive ones are ok too | |
1102 | text_low = text.lower() |
|
1102 | text_low = text.lower() | |
1103 | return [r for r in res if r.lower().startswith(text_low)] |
|
1103 | return [r for r in res if r.lower().startswith(text_low)] | |
1104 | except TryNext: |
|
1104 | except TryNext: | |
1105 | pass |
|
1105 | pass | |
1106 |
|
1106 | |||
1107 | return None |
|
1107 | return None | |
1108 |
|
1108 | |||
1109 | def complete(self, text=None, line_buffer=None, cursor_pos=None): |
|
1109 | def complete(self, text=None, line_buffer=None, cursor_pos=None): | |
1110 | """Find completions for the given text and line context. |
|
1110 | """Find completions for the given text and line context. | |
1111 |
|
1111 | |||
1112 | Note that both the text and the line_buffer are optional, but at least |
|
1112 | Note that both the text and the line_buffer are optional, but at least | |
1113 | one of them must be given. |
|
1113 | one of them must be given. | |
1114 |
|
1114 | |||
1115 | Parameters |
|
1115 | Parameters | |
1116 | ---------- |
|
1116 | ---------- | |
1117 | text : string, optional |
|
1117 | text : string, optional | |
1118 | Text to perform the completion on. If not given, the line buffer |
|
1118 | Text to perform the completion on. If not given, the line buffer | |
1119 | is split using the instance's CompletionSplitter object. |
|
1119 | is split using the instance's CompletionSplitter object. | |
1120 |
|
1120 | |||
1121 | line_buffer : string, optional |
|
1121 | line_buffer : string, optional | |
1122 | If not given, the completer attempts to obtain the current line |
|
1122 | If not given, the completer attempts to obtain the current line | |
1123 | buffer via readline. This keyword allows clients which are |
|
1123 | buffer via readline. This keyword allows clients which are | |
1124 | requesting for text completions in non-readline contexts to inform |
|
1124 | requesting for text completions in non-readline contexts to inform | |
1125 | the completer of the entire text. |
|
1125 | the completer of the entire text. | |
1126 |
|
1126 | |||
1127 | cursor_pos : int, optional |
|
1127 | cursor_pos : int, optional | |
1128 | Index of the cursor in the full line buffer. Should be provided by |
|
1128 | Index of the cursor in the full line buffer. Should be provided by | |
1129 | remote frontends where kernel has no access to frontend state. |
|
1129 | remote frontends where kernel has no access to frontend state. | |
1130 |
|
1130 | |||
1131 | Returns |
|
1131 | Returns | |
1132 | ------- |
|
1132 | ------- | |
1133 | text : str |
|
1133 | text : str | |
1134 | Text that was actually used in the completion. |
|
1134 | Text that was actually used in the completion. | |
1135 |
|
1135 | |||
1136 | matches : list |
|
1136 | matches : list | |
1137 | A list of completion matches. |
|
1137 | A list of completion matches. | |
1138 | """ |
|
1138 | """ | |
1139 | # io.rprint('\nCOMP1 %r %r %r' % (text, line_buffer, cursor_pos)) # dbg |
|
1139 | # io.rprint('\nCOMP1 %r %r %r' % (text, line_buffer, cursor_pos)) # dbg | |
1140 |
|
1140 | |||
1141 | # if the cursor position isn't given, the only sane assumption we can |
|
1141 | # if the cursor position isn't given, the only sane assumption we can | |
1142 | # make is that it's at the end of the line (the common case) |
|
1142 | # make is that it's at the end of the line (the common case) | |
1143 | if cursor_pos is None: |
|
1143 | if cursor_pos is None: | |
1144 | cursor_pos = len(line_buffer) if text is None else len(text) |
|
1144 | cursor_pos = len(line_buffer) if text is None else len(text) | |
1145 |
|
1145 | |||
1146 | if PY3: |
|
1146 | if PY3: | |
1147 |
|
1147 | |||
1148 | base_text = text if not line_buffer else line_buffer[:cursor_pos] |
|
1148 | base_text = text if not line_buffer else line_buffer[:cursor_pos] | |
1149 | latex_text, latex_matches = self.latex_matches(base_text) |
|
1149 | latex_text, latex_matches = self.latex_matches(base_text) | |
1150 | if latex_matches: |
|
1150 | if latex_matches: | |
1151 | return latex_text, latex_matches |
|
1151 | return latex_text, latex_matches | |
1152 | name_text = '' |
|
1152 | name_text = '' | |
1153 | name_matches = [] |
|
1153 | name_matches = [] | |
1154 | for meth in (self.unicode_name_matches, back_latex_name_matches, back_unicode_name_matches): |
|
1154 | for meth in (self.unicode_name_matches, back_latex_name_matches, back_unicode_name_matches): | |
1155 | name_text, name_matches = meth(base_text) |
|
1155 | name_text, name_matches = meth(base_text) | |
1156 | if name_text: |
|
1156 | if name_text: | |
1157 | return name_text, name_matches |
|
1157 | return name_text, name_matches | |
1158 |
|
1158 | |||
1159 | # if text is either None or an empty string, rely on the line buffer |
|
1159 | # if text is either None or an empty string, rely on the line buffer | |
1160 | if not text: |
|
1160 | if not text: | |
1161 | text = self.splitter.split_line(line_buffer, cursor_pos) |
|
1161 | text = self.splitter.split_line(line_buffer, cursor_pos) | |
1162 |
|
1162 | |||
1163 | # If no line buffer is given, assume the input text is all there was |
|
1163 | # If no line buffer is given, assume the input text is all there was | |
1164 | if line_buffer is None: |
|
1164 | if line_buffer is None: | |
1165 | line_buffer = text |
|
1165 | line_buffer = text | |
1166 |
|
1166 | |||
1167 | self.line_buffer = line_buffer |
|
1167 | self.line_buffer = line_buffer | |
1168 | self.text_until_cursor = self.line_buffer[:cursor_pos] |
|
1168 | self.text_until_cursor = self.line_buffer[:cursor_pos] | |
1169 | # io.rprint('COMP2 %r %r %r' % (text, line_buffer, cursor_pos)) # dbg |
|
1169 | # io.rprint('COMP2 %r %r %r' % (text, line_buffer, cursor_pos)) # dbg | |
1170 |
|
1170 | |||
1171 | # Start with a clean slate of completions |
|
1171 | # Start with a clean slate of completions | |
1172 | self.matches[:] = [] |
|
1172 | self.matches[:] = [] | |
1173 | custom_res = self.dispatch_custom_completer(text) |
|
1173 | custom_res = self.dispatch_custom_completer(text) | |
1174 | if custom_res is not None: |
|
1174 | if custom_res is not None: | |
1175 | # did custom completers produce something? |
|
1175 | # did custom completers produce something? | |
1176 | self.matches = custom_res |
|
1176 | self.matches = custom_res | |
1177 | else: |
|
1177 | else: | |
1178 | # Extend the list of completions with the results of each |
|
1178 | # Extend the list of completions with the results of each | |
1179 | # matcher, so we return results to the user from all |
|
1179 | # matcher, so we return results to the user from all | |
1180 | # namespaces. |
|
1180 | # namespaces. | |
1181 | if self.merge_completions: |
|
1181 | if self.merge_completions: | |
1182 | self.matches = [] |
|
1182 | self.matches = [] | |
1183 | for matcher in self.matchers: |
|
1183 | for matcher in self.matchers: | |
1184 | try: |
|
1184 | try: | |
1185 | self.matches.extend(matcher(text)) |
|
1185 | self.matches.extend(matcher(text)) | |
1186 | except: |
|
1186 | except: | |
1187 | # Show the ugly traceback if the matcher causes an |
|
1187 | # Show the ugly traceback if the matcher causes an | |
1188 | # exception, but do NOT crash the kernel! |
|
1188 | # exception, but do NOT crash the kernel! | |
1189 | sys.excepthook(*sys.exc_info()) |
|
1189 | sys.excepthook(*sys.exc_info()) | |
1190 | else: |
|
1190 | else: | |
1191 | for matcher in self.matchers: |
|
1191 | for matcher in self.matchers: | |
1192 | self.matches = matcher(text) |
|
1192 | self.matches = matcher(text) | |
1193 | if self.matches: |
|
1193 | if self.matches: | |
1194 | break |
|
1194 | break | |
1195 | # FIXME: we should extend our api to return a dict with completions for |
|
1195 | # FIXME: we should extend our api to return a dict with completions for | |
1196 | # different types of objects. The rlcomplete() method could then |
|
1196 | # different types of objects. The rlcomplete() method could then | |
1197 | # simply collapse the dict into a list for readline, but we'd have |
|
1197 | # simply collapse the dict into a list for readline, but we'd have | |
1198 | # richer completion semantics in other evironments. |
|
1198 | # richer completion semantics in other evironments. | |
1199 |
|
1199 | |||
1200 | # use penalize_magics_key to put magics after variables with same name |
|
1200 | # use penalize_magics_key to put magics after variables with same name | |
1201 | self.matches = sorted(set(self.matches), key=penalize_magics_key) |
|
1201 | self.matches = sorted(set(self.matches), key=penalize_magics_key) | |
1202 |
|
1202 | |||
1203 | #io.rprint('COMP TEXT, MATCHES: %r, %r' % (text, self.matches)) # dbg |
|
1203 | #io.rprint('COMP TEXT, MATCHES: %r, %r' % (text, self.matches)) # dbg | |
1204 | return text, self.matches |
|
1204 | return text, self.matches | |
1205 |
|
1205 | |||
1206 | def rlcomplete(self, text, state): |
|
1206 | def rlcomplete(self, text, state): | |
1207 | """Return the state-th possible completion for 'text'. |
|
1207 | """Return the state-th possible completion for 'text'. | |
1208 |
|
1208 | |||
1209 | This is called successively with state == 0, 1, 2, ... until it |
|
1209 | This is called successively with state == 0, 1, 2, ... until it | |
1210 | returns None. The completion should begin with 'text'. |
|
1210 | returns None. The completion should begin with 'text'. | |
1211 |
|
1211 | |||
1212 | Parameters |
|
1212 | Parameters | |
1213 | ---------- |
|
1213 | ---------- | |
1214 | text : string |
|
1214 | text : string | |
1215 | Text to perform the completion on. |
|
1215 | Text to perform the completion on. | |
1216 |
|
1216 | |||
1217 | state : int |
|
1217 | state : int | |
1218 | Counter used by readline. |
|
1218 | Counter used by readline. | |
1219 | """ |
|
1219 | """ | |
1220 | if state==0: |
|
1220 | if state==0: | |
1221 |
|
1221 | |||
1222 | self.line_buffer = line_buffer = self.readline.get_line_buffer() |
|
1222 | self.line_buffer = line_buffer = self.readline.get_line_buffer() | |
1223 | cursor_pos = self.readline.get_endidx() |
|
1223 | cursor_pos = self.readline.get_endidx() | |
1224 |
|
1224 | |||
1225 | #io.rprint("\nRLCOMPLETE: %r %r %r" % |
|
1225 | #io.rprint("\nRLCOMPLETE: %r %r %r" % | |
1226 | # (text, line_buffer, cursor_pos) ) # dbg |
|
1226 | # (text, line_buffer, cursor_pos) ) # dbg | |
1227 |
|
1227 | |||
1228 | # if there is only a tab on a line with only whitespace, instead of |
|
1228 | # if there is only a tab on a line with only whitespace, instead of | |
1229 | # the mostly useless 'do you want to see all million completions' |
|
1229 | # the mostly useless 'do you want to see all million completions' | |
1230 | # message, just do the right thing and give the user his tab! |
|
1230 | # message, just do the right thing and give the user his tab! | |
1231 | # Incidentally, this enables pasting of tabbed text from an editor |
|
1231 | # Incidentally, this enables pasting of tabbed text from an editor | |
1232 | # (as long as autoindent is off). |
|
1232 | # (as long as autoindent is off). | |
1233 |
|
1233 | |||
1234 | # It should be noted that at least pyreadline still shows file |
|
1234 | # It should be noted that at least pyreadline still shows file | |
1235 | # completions - is there a way around it? |
|
1235 | # completions - is there a way around it? | |
1236 |
|
1236 | |||
1237 | # don't apply this on 'dumb' terminals, such as emacs buffers, so |
|
1237 | # don't apply this on 'dumb' terminals, such as emacs buffers, so | |
1238 | # we don't interfere with their own tab-completion mechanism. |
|
1238 | # we don't interfere with their own tab-completion mechanism. | |
1239 | if not (self.dumb_terminal or line_buffer.strip()): |
|
1239 | if not (self.dumb_terminal or line_buffer.strip()): | |
1240 | self.readline.insert_text('\t') |
|
1240 | self.readline.insert_text('\t') | |
1241 | sys.stdout.flush() |
|
1241 | sys.stdout.flush() | |
1242 | return None |
|
1242 | return None | |
1243 |
|
1243 | |||
1244 | # Note: debugging exceptions that may occur in completion is very |
|
1244 | # Note: debugging exceptions that may occur in completion is very | |
1245 | # tricky, because readline unconditionally silences them. So if |
|
1245 | # tricky, because readline unconditionally silences them. So if | |
1246 | # during development you suspect a bug in the completion code, turn |
|
1246 | # during development you suspect a bug in the completion code, turn | |
1247 | # this flag on temporarily by uncommenting the second form (don't |
|
1247 | # this flag on temporarily by uncommenting the second form (don't | |
1248 | # flip the value in the first line, as the '# dbg' marker can be |
|
1248 | # flip the value in the first line, as the '# dbg' marker can be | |
1249 | # automatically detected and is used elsewhere). |
|
1249 | # automatically detected and is used elsewhere). | |
1250 | DEBUG = False |
|
1250 | DEBUG = False | |
1251 | #DEBUG = True # dbg |
|
1251 | #DEBUG = True # dbg | |
1252 | if DEBUG: |
|
1252 | if DEBUG: | |
1253 | try: |
|
1253 | try: | |
1254 | self.complete(text, line_buffer, cursor_pos) |
|
1254 | self.complete(text, line_buffer, cursor_pos) | |
1255 | except: |
|
1255 | except: | |
1256 | import traceback; traceback.print_exc() |
|
1256 | import traceback; traceback.print_exc() | |
1257 | else: |
|
1257 | else: | |
1258 | # The normal production version is here |
|
1258 | # The normal production version is here | |
1259 |
|
1259 | |||
1260 | # This method computes the self.matches array |
|
1260 | # This method computes the self.matches array | |
1261 | self.complete(text, line_buffer, cursor_pos) |
|
1261 | self.complete(text, line_buffer, cursor_pos) | |
1262 |
|
1262 | |||
1263 | try: |
|
1263 | try: | |
1264 | return self.matches[state] |
|
1264 | return self.matches[state] | |
1265 | except IndexError: |
|
1265 | except IndexError: | |
1266 | return None |
|
1266 | return None | |
1267 |
|
1267 |
@@ -1,167 +1,167 b'' | |||||
1 | """Implementation of magic functions for matplotlib/pylab support. |
|
1 | """Implementation of magic functions for matplotlib/pylab support. | |
2 | """ |
|
2 | """ | |
3 | from __future__ import print_function |
|
3 | from __future__ import print_function | |
4 | #----------------------------------------------------------------------------- |
|
4 | #----------------------------------------------------------------------------- | |
5 | # Copyright (c) 2012 The IPython Development Team. |
|
5 | # Copyright (c) 2012 The IPython Development Team. | |
6 | # |
|
6 | # | |
7 | # Distributed under the terms of the Modified BSD License. |
|
7 | # Distributed under the terms of the Modified BSD License. | |
8 | # |
|
8 | # | |
9 | # The full license is in the file COPYING.txt, distributed with this software. |
|
9 | # The full license is in the file COPYING.txt, distributed with this software. | |
10 | #----------------------------------------------------------------------------- |
|
10 | #----------------------------------------------------------------------------- | |
11 |
|
11 | |||
12 | #----------------------------------------------------------------------------- |
|
12 | #----------------------------------------------------------------------------- | |
13 | # Imports |
|
13 | # Imports | |
14 | #----------------------------------------------------------------------------- |
|
14 | #----------------------------------------------------------------------------- | |
15 |
|
15 | |||
16 | # Our own packages |
|
16 | # Our own packages | |
17 | from traitlets.config.application import Application |
|
17 | from traitlets.config.application import Application | |
18 | from IPython.core import magic_arguments |
|
18 | from IPython.core import magic_arguments | |
19 | from IPython.core.magic import Magics, magics_class, line_magic |
|
19 | from IPython.core.magic import Magics, magics_class, line_magic | |
20 | from IPython.testing.skipdoctest import skip_doctest |
|
20 | from IPython.testing.skipdoctest import skip_doctest | |
21 | from IPython.utils.warn import warn |
|
21 | from IPython.utils.warn import warn | |
22 | from IPython.core.pylabtools import backends |
|
22 | from IPython.core.pylabtools import backends | |
23 |
|
23 | |||
24 | #----------------------------------------------------------------------------- |
|
24 | #----------------------------------------------------------------------------- | |
25 | # Magic implementation classes |
|
25 | # Magic implementation classes | |
26 | #----------------------------------------------------------------------------- |
|
26 | #----------------------------------------------------------------------------- | |
27 |
|
27 | |||
28 | magic_gui_arg = magic_arguments.argument( |
|
28 | magic_gui_arg = magic_arguments.argument( | |
29 | 'gui', nargs='?', |
|
29 | 'gui', nargs='?', | |
30 | help="""Name of the matplotlib backend to use %s. |
|
30 | help="""Name of the matplotlib backend to use %s. | |
31 | If given, the corresponding matplotlib backend is used, |
|
31 | If given, the corresponding matplotlib backend is used, | |
32 | otherwise it will be matplotlib's default |
|
32 | otherwise it will be matplotlib's default | |
33 | (which you can set in your matplotlib config file). |
|
33 | (which you can set in your matplotlib config file). | |
34 | """ % str(tuple(sorted(backends.keys()))) |
|
34 | """ % str(tuple(sorted(backends.keys()))) | |
35 | ) |
|
35 | ) | |
36 |
|
36 | |||
37 |
|
37 | |||
38 | @magics_class |
|
38 | @magics_class | |
39 | class PylabMagics(Magics): |
|
39 | class PylabMagics(Magics): | |
40 | """Magics related to matplotlib's pylab support""" |
|
40 | """Magics related to matplotlib's pylab support""" | |
41 |
|
41 | |||
42 | @skip_doctest |
|
42 | @skip_doctest | |
43 | @line_magic |
|
43 | @line_magic | |
44 | @magic_arguments.magic_arguments() |
|
44 | @magic_arguments.magic_arguments() | |
45 | @magic_arguments.argument('-l', '--list', action='store_true', |
|
45 | @magic_arguments.argument('-l', '--list', action='store_true', | |
46 | help='Show available matplotlib backends') |
|
46 | help='Show available matplotlib backends') | |
47 | @magic_gui_arg |
|
47 | @magic_gui_arg | |
48 | def matplotlib(self, line=''): |
|
48 | def matplotlib(self, line=''): | |
49 | """Set up matplotlib to work interactively. |
|
49 | """Set up matplotlib to work interactively. | |
50 |
|
50 | |||
51 | This function lets you activate matplotlib interactive support |
|
51 | This function lets you activate matplotlib interactive support | |
52 | at any point during an IPython session. It does not import anything |
|
52 | at any point during an IPython session. It does not import anything | |
53 | into the interactive namespace. |
|
53 | into the interactive namespace. | |
54 |
|
54 | |||
55 | If you are using the inline matplotlib backend in the IPython Notebook |
|
55 | If you are using the inline matplotlib backend in the IPython Notebook | |
56 | you can set which figure formats are enabled using the following:: |
|
56 | you can set which figure formats are enabled using the following:: | |
57 |
|
57 | |||
58 | In [1]: from IPython.display import set_matplotlib_formats |
|
58 | In [1]: from IPython.display import set_matplotlib_formats | |
59 |
|
59 | |||
60 | In [2]: set_matplotlib_formats('pdf', 'svg') |
|
60 | In [2]: set_matplotlib_formats('pdf', 'svg') | |
61 |
|
61 | |||
62 | The default for inline figures sets `bbox_inches` to 'tight'. This can |
|
62 | The default for inline figures sets `bbox_inches` to 'tight'. This can | |
63 | cause discrepancies between the displayed image and the identical |
|
63 | cause discrepancies between the displayed image and the identical | |
64 | image created using `savefig`. This behavior can be disabled using the |
|
64 | image created using `savefig`. This behavior can be disabled using the | |
65 | `%config` magic:: |
|
65 | `%config` magic:: | |
66 |
|
66 | |||
67 | In [3]: %config InlineBackend.print_figure_kwargs = {'bbox_inches':None} |
|
67 | In [3]: %config InlineBackend.print_figure_kwargs = {'bbox_inches':None} | |
68 |
|
68 | |||
69 | In addition, see the docstring of |
|
69 | In addition, see the docstring of | |
70 | `IPython.display.set_matplotlib_formats` and |
|
70 | `IPython.display.set_matplotlib_formats` and | |
71 | `IPython.display.set_matplotlib_close` for more information on |
|
71 | `IPython.display.set_matplotlib_close` for more information on | |
72 | changing additional behaviors of the inline backend. |
|
72 | changing additional behaviors of the inline backend. | |
73 |
|
73 | |||
74 | Examples |
|
74 | Examples | |
75 | -------- |
|
75 | -------- | |
76 | To enable the inline backend for usage with the IPython Notebook:: |
|
76 | To enable the inline backend for usage with the IPython Notebook:: | |
77 |
|
77 | |||
78 | In [1]: %matplotlib inline |
|
78 | In [1]: %matplotlib inline | |
79 |
|
79 | |||
80 | In this case, where the matplotlib default is TkAgg:: |
|
80 | In this case, where the matplotlib default is TkAgg:: | |
81 |
|
81 | |||
82 | In [2]: %matplotlib |
|
82 | In [2]: %matplotlib | |
83 | Using matplotlib backend: TkAgg |
|
83 | Using matplotlib backend: TkAgg | |
84 |
|
84 | |||
85 | But you can explicitly request a different GUI backend:: |
|
85 | But you can explicitly request a different GUI backend:: | |
86 |
|
86 | |||
87 | In [3]: %matplotlib qt |
|
87 | In [3]: %matplotlib qt | |
88 |
|
88 | |||
89 | You can list the available backends using the -l/--list option |
|
89 | You can list the available backends using the -l/--list option:: | |
90 |
|
90 | |||
91 | In [4]: %matplotlib --list |
|
91 | In [4]: %matplotlib --list | |
92 | Available matplotlib backends: ['osx', 'qt4', 'qt5', 'gtk3', 'notebook', 'wx', 'qt', 'nbagg', |
|
92 | Available matplotlib backends: ['osx', 'qt4', 'qt5', 'gtk3', 'notebook', 'wx', 'qt', 'nbagg', | |
93 |
|
|
93 | 'gtk', 'tk', 'inline'] | |
94 | """ |
|
94 | """ | |
95 | args = magic_arguments.parse_argstring(self.matplotlib, line) |
|
95 | args = magic_arguments.parse_argstring(self.matplotlib, line) | |
96 | if args.list: |
|
96 | if args.list: | |
97 | backends_list = list(backends.keys()) |
|
97 | backends_list = list(backends.keys()) | |
98 | print("Available matplotlib backends: %s" % backends_list) |
|
98 | print("Available matplotlib backends: %s" % backends_list) | |
99 | else: |
|
99 | else: | |
100 | gui, backend = self.shell.enable_matplotlib(args.gui) |
|
100 | gui, backend = self.shell.enable_matplotlib(args.gui) | |
101 | self._show_matplotlib_backend(args.gui, backend) |
|
101 | self._show_matplotlib_backend(args.gui, backend) | |
102 |
|
102 | |||
103 | @skip_doctest |
|
103 | @skip_doctest | |
104 | @line_magic |
|
104 | @line_magic | |
105 | @magic_arguments.magic_arguments() |
|
105 | @magic_arguments.magic_arguments() | |
106 | @magic_arguments.argument( |
|
106 | @magic_arguments.argument( | |
107 | '--no-import-all', action='store_true', default=None, |
|
107 | '--no-import-all', action='store_true', default=None, | |
108 | help="""Prevent IPython from performing ``import *`` into the interactive namespace. |
|
108 | help="""Prevent IPython from performing ``import *`` into the interactive namespace. | |
109 |
|
109 | |||
110 | You can govern the default behavior of this flag with the |
|
110 | You can govern the default behavior of this flag with the | |
111 | InteractiveShellApp.pylab_import_all configurable. |
|
111 | InteractiveShellApp.pylab_import_all configurable. | |
112 | """ |
|
112 | """ | |
113 | ) |
|
113 | ) | |
114 | @magic_gui_arg |
|
114 | @magic_gui_arg | |
115 | def pylab(self, line=''): |
|
115 | def pylab(self, line=''): | |
116 | """Load numpy and matplotlib to work interactively. |
|
116 | """Load numpy and matplotlib to work interactively. | |
117 |
|
117 | |||
118 | This function lets you activate pylab (matplotlib, numpy and |
|
118 | This function lets you activate pylab (matplotlib, numpy and | |
119 | interactive support) at any point during an IPython session. |
|
119 | interactive support) at any point during an IPython session. | |
120 |
|
120 | |||
121 | %pylab makes the following imports:: |
|
121 | %pylab makes the following imports:: | |
122 |
|
122 | |||
123 | import numpy |
|
123 | import numpy | |
124 | import matplotlib |
|
124 | import matplotlib | |
125 | from matplotlib import pylab, mlab, pyplot |
|
125 | from matplotlib import pylab, mlab, pyplot | |
126 | np = numpy |
|
126 | np = numpy | |
127 | plt = pyplot |
|
127 | plt = pyplot | |
128 |
|
128 | |||
129 | from IPython.display import display |
|
129 | from IPython.display import display | |
130 | from IPython.core.pylabtools import figsize, getfigs |
|
130 | from IPython.core.pylabtools import figsize, getfigs | |
131 |
|
131 | |||
132 | from pylab import * |
|
132 | from pylab import * | |
133 | from numpy import * |
|
133 | from numpy import * | |
134 |
|
134 | |||
135 | If you pass `--no-import-all`, the last two `*` imports will be excluded. |
|
135 | If you pass `--no-import-all`, the last two `*` imports will be excluded. | |
136 |
|
136 | |||
137 | See the %matplotlib magic for more details about activating matplotlib |
|
137 | See the %matplotlib magic for more details about activating matplotlib | |
138 | without affecting the interactive namespace. |
|
138 | without affecting the interactive namespace. | |
139 | """ |
|
139 | """ | |
140 | args = magic_arguments.parse_argstring(self.pylab, line) |
|
140 | args = magic_arguments.parse_argstring(self.pylab, line) | |
141 | if args.no_import_all is None: |
|
141 | if args.no_import_all is None: | |
142 | # get default from Application |
|
142 | # get default from Application | |
143 | if Application.initialized(): |
|
143 | if Application.initialized(): | |
144 | app = Application.instance() |
|
144 | app = Application.instance() | |
145 | try: |
|
145 | try: | |
146 | import_all = app.pylab_import_all |
|
146 | import_all = app.pylab_import_all | |
147 | except AttributeError: |
|
147 | except AttributeError: | |
148 | import_all = True |
|
148 | import_all = True | |
149 | else: |
|
149 | else: | |
150 | # nothing specified, no app - default True |
|
150 | # nothing specified, no app - default True | |
151 | import_all = True |
|
151 | import_all = True | |
152 | else: |
|
152 | else: | |
153 | # invert no-import flag |
|
153 | # invert no-import flag | |
154 | import_all = not args.no_import_all |
|
154 | import_all = not args.no_import_all | |
155 |
|
155 | |||
156 | gui, backend, clobbered = self.shell.enable_pylab(args.gui, import_all=import_all) |
|
156 | gui, backend, clobbered = self.shell.enable_pylab(args.gui, import_all=import_all) | |
157 | self._show_matplotlib_backend(args.gui, backend) |
|
157 | self._show_matplotlib_backend(args.gui, backend) | |
158 | print ("Populating the interactive namespace from numpy and matplotlib") |
|
158 | print ("Populating the interactive namespace from numpy and matplotlib") | |
159 | if clobbered: |
|
159 | if clobbered: | |
160 | warn("pylab import has clobbered these variables: %s" % clobbered + |
|
160 | warn("pylab import has clobbered these variables: %s" % clobbered + | |
161 | "\n`%matplotlib` prevents importing * from pylab and numpy" |
|
161 | "\n`%matplotlib` prevents importing * from pylab and numpy" | |
162 | ) |
|
162 | ) | |
163 |
|
163 | |||
164 | def _show_matplotlib_backend(self, gui, backend): |
|
164 | def _show_matplotlib_backend(self, gui, backend): | |
165 | """show matplotlib message backend message""" |
|
165 | """show matplotlib message backend message""" | |
166 | if not gui or gui == 'auto': |
|
166 | if not gui or gui == 'auto': | |
167 | print("Using matplotlib backend: %s" % backend) |
|
167 | print("Using matplotlib backend: %s" % backend) |
@@ -1,203 +1,205 b'' | |||||
1 | .. _tutorial: |
|
1 | .. _tutorial: | |
2 |
|
2 | |||
3 | ====================== |
|
3 | ====================== | |
4 | Introducing IPython |
|
4 | Introducing IPython | |
5 | ====================== |
|
5 | ====================== | |
6 |
|
6 | |||
7 | You don't need to know anything beyond Python to start using IPython β just type |
|
7 | You don't need to know anything beyond Python to start using IPython β just type | |
8 | commands as you would at the standard Python prompt. But IPython can do much |
|
8 | commands as you would at the standard Python prompt. But IPython can do much | |
9 | more than the standard prompt. Some key features are described here. For more |
|
9 | more than the standard prompt. Some key features are described here. For more | |
10 | information, check the :ref:`tips page <tips>`, or look at examples in the |
|
10 | information, check the :ref:`tips page <tips>`, or look at examples in the | |
11 | `IPython cookbook <https://github.com/ipython/ipython/wiki/Cookbook%3A-Index>`_. |
|
11 | `IPython cookbook <https://github.com/ipython/ipython/wiki/Cookbook%3A-Index>`_. | |
12 |
|
12 | |||
13 | If you've never used Python before, you might want to look at `the official |
|
13 | If you've never used Python before, you might want to look at `the official | |
14 | tutorial <http://docs.python.org/tutorial/>`_ or an alternative, `Dive into |
|
14 | tutorial <http://docs.python.org/tutorial/>`_ or an alternative, `Dive into | |
15 | Python <http://diveintopython.net/toc/index.html>`_. |
|
15 | Python <http://diveintopython.net/toc/index.html>`_. | |
16 |
|
16 | |||
17 | The four most helpful commands |
|
17 | The four most helpful commands | |
18 | =============================== |
|
18 | =============================== | |
19 |
|
19 | |||
20 | The four most helpful commands, as well as their brief description, is shown |
|
20 | The four most helpful commands, as well as their brief description, is shown | |
21 | to you in a banner, every time you start IPython: |
|
21 | to you in a banner, every time you start IPython: | |
22 |
|
22 | |||
23 | ========== ========================================================= |
|
23 | ========== ========================================================= | |
24 | command description |
|
24 | command description | |
25 | ========== ========================================================= |
|
25 | ========== ========================================================= | |
26 | ? Introduction and overview of IPython's features. |
|
26 | ? Introduction and overview of IPython's features. | |
27 | %quickref Quick reference. |
|
27 | %quickref Quick reference. | |
28 | help Python's own help system. |
|
28 | help Python's own help system. | |
29 | object? Details about 'object', use 'object??' for extra details. |
|
29 | object? Details about 'object', use 'object??' for extra details. | |
30 | ========== ========================================================= |
|
30 | ========== ========================================================= | |
31 |
|
31 | |||
32 | Tab completion |
|
32 | Tab completion | |
33 | ============== |
|
33 | ============== | |
34 |
|
34 | |||
35 | Tab completion, especially for attributes, is a convenient way to explore the |
|
35 | Tab completion, especially for attributes, is a convenient way to explore the | |
36 | structure of any object you're dealing with. Simply type ``object_name.<TAB>`` |
|
36 | structure of any object you're dealing with. Simply type ``object_name.<TAB>`` | |
37 | to view the object's attributes (see :ref:`the readline section <readline>` for |
|
37 | to view the object's attributes (see :ref:`the readline section <readline>` for | |
38 | more). Besides Python objects and keywords, tab completion also works on file |
|
38 | more). Besides Python objects and keywords, tab completion also works on file | |
39 | and directory names. |
|
39 | and directory names. | |
40 |
|
40 | |||
41 | Exploring your objects |
|
41 | Exploring your objects | |
42 | ====================== |
|
42 | ====================== | |
43 |
|
43 | |||
44 | Typing ``object_name?`` will print all sorts of details about any object, |
|
44 | Typing ``object_name?`` will print all sorts of details about any object, | |
45 | including docstrings, function definition lines (for call arguments) and |
|
45 | including docstrings, function definition lines (for call arguments) and | |
46 | constructor details for classes. To get specific information on an object, you |
|
46 | constructor details for classes. To get specific information on an object, you | |
47 | can use the magic commands ``%pdoc``, ``%pdef``, ``%psource`` and ``%pfile`` |
|
47 | can use the magic commands ``%pdoc``, ``%pdef``, ``%psource`` and ``%pfile`` | |
48 |
|
48 | |||
49 | .. _magics_explained: |
|
49 | .. _magics_explained: | |
50 |
|
50 | |||
51 | Magic functions |
|
51 | Magic functions | |
52 | =============== |
|
52 | =============== | |
53 |
|
53 | |||
54 | IPython has a set of predefined 'magic functions' that you can call with a |
|
54 | IPython has a set of predefined 'magic functions' that you can call with a | |
55 | command line style syntax. There are two kinds of magics, line-oriented and |
|
55 | command line style syntax. There are two kinds of magics, line-oriented and | |
56 | cell-oriented. **Line magics** are prefixed with the ``%`` character and work much |
|
56 | cell-oriented. **Line magics** are prefixed with the ``%`` character and work much | |
57 | like OS command-line calls: they get as an argument the rest of the line, where |
|
57 | like OS command-line calls: they get as an argument the rest of the line, where | |
58 | arguments are passed without parentheses or quotes. **Cell magics** are |
|
58 | arguments are passed without parentheses or quotes. **Cell magics** are | |
59 | prefixed with a double ``%%``, and they are functions that get as an argument |
|
59 | prefixed with a double ``%%``, and they are functions that get as an argument | |
60 | not only the rest of the line, but also the lines below it in a separate |
|
60 | not only the rest of the line, but also the lines below it in a separate | |
61 | argument. |
|
61 | argument. | |
62 |
|
62 | |||
63 | The following examples show how to call the builtin :magic:`timeit` magic, both in |
|
63 | The following examples show how to call the builtin :magic:`timeit` magic, both in | |
64 | line and cell mode:: |
|
64 | line and cell mode:: | |
65 |
|
65 | |||
66 | In [1]: %timeit range(1000) |
|
66 | In [1]: %timeit range(1000) | |
67 | 100000 loops, best of 3: 7.76 us per loop |
|
67 | 100000 loops, best of 3: 7.76 us per loop | |
68 |
|
68 | |||
69 | In [2]: %%timeit x = range(10000) |
|
69 | In [2]: %%timeit x = range(10000) | |
70 | ...: max(x) |
|
70 | ...: max(x) | |
71 | ...: |
|
71 | ...: | |
72 | 1000 loops, best of 3: 223 us per loop |
|
72 | 1000 loops, best of 3: 223 us per loop | |
73 |
|
73 | |||
74 | The builtin magics include: |
|
74 | The builtin magics include: | |
75 |
|
75 | |||
76 | - Functions that work with code: :magic:`run`, :magic:`edit`, :magic:`save`, :magic:`macro`, |
|
76 | - Functions that work with code: :magic:`run`, :magic:`edit`, :magic:`save`, :magic:`macro`, | |
77 | :magic:`recall`, etc. |
|
77 | :magic:`recall`, etc. | |
78 | - Functions which affect the shell: :magic:`colors`, :magic:`xmode`, :magic:`autoindent`, |
|
78 | - Functions which affect the shell: :magic:`colors`, :magic:`xmode`, :magic:`autoindent`, | |
79 | :magic:`automagic`, etc. |
|
79 | :magic:`automagic`, etc. | |
80 | - Other functions such as :magic:`reset`, :magic:`timeit`, :cellmagic:`writefile`, :magic:`load`, or |
|
80 | - Other functions such as :magic:`reset`, :magic:`timeit`, :cellmagic:`writefile`, :magic:`load`, or | |
81 | :magic:`paste`. |
|
81 | :magic:`paste`. | |
82 |
|
82 | |||
83 | You can always call them using the ``%`` prefix, and if you're calling a line |
|
83 | You can always call them using the ``%`` prefix, and if you're calling a line | |
84 | magic on a line by itself, you can omit even that:: |
|
84 | magic on a line by itself, you can omit even that:: | |
85 |
|
85 | |||
86 | run thescript.py |
|
86 | run thescript.py | |
87 |
|
87 | |||
88 | You can toggle this behavior by running the :magic:`automagic` magic. Cell magics |
|
88 | You can toggle this behavior by running the :magic:`automagic` magic. Cell magics | |
89 | must always have the ``%%`` prefix. |
|
89 | must always have the ``%%`` prefix. | |
90 |
|
90 | |||
91 | A more detailed explanation of the magic system can be obtained by calling |
|
91 | A more detailed explanation of the magic system can be obtained by calling | |
92 | ``%magic``, and for more details on any magic function, call ``%somemagic?`` to |
|
92 | ``%magic``, and for more details on any magic function, call ``%somemagic?`` to | |
93 | read its docstring. To see all the available magic functions, call |
|
93 | read its docstring. To see all the available magic functions, call | |
94 | ``%lsmagic``. |
|
94 | ``%lsmagic``. | |
95 |
|
95 | |||
96 | .. seealso:: |
|
96 | .. seealso:: | |
97 |
|
97 | |||
98 | :doc:`magics` |
|
98 | :doc:`magics` | |
99 |
|
99 | |||
100 | `Cell magics`_ example notebook |
|
100 | `Cell magics`_ example notebook | |
101 |
|
101 | |||
102 | Running and Editing |
|
102 | Running and Editing | |
103 | ------------------- |
|
103 | ------------------- | |
104 |
|
104 | |||
105 | The :magic:`run` magic command allows you to run any python script and load all of |
|
105 | The :magic:`run` magic command allows you to run any python script and load all of | |
106 | its data directly into the interactive namespace. Since the file is re-read |
|
106 | its data directly into the interactive namespace. Since the file is re-read | |
107 | from disk each time, changes you make to it are reflected immediately (unlike |
|
107 | from disk each time, changes you make to it are reflected immediately (unlike | |
108 | imported modules, which have to be specifically reloaded). IPython also |
|
108 | imported modules, which have to be specifically reloaded). IPython also | |
109 | includes :ref:`dreload <dreload>`, a recursive reload function. |
|
109 | includes :ref:`dreload <dreload>`, a recursive reload function. | |
110 |
|
110 | |||
111 | ``%run`` has special flags for timing the execution of your scripts (-t), or |
|
111 | ``%run`` has special flags for timing the execution of your scripts (-t), or | |
112 | for running them under the control of either Python's pdb debugger (-d) or |
|
112 | for running them under the control of either Python's pdb debugger (-d) or | |
113 | profiler (-p). |
|
113 | profiler (-p). | |
114 |
|
114 | |||
115 | The :magic:`edit` command gives a reasonable approximation of multiline editing, |
|
115 | The :magic:`edit` command gives a reasonable approximation of multiline editing, | |
116 | by invoking your favorite editor on the spot. IPython will execute the |
|
116 | by invoking your favorite editor on the spot. IPython will execute the | |
117 | code you type in there as if it were typed interactively. |
|
117 | code you type in there as if it were typed interactively. | |
118 |
|
118 | |||
119 | Debugging |
|
119 | Debugging | |
120 | --------- |
|
120 | --------- | |
121 |
|
121 | |||
122 | After an exception occurs, you can call :magic:`debug` to jump into the Python |
|
122 | After an exception occurs, you can call :magic:`debug` to jump into the Python | |
123 | debugger (pdb) and examine the problem. Alternatively, if you call :magic:`pdb`, |
|
123 | debugger (pdb) and examine the problem. Alternatively, if you call :magic:`pdb`, | |
124 | IPython will automatically start the debugger on any uncaught exception. You can |
|
124 | IPython will automatically start the debugger on any uncaught exception. You can | |
125 | print variables, see code, execute statements and even walk up and down the |
|
125 | print variables, see code, execute statements and even walk up and down the | |
126 | call stack to track down the true source of the problem. This can be an efficient |
|
126 | call stack to track down the true source of the problem. This can be an efficient | |
127 | way to develop and debug code, in many cases eliminating the need for print |
|
127 | way to develop and debug code, in many cases eliminating the need for print | |
128 | statements or external debugging tools. |
|
128 | statements or external debugging tools. | |
129 |
|
129 | |||
130 | You can also step through a program from the beginning by calling |
|
130 | You can also step through a program from the beginning by calling | |
131 | ``%run -d theprogram.py``. |
|
131 | ``%run -d theprogram.py``. | |
132 |
|
132 | |||
133 | History |
|
133 | History | |
134 | ======= |
|
134 | ======= | |
135 |
|
135 | |||
136 | IPython stores both the commands you enter, and the results it produces. You |
|
136 | IPython stores both the commands you enter, and the results it produces. You | |
137 | can easily go through previous commands with the up- and down-arrow keys, or |
|
137 | can easily go through previous commands with the up- and down-arrow keys, or | |
138 | access your history in more sophisticated ways. |
|
138 | access your history in more sophisticated ways. | |
139 |
|
139 | |||
140 | Input and output history are kept in variables called ``In`` and ``Out``, keyed |
|
140 | Input and output history are kept in variables called ``In`` and ``Out``, keyed | |
141 | by the prompt numbers, e.g. ``In[4]``. The last three objects in output history |
|
141 | by the prompt numbers, e.g. ``In[4]``. The last three objects in output history | |
142 | are also kept in variables named ``_``, ``__`` and ``___``. |
|
142 | are also kept in variables named ``_``, ``__`` and ``___``. | |
143 |
|
143 | |||
144 | You can use the ``%history`` magic function to examine past input and output. |
|
144 | You can use the ``%history`` magic function to examine past input and output. | |
145 | Input history from previous sessions is saved in a database, and IPython can be |
|
145 | Input history from previous sessions is saved in a database, and IPython can be | |
146 | configured to save output history. |
|
146 | configured to save output history. | |
147 |
|
147 | |||
148 | Several other magic functions can use your input history, including ``%edit``, |
|
148 | Several other magic functions can use your input history, including ``%edit``, | |
149 | ``%rerun``, ``%recall``, ``%macro``, ``%save`` and ``%pastebin``. You can use a |
|
149 | ``%rerun``, ``%recall``, ``%macro``, ``%save`` and ``%pastebin``. You can use a | |
150 | standard format to refer to lines:: |
|
150 | standard format to refer to lines:: | |
151 |
|
151 | |||
152 | %pastebin 3 18-20 ~1/1-5 |
|
152 | %pastebin 3 18-20 ~1/1-5 | |
153 |
|
153 | |||
154 | This will take line 3 and lines 18 to 20 from the current session, and lines |
|
154 | This will take line 3 and lines 18 to 20 from the current session, and lines | |
155 | 1-5 from the previous session. |
|
155 | 1-5 from the previous session. | |
156 |
|
156 | |||
157 | System shell commands |
|
157 | System shell commands | |
158 | ===================== |
|
158 | ===================== | |
159 |
|
159 | |||
160 | To run any command at the system shell, simply prefix it with !, e.g.:: |
|
160 | To run any command at the system shell, simply prefix it with !, e.g.:: | |
161 |
|
161 | |||
162 | !ping www.bbc.co.uk |
|
162 | !ping www.bbc.co.uk | |
163 |
|
163 | |||
164 | You can capture the output into a Python list, e.g.: ``files = !ls``. To pass |
|
164 | You can capture the output into a Python list, e.g.: ``files = !ls``. To pass | |
165 | the values of Python variables or expressions to system commands, prefix them |
|
165 | the values of Python variables or expressions to system commands, prefix them | |
166 | with $: ``!grep -rF $pattern ipython/*``. See :ref:`our shell section |
|
166 | with $: ``!grep -rF $pattern ipython/*``. See :ref:`our shell section | |
167 | <system_shell_access>` for more details. |
|
167 | <system_shell_access>` for more details. | |
168 |
|
168 | |||
169 | Define your own system aliases |
|
169 | Define your own system aliases | |
170 | ------------------------------ |
|
170 | ------------------------------ | |
171 |
|
171 | |||
172 | It's convenient to have aliases to the system commands you use most often. |
|
172 | It's convenient to have aliases to the system commands you use most often. | |
173 | This allows you to work seamlessly from inside IPython with the same commands |
|
173 | This allows you to work seamlessly from inside IPython with the same commands | |
174 | you are used to in your system shell. IPython comes with some pre-defined |
|
174 | you are used to in your system shell. IPython comes with some pre-defined | |
175 | aliases and a complete system for changing directories, both via a stack (see |
|
175 | aliases and a complete system for changing directories, both via a stack (see | |
176 | :magic:`pushd`, :magic:`popd` and :magic:`dhist`) and via direct :magic:`cd`. The latter keeps a history of |
|
176 | :magic:`pushd`, :magic:`popd` and :magic:`dhist`) and via direct :magic:`cd`. The latter keeps a history of | |
177 | visited directories and allows you to go to any previously visited one. |
|
177 | visited directories and allows you to go to any previously visited one. | |
178 |
|
178 | |||
179 |
|
179 | |||
180 | Configuration |
|
180 | Configuration | |
181 | ============= |
|
181 | ============= | |
182 |
|
182 | |||
183 | Much of IPython can be tweaked through :doc:`configuration </config/intro>`. |
|
183 | Much of IPython can be tweaked through :doc:`configuration </config/intro>`. | |
184 | To get started, use the command ``ipython profile create`` to produce the |
|
184 | To get started, use the command ``ipython profile create`` to produce the | |
185 | default config files. These will be placed in |
|
185 | default config files. These will be placed in | |
186 | :file:`~/.ipython/profile_default`, and contain comments explaining |
|
186 | :file:`~/.ipython/profile_default`, and contain comments explaining | |
187 | what the various options do. |
|
187 | what the various options do. | |
188 |
|
188 | |||
189 | Profiles allow you to use IPython for different tasks, keeping separate config |
|
189 | Profiles allow you to use IPython for different tasks, keeping separate config | |
190 | files and history for each one. More details in :ref:`the profiles section |
|
190 | files and history for each one. More details in :ref:`the profiles section | |
191 | <profiles>`. |
|
191 | <profiles>`. | |
192 |
|
192 | |||
|
193 | .. _startup_files: | |||
|
194 | ||||
193 | Startup Files |
|
195 | Startup Files | |
194 | ------------- |
|
196 | ------------- | |
195 |
|
197 | |||
196 | If you want some code to be run at the beginning of every IPython session, the |
|
198 | If you want some code to be run at the beginning of every IPython session, the | |
197 | easiest way is to add Python (.py) or IPython (.ipy) scripts to your |
|
199 | easiest way is to add Python (.py) or IPython (.ipy) scripts to your | |
198 | :file:`profile_default/startup/` directory. Files here will be executed as soon |
|
200 | :file:`profile_default/startup/` directory. Files here will be executed as soon | |
199 | as the IPython shell is constructed, before any other code or scripts you have |
|
201 | as the IPython shell is constructed, before any other code or scripts you have | |
200 | specified. The files will be run in order of their names, so you can control the |
|
202 | specified. The files will be run in order of their names, so you can control the | |
201 | ordering with prefixes, like ``10-myimports.py``. |
|
203 | ordering with prefixes, like ``10-myimports.py``. | |
202 |
|
204 | |||
203 | .. include:: ../links.txt |
|
205 | .. include:: ../links.txt |
@@ -1,220 +1,220 b'' | |||||
1 | .. _issues_list_3: |
|
1 | .. _issues_list_3: | |
2 |
|
2 | |||
3 | Issues closed in the 3.x development cycle |
|
3 | Issues closed in the 3.x development cycle | |
4 | ========================================== |
|
4 | ========================================== | |
5 |
|
5 | |||
6 | Issues closed in 3.1 |
|
6 | Issues closed in 3.1 | |
7 | -------------------- |
|
7 | -------------------- | |
8 |
|
8 | |||
9 | GitHub stats for 2015/02/27 - 2015/04/03 (since 3.0) |
|
9 | GitHub stats for 2015/02/27 - 2015/04/03 (since 3.0) | |
10 |
|
10 | |||
11 | These lists are automatically generated, and may be incomplete or contain duplicates. |
|
11 | These lists are automatically generated, and may be incomplete or contain duplicates. | |
12 |
|
12 | |||
13 | We closed 46 issues and merged 133 pull requests. |
|
13 | We closed 46 issues and merged 133 pull requests. | |
14 | The full list can be seen `on GitHub <https://github.com/ipython/ipython/milestones/3.1>`_. |
|
14 | The full list can be seen `on GitHub <https://github.com/ipython/ipython/milestones/3.1>`__. | |
15 |
|
15 | |||
16 | The following 33 authors contributed 344 commits: |
|
16 | The following 33 authors contributed 344 commits: | |
17 |
|
17 | |||
18 | * Abe Guerra |
|
18 | * Abe Guerra | |
19 | * Adal Chiriliuc |
|
19 | * Adal Chiriliuc | |
20 | * Benjamin Ragan-Kelley |
|
20 | * Benjamin Ragan-Kelley | |
21 | * Brian Drawert |
|
21 | * Brian Drawert | |
22 | * Fernando Perez |
|
22 | * Fernando Perez | |
23 | * Gareth Elston |
|
23 | * Gareth Elston | |
24 | * Gert-Ludwig Ingold |
|
24 | * Gert-Ludwig Ingold | |
25 | * Giuseppe Venturini |
|
25 | * Giuseppe Venturini | |
26 | * Jakob Gager |
|
26 | * Jakob Gager | |
27 | * Jan Schulz |
|
27 | * Jan Schulz | |
28 | * Jason Grout |
|
28 | * Jason Grout | |
29 | * Jessica B. Hamrick |
|
29 | * Jessica B. Hamrick | |
30 | * Jonathan Frederic |
|
30 | * Jonathan Frederic | |
31 | * Justin Tyberg |
|
31 | * Justin Tyberg | |
32 | * Lorena Pantano |
|
32 | * Lorena Pantano | |
33 | * mashenjun |
|
33 | * mashenjun | |
34 | * Mathieu |
|
34 | * Mathieu | |
35 | * Matthias Bussonnier |
|
35 | * Matthias Bussonnier | |
36 | * Morten Enemark Lund |
|
36 | * Morten Enemark Lund | |
37 | * Naveen Nathan |
|
37 | * Naveen Nathan | |
38 | * Nicholas Bollweg |
|
38 | * Nicholas Bollweg | |
39 | * onesandzeroes |
|
39 | * onesandzeroes | |
40 | * Patrick Snape |
|
40 | * Patrick Snape | |
41 | * Peter Parente |
|
41 | * Peter Parente | |
42 | * RickWinter |
|
42 | * RickWinter | |
43 | * Robert Smith |
|
43 | * Robert Smith | |
44 | * Ryan Nelson |
|
44 | * Ryan Nelson | |
45 | * Scott Sanderson |
|
45 | * Scott Sanderson | |
46 | * Sylvain Corlay |
|
46 | * Sylvain Corlay | |
47 | * Thomas Kluyver |
|
47 | * Thomas Kluyver | |
48 | * tmtabor |
|
48 | * tmtabor | |
49 | * Wieland Hoffmann |
|
49 | * Wieland Hoffmann | |
50 | * Yuval Langer |
|
50 | * Yuval Langer | |
51 |
|
51 | |||
52 |
|
52 | |||
53 | Issues closed in 3.0 |
|
53 | Issues closed in 3.0 | |
54 | -------------------- |
|
54 | -------------------- | |
55 |
|
55 | |||
56 | GitHub stats for 2014/04/02 - 2015/02/13 (since 2.0) |
|
56 | GitHub stats for 2014/04/02 - 2015/02/13 (since 2.0) | |
57 |
|
57 | |||
58 | These lists are automatically generated, and may be incomplete or contain duplicates. |
|
58 | These lists are automatically generated, and may be incomplete or contain duplicates. | |
59 |
|
59 | |||
60 | We closed 469 issues and merged 925 pull requests. |
|
60 | We closed 469 issues and merged 925 pull requests. | |
61 | The full list can be seen `on GitHub <https://github.com/ipython/ipython/milestones/3.0>`_. |
|
61 | The full list can be seen `on GitHub <https://github.com/ipython/ipython/milestones/3.0>`__. | |
62 |
|
62 | |||
63 | The following 155 authors contributed 5975 commits. |
|
63 | The following 155 authors contributed 5975 commits. | |
64 |
|
64 | |||
65 | * A.J. Holyoake |
|
65 | * A.J. Holyoake | |
66 | * abalkin |
|
66 | * abalkin | |
67 | * Adam Hodgen |
|
67 | * Adam Hodgen | |
68 | * Adrian Price-Whelan |
|
68 | * Adrian Price-Whelan | |
69 | * Amin Bandali |
|
69 | * Amin Bandali | |
70 | * Andreas Amann |
|
70 | * Andreas Amann | |
71 | * Andrew Dawes |
|
71 | * Andrew Dawes | |
72 | * Andrew Jesaitis |
|
72 | * Andrew Jesaitis | |
73 | * Andrew Payne |
|
73 | * Andrew Payne | |
74 | * AnneTheAgile |
|
74 | * AnneTheAgile | |
75 | * Aron Ahmadia |
|
75 | * Aron Ahmadia | |
76 | * Ben Duffield |
|
76 | * Ben Duffield | |
77 | * Benjamin ABEL |
|
77 | * Benjamin ABEL | |
78 | * Benjamin Ragan-Kelley |
|
78 | * Benjamin Ragan-Kelley | |
79 | * Benjamin Schultz |
|
79 | * Benjamin Schultz | |
80 | * BjΓΆrn GrΓΌning |
|
80 | * BjΓΆrn GrΓΌning | |
81 | * BjΓΆrn Linse |
|
81 | * BjΓΆrn Linse | |
82 | * Blake Griffith |
|
82 | * Blake Griffith | |
83 | * Boris Egorov |
|
83 | * Boris Egorov | |
84 | * Brian E. Granger |
|
84 | * Brian E. Granger | |
85 | * bsvh |
|
85 | * bsvh | |
86 | * Carlos Cordoba |
|
86 | * Carlos Cordoba | |
87 | * Cedric GESTES |
|
87 | * Cedric GESTES | |
88 | * cel |
|
88 | * cel | |
89 | * chebee7i |
|
89 | * chebee7i | |
90 | * Christoph Gohlke |
|
90 | * Christoph Gohlke | |
91 | * CJ Carey |
|
91 | * CJ Carey | |
92 | * Cyrille Rossant |
|
92 | * Cyrille Rossant | |
93 | * Dale Jung |
|
93 | * Dale Jung | |
94 | * DamiΓ‘n Avila |
|
94 | * DamiΓ‘n Avila | |
95 | * Damon Allen |
|
95 | * Damon Allen | |
96 | * Daniel B. Vasquez |
|
96 | * Daniel B. Vasquez | |
97 | * Daniel Rocco |
|
97 | * Daniel Rocco | |
98 | * Daniel Wehner |
|
98 | * Daniel Wehner | |
99 | * Dav Clark |
|
99 | * Dav Clark | |
100 | * David Hirschfeld |
|
100 | * David Hirschfeld | |
101 | * David Neto |
|
101 | * David Neto | |
102 | * dexterdev |
|
102 | * dexterdev | |
103 | * Dimitry Kloper |
|
103 | * Dimitry Kloper | |
104 | * dongweiming |
|
104 | * dongweiming | |
105 | * Doug Blank |
|
105 | * Doug Blank | |
106 | * drevicko |
|
106 | * drevicko | |
107 | * Dustin Rodriguez |
|
107 | * Dustin Rodriguez | |
108 | * Eric Firing |
|
108 | * Eric Firing | |
109 | * Eric Galloway |
|
109 | * Eric Galloway | |
110 | * Erik M. Bray |
|
110 | * Erik M. Bray | |
111 | * Erik Tollerud |
|
111 | * Erik Tollerud | |
112 | * Ezequiel (Zac) Panepucci |
|
112 | * Ezequiel (Zac) Panepucci | |
113 | * Fernando Perez |
|
113 | * Fernando Perez | |
114 | * foogunlana |
|
114 | * foogunlana | |
115 | * Francisco de la PeΓ±a |
|
115 | * Francisco de la PeΓ±a | |
116 | * George Titsworth |
|
116 | * George Titsworth | |
117 | * Gordon Ball |
|
117 | * Gordon Ball | |
118 | * gporras |
|
118 | * gporras | |
119 | * Grzegorz RoΕΌniecki |
|
119 | * Grzegorz RoΕΌniecki | |
120 | * Helen ST |
|
120 | * Helen ST | |
121 | * immerrr |
|
121 | * immerrr | |
122 | * Ingolf Becker |
|
122 | * Ingolf Becker | |
123 | * Jakob Gager |
|
123 | * Jakob Gager | |
124 | * James Goppert |
|
124 | * James Goppert | |
125 | * James Porter |
|
125 | * James Porter | |
126 | * Jan Schulz |
|
126 | * Jan Schulz | |
127 | * Jason Goad |
|
127 | * Jason Goad | |
128 | * Jason Gors |
|
128 | * Jason Gors | |
129 | * Jason Grout |
|
129 | * Jason Grout | |
130 | * Jason Newton |
|
130 | * Jason Newton | |
131 | * jdavidheiser |
|
131 | * jdavidheiser | |
132 | * Jean-Christophe Jaskula |
|
132 | * Jean-Christophe Jaskula | |
133 | * Jeff Hemmelgarn |
|
133 | * Jeff Hemmelgarn | |
134 | * Jeffrey Bush |
|
134 | * Jeffrey Bush | |
135 | * Jeroen Demeyer |
|
135 | * Jeroen Demeyer | |
136 | * Jessica B. Hamrick |
|
136 | * Jessica B. Hamrick | |
137 | * Jessica Frazelle |
|
137 | * Jessica Frazelle | |
138 | * jhemmelg |
|
138 | * jhemmelg | |
139 | * Jim Garrison |
|
139 | * Jim Garrison | |
140 | * Joel Nothman |
|
140 | * Joel Nothman | |
141 | * Johannes Feist |
|
141 | * Johannes Feist | |
142 | * John Stowers |
|
142 | * John Stowers | |
143 | * John Zwinck |
|
143 | * John Zwinck | |
144 | * jonasc |
|
144 | * jonasc | |
145 | * Jonathan Frederic |
|
145 | * Jonathan Frederic | |
146 | * Juergen Hasch |
|
146 | * Juergen Hasch | |
147 | * Julia Evans |
|
147 | * Julia Evans | |
148 | * Justyna Ilczuk |
|
148 | * Justyna Ilczuk | |
149 | * JΓΆrg Dietrich |
|
149 | * JΓΆrg Dietrich | |
150 | * K.-Michael Aye |
|
150 | * K.-Michael Aye | |
151 | * Kalibri |
|
151 | * Kalibri | |
152 | * Kester Tong |
|
152 | * Kester Tong | |
153 | * Kyle Kelley |
|
153 | * Kyle Kelley | |
154 | * Kyle Rawlins |
|
154 | * Kyle Rawlins | |
155 | * Lev Abalkin |
|
155 | * Lev Abalkin | |
156 | * Manuel Riel |
|
156 | * Manuel Riel | |
157 | * Martin Bergtholdt |
|
157 | * Martin Bergtholdt | |
158 | * Martin Spacek |
|
158 | * Martin Spacek | |
159 | * Mateusz Paprocki |
|
159 | * Mateusz Paprocki | |
160 | * Mathieu |
|
160 | * Mathieu | |
161 | * Matthias Bussonnier |
|
161 | * Matthias Bussonnier | |
162 | * Maximilian Albert |
|
162 | * Maximilian Albert | |
163 | * mbyt |
|
163 | * mbyt | |
164 | * MechCoder |
|
164 | * MechCoder | |
165 | * Mohan Raj Rajamanickam |
|
165 | * Mohan Raj Rajamanickam | |
166 | * mvr |
|
166 | * mvr | |
167 | * Narahari |
|
167 | * Narahari | |
168 | * Nathan Goldbaum |
|
168 | * Nathan Goldbaum | |
169 | * Nathan Heijermans |
|
169 | * Nathan Heijermans | |
170 | * Nathaniel J. Smith |
|
170 | * Nathaniel J. Smith | |
171 | * ncornette |
|
171 | * ncornette | |
172 | * Nicholas Bollweg |
|
172 | * Nicholas Bollweg | |
173 | * Nick White |
|
173 | * Nick White | |
174 | * Nikolay Koldunov |
|
174 | * Nikolay Koldunov | |
175 | * Nile Geisinger |
|
175 | * Nile Geisinger | |
176 | * Olga Botvinnik |
|
176 | * Olga Botvinnik | |
177 | * Osada Paranaliyanage |
|
177 | * Osada Paranaliyanage | |
178 | * Pankaj Pandey |
|
178 | * Pankaj Pandey | |
179 | * Pascal Bugnion |
|
179 | * Pascal Bugnion | |
180 | * patricktokeeffe |
|
180 | * patricktokeeffe | |
181 | * Paul Ivanov |
|
181 | * Paul Ivanov | |
182 | * Peter Odding |
|
182 | * Peter Odding | |
183 | * Peter Parente |
|
183 | * Peter Parente | |
184 | * Peter WΓΌrtz |
|
184 | * Peter WΓΌrtz | |
185 | * Phil Elson |
|
185 | * Phil Elson | |
186 | * Phillip Nordwall |
|
186 | * Phillip Nordwall | |
187 | * Pierre Gerold |
|
187 | * Pierre Gerold | |
188 | * Pierre Haessig |
|
188 | * Pierre Haessig | |
189 | * Raffaele De Feo |
|
189 | * Raffaele De Feo | |
190 | * Ramiro GΓ³mez |
|
190 | * Ramiro GΓ³mez | |
191 | * Reggie Pierce |
|
191 | * Reggie Pierce | |
192 | * Remi Rampin |
|
192 | * Remi Rampin | |
193 | * Renaud Richardet |
|
193 | * Renaud Richardet | |
194 | * Richard Everson |
|
194 | * Richard Everson | |
195 | * Scott Sanderson |
|
195 | * Scott Sanderson | |
196 | * Silvia Vinyes |
|
196 | * Silvia Vinyes | |
197 | * Simon Guillot |
|
197 | * Simon Guillot | |
198 | * Spencer Nelson |
|
198 | * Spencer Nelson | |
199 | * Stefan Zimmermann |
|
199 | * Stefan Zimmermann | |
200 | * Steve Chan |
|
200 | * Steve Chan | |
201 | * Steven Anton |
|
201 | * Steven Anton | |
202 | * Steven Silvester |
|
202 | * Steven Silvester | |
203 | * sunny |
|
203 | * sunny | |
204 | * Susan Tan |
|
204 | * Susan Tan | |
205 | * Sylvain Corlay |
|
205 | * Sylvain Corlay | |
206 | * Tarun Gaba |
|
206 | * Tarun Gaba | |
207 | * Thomas Ballinger |
|
207 | * Thomas Ballinger | |
208 | * Thomas Kluyver |
|
208 | * Thomas Kluyver | |
209 | * Thomas Robitaille |
|
209 | * Thomas Robitaille | |
210 | * Thomas Spura |
|
210 | * Thomas Spura | |
211 | * Tobias Oberstein |
|
211 | * Tobias Oberstein | |
212 | * Torsten Bittner |
|
212 | * Torsten Bittner | |
213 | * unknown |
|
213 | * unknown | |
214 | * v923z |
|
214 | * v923z | |
215 | * vaibhavsagar |
|
215 | * vaibhavsagar | |
216 | * W. Trevor King |
|
216 | * W. Trevor King | |
217 | * weichm |
|
217 | * weichm | |
218 | * Xiuming Chen |
|
218 | * Xiuming Chen | |
219 | * Yaroslav Halchenko |
|
219 | * Yaroslav Halchenko | |
220 | * zah |
|
220 | * zah |
@@ -1,765 +1,765 b'' | |||||
1 | ============= |
|
1 | ============= | |
2 | 0.11 Series |
|
2 | 0.11 Series | |
3 | ============= |
|
3 | ============= | |
4 |
|
4 | |||
5 | Release 0.11 |
|
5 | Release 0.11 | |
6 | ============ |
|
6 | ============ | |
7 |
|
7 | |||
8 | IPython 0.11 is a *major* overhaul of IPython, two years in the making. Most |
|
8 | IPython 0.11 is a *major* overhaul of IPython, two years in the making. Most | |
9 | of the code base has been rewritten or at least reorganized, breaking backward |
|
9 | of the code base has been rewritten or at least reorganized, breaking backward | |
10 | compatibility with several APIs in previous versions. It is the first major |
|
10 | compatibility with several APIs in previous versions. It is the first major | |
11 | release in two years, and probably the most significant change to IPython since |
|
11 | release in two years, and probably the most significant change to IPython since | |
12 | its inception. We plan to have a relatively quick succession of releases, as |
|
12 | its inception. We plan to have a relatively quick succession of releases, as | |
13 | people discover new bugs and regressions. Once we iron out any significant |
|
13 | people discover new bugs and regressions. Once we iron out any significant | |
14 | bugs in this process and settle down the new APIs, this series will become |
|
14 | bugs in this process and settle down the new APIs, this series will become | |
15 | IPython 1.0. We encourage feedback now on the core APIs, which we hope to |
|
15 | IPython 1.0. We encourage feedback now on the core APIs, which we hope to | |
16 | maintain stable during the 1.0 series. |
|
16 | maintain stable during the 1.0 series. | |
17 |
|
17 | |||
18 | Since the internal APIs have changed so much, projects using IPython as a |
|
18 | Since the internal APIs have changed so much, projects using IPython as a | |
19 | library (as opposed to end-users of the application) are the most likely to |
|
19 | library (as opposed to end-users of the application) are the most likely to | |
20 | encounter regressions or changes that break their existing use patterns. We |
|
20 | encounter regressions or changes that break their existing use patterns. We | |
21 | will make every effort to provide updated versions of the APIs to facilitate |
|
21 | will make every effort to provide updated versions of the APIs to facilitate | |
22 | the transition, and we encourage you to contact us on the `development mailing |
|
22 | the transition, and we encourage you to contact us on the `development mailing | |
23 | list`__ with questions and feedback. |
|
23 | list`__ with questions and feedback. | |
24 |
|
24 | |||
25 | .. __: http://mail.scipy.org/mailman/listinfo/ipython-dev |
|
25 | .. __: http://mail.scipy.org/mailman/listinfo/ipython-dev | |
26 |
|
26 | |||
27 | Chris Fonnesbeck recently wrote an `excellent post`__ that highlights some of |
|
27 | Chris Fonnesbeck recently wrote an `excellent post`__ that highlights some of | |
28 | our major new features, with examples and screenshots. We encourage you to |
|
28 | our major new features, with examples and screenshots. We encourage you to | |
29 | read it as it provides an illustrated, high-level overview complementing the |
|
29 | read it as it provides an illustrated, high-level overview complementing the | |
30 | detailed feature breakdown in this document. |
|
30 | detailed feature breakdown in this document. | |
31 |
|
31 | |||
32 | .. __: http://stronginference.com/post/innovations-in-ipython |
|
32 | .. __: http://stronginference.com/post/innovations-in-ipython | |
33 |
|
33 | |||
34 | A quick summary of the major changes (see below for details): |
|
34 | A quick summary of the major changes (see below for details): | |
35 |
|
35 | |||
36 | * **Standalone Qt console**: a new rich console has been added to IPython, |
|
36 | * **Standalone Qt console**: a new rich console has been added to IPython, | |
37 | started with `ipython qtconsole`. In this application we have tried to |
|
37 | started with `ipython qtconsole`. In this application we have tried to | |
38 | retain the feel of a terminal for fast and efficient workflows, while adding |
|
38 | retain the feel of a terminal for fast and efficient workflows, while adding | |
39 | many features that a line-oriented terminal simply can not support, such as |
|
39 | many features that a line-oriented terminal simply can not support, such as | |
40 | inline figures, full multiline editing with syntax highlighting, graphical |
|
40 | inline figures, full multiline editing with syntax highlighting, graphical | |
41 | tooltips for function calls and much more. This development was sponsored by |
|
41 | tooltips for function calls and much more. This development was sponsored by | |
42 | `Enthought Inc.`__. See :ref:`below <qtconsole_011>` for details. |
|
42 | `Enthought Inc.`__. See :ref:`below <qtconsole_011>` for details. | |
43 |
|
43 | |||
44 | .. __: http://enthought.com |
|
44 | .. __: http://enthought.com | |
45 |
|
45 | |||
46 | * **High-level parallel computing with ZeroMQ**. Using the same architecture |
|
46 | * **High-level parallel computing with ZeroMQ**. Using the same architecture | |
47 | that our Qt console is based on, we have completely rewritten our high-level |
|
47 | that our Qt console is based on, we have completely rewritten our high-level | |
48 | parallel computing machinery that in prior versions used the Twisted |
|
48 | parallel computing machinery that in prior versions used the Twisted | |
49 | networking framework. While this change will require users to update their |
|
49 | networking framework. While this change will require users to update their | |
50 | codes, the improvements in performance, memory control and internal |
|
50 | codes, the improvements in performance, memory control and internal | |
51 | consistency across our codebase convinced us it was a price worth paying. We |
|
51 | consistency across our codebase convinced us it was a price worth paying. We | |
52 | have tried to explain how to best proceed with this update, and will be happy |
|
52 | have tried to explain how to best proceed with this update, and will be happy | |
53 | to answer questions that may arise. A full tutorial describing these |
|
53 | to answer questions that may arise. A full tutorial describing these | |
54 | features `was presented at SciPy'11`__, more details :ref:`below |
|
54 | features `was presented at SciPy'11`__, more details :ref:`below | |
55 | <parallel_011>`. |
|
55 | <parallel_011>`. | |
56 |
|
56 | |||
57 | .. __: http://minrk.github.com/scipy-tutorial-2011 |
|
57 | .. __: http://minrk.github.com/scipy-tutorial-2011 | |
58 |
|
58 | |||
59 | * **New model for GUI/plotting support in the terminal**. Now instead of the |
|
59 | * **New model for GUI/plotting support in the terminal**. Now instead of the | |
60 | various `-Xthread` flags we had before, GUI support is provided without the |
|
60 | various `-Xthread` flags we had before, GUI support is provided without the | |
61 | use of any threads, by directly integrating GUI event loops with Python's |
|
61 | use of any threads, by directly integrating GUI event loops with Python's | |
62 | `PyOS_InputHook` API. A new command-line flag `--gui` controls GUI support, |
|
62 | `PyOS_InputHook` API. A new command-line flag `--gui` controls GUI support, | |
63 | and it can also be enabled after IPython startup via the new `%gui` magic. |
|
63 | and it can also be enabled after IPython startup via the new `%gui` magic. | |
64 | This requires some changes if you want to execute GUI-using scripts inside |
|
64 | This requires some changes if you want to execute GUI-using scripts inside | |
65 | IPython, see :ref:`the GUI support section <gui_support>` for more details. |
|
65 | IPython, see :ref:`the GUI support section <gui_support>` for more details. | |
66 |
|
66 | |||
67 | * **A two-process architecture.** The Qt console is the first use of a new |
|
67 | * **A two-process architecture.** The Qt console is the first use of a new | |
68 | model that splits IPython between a kernel process where code is executed and |
|
68 | model that splits IPython between a kernel process where code is executed and | |
69 | a client that handles user interaction. We plan on also providing terminal |
|
69 | a client that handles user interaction. We plan on also providing terminal | |
70 | and web-browser based clients using this infrastructure in future releases. |
|
70 | and web-browser based clients using this infrastructure in future releases. | |
71 | This model allows multiple clients to interact with an IPython process |
|
71 | This model allows multiple clients to interact with an IPython process | |
72 | through a :ref:`well-documented messaging protocol <messaging>` using the |
|
72 | through a :ref:`well-documented messaging protocol <messaging>` using the | |
73 | ZeroMQ networking library. |
|
73 | ZeroMQ networking library. | |
74 |
|
74 | |||
75 | * **Refactoring.** the entire codebase has been refactored, in order to make it |
|
75 | * **Refactoring.** the entire codebase has been refactored, in order to make it | |
76 | more modular and easier to contribute to. IPython has traditionally been a |
|
76 | more modular and easier to contribute to. IPython has traditionally been a | |
77 | hard project to participate because the old codebase was very monolithic. We |
|
77 | hard project to participate because the old codebase was very monolithic. We | |
78 | hope this (ongoing) restructuring will make it easier for new developers to |
|
78 | hope this (ongoing) restructuring will make it easier for new developers to | |
79 | join us. |
|
79 | join us. | |
80 |
|
80 | |||
81 | * **Vim integration**. Vim can be configured to seamlessly control an IPython |
|
81 | * **Vim integration**. Vim can be configured to seamlessly control an IPython | |
82 | kernel, see the files in :file:`docs/examples/vim` for the full details. |
|
82 | kernel, see the files in :file:`docs/examples/vim` for the full details. | |
83 | This work was done by Paul Ivanov, who prepared a nice `video |
|
83 | This work was done by Paul Ivanov, who prepared a nice `video | |
84 | demonstration`__ of the features it provides. |
|
84 | demonstration`__ of the features it provides. | |
85 |
|
85 | |||
86 | .. __: http://pirsquared.org/blog/2011/07/28/vim-ipython/ |
|
86 | .. __: http://pirsquared.org/blog/2011/07/28/vim-ipython/ | |
87 |
|
87 | |||
88 | * **Integration into Microsoft Visual Studio**. Thanks to the work of the |
|
88 | * **Integration into Microsoft Visual Studio**. Thanks to the work of the | |
89 | Microsoft `Python Tools for Visual Studio`__ team, this version of IPython |
|
89 | Microsoft `Python Tools for Visual Studio`__ team, this version of IPython | |
90 | has been integrated into Microsoft Visual Studio's Python tools open source |
|
90 | has been integrated into Microsoft Visual Studio's Python tools open source | |
91 | plug-in. `Details below`_ |
|
91 | plug-in. `Details below`_ | |
92 |
|
92 | |||
93 | .. __: http://pytools.codeplex.com |
|
93 | .. __: http://pytools.codeplex.com | |
94 | .. _details below: ms_visual_studio_011_ |
|
94 | .. _details below: ms_visual_studio_011_ | |
95 |
|
95 | |||
96 | * **Improved unicode support**. We closed many bugs related to unicode input. |
|
96 | * **Improved unicode support**. We closed many bugs related to unicode input. | |
97 |
|
97 | |||
98 | * **Python 3**. IPython now runs on Python 3.x. See :ref:`python3_011` for |
|
98 | * **Python 3**. IPython now runs on Python 3.x. See :ref:`python3_011` for | |
99 | details. |
|
99 | details. | |
100 |
|
100 | |||
101 | * **New profile model**. Profiles are now directories that contain all relevant |
|
101 | * **New profile model**. Profiles are now directories that contain all relevant | |
102 | information for that session, and thus better isolate IPython use-cases. |
|
102 | information for that session, and thus better isolate IPython use-cases. | |
103 |
|
103 | |||
104 | * **SQLite storage for history**. All history is now stored in a SQLite |
|
104 | * **SQLite storage for history**. All history is now stored in a SQLite | |
105 | database, providing support for multiple simultaneous sessions that won't |
|
105 | database, providing support for multiple simultaneous sessions that won't | |
106 | clobber each other as well as the ability to perform queries on all stored |
|
106 | clobber each other as well as the ability to perform queries on all stored | |
107 | data. |
|
107 | data. | |
108 |
|
108 | |||
109 | * **New configuration system**. All parts of IPython are now configured via a |
|
109 | * **New configuration system**. All parts of IPython are now configured via a | |
110 | mechanism inspired by the Enthought Traits library. Any configurable element |
|
110 | mechanism inspired by the Enthought Traits library. Any configurable element | |
111 | can have its attributes set either via files that now use real Python syntax |
|
111 | can have its attributes set either via files that now use real Python syntax | |
112 | or from the command-line. |
|
112 | or from the command-line. | |
113 |
|
113 | |||
114 | * **Pasting of code with prompts**. IPython now intelligently strips out input |
|
114 | * **Pasting of code with prompts**. IPython now intelligently strips out input | |
115 | prompts , be they plain Python ones (``>>>`` and ``...``) or IPython ones |
|
115 | prompts , be they plain Python ones (``>>>`` and ``...``) or IPython ones | |
116 | (``In [N]:`` and ``...:``). More details :ref:`here <pasting_with_prompts>`. |
|
116 | (``In [N]:`` and ``...:``). More details :ref:`here <pasting_with_prompts>`. | |
117 |
|
117 | |||
118 |
|
118 | |||
119 | Authors and support |
|
119 | Authors and support | |
120 | ------------------- |
|
120 | ------------------- | |
121 |
|
121 | |||
122 | Over 60 separate authors have contributed to this release, see :ref:`below |
|
122 | Over 60 separate authors have contributed to this release, see :ref:`below | |
123 | <credits_011>` for a full list. In particular, we want to highlight the |
|
123 | <credits_011>` for a full list. In particular, we want to highlight the | |
124 | extremely active participation of two new core team members: Evan Patterson |
|
124 | extremely active participation of two new core team members: Evan Patterson | |
125 | implemented the Qt console, and Thomas Kluyver started with our Python 3 port |
|
125 | implemented the Qt console, and Thomas Kluyver started with our Python 3 port | |
126 | and by now has made major contributions to just about every area of IPython. |
|
126 | and by now has made major contributions to just about every area of IPython. | |
127 |
|
127 | |||
128 | We are also grateful for the support we have received during this development |
|
128 | We are also grateful for the support we have received during this development | |
129 | cycle from several institutions: |
|
129 | cycle from several institutions: | |
130 |
|
130 | |||
131 | - `Enthought Inc`__ funded the development of our new Qt console, an effort that |
|
131 | - `Enthought Inc`__ funded the development of our new Qt console, an effort that | |
132 | required developing major pieces of underlying infrastructure, which now |
|
132 | required developing major pieces of underlying infrastructure, which now | |
133 | power not only the Qt console but also our new parallel machinery. We'd like |
|
133 | power not only the Qt console but also our new parallel machinery. We'd like | |
134 | to thank Eric Jones and Travis Oliphant for their support, as well as Ilan |
|
134 | to thank Eric Jones and Travis Oliphant for their support, as well as Ilan | |
135 | Schnell for his tireless work integrating and testing IPython in the |
|
135 | Schnell for his tireless work integrating and testing IPython in the | |
136 | `Enthought Python Distribution`_. |
|
136 | `Enthought Python Distribution`_. | |
137 |
|
137 | |||
138 | .. __: http://enthought.com |
|
138 | .. __: http://enthought.com | |
139 | .. _Enthought Python Distribution: http://www.enthought.com/products/epd.php |
|
139 | .. _Enthought Python Distribution: http://www.enthought.com/products/epd.php | |
140 |
|
140 | |||
141 | - Nipy/NIH: funding via the `NiPy project`__ (NIH grant 5R01MH081909-02) helped |
|
141 | - Nipy/NIH: funding via the `NiPy project`__ (NIH grant 5R01MH081909-02) helped | |
142 | us jumpstart the development of this series by restructuring the entire |
|
142 | us jumpstart the development of this series by restructuring the entire | |
143 | codebase two years ago in a way that would make modular development and |
|
143 | codebase two years ago in a way that would make modular development and | |
144 | testing more approachable. Without this initial groundwork, all the new |
|
144 | testing more approachable. Without this initial groundwork, all the new | |
145 | features we have added would have been impossible to develop. |
|
145 | features we have added would have been impossible to develop. | |
146 |
|
146 | |||
147 | .. __: http://nipy.org |
|
147 | .. __: http://nipy.org | |
148 |
|
148 | |||
149 | - Sage/NSF: funding via the grant `Sage: Unifying Mathematical Software for |
|
149 | - Sage/NSF: funding via the grant `Sage: Unifying Mathematical Software for | |
150 | Scientists, Engineers, and Mathematicians`__ (NSF grant DMS-1015114) |
|
150 | Scientists, Engineers, and Mathematicians`__ (NSF grant DMS-1015114) | |
151 | supported a meeting in spring 2011 of several of the core IPython developers |
|
151 | supported a meeting in spring 2011 of several of the core IPython developers | |
152 | where major progress was made integrating the last key pieces leading to this |
|
152 | where major progress was made integrating the last key pieces leading to this | |
153 | release. |
|
153 | release. | |
154 |
|
154 | |||
155 | .. __: http://modular.math.washington.edu/grants/compmath09 |
|
155 | .. __: http://modular.math.washington.edu/grants/compmath09 | |
156 |
|
156 | |||
157 | - Microsoft's team working on `Python Tools for Visual Studio`__ developed the |
|
157 | - Microsoft's team working on `Python Tools for Visual Studio`__ developed the | |
158 | integraton of IPython into the Python plugin for Visual Studio 2010. |
|
158 | integraton of IPython into the Python plugin for Visual Studio 2010. | |
159 |
|
159 | |||
160 | .. __: http://pytools.codeplex.com |
|
160 | .. __: http://pytools.codeplex.com | |
161 |
|
161 | |||
162 | - Google Summer of Code: in 2010, we had two students developing prototypes of |
|
162 | - Google Summer of Code: in 2010, we had two students developing prototypes of | |
163 | the new machinery that is now maturing in this release: `Omar Zapata`_ and |
|
163 | the new machinery that is now maturing in this release: `Omar Zapata`_ and | |
164 | `Gerardo GutiΓ©rrez`_. |
|
164 | `Gerardo GutiΓ©rrez`_. | |
165 |
|
165 | |||
166 | .. _Omar Zapata: http://ipythonzmq.blogspot.com/2010/08/ipython-zmq-status.html |
|
166 | .. _Omar Zapata: http://ipythonzmq.blogspot.com/2010/08/ipython-zmq-status.html | |
167 | .. _Gerardo GutiΓ©rrez: http://ipythonqt.blogspot.com/2010/04/ipython-qt-interface-gsoc-2010-proposal.html> |
|
167 | .. _Gerardo GutiΓ©rrez: http://ipythonqt.blogspot.com/2010/04/ipython-qt-interface-gsoc-2010-proposal.html> | |
168 |
|
168 | |||
169 |
|
169 | |||
170 | Development summary: moving to Git and Github |
|
170 | Development summary: moving to Git and Github | |
171 | --------------------------------------------- |
|
171 | --------------------------------------------- | |
172 |
|
172 | |||
173 | In April 2010, after `one breakage too many with bzr`__, we decided to move our |
|
173 | In April 2010, after `one breakage too many with bzr`__, we decided to move our | |
174 | entire development process to Git and Github.com. This has proven to be one of |
|
174 | entire development process to Git and Github.com. This has proven to be one of | |
175 | the best decisions in the project's history, as the combination of git and |
|
175 | the best decisions in the project's history, as the combination of git and | |
176 | github have made us far, far more productive than we could be with our previous |
|
176 | github have made us far, far more productive than we could be with our previous | |
177 | tools. We first converted our bzr repo to a git one without losing history, |
|
177 | tools. We first converted our bzr repo to a git one without losing history, | |
178 | and a few weeks later ported all open Launchpad bugs to github issues with |
|
178 | and a few weeks later ported all open Launchpad bugs to github issues with | |
179 | their comments mostly intact (modulo some formatting changes). This ensured a |
|
179 | their comments mostly intact (modulo some formatting changes). This ensured a | |
180 | smooth transition where no development history or submitted bugs were lost. |
|
180 | smooth transition where no development history or submitted bugs were lost. | |
181 | Feel free to use our little Launchpad to Github issues `porting script`_ if you |
|
181 | Feel free to use our little Launchpad to Github issues `porting script`_ if you | |
182 | need to make a similar transition. |
|
182 | need to make a similar transition. | |
183 |
|
183 | |||
184 | .. __: http://mail.scipy.org/pipermail/ipython-dev/2010-April/005944.html |
|
184 | .. __: http://mail.scipy.org/pipermail/ipython-dev/2010-April/005944.html | |
185 | .. _porting script: https://gist.github.com/835577 |
|
185 | .. _porting script: https://gist.github.com/835577 | |
186 |
|
186 | |||
187 | These simple statistics show how much work has been done on the new release, by |
|
187 | These simple statistics show how much work has been done on the new release, by | |
188 | comparing the current code to the last point it had in common with the 0.10 |
|
188 | comparing the current code to the last point it had in common with the 0.10 | |
189 | series. A huge diff and ~2200 commits make up this cycle:: |
|
189 | series. A huge diff and ~2200 commits make up this cycle:: | |
190 |
|
190 | |||
191 | git diff $(git merge-base 0.10.2 HEAD) | wc -l |
|
191 | git diff $(git merge-base 0.10.2 HEAD) | wc -l | |
192 | 288019 |
|
192 | 288019 | |
193 |
|
193 | |||
194 | git log $(git merge-base 0.10.2 HEAD)..HEAD --oneline | wc -l |
|
194 | git log $(git merge-base 0.10.2 HEAD)..HEAD --oneline | wc -l | |
195 | 2200 |
|
195 | 2200 | |
196 |
|
196 | |||
197 | Since our move to github, 511 issues were closed, 226 of which were pull |
|
197 | Since our move to github, 511 issues were closed, 226 of which were pull | |
198 | requests and 285 regular issues (:ref:`a full list with links |
|
198 | requests and 285 regular issues (:ref:`a full list with links | |
199 | <issues_list_011>` is available for those interested in the details). Github's |
|
199 | <issues_list_011>` is available for those interested in the details). Github's | |
200 | pull requests are a fantastic mechanism for reviewing code and building a |
|
200 | pull requests are a fantastic mechanism for reviewing code and building a | |
201 | shared ownership of the project, and we are making enthusiastic use of it. |
|
201 | shared ownership of the project, and we are making enthusiastic use of it. | |
202 |
|
202 | |||
203 | .. Note:: |
|
203 | .. Note:: | |
204 |
|
204 | |||
205 | This undercounts the number of issues closed in this development cycle, |
|
205 | This undercounts the number of issues closed in this development cycle, | |
206 | since we only moved to github for issue tracking in May 2010, but we have no |
|
206 | since we only moved to github for issue tracking in May 2010, but we have no | |
207 | way of collecting statistics on the number of issues closed in the old |
|
207 | way of collecting statistics on the number of issues closed in the old | |
208 | Launchpad bug tracker prior to that. |
|
208 | Launchpad bug tracker prior to that. | |
209 |
|
209 | |||
210 |
|
210 | |||
211 | .. _qtconsole_011: |
|
211 | .. _qtconsole_011: | |
212 |
|
212 | |||
213 | Qt Console |
|
213 | Qt Console | |
214 | ---------- |
|
214 | ---------- | |
215 |
|
215 | |||
216 | IPython now ships with a Qt application that feels very much like a terminal, |
|
216 | IPython now ships with a Qt application that feels very much like a terminal, | |
217 | but is in fact a rich GUI that runs an IPython client but supports inline |
|
217 | but is in fact a rich GUI that runs an IPython client but supports inline | |
218 | figures, saving sessions to PDF and HTML, multiline editing with syntax |
|
218 | figures, saving sessions to PDF and HTML, multiline editing with syntax | |
219 | highlighting, graphical calltips and much more: |
|
219 | highlighting, graphical calltips and much more: | |
220 |
|
220 | |||
221 | .. figure:: ../_images/qtconsole.png |
|
221 | .. figure:: ../_images/qtconsole.png | |
222 | :width: 400px |
|
222 | :width: 400px | |
223 | :alt: IPython Qt console with embedded plots |
|
223 | :alt: IPython Qt console with embedded plots | |
224 | :align: center |
|
224 | :align: center | |
225 | :target: ../_images/qtconsole.png |
|
225 | :target: ../_images/qtconsole.png | |
226 |
|
226 | |||
227 | The Qt console for IPython, using inline matplotlib plots. |
|
227 | The Qt console for IPython, using inline matplotlib plots. | |
228 |
|
228 | |||
229 | We hope that many projects will embed this widget, which we've kept |
|
229 | We hope that many projects will embed this widget, which we've kept | |
230 | deliberately very lightweight, into their own environments. In the future we |
|
230 | deliberately very lightweight, into their own environments. In the future we | |
231 | may also offer a slightly more featureful application (with menus and other GUI |
|
231 | may also offer a slightly more featureful application (with menus and other GUI | |
232 | elements), but we remain committed to always shipping this easy to embed |
|
232 | elements), but we remain committed to always shipping this easy to embed | |
233 | widget. |
|
233 | widget. | |
234 |
|
234 | |||
235 | See the :ref:`Qt console section <qtconsole>` of the docs for a detailed |
|
235 | See the :ref:`Qt console section <qtconsole>` of the docs for a detailed | |
236 | description of the console's features and use. |
|
236 | description of the console's features and use. | |
237 |
|
237 | |||
238 |
|
238 | |||
239 | .. _parallel_011: |
|
239 | .. _parallel_011: | |
240 |
|
240 | |||
241 | High-level parallel computing with ZeroMQ |
|
241 | High-level parallel computing with ZeroMQ | |
242 | ----------------------------------------- |
|
242 | ----------------------------------------- | |
243 |
|
243 | |||
244 | We have completely rewritten the Twisted-based code for high-level parallel |
|
244 | We have completely rewritten the Twisted-based code for high-level parallel | |
245 | computing to work atop our new ZeroMQ architecture. While we realize this will |
|
245 | computing to work atop our new ZeroMQ architecture. While we realize this will | |
246 | break compatibility for a number of users, we hope to make the transition as |
|
246 | break compatibility for a number of users, we hope to make the transition as | |
247 | easy as possible with our docs, and we are convinced the change is worth it. |
|
247 | easy as possible with our docs, and we are convinced the change is worth it. | |
248 | ZeroMQ provides us with much tighter control over memory, higher performance, |
|
248 | ZeroMQ provides us with much tighter control over memory, higher performance, | |
249 | and its communications are impervious to the Python Global Interpreter Lock |
|
249 | and its communications are impervious to the Python Global Interpreter Lock | |
250 | because they take place in a system-level C++ thread. The impact of the GIL in |
|
250 | because they take place in a system-level C++ thread. The impact of the GIL in | |
251 | our previous code was something we could simply not work around, given that |
|
251 | our previous code was something we could simply not work around, given that | |
252 | Twisted is itself a Python library. So while Twisted is a very capable |
|
252 | Twisted is itself a Python library. So while Twisted is a very capable | |
253 | framework, we think ZeroMQ fits our needs much better and we hope you will find |
|
253 | framework, we think ZeroMQ fits our needs much better and we hope you will find | |
254 | the change to be a significant improvement in the long run. |
|
254 | the change to be a significant improvement in the long run. | |
255 |
|
255 | |||
256 |
Our manual contains |
|
256 | Our manual contains a full description of how to use IPython for parallel | |
257 |
computing |
|
257 | computing, and the `tutorial`__ presented by Min | |
258 | Ragan-Kelley at the SciPy 2011 conference provides a hands-on complement to the |
|
258 | Ragan-Kelley at the SciPy 2011 conference provides a hands-on complement to the | |
259 | reference docs. |
|
259 | reference docs. | |
260 |
|
260 | |||
261 | .. __: http://minrk.github.com/scipy-tutorial-2011 |
|
261 | .. __: http://minrk.github.com/scipy-tutorial-2011 | |
262 |
|
262 | |||
263 |
|
263 | |||
264 | Refactoring |
|
264 | Refactoring | |
265 | ----------- |
|
265 | ----------- | |
266 |
|
266 | |||
267 | As of this release, a signifiant portion of IPython has been refactored. This |
|
267 | As of this release, a signifiant portion of IPython has been refactored. This | |
268 | refactoring is founded on a number of new abstractions. The main new classes |
|
268 | refactoring is founded on a number of new abstractions. The main new classes | |
269 | that implement these abstractions are: |
|
269 | that implement these abstractions are: | |
270 |
|
270 | |||
271 | * :class:`traitlets.HasTraits`. |
|
271 | * :class:`traitlets.HasTraits`. | |
272 | * :class:`traitlets.config.configurable.Configurable`. |
|
272 | * :class:`traitlets.config.configurable.Configurable`. | |
273 | * :class:`traitlets.config.application.Application`. |
|
273 | * :class:`traitlets.config.application.Application`. | |
274 | * :class:`traitlets.config.loader.ConfigLoader`. |
|
274 | * :class:`traitlets.config.loader.ConfigLoader`. | |
275 | * :class:`traitlets.config.loader.Config` |
|
275 | * :class:`traitlets.config.loader.Config` | |
276 |
|
276 | |||
277 | We are still in the process of writing developer focused documentation about |
|
277 | We are still in the process of writing developer focused documentation about | |
278 | these classes, but for now our :ref:`configuration documentation |
|
278 | these classes, but for now our :ref:`configuration documentation | |
279 | <config_overview>` contains a high level overview of the concepts that these |
|
279 | <config_overview>` contains a high level overview of the concepts that these | |
280 | classes express. |
|
280 | classes express. | |
281 |
|
281 | |||
282 | The biggest user-visible change is likely the move to using the config system |
|
282 | The biggest user-visible change is likely the move to using the config system | |
283 | to determine the command-line arguments for IPython applications. The benefit |
|
283 | to determine the command-line arguments for IPython applications. The benefit | |
284 | of this is that *all* configurable values in IPython are exposed on the |
|
284 | of this is that *all* configurable values in IPython are exposed on the | |
285 | command-line, but the syntax for specifying values has changed. The gist is |
|
285 | command-line, but the syntax for specifying values has changed. The gist is | |
286 | that assigning values is pure Python assignment. Simple flags exist for |
|
286 | that assigning values is pure Python assignment. Simple flags exist for | |
287 | commonly used options, these are always prefixed with '--'. |
|
287 | commonly used options, these are always prefixed with '--'. | |
288 |
|
288 | |||
289 | The IPython command-line help has the details of all the options (via |
|
289 | The IPython command-line help has the details of all the options (via | |
290 |
``ipyth |
|
290 | ``ipython --help``), but a simple example should clarify things; the ``pylab`` | |
291 | flag can be used to start in pylab mode with the qt4 backend:: |
|
291 | flag can be used to start in pylab mode with the qt4 backend:: | |
292 |
|
292 | |||
293 | ipython --pylab=qt |
|
293 | ipython --pylab=qt | |
294 |
|
294 | |||
295 | which is equivalent to using the fully qualified form:: |
|
295 | which is equivalent to using the fully qualified form:: | |
296 |
|
296 | |||
297 | ipython --TerminalIPythonApp.pylab=qt |
|
297 | ipython --TerminalIPythonApp.pylab=qt | |
298 |
|
298 | |||
299 | The long-form options can be listed via ``ipython --help-all``. |
|
299 | The long-form options can be listed via ``ipython --help-all``. | |
300 |
|
300 | |||
301 |
|
301 | |||
302 | ZeroMQ architecture |
|
302 | ZeroMQ architecture | |
303 | ------------------- |
|
303 | ------------------- | |
304 |
|
304 | |||
305 | There is a new GUI framework for IPython, based on a client-server model in |
|
305 | There is a new GUI framework for IPython, based on a client-server model in | |
306 | which multiple clients can communicate with one IPython kernel, using the |
|
306 | which multiple clients can communicate with one IPython kernel, using the | |
307 | ZeroMQ messaging framework. There is already a Qt console client, which can |
|
307 | ZeroMQ messaging framework. There is already a Qt console client, which can | |
308 | be started by calling ``ipython qtconsole``. The protocol is :ref:`documented |
|
308 | be started by calling ``ipython qtconsole``. The protocol is :ref:`documented | |
309 | <messaging>`. |
|
309 | <messaging>`. | |
310 |
|
310 | |||
311 | The parallel computing framework has also been rewritten using ZMQ. The |
|
311 | The parallel computing framework has also been rewritten using ZMQ. The | |
312 | protocol is described :ref:`here <parallel_messages>`, and the code is in the |
|
312 | protocol is described :ref:`here <parallel_messages>`, and the code is in the | |
313 | new :mod:`IPython.parallel` module. |
|
313 | new :mod:`IPython.parallel` module. | |
314 |
|
314 | |||
315 | .. _python3_011: |
|
315 | .. _python3_011: | |
316 |
|
316 | |||
317 | Python 3 support |
|
317 | Python 3 support | |
318 | ---------------- |
|
318 | ---------------- | |
319 |
|
319 | |||
320 | A Python 3 version of IPython has been prepared. For the time being, this is |
|
320 | A Python 3 version of IPython has been prepared. For the time being, this is | |
321 | maintained separately and updated from the main codebase. Its code can be found |
|
321 | maintained separately and updated from the main codebase. Its code can be found | |
322 | `here <https://github.com/ipython/ipython-py3k>`_. The parallel computing |
|
322 | `here <https://github.com/ipython/ipython-py3k>`_. The parallel computing | |
323 | components are not perfect on Python3, but most functionality appears to be |
|
323 | components are not perfect on Python3, but most functionality appears to be | |
324 | working. As this work is evolving quickly, the best place to find updated |
|
324 | working. As this work is evolving quickly, the best place to find updated | |
325 | information about it is our `Python 3 wiki page`__. |
|
325 | information about it is our `Python 3 wiki page`__. | |
326 |
|
326 | |||
327 | .. __: http://wiki.ipython.org/index.php?title=Python_3 |
|
327 | .. __: http://wiki.ipython.org/index.php?title=Python_3 | |
328 |
|
328 | |||
329 |
|
329 | |||
330 | Unicode |
|
330 | Unicode | |
331 | ------- |
|
331 | ------- | |
332 |
|
332 | |||
333 | Entering non-ascii characters in unicode literals (``u"β¬ΓΈ"``) now works |
|
333 | Entering non-ascii characters in unicode literals (``u"β¬ΓΈ"``) now works | |
334 | properly on all platforms. However, entering these in byte/string literals |
|
334 | properly on all platforms. However, entering these in byte/string literals | |
335 | (``"β¬ΓΈ"``) will not work as expected on Windows (or any platform where the |
|
335 | (``"β¬ΓΈ"``) will not work as expected on Windows (or any platform where the | |
336 | terminal encoding is not UTF-8, as it typically is for Linux & Mac OS X). You |
|
336 | terminal encoding is not UTF-8, as it typically is for Linux & Mac OS X). You | |
337 | can use escape sequences (``"\xe9\x82"``) to get bytes above 128, or use |
|
337 | can use escape sequences (``"\xe9\x82"``) to get bytes above 128, or use | |
338 | unicode literals and encode them. This is a limitation of Python 2 which we |
|
338 | unicode literals and encode them. This is a limitation of Python 2 which we | |
339 | cannot easily work around. |
|
339 | cannot easily work around. | |
340 |
|
340 | |||
341 | .. _ms_visual_studio_011: |
|
341 | .. _ms_visual_studio_011: | |
342 |
|
342 | |||
343 | Integration with Microsoft Visual Studio |
|
343 | Integration with Microsoft Visual Studio | |
344 | ---------------------------------------- |
|
344 | ---------------------------------------- | |
345 |
|
345 | |||
346 | IPython can be used as the interactive shell in the `Python plugin for |
|
346 | IPython can be used as the interactive shell in the `Python plugin for | |
347 | Microsoft Visual Studio`__, as seen here: |
|
347 | Microsoft Visual Studio`__, as seen here: | |
348 |
|
348 | |||
349 | .. figure:: ../_images/ms_visual_studio.png |
|
349 | .. figure:: ../_images/ms_visual_studio.png | |
350 | :width: 500px |
|
350 | :width: 500px | |
351 | :alt: IPython console embedded in Microsoft Visual Studio. |
|
351 | :alt: IPython console embedded in Microsoft Visual Studio. | |
352 | :align: center |
|
352 | :align: center | |
353 | :target: ../_images/ms_visual_studio.png |
|
353 | :target: ../_images/ms_visual_studio.png | |
354 |
|
354 | |||
355 | IPython console embedded in Microsoft Visual Studio. |
|
355 | IPython console embedded in Microsoft Visual Studio. | |
356 |
|
356 | |||
357 | The Microsoft team developing this currently has a release candidate out using |
|
357 | The Microsoft team developing this currently has a release candidate out using | |
358 | IPython 0.11. We will continue to collaborate with them to ensure that as they |
|
358 | IPython 0.11. We will continue to collaborate with them to ensure that as they | |
359 | approach their final release date, the integration with IPython remains smooth. |
|
359 | approach their final release date, the integration with IPython remains smooth. | |
360 | We'd like to thank Dino Viehland and Shahrokh Mortazavi for the work they have |
|
360 | We'd like to thank Dino Viehland and Shahrokh Mortazavi for the work they have | |
361 | done towards this feature, as well as Wenming Ye for his support of our WinHPC |
|
361 | done towards this feature, as well as Wenming Ye for his support of our WinHPC | |
362 | capabilities. |
|
362 | capabilities. | |
363 |
|
363 | |||
364 | .. __: http://pytools.codeplex.com |
|
364 | .. __: http://pytools.codeplex.com | |
365 |
|
365 | |||
366 |
|
366 | |||
367 | Additional new features |
|
367 | Additional new features | |
368 | ----------------------- |
|
368 | ----------------------- | |
369 |
|
369 | |||
370 | * Added ``Bytes`` traitlet, removing ``Str``. All 'string' traitlets should |
|
370 | * Added ``Bytes`` traitlet, removing ``Str``. All 'string' traitlets should | |
371 | either be ``Unicode`` if a real string, or ``Bytes`` if a C-string. This |
|
371 | either be ``Unicode`` if a real string, or ``Bytes`` if a C-string. This | |
372 | removes ambiguity and helps the Python 3 transition. |
|
372 | removes ambiguity and helps the Python 3 transition. | |
373 |
|
373 | |||
374 | * New magic ``%loadpy`` loads a python file from disk or web URL into |
|
374 | * New magic ``%loadpy`` loads a python file from disk or web URL into | |
375 | the current input buffer. |
|
375 | the current input buffer. | |
376 |
|
376 | |||
377 | * New magic ``%pastebin`` for sharing code via the 'Lodge it' pastebin. |
|
377 | * New magic ``%pastebin`` for sharing code via the 'Lodge it' pastebin. | |
378 |
|
378 | |||
379 | * New magic ``%precision`` for controlling float and numpy pretty printing. |
|
379 | * New magic ``%precision`` for controlling float and numpy pretty printing. | |
380 |
|
380 | |||
381 | * IPython applications initiate logging, so any object can gain access to |
|
381 | * IPython applications initiate logging, so any object can gain access to | |
382 | a the logger of the currently running Application with: |
|
382 | a the logger of the currently running Application with: | |
383 |
|
383 | |||
384 | .. sourcecode:: python |
|
384 | .. sourcecode:: python | |
385 |
|
385 | |||
386 | from traitlets.config.application import Application |
|
386 | from traitlets.config.application import Application | |
387 | logger = Application.instance().log |
|
387 | logger = Application.instance().log | |
388 |
|
388 | |||
389 | * You can now get help on an object halfway through typing a command. For |
|
389 | * You can now get help on an object halfway through typing a command. For | |
390 | instance, typing ``a = zip?`` shows the details of :func:`zip`. It also |
|
390 | instance, typing ``a = zip?`` shows the details of :func:`zip`. It also | |
391 | leaves the command at the next prompt so you can carry on with it. |
|
391 | leaves the command at the next prompt so you can carry on with it. | |
392 |
|
392 | |||
393 | * The input history is now written to an SQLite database. The API for |
|
393 | * The input history is now written to an SQLite database. The API for | |
394 | retrieving items from the history has also been redesigned. |
|
394 | retrieving items from the history has also been redesigned. | |
395 |
|
395 | |||
396 | * The :mod:`IPython.extensions.pretty` extension has been moved out of |
|
396 | * The :mod:`IPython.extensions.pretty` extension has been moved out of | |
397 | quarantine and fully updated to the new extension API. |
|
397 | quarantine and fully updated to the new extension API. | |
398 |
|
398 | |||
399 | * New magics for loading/unloading/reloading extensions have been added: |
|
399 | * New magics for loading/unloading/reloading extensions have been added: | |
400 | ``%load_ext``, ``%unload_ext`` and ``%reload_ext``. |
|
400 | ``%load_ext``, ``%unload_ext`` and ``%reload_ext``. | |
401 |
|
401 | |||
402 | * The configuration system and configuration files are brand new. See the |
|
402 | * The configuration system and configuration files are brand new. See the | |
403 | configuration system :ref:`documentation <config_index>` for more details. |
|
403 | configuration system :ref:`documentation <config_index>` for more details. | |
404 |
|
404 | |||
405 | * The :class:`~IPython.core.interactiveshell.InteractiveShell` class is now a |
|
405 | * The :class:`~IPython.core.interactiveshell.InteractiveShell` class is now a | |
406 | :class:`~traitlets.config.configurable.Configurable` subclass and has traitlets |
|
406 | :class:`~traitlets.config.configurable.Configurable` subclass and has traitlets | |
407 | that determine the defaults and runtime environment. The ``__init__`` method |
|
407 | that determine the defaults and runtime environment. The ``__init__`` method | |
408 | has also been refactored so this class can be instantiated and run without |
|
408 | has also been refactored so this class can be instantiated and run without | |
409 | the old :mod:`ipmaker` module. |
|
409 | the old :mod:`ipmaker` module. | |
410 |
|
410 | |||
411 | * The methods of :class:`~IPython.core.interactiveshell.InteractiveShell` have |
|
411 | * The methods of :class:`~IPython.core.interactiveshell.InteractiveShell` have | |
412 | been organized into sections to make it easier to turn more sections |
|
412 | been organized into sections to make it easier to turn more sections | |
413 | of functionality into components. |
|
413 | of functionality into components. | |
414 |
|
414 | |||
415 | * The embedded shell has been refactored into a truly standalone subclass of |
|
415 | * The embedded shell has been refactored into a truly standalone subclass of | |
416 | :class:`InteractiveShell` called :class:`InteractiveShellEmbed`. All |
|
416 | :class:`InteractiveShell` called :class:`InteractiveShellEmbed`. All | |
417 | embedding logic has been taken out of the base class and put into the |
|
417 | embedding logic has been taken out of the base class and put into the | |
418 | embedded subclass. |
|
418 | embedded subclass. | |
419 |
|
419 | |||
420 | * Added methods of :class:`~IPython.core.interactiveshell.InteractiveShell` to |
|
420 | * Added methods of :class:`~IPython.core.interactiveshell.InteractiveShell` to | |
421 | help it cleanup after itself. The :meth:`cleanup` method controls this. We |
|
421 | help it cleanup after itself. The :meth:`cleanup` method controls this. We | |
422 | couldn't do this in :meth:`__del__` because we have cycles in our object |
|
422 | couldn't do this in :meth:`__del__` because we have cycles in our object | |
423 | graph that prevent it from being called. |
|
423 | graph that prevent it from being called. | |
424 |
|
424 | |||
425 | * Created a new module :mod:`IPython.utils.importstring` for resolving |
|
425 | * Created a new module :mod:`IPython.utils.importstring` for resolving | |
426 | strings like ``foo.bar.Bar`` to the actual class. |
|
426 | strings like ``foo.bar.Bar`` to the actual class. | |
427 |
|
427 | |||
428 | * Completely refactored the :mod:`IPython.core.prefilter` module into |
|
428 | * Completely refactored the :mod:`IPython.core.prefilter` module into | |
429 | :class:`~traitlets.config.configurable.Configurable` subclasses. Added a new |
|
429 | :class:`~traitlets.config.configurable.Configurable` subclasses. Added a new | |
430 | layer into the prefilter system, called "transformations" that all new |
|
430 | layer into the prefilter system, called "transformations" that all new | |
431 | prefilter logic should use (rather than the older "checker/handler" |
|
431 | prefilter logic should use (rather than the older "checker/handler" | |
432 | approach). |
|
432 | approach). | |
433 |
|
433 | |||
434 | * Aliases are now components (:mod:`IPython.core.alias`). |
|
434 | * Aliases are now components (:mod:`IPython.core.alias`). | |
435 |
|
435 | |||
436 | * New top level :func:`~IPython.frontend.terminal.embed.embed` function that can |
|
436 | * New top level :func:`~IPython.frontend.terminal.embed.embed` function that can | |
437 | be called to embed IPython at any place in user's code. On the first call it |
|
437 | be called to embed IPython at any place in user's code. On the first call it | |
438 | will create an :class:`~IPython.frontend.terminal.embed.InteractiveShellEmbed` |
|
438 | will create an :class:`~IPython.frontend.terminal.embed.InteractiveShellEmbed` | |
439 | instance and call it. In later calls, it just calls the previously created |
|
439 | instance and call it. In later calls, it just calls the previously created | |
440 | :class:`~IPython.frontend.terminal.embed.InteractiveShellEmbed`. |
|
440 | :class:`~IPython.frontend.terminal.embed.InteractiveShellEmbed`. | |
441 |
|
441 | |||
442 | * Created a configuration system (:mod:`traitlets.config.configurable`) that is |
|
442 | * Created a configuration system (:mod:`traitlets.config.configurable`) that is | |
443 | based on :mod:`traitlets`. Configurables are arranged into a |
|
443 | based on :mod:`traitlets`. Configurables are arranged into a | |
444 | runtime containment tree (not inheritance) that i) automatically propagates |
|
444 | runtime containment tree (not inheritance) that i) automatically propagates | |
445 | configuration information and ii) allows singletons to discover each other in |
|
445 | configuration information and ii) allows singletons to discover each other in | |
446 | a loosely coupled manner. In the future all parts of IPython will be |
|
446 | a loosely coupled manner. In the future all parts of IPython will be | |
447 | subclasses of :class:`~traitlets.config.configurable.Configurable`. All IPython |
|
447 | subclasses of :class:`~traitlets.config.configurable.Configurable`. All IPython | |
448 | developers should become familiar with the config system. |
|
448 | developers should become familiar with the config system. | |
449 |
|
449 | |||
450 | * Created a new :class:`~traitlets.config.loader.Config` for holding |
|
450 | * Created a new :class:`~traitlets.config.loader.Config` for holding | |
451 | configuration information. This is a dict like class with a few extras: i) |
|
451 | configuration information. This is a dict like class with a few extras: i) | |
452 | it supports attribute style access, ii) it has a merge function that merges |
|
452 | it supports attribute style access, ii) it has a merge function that merges | |
453 | two :class:`~traitlets.config.loader.Config` instances recursively and iii) it |
|
453 | two :class:`~traitlets.config.loader.Config` instances recursively and iii) it | |
454 | will automatically create sub-:class:`~traitlets.config.loader.Config` |
|
454 | will automatically create sub-:class:`~traitlets.config.loader.Config` | |
455 | instances for attributes that start with an uppercase character. |
|
455 | instances for attributes that start with an uppercase character. | |
456 |
|
456 | |||
457 | * Created new configuration loaders in :mod:`traitlets.config.loader`. These |
|
457 | * Created new configuration loaders in :mod:`traitlets.config.loader`. These | |
458 | loaders provide a unified loading interface for all configuration |
|
458 | loaders provide a unified loading interface for all configuration | |
459 | information including command line arguments and configuration files. We |
|
459 | information including command line arguments and configuration files. We | |
460 | have two default implementations based on :mod:`argparse` and plain python |
|
460 | have two default implementations based on :mod:`argparse` and plain python | |
461 | files. These are used to implement the new configuration system. |
|
461 | files. These are used to implement the new configuration system. | |
462 |
|
462 | |||
463 | * Created a top-level :class:`Application` class in |
|
463 | * Created a top-level :class:`Application` class in | |
464 | :mod:`IPython.core.application` that is designed to encapsulate the starting |
|
464 | :mod:`IPython.core.application` that is designed to encapsulate the starting | |
465 | of any basic Python program. An application loads and merges all the |
|
465 | of any basic Python program. An application loads and merges all the | |
466 | configuration objects, constructs the main application, configures and |
|
466 | configuration objects, constructs the main application, configures and | |
467 | initiates logging, and creates and configures any :class:`Configurable` |
|
467 | initiates logging, and creates and configures any :class:`Configurable` | |
468 | instances and then starts the application running. An extended |
|
468 | instances and then starts the application running. An extended | |
469 | :class:`BaseIPythonApplication` class adds logic for handling the |
|
469 | :class:`BaseIPythonApplication` class adds logic for handling the | |
470 | IPython directory as well as profiles, and all IPython entry points |
|
470 | IPython directory as well as profiles, and all IPython entry points | |
471 | extend it. |
|
471 | extend it. | |
472 |
|
472 | |||
473 | * The :class:`Type` and :class:`Instance` traitlets now handle classes given |
|
473 | * The :class:`Type` and :class:`Instance` traitlets now handle classes given | |
474 | as strings, like ``foo.bar.Bar``. This is needed for forward declarations. |
|
474 | as strings, like ``foo.bar.Bar``. This is needed for forward declarations. | |
475 | But, this was implemented in a careful way so that string to class |
|
475 | But, this was implemented in a careful way so that string to class | |
476 | resolution is done at a single point, when the parent |
|
476 | resolution is done at a single point, when the parent | |
477 | :class:`~traitlets.HasTraitlets` is instantiated. |
|
477 | :class:`~traitlets.HasTraitlets` is instantiated. | |
478 |
|
478 | |||
479 | * :mod:`IPython.utils.ipstruct` has been refactored to be a subclass of |
|
479 | * :mod:`IPython.utils.ipstruct` has been refactored to be a subclass of | |
480 | dict. It also now has full docstrings and doctests. |
|
480 | dict. It also now has full docstrings and doctests. | |
481 |
|
481 | |||
482 | * Created a Traits like implementation in :mod:`traitlets`. This |
|
482 | * Created a Traits like implementation in :mod:`traitlets`. This | |
483 | is a pure Python, lightweight version of a library that is similar to |
|
483 | is a pure Python, lightweight version of a library that is similar to | |
484 | Enthought's Traits project, but has no dependencies on Enthought's code. We |
|
484 | Enthought's Traits project, but has no dependencies on Enthought's code. We | |
485 | are using this for validation, defaults and notification in our new component |
|
485 | are using this for validation, defaults and notification in our new component | |
486 | system. Although it is not 100% API compatible with Enthought's Traits, we |
|
486 | system. Although it is not 100% API compatible with Enthought's Traits, we | |
487 | plan on moving in this direction so that eventually our implementation could |
|
487 | plan on moving in this direction so that eventually our implementation could | |
488 | be replaced by a (yet to exist) pure Python version of Enthought Traits. |
|
488 | be replaced by a (yet to exist) pure Python version of Enthought Traits. | |
489 |
|
489 | |||
490 | * Added a new module :mod:`IPython.lib.inputhook` to manage the integration |
|
490 | * Added a new module :mod:`IPython.lib.inputhook` to manage the integration | |
491 | with GUI event loops using `PyOS_InputHook`. See the docstrings in this |
|
491 | with GUI event loops using `PyOS_InputHook`. See the docstrings in this | |
492 | module or the main IPython docs for details. |
|
492 | module or the main IPython docs for details. | |
493 |
|
493 | |||
494 | * For users, GUI event loop integration is now handled through the new |
|
494 | * For users, GUI event loop integration is now handled through the new | |
495 | :command:`%gui` magic command. Type ``%gui?`` at an IPython prompt for |
|
495 | :command:`%gui` magic command. Type ``%gui?`` at an IPython prompt for | |
496 | documentation. |
|
496 | documentation. | |
497 |
|
497 | |||
498 | * For developers :mod:`IPython.lib.inputhook` provides a simple interface |
|
498 | * For developers :mod:`IPython.lib.inputhook` provides a simple interface | |
499 | for managing the event loops in their interactive GUI applications. |
|
499 | for managing the event loops in their interactive GUI applications. | |
500 | Examples can be found in our :file:`examples/lib` directory. |
|
500 | Examples can be found in our :file:`examples/lib` directory. | |
501 |
|
501 | |||
502 | Backwards incompatible changes |
|
502 | Backwards incompatible changes | |
503 | ------------------------------ |
|
503 | ------------------------------ | |
504 |
|
504 | |||
505 | * The Twisted-based :mod:`IPython.kernel` has been removed, and completely |
|
505 | * The Twisted-based :mod:`IPython.kernel` has been removed, and completely | |
506 | rewritten as :mod:`IPython.parallel`, using ZeroMQ. |
|
506 | rewritten as :mod:`IPython.parallel`, using ZeroMQ. | |
507 |
|
507 | |||
508 | * Profiles are now directories. Instead of a profile being a single config file, |
|
508 | * Profiles are now directories. Instead of a profile being a single config file, | |
509 | profiles are now self-contained directories. By default, profiles get their |
|
509 | profiles are now self-contained directories. By default, profiles get their | |
510 | own IPython history, log files, and everything. To create a new profile, do |
|
510 | own IPython history, log files, and everything. To create a new profile, do | |
511 | ``ipython profile create <name>``. |
|
511 | ``ipython profile create <name>``. | |
512 |
|
512 | |||
513 | * All IPython applications have been rewritten to use |
|
513 | * All IPython applications have been rewritten to use | |
514 | :class:`~traitlets.config.loader.KeyValueConfigLoader`. This means that |
|
514 | :class:`~traitlets.config.loader.KeyValueConfigLoader`. This means that | |
515 | command-line options have changed. Now, all configurable values are accessible |
|
515 | command-line options have changed. Now, all configurable values are accessible | |
516 | from the command-line with the same syntax as in a configuration file. |
|
516 | from the command-line with the same syntax as in a configuration file. | |
517 |
|
517 | |||
518 | * The command line options ``-wthread``, ``-qthread`` and |
|
518 | * The command line options ``-wthread``, ``-qthread`` and | |
519 | ``-gthread`` have been removed. Use ``--gui=wx``, ``--gui=qt``, ``--gui=gtk`` |
|
519 | ``-gthread`` have been removed. Use ``--gui=wx``, ``--gui=qt``, ``--gui=gtk`` | |
520 | instead. |
|
520 | instead. | |
521 |
|
521 | |||
522 | * The extension loading functions have been renamed to |
|
522 | * The extension loading functions have been renamed to | |
523 | :func:`load_ipython_extension` and :func:`unload_ipython_extension`. |
|
523 | :func:`load_ipython_extension` and :func:`unload_ipython_extension`. | |
524 |
|
524 | |||
525 | * :class:`~IPython.core.interactiveshell.InteractiveShell` no longer takes an |
|
525 | * :class:`~IPython.core.interactiveshell.InteractiveShell` no longer takes an | |
526 | ``embedded`` argument. Instead just use the |
|
526 | ``embedded`` argument. Instead just use the | |
527 | :class:`~IPython.core.interactiveshell.InteractiveShellEmbed` class. |
|
527 | :class:`~IPython.core.interactiveshell.InteractiveShellEmbed` class. | |
528 |
|
528 | |||
529 | * ``__IPYTHON__`` is no longer injected into ``__builtin__``. |
|
529 | * ``__IPYTHON__`` is no longer injected into ``__builtin__``. | |
530 |
|
530 | |||
531 | * :meth:`Struct.__init__` no longer takes `None` as its first argument. It |
|
531 | * :meth:`Struct.__init__` no longer takes `None` as its first argument. It | |
532 | must be a :class:`dict` or :class:`Struct`. |
|
532 | must be a :class:`dict` or :class:`Struct`. | |
533 |
|
533 | |||
534 | * :meth:`~IPython.core.interactiveshell.InteractiveShell.ipmagic` has been |
|
534 | * :meth:`~IPython.core.interactiveshell.InteractiveShell.ipmagic` has been | |
535 | renamed :meth:`~IPython.core.interactiveshell.InteractiveShell.magic.` |
|
535 | renamed :meth:`~IPython.core.interactiveshell.InteractiveShell.magic.` | |
536 |
|
536 | |||
537 | * The functions :func:`ipmagic` and :func:`ipalias` have been removed from |
|
537 | * The functions :func:`ipmagic` and :func:`ipalias` have been removed from | |
538 | :mod:`__builtins__`. |
|
538 | :mod:`__builtins__`. | |
539 |
|
539 | |||
540 | * The references to the global |
|
540 | * The references to the global | |
541 | :class:`~IPython.core.interactivehell.InteractiveShell` instance (``_ip``, and |
|
541 | :class:`~IPython.core.interactivehell.InteractiveShell` instance (``_ip``, and | |
542 | ``__IP``) have been removed from the user's namespace. They are replaced by a |
|
542 | ``__IP``) have been removed from the user's namespace. They are replaced by a | |
543 | new function called :func:`get_ipython` that returns the current |
|
543 | new function called :func:`get_ipython` that returns the current | |
544 | :class:`~IPython.core.interactiveshell.InteractiveShell` instance. This |
|
544 | :class:`~IPython.core.interactiveshell.InteractiveShell` instance. This | |
545 | function is injected into the user's namespace and is now the main way of |
|
545 | function is injected into the user's namespace and is now the main way of | |
546 | accessing the running IPython. |
|
546 | accessing the running IPython. | |
547 |
|
547 | |||
548 | * Old style configuration files :file:`ipythonrc` and :file:`ipy_user_conf.py` |
|
548 | * Old style configuration files :file:`ipythonrc` and :file:`ipy_user_conf.py` | |
549 | are no longer supported. Users should migrate there configuration files to |
|
549 | are no longer supported. Users should migrate there configuration files to | |
550 | the new format described :doc:`here </config/intro>` and |
|
550 | the new format described :doc:`here </config/intro>` and | |
551 | :ref:`here <config_overview>`. |
|
551 | :ref:`here <config_overview>`. | |
552 |
|
552 | |||
553 | * The old IPython extension API that relied on :func:`ipapi` has been |
|
553 | * The old IPython extension API that relied on :func:`ipapi` has been | |
554 | completely removed. The new extension API is described :ref:`here |
|
554 | completely removed. The new extension API is described :ref:`here | |
555 | <extensions_overview>`. |
|
555 | <extensions_overview>`. | |
556 |
|
556 | |||
557 | * Support for ``qt3`` has been dropped. Users who need this should use |
|
557 | * Support for ``qt3`` has been dropped. Users who need this should use | |
558 | previous versions of IPython. |
|
558 | previous versions of IPython. | |
559 |
|
559 | |||
560 | * Removed :mod:`shellglobals` as it was obsolete. |
|
560 | * Removed :mod:`shellglobals` as it was obsolete. | |
561 |
|
561 | |||
562 | * Removed all the threaded shells in :mod:`IPython.core.shell`. These are no |
|
562 | * Removed all the threaded shells in :mod:`IPython.core.shell`. These are no | |
563 | longer needed because of the new capabilities in |
|
563 | longer needed because of the new capabilities in | |
564 | :mod:`IPython.lib.inputhook`. |
|
564 | :mod:`IPython.lib.inputhook`. | |
565 |
|
565 | |||
566 | * New top-level sub-packages have been created: :mod:`IPython.core`, |
|
566 | * New top-level sub-packages have been created: :mod:`IPython.core`, | |
567 | :mod:`IPython.lib`, :mod:`IPython.utils`, :mod:`IPython.deathrow`, |
|
567 | :mod:`IPython.lib`, :mod:`IPython.utils`, :mod:`IPython.deathrow`, | |
568 | :mod:`IPython.quarantine`. All existing top-level modules have been |
|
568 | :mod:`IPython.quarantine`. All existing top-level modules have been | |
569 | moved to appropriate sub-packages. All internal import statements |
|
569 | moved to appropriate sub-packages. All internal import statements | |
570 | have been updated and tests have been added. The build system (setup.py |
|
570 | have been updated and tests have been added. The build system (setup.py | |
571 | and friends) have been updated. See :doc:`/api/index` for details of these |
|
571 | and friends) have been updated. See :doc:`/api/index` for details of these | |
572 | new sub-packages. |
|
572 | new sub-packages. | |
573 |
|
573 | |||
574 | * :mod:`IPython.ipapi` has been moved to :mod:`IPython.core.ipapi`. |
|
574 | * :mod:`IPython.ipapi` has been moved to :mod:`IPython.core.ipapi`. | |
575 | :mod:`IPython.Shell` and :mod:`IPython.iplib` have been split and removed as |
|
575 | :mod:`IPython.Shell` and :mod:`IPython.iplib` have been split and removed as | |
576 | part of the refactor. |
|
576 | part of the refactor. | |
577 |
|
577 | |||
578 | * :mod:`Extensions` has been moved to :mod:`extensions` and all existing |
|
578 | * :mod:`Extensions` has been moved to :mod:`extensions` and all existing | |
579 | extensions have been moved to either :mod:`IPython.quarantine` or |
|
579 | extensions have been moved to either :mod:`IPython.quarantine` or | |
580 | :mod:`IPython.deathrow`. :mod:`IPython.quarantine` contains modules that we |
|
580 | :mod:`IPython.deathrow`. :mod:`IPython.quarantine` contains modules that we | |
581 | plan on keeping but that need to be updated. :mod:`IPython.deathrow` contains |
|
581 | plan on keeping but that need to be updated. :mod:`IPython.deathrow` contains | |
582 | modules that are either dead or that should be maintained as third party |
|
582 | modules that are either dead or that should be maintained as third party | |
583 | libraries. |
|
583 | libraries. | |
584 |
|
584 | |||
585 | * Previous IPython GUIs in :mod:`IPython.frontend` and :mod:`IPython.gui` are |
|
585 | * Previous IPython GUIs in :mod:`IPython.frontend` and :mod:`IPython.gui` are | |
586 | likely broken, and have been removed to :mod:`IPython.deathrow` because of the |
|
586 | likely broken, and have been removed to :mod:`IPython.deathrow` because of the | |
587 | refactoring in the core. With proper updates, these should still work. |
|
587 | refactoring in the core. With proper updates, these should still work. | |
588 |
|
588 | |||
589 |
|
589 | |||
590 | Known Regressions |
|
590 | Known Regressions | |
591 | ----------------- |
|
591 | ----------------- | |
592 |
|
592 | |||
593 | We do our best to improve IPython, but there are some known regressions in 0.11 |
|
593 | We do our best to improve IPython, but there are some known regressions in 0.11 | |
594 | relative to 0.10.2. First of all, there are features that have yet to be |
|
594 | relative to 0.10.2. First of all, there are features that have yet to be | |
595 | ported to the new APIs, and in order to ensure that all of the installed code |
|
595 | ported to the new APIs, and in order to ensure that all of the installed code | |
596 | runs for our users, we have moved them to two separate directories in the |
|
596 | runs for our users, we have moved them to two separate directories in the | |
597 | source distribution, `quarantine` and `deathrow`. Finally, we have some other |
|
597 | source distribution, `quarantine` and `deathrow`. Finally, we have some other | |
598 | miscellaneous regressions that we hope to fix as soon as possible. We now |
|
598 | miscellaneous regressions that we hope to fix as soon as possible. We now | |
599 | describe all of these in more detail. |
|
599 | describe all of these in more detail. | |
600 |
|
600 | |||
601 | Quarantine |
|
601 | Quarantine | |
602 | ~~~~~~~~~~ |
|
602 | ~~~~~~~~~~ | |
603 |
|
603 | |||
604 | These are tools and extensions that we consider relatively easy to update to |
|
604 | These are tools and extensions that we consider relatively easy to update to | |
605 | the new classes and APIs, but that we simply haven't had time for. Any user |
|
605 | the new classes and APIs, but that we simply haven't had time for. Any user | |
606 | who is interested in one of these is encouraged to help us by porting it and |
|
606 | who is interested in one of these is encouraged to help us by porting it and | |
607 | submitting a pull request on our `development site`_. |
|
607 | submitting a pull request on our `development site`_. | |
608 |
|
608 | |||
609 | .. _development site: http://github.com/ipython/ipython |
|
609 | .. _development site: http://github.com/ipython/ipython | |
610 |
|
610 | |||
611 | Currently, the quarantine directory contains:: |
|
611 | Currently, the quarantine directory contains:: | |
612 |
|
612 | |||
613 | clearcmd.py ipy_fsops.py ipy_signals.py |
|
613 | clearcmd.py ipy_fsops.py ipy_signals.py | |
614 | envpersist.py ipy_gnuglobal.py ipy_synchronize_with.py |
|
614 | envpersist.py ipy_gnuglobal.py ipy_synchronize_with.py | |
615 | ext_rescapture.py ipy_greedycompleter.py ipy_system_conf.py |
|
615 | ext_rescapture.py ipy_greedycompleter.py ipy_system_conf.py | |
616 | InterpreterExec.py ipy_jot.py ipy_which.py |
|
616 | InterpreterExec.py ipy_jot.py ipy_which.py | |
617 | ipy_app_completers.py ipy_lookfor.py ipy_winpdb.py |
|
617 | ipy_app_completers.py ipy_lookfor.py ipy_winpdb.py | |
618 | ipy_autoreload.py ipy_profile_doctest.py ipy_workdir.py |
|
618 | ipy_autoreload.py ipy_profile_doctest.py ipy_workdir.py | |
619 | ipy_completers.py ipy_pydb.py jobctrl.py |
|
619 | ipy_completers.py ipy_pydb.py jobctrl.py | |
620 | ipy_editors.py ipy_rehashdir.py ledit.py |
|
620 | ipy_editors.py ipy_rehashdir.py ledit.py | |
621 | ipy_exportdb.py ipy_render.py pspersistence.py |
|
621 | ipy_exportdb.py ipy_render.py pspersistence.py | |
622 | ipy_extutil.py ipy_server.py win32clip.py |
|
622 | ipy_extutil.py ipy_server.py win32clip.py | |
623 |
|
623 | |||
624 | Deathrow |
|
624 | Deathrow | |
625 | ~~~~~~~~ |
|
625 | ~~~~~~~~ | |
626 |
|
626 | |||
627 | These packages may be harder to update or make most sense as third-party |
|
627 | These packages may be harder to update or make most sense as third-party | |
628 | libraries. Some of them are completely obsolete and have been already replaced |
|
628 | libraries. Some of them are completely obsolete and have been already replaced | |
629 | by better functionality (we simply haven't had the time to carefully weed them |
|
629 | by better functionality (we simply haven't had the time to carefully weed them | |
630 | out so they are kept here for now). Others simply require fixes to code that |
|
630 | out so they are kept here for now). Others simply require fixes to code that | |
631 | the current core team may not be familiar with. If a tool you were used to is |
|
631 | the current core team may not be familiar with. If a tool you were used to is | |
632 | included here, we encourage you to contact the dev list and we can discuss |
|
632 | included here, we encourage you to contact the dev list and we can discuss | |
633 | whether it makes sense to keep it in IPython (if it can be maintained). |
|
633 | whether it makes sense to keep it in IPython (if it can be maintained). | |
634 |
|
634 | |||
635 | Currently, the deathrow directory contains:: |
|
635 | Currently, the deathrow directory contains:: | |
636 |
|
636 | |||
637 | astyle.py ipy_defaults.py ipy_vimserver.py |
|
637 | astyle.py ipy_defaults.py ipy_vimserver.py | |
638 | dtutils.py ipy_kitcfg.py numeric_formats.py |
|
638 | dtutils.py ipy_kitcfg.py numeric_formats.py | |
639 | Gnuplot2.py ipy_legacy.py numutils.py |
|
639 | Gnuplot2.py ipy_legacy.py numutils.py | |
640 | GnuplotInteractive.py ipy_p4.py outputtrap.py |
|
640 | GnuplotInteractive.py ipy_p4.py outputtrap.py | |
641 | GnuplotRuntime.py ipy_profile_none.py PhysicalQInput.py |
|
641 | GnuplotRuntime.py ipy_profile_none.py PhysicalQInput.py | |
642 | ibrowse.py ipy_profile_numpy.py PhysicalQInteractive.py |
|
642 | ibrowse.py ipy_profile_numpy.py PhysicalQInteractive.py | |
643 | igrid.py ipy_profile_scipy.py quitter.py* |
|
643 | igrid.py ipy_profile_scipy.py quitter.py* | |
644 | ipipe.py ipy_profile_sh.py scitedirector.py |
|
644 | ipipe.py ipy_profile_sh.py scitedirector.py | |
645 | iplib.py ipy_profile_zope.py Shell.py |
|
645 | iplib.py ipy_profile_zope.py Shell.py | |
646 | ipy_constants.py ipy_traits_completer.py twshell.py |
|
646 | ipy_constants.py ipy_traits_completer.py twshell.py | |
647 |
|
647 | |||
648 |
|
648 | |||
649 | Other regressions |
|
649 | Other regressions | |
650 | ~~~~~~~~~~~~~~~~~ |
|
650 | ~~~~~~~~~~~~~~~~~ | |
651 |
|
651 | |||
652 | * The machinery that adds functionality to the 'sh' profile for using IPython |
|
652 | * The machinery that adds functionality to the 'sh' profile for using IPython | |
653 | as your system shell has not been updated to use the new APIs. As a result, |
|
653 | as your system shell has not been updated to use the new APIs. As a result, | |
654 | only the aesthetic (prompt) changes are still implemented. We intend to fix |
|
654 | only the aesthetic (prompt) changes are still implemented. We intend to fix | |
655 | this by 0.12. Tracked as issue 547_. |
|
655 | this by 0.12. Tracked as issue 547_. | |
656 |
|
656 | |||
657 | .. _547: https://github.com/ipython/ipython/issues/547 |
|
657 | .. _547: https://github.com/ipython/ipython/issues/547 | |
658 |
|
658 | |||
659 | * The installation of scripts on Windows was broken without setuptools, so we |
|
659 | * The installation of scripts on Windows was broken without setuptools, so we | |
660 | now depend on setuptools on Windows. We hope to fix setuptools-less |
|
660 | now depend on setuptools on Windows. We hope to fix setuptools-less | |
661 | installation, and then remove the setuptools dependency. Issue 539_. |
|
661 | installation, and then remove the setuptools dependency. Issue 539_. | |
662 |
|
662 | |||
663 | .. _539: https://github.com/ipython/ipython/issues/539 |
|
663 | .. _539: https://github.com/ipython/ipython/issues/539 | |
664 |
|
664 | |||
665 | * The directory history `_dh` is not saved between sessions. Issue 634_. |
|
665 | * The directory history `_dh` is not saved between sessions. Issue 634_. | |
666 |
|
666 | |||
667 | .. _634: https://github.com/ipython/ipython/issues/634 |
|
667 | .. _634: https://github.com/ipython/ipython/issues/634 | |
668 |
|
668 | |||
669 |
|
669 | |||
670 | Removed Features |
|
670 | Removed Features | |
671 | ---------------- |
|
671 | ---------------- | |
672 |
|
672 | |||
673 | As part of the updating of IPython, we have removed a few features for the |
|
673 | As part of the updating of IPython, we have removed a few features for the | |
674 | purposes of cleaning up the codebase and interfaces. These removals are |
|
674 | purposes of cleaning up the codebase and interfaces. These removals are | |
675 | permanent, but for any item listed below, equivalent functionality is |
|
675 | permanent, but for any item listed below, equivalent functionality is | |
676 | available. |
|
676 | available. | |
677 |
|
677 | |||
678 | * The magics Exit and Quit have been dropped as ways to exit IPython. Instead, |
|
678 | * The magics Exit and Quit have been dropped as ways to exit IPython. Instead, | |
679 | the lowercase forms of both work either as a bare name (``exit``) or a |
|
679 | the lowercase forms of both work either as a bare name (``exit``) or a | |
680 | function call (``exit()``). You can assign these to other names using |
|
680 | function call (``exit()``). You can assign these to other names using | |
681 | exec_lines in the config file. |
|
681 | exec_lines in the config file. | |
682 |
|
682 | |||
683 |
|
683 | |||
684 | .. _credits_011: |
|
684 | .. _credits_011: | |
685 |
|
685 | |||
686 | Credits |
|
686 | Credits | |
687 | ------- |
|
687 | ------- | |
688 |
|
688 | |||
689 | Many users and developers contributed code, features, bug reports and ideas to |
|
689 | Many users and developers contributed code, features, bug reports and ideas to | |
690 | this release. Please do not hesitate in contacting us if we've failed to |
|
690 | this release. Please do not hesitate in contacting us if we've failed to | |
691 | acknowledge your contribution here. In particular, for this release we have |
|
691 | acknowledge your contribution here. In particular, for this release we have | |
692 | contribution from the following people, a mix of new and regular names (in |
|
692 | contribution from the following people, a mix of new and regular names (in | |
693 | alphabetical order by first name): |
|
693 | alphabetical order by first name): | |
694 |
|
694 | |||
695 | * Aenugu Sai Kiran Reddy <saikrn08-at-gmail.com> |
|
695 | * Aenugu Sai Kiran Reddy <saikrn08-at-gmail.com> | |
696 | * andy wilson <wilson.andrew.j+github-at-gmail.com> |
|
696 | * andy wilson <wilson.andrew.j+github-at-gmail.com> | |
697 | * Antonio Cuni <antocuni> |
|
697 | * Antonio Cuni <antocuni> | |
698 | * Barry Wark <barrywark-at-gmail.com> |
|
698 | * Barry Wark <barrywark-at-gmail.com> | |
699 | * Beetoju Anuradha <anu.beethoju-at-gmail.com> |
|
699 | * Beetoju Anuradha <anu.beethoju-at-gmail.com> | |
700 | * Benjamin Ragan-Kelley <minrk-at-Mercury.local> |
|
700 | * Benjamin Ragan-Kelley <minrk-at-Mercury.local> | |
701 | * Brad Reisfeld |
|
701 | * Brad Reisfeld | |
702 | * Brian E. Granger <ellisonbg-at-gmail.com> |
|
702 | * Brian E. Granger <ellisonbg-at-gmail.com> | |
703 | * Christoph Gohlke <cgohlke-at-uci.edu> |
|
703 | * Christoph Gohlke <cgohlke-at-uci.edu> | |
704 | * Cody Precord |
|
704 | * Cody Precord | |
705 | * dan.milstein |
|
705 | * dan.milstein | |
706 | * Darren Dale <dsdale24-at-gmail.com> |
|
706 | * Darren Dale <dsdale24-at-gmail.com> | |
707 | * Dav Clark <davclark-at-berkeley.edu> |
|
707 | * Dav Clark <davclark-at-berkeley.edu> | |
708 | * David Warde-Farley <wardefar-at-iro.umontreal.ca> |
|
708 | * David Warde-Farley <wardefar-at-iro.umontreal.ca> | |
709 | * epatters <ejpatters-at-gmail.com> |
|
709 | * epatters <ejpatters-at-gmail.com> | |
710 | * epatters <epatters-at-caltech.edu> |
|
710 | * epatters <epatters-at-caltech.edu> | |
711 | * epatters <epatters-at-enthought.com> |
|
711 | * epatters <epatters-at-enthought.com> | |
712 | * Eric Firing <efiring-at-hawaii.edu> |
|
712 | * Eric Firing <efiring-at-hawaii.edu> | |
713 | * Erik Tollerud <erik.tollerud-at-gmail.com> |
|
713 | * Erik Tollerud <erik.tollerud-at-gmail.com> | |
714 | * Evan Patterson <epatters-at-enthought.com> |
|
714 | * Evan Patterson <epatters-at-enthought.com> | |
715 | * Fernando Perez <Fernando.Perez-at-berkeley.edu> |
|
715 | * Fernando Perez <Fernando.Perez-at-berkeley.edu> | |
716 | * Gael Varoquaux <gael.varoquaux-at-normalesup.org> |
|
716 | * Gael Varoquaux <gael.varoquaux-at-normalesup.org> | |
717 | * Gerardo <muzgash-at-Muzpelheim> |
|
717 | * Gerardo <muzgash-at-Muzpelheim> | |
718 | * Jason Grout <jason.grout-at-drake.edu> |
|
718 | * Jason Grout <jason.grout-at-drake.edu> | |
719 | * John Hunter <jdh2358-at-gmail.com> |
|
719 | * John Hunter <jdh2358-at-gmail.com> | |
720 | * Jens Hedegaard Nielsen <jenshnielsen-at-gmail.com> |
|
720 | * Jens Hedegaard Nielsen <jenshnielsen-at-gmail.com> | |
721 | * Johann Cohen-Tanugi <johann.cohentanugi-at-gmail.com> |
|
721 | * Johann Cohen-Tanugi <johann.cohentanugi-at-gmail.com> | |
722 | * JΓΆrgen Stenarson <jorgen.stenarson-at-bostream.nu> |
|
722 | * JΓΆrgen Stenarson <jorgen.stenarson-at-bostream.nu> | |
723 | * Justin Riley <justin.t.riley-at-gmail.com> |
|
723 | * Justin Riley <justin.t.riley-at-gmail.com> | |
724 | * Kiorky |
|
724 | * Kiorky | |
725 | * Laurent Dufrechou <laurent.dufrechou-at-gmail.com> |
|
725 | * Laurent Dufrechou <laurent.dufrechou-at-gmail.com> | |
726 | * Luis Pedro Coelho <lpc-at-cmu.edu> |
|
726 | * Luis Pedro Coelho <lpc-at-cmu.edu> | |
727 | * Mani chandra <mchandra-at-iitk.ac.in> |
|
727 | * Mani chandra <mchandra-at-iitk.ac.in> | |
728 | * Mark E. Smith |
|
728 | * Mark E. Smith | |
729 | * Mark Voorhies <mark.voorhies-at-ucsf.edu> |
|
729 | * Mark Voorhies <mark.voorhies-at-ucsf.edu> | |
730 | * Martin Spacek <git-at-mspacek.mm.st> |
|
730 | * Martin Spacek <git-at-mspacek.mm.st> | |
731 | * Michael Droettboom <mdroe-at-stsci.edu> |
|
731 | * Michael Droettboom <mdroe-at-stsci.edu> | |
732 | * MinRK <benjaminrk-at-gmail.com> |
|
732 | * MinRK <benjaminrk-at-gmail.com> | |
733 | * muzuiget <muzuiget-at-gmail.com> |
|
733 | * muzuiget <muzuiget-at-gmail.com> | |
734 | * Nick Tarleton <nick-at-quixey.com> |
|
734 | * Nick Tarleton <nick-at-quixey.com> | |
735 | * Nicolas Rougier <Nicolas.rougier-at-inria.fr> |
|
735 | * Nicolas Rougier <Nicolas.rougier-at-inria.fr> | |
736 | * Omar Andres Zapata Mesa <andresete.chaos-at-gmail.com> |
|
736 | * Omar Andres Zapata Mesa <andresete.chaos-at-gmail.com> | |
737 | * Paul Ivanov <pivanov314-at-gmail.com> |
|
737 | * Paul Ivanov <pivanov314-at-gmail.com> | |
738 | * Pauli Virtanen <pauli.virtanen-at-iki.fi> |
|
738 | * Pauli Virtanen <pauli.virtanen-at-iki.fi> | |
739 | * Prabhu Ramachandran |
|
739 | * Prabhu Ramachandran | |
740 | * Ramana <sramana9-at-gmail.com> |
|
740 | * Ramana <sramana9-at-gmail.com> | |
741 | * Robert Kern <robert.kern-at-gmail.com> |
|
741 | * Robert Kern <robert.kern-at-gmail.com> | |
742 | * Sathesh Chandra <satheshchandra88-at-gmail.com> |
|
742 | * Sathesh Chandra <satheshchandra88-at-gmail.com> | |
743 | * Satrajit Ghosh <satra-at-mit.edu> |
|
743 | * Satrajit Ghosh <satra-at-mit.edu> | |
744 | * Sebastian Busch |
|
744 | * Sebastian Busch | |
745 | * Skipper Seabold <jsseabold-at-gmail.com> |
|
745 | * Skipper Seabold <jsseabold-at-gmail.com> | |
746 | * Stefan van der Walt <bzr-at-mentat.za.net> |
|
746 | * Stefan van der Walt <bzr-at-mentat.za.net> | |
747 | * Stephan Peijnik <debian-at-sp.or.at> |
|
747 | * Stephan Peijnik <debian-at-sp.or.at> | |
748 | * Steven Bethard |
|
748 | * Steven Bethard | |
749 | * Thomas Kluyver <takowl-at-gmail.com> |
|
749 | * Thomas Kluyver <takowl-at-gmail.com> | |
750 | * Thomas Spura <tomspur-at-fedoraproject.org> |
|
750 | * Thomas Spura <tomspur-at-fedoraproject.org> | |
751 | * Tom Fetherston <tfetherston-at-aol.com> |
|
751 | * Tom Fetherston <tfetherston-at-aol.com> | |
752 | * Tom MacWright |
|
752 | * Tom MacWright | |
753 | * tzanko |
|
753 | * tzanko | |
754 | * vankayala sowjanya <hai.sowjanya-at-gmail.com> |
|
754 | * vankayala sowjanya <hai.sowjanya-at-gmail.com> | |
755 | * Vivian De Smedt <vds2212-at-VIVIAN> |
|
755 | * Vivian De Smedt <vds2212-at-VIVIAN> | |
756 | * Ville M. Vainio <vivainio-at-gmail.com> |
|
756 | * Ville M. Vainio <vivainio-at-gmail.com> | |
757 | * Vishal Vatsa <vishal.vatsa-at-gmail.com> |
|
757 | * Vishal Vatsa <vishal.vatsa-at-gmail.com> | |
758 | * Vishnu S G <sgvishnu777-at-gmail.com> |
|
758 | * Vishnu S G <sgvishnu777-at-gmail.com> | |
759 | * Walter Doerwald <walter-at-livinglogic.de> |
|
759 | * Walter Doerwald <walter-at-livinglogic.de> | |
760 |
|
760 | |||
761 | .. note:: |
|
761 | .. note:: | |
762 |
|
762 | |||
763 | This list was generated with the output of |
|
763 | This list was generated with the output of | |
764 | ``git log dev-0.11 HEAD --format='* %aN <%aE>' | sed 's/@/\-at\-/' | sed 's/<>//' | sort -u`` |
|
764 | ``git log dev-0.11 HEAD --format='* %aN <%aE>' | sed 's/@/\-at\-/' | sed 's/<>//' | sort -u`` | |
765 | after some cleanup. If you should be on this list, please add yourself. |
|
765 | after some cleanup. If you should be on this list, please add yourself. |
@@ -1,673 +1,670 b'' | |||||
1 | ============= |
|
1 | ============= | |
2 | 0.13 Series |
|
2 | 0.13 Series | |
3 | ============= |
|
3 | ============= | |
4 |
|
4 | |||
5 | Release 0.13 |
|
5 | Release 0.13 | |
6 | ============ |
|
6 | ============ | |
7 |
|
7 | |||
8 | IPython 0.13 contains several major new features, as well as a large amount of |
|
8 | IPython 0.13 contains several major new features, as well as a large amount of | |
9 | bug and regression fixes. The previous version (0.12) was released on December |
|
9 | bug and regression fixes. The previous version (0.12) was released on December | |
10 | 19 2011, and in this development cycle we had: |
|
10 | 19 2011, and in this development cycle we had: | |
11 |
|
11 | |||
12 | - ~6 months of work. |
|
12 | - ~6 months of work. | |
13 | - 373 pull requests merged. |
|
13 | - 373 pull requests merged. | |
14 | - 742 issues closed (non-pull requests). |
|
14 | - 742 issues closed (non-pull requests). | |
15 | - contributions from 62 authors. |
|
15 | - contributions from 62 authors. | |
16 | - 1760 commits. |
|
16 | - 1760 commits. | |
17 | - a diff of 114226 lines. |
|
17 | - a diff of 114226 lines. | |
18 |
|
18 | |||
19 | The amount of work included in this release is so large, that we can only cover |
|
19 | The amount of work included in this release is so large, that we can only cover | |
20 | here the main highlights; please see our :ref:`detailed release statistics |
|
20 | here the main highlights; please see our :ref:`detailed release statistics | |
21 | <issues_list_013>` for links to every issue and pull request closed on GitHub |
|
21 | <issues_list_013>` for links to every issue and pull request closed on GitHub | |
22 | as well as a full list of individual contributors. |
|
22 | as well as a full list of individual contributors. | |
23 |
|
23 | |||
24 |
|
24 | |||
25 | Major Notebook improvements: new user interface and more |
|
25 | Major Notebook improvements: new user interface and more | |
26 | -------------------------------------------------------- |
|
26 | -------------------------------------------------------- | |
27 |
|
27 | |||
28 | The IPython Notebook, which has proven since its release to be wildly popular, |
|
28 | The IPython Notebook, which has proven since its release to be wildly popular, | |
29 | has seen a massive amount of work in this release cycle, leading to a |
|
29 | has seen a massive amount of work in this release cycle, leading to a | |
30 | significantly improved user experience as well as many new features. |
|
30 | significantly improved user experience as well as many new features. | |
31 |
|
31 | |||
32 | The first user-visible change is a reorganization of the user interface; the |
|
32 | The first user-visible change is a reorganization of the user interface; the | |
33 | left panel has been removed and was replaced by a real menu system and a |
|
33 | left panel has been removed and was replaced by a real menu system and a | |
34 | toolbar with icons. Both the toolbar and the header above the menu can be |
|
34 | toolbar with icons. Both the toolbar and the header above the menu can be | |
35 | collapsed to leave an unobstructed working area: |
|
35 | collapsed to leave an unobstructed working area: | |
36 |
|
36 | |||
37 | .. image:: ../_images/ipy_013_notebook_spectrogram.png |
|
37 | .. image:: ../_images/ipy_013_notebook_spectrogram.png | |
38 | :width: 460px |
|
38 | :width: 460px | |
39 | :alt: New user interface for Notebook |
|
39 | :alt: New user interface for Notebook | |
40 | :align: center |
|
40 | :align: center | |
41 | :target: ../_images/ipy_013_notebook_spectrogram.png |
|
41 | :target: ../_images/ipy_013_notebook_spectrogram.png | |
42 |
|
42 | |||
43 | The notebook handles very long outputs much better than before (this was a |
|
43 | The notebook handles very long outputs much better than before (this was a | |
44 | serious usability issue when running processes that generated massive amounts |
|
44 | serious usability issue when running processes that generated massive amounts | |
45 | of output). Now, in the presence of outputs longer than ~100 lines, the |
|
45 | of output). Now, in the presence of outputs longer than ~100 lines, the | |
46 | notebook will automatically collapse to a scrollable area and the entire left |
|
46 | notebook will automatically collapse to a scrollable area and the entire left | |
47 | part of this area controls the display: one click in this area will expand the |
|
47 | part of this area controls the display: one click in this area will expand the | |
48 | output region completely, and a double-click will hide it completely. This |
|
48 | output region completely, and a double-click will hide it completely. This | |
49 | figure shows both the scrolled and hidden modes: |
|
49 | figure shows both the scrolled and hidden modes: | |
50 |
|
50 | |||
51 | .. image:: ../_images/ipy_013_notebook_long_out.png |
|
51 | .. image:: ../_images/ipy_013_notebook_long_out.png | |
52 | :width: 460px |
|
52 | :width: 460px | |
53 | :alt: Scrolling and hiding of long output in the notebook. |
|
53 | :alt: Scrolling and hiding of long output in the notebook. | |
54 | :align: center |
|
54 | :align: center | |
55 | :target: ../_images/ipy_013_notebook_long_out.png |
|
55 | :target: ../_images/ipy_013_notebook_long_out.png | |
56 |
|
56 | |||
57 | .. note:: |
|
57 | .. note:: | |
58 |
|
58 | |||
59 | The auto-folding of long outputs is disabled in Firefox due to bugs in its |
|
59 | The auto-folding of long outputs is disabled in Firefox due to bugs in its | |
60 | scrolling behavior. See :ghpull:`2047` for details. |
|
60 | scrolling behavior. See :ghpull:`2047` for details. | |
61 |
|
61 | |||
62 | Uploading notebooks to the dashboard is now easier: in addition to drag and |
|
62 | Uploading notebooks to the dashboard is now easier: in addition to drag and | |
63 | drop (which can be finicky sometimes), you can now click on the upload text and |
|
63 | drop (which can be finicky sometimes), you can now click on the upload text and | |
64 | use a regular file dialog box to select notebooks to upload. Furthermore, the |
|
64 | use a regular file dialog box to select notebooks to upload. Furthermore, the | |
65 | notebook dashboard now auto-refreshes its contents and offers buttons to shut |
|
65 | notebook dashboard now auto-refreshes its contents and offers buttons to shut | |
66 | down any running kernels (:ghpull:`1739`): |
|
66 | down any running kernels (:ghpull:`1739`): | |
67 |
|
67 | |||
68 | .. image:: ../_images/ipy_013_dashboard.png |
|
68 | .. image:: ../_images/ipy_013_dashboard.png | |
69 | :width: 460px |
|
69 | :width: 460px | |
70 | :alt: Improved dashboard |
|
70 | :alt: Improved dashboard | |
71 | :align: center |
|
71 | :align: center | |
72 | :target: ../_images/ipy_013_dashboard.png |
|
72 | :target: ../_images/ipy_013_dashboard.png | |
73 |
|
73 | |||
74 |
|
74 | |||
75 | Cluster management |
|
75 | Cluster management | |
76 | ~~~~~~~~~~~~~~~~~~ |
|
76 | ~~~~~~~~~~~~~~~~~~ | |
77 |
|
77 | |||
78 | The notebook dashboard can now also start and stop clusters, thanks to a new |
|
78 | The notebook dashboard can now also start and stop clusters, thanks to a new | |
79 | tab in the dashboard user interface: |
|
79 | tab in the dashboard user interface: | |
80 |
|
80 | |||
81 | .. image:: ../_images/ipy_013_dashboard_cluster.png |
|
81 | .. image:: ../_images/ipy_013_dashboard_cluster.png | |
82 | :width: 460px |
|
82 | :width: 460px | |
83 | :alt: Cluster management from the notebook dashboard |
|
83 | :alt: Cluster management from the notebook dashboard | |
84 | :align: center |
|
84 | :align: center | |
85 | :target: ../_images/ipy_013_dashboard_cluster.png |
|
85 | :target: ../_images/ipy_013_dashboard_cluster.png | |
86 |
|
86 | |||
87 | This interface allows, for each profile you have configured, to start and stop |
|
87 | This interface allows, for each profile you have configured, to start and stop | |
88 | a cluster (and optionally override the default number of engines corresponding |
|
88 | a cluster (and optionally override the default number of engines corresponding | |
89 | to that configuration). While this hides all error reporting, once you have a |
|
89 | to that configuration). While this hides all error reporting, once you have a | |
90 | configuration that you know works smoothly, it is a very convenient interface |
|
90 | configuration that you know works smoothly, it is a very convenient interface | |
91 | for controlling your parallel resources. |
|
91 | for controlling your parallel resources. | |
92 |
|
92 | |||
93 |
|
93 | |||
94 | New notebook format |
|
94 | New notebook format | |
95 | ~~~~~~~~~~~~~~~~~~~ |
|
95 | ~~~~~~~~~~~~~~~~~~~ | |
96 |
|
96 | |||
97 | The notebooks saved now use version 3 of our format, which supports heading |
|
97 | The notebooks saved now use version 3 of our format, which supports heading | |
98 | levels as well as the concept of 'raw' text cells that are not rendered as |
|
98 | levels as well as the concept of 'raw' text cells that are not rendered as | |
99 | Markdown. These will be useful with converters_ we are developing, to pass raw |
|
99 | Markdown. These will be useful with converters_ we are developing, to pass raw | |
100 | markup (say LaTeX). That conversion code is still under heavy development and |
|
100 | markup (say LaTeX). That conversion code is still under heavy development and | |
101 | not quite ready for prime time, but we welcome help on this front so that we |
|
101 | not quite ready for prime time, but we welcome help on this front so that we | |
102 | can merge it for full production use as soon as possible. |
|
102 | can merge it for full production use as soon as possible. | |
103 |
|
103 | |||
104 | .. _converters: https://github.com/ipython/nbconvert |
|
104 | .. _converters: https://github.com/ipython/nbconvert | |
105 |
|
105 | |||
106 | .. note:: |
|
106 | .. note:: | |
107 |
|
107 | |||
108 | v3 notebooks can *not* be read by older versions of IPython, but we provide |
|
108 | v3 notebooks can *not* be read by older versions of IPython, but we provide | |
109 | a `simple script`_ that you can use in case you need to export a v3 |
|
109 | a `simple script`_ that you can use in case you need to export a v3 | |
110 | notebook to share with a v2 user. |
|
110 | notebook to share with a v2 user. | |
111 |
|
111 | |||
112 | .. _simple script: https://gist.github.com/1935808 |
|
112 | .. _simple script: https://gist.github.com/1935808 | |
113 |
|
113 | |||
114 |
|
114 | |||
115 | JavaScript refactoring |
|
115 | JavaScript refactoring | |
116 | ~~~~~~~~~~~~~~~~~~~~~~ |
|
116 | ~~~~~~~~~~~~~~~~~~~~~~ | |
117 |
|
117 | |||
118 | All the client-side JavaScript has been decoupled to ease reuse of parts of the |
|
118 | All the client-side JavaScript has been decoupled to ease reuse of parts of the | |
119 | machinery without having to build a full-blown notebook. This will make it much |
|
119 | machinery without having to build a full-blown notebook. This will make it much | |
120 | easier to communicate with an IPython kernel from existing web pages and to |
|
120 | easier to communicate with an IPython kernel from existing web pages and to | |
121 | integrate single cells into other sites, without loading the full notebook |
|
121 | integrate single cells into other sites, without loading the full notebook | |
122 | document-like UI. :ghpull:`1711`. |
|
122 | document-like UI. :ghpull:`1711`. | |
123 |
|
123 | |||
124 | This refactoring also enables the possibility of writing dynamic javascript |
|
124 | This refactoring also enables the possibility of writing dynamic javascript | |
125 | widgets that are returned from Python code and that present an interactive view |
|
125 | widgets that are returned from Python code and that present an interactive view | |
126 | to the user, with callbacks in Javascript executing calls to the Kernel. This |
|
126 | to the user, with callbacks in Javascript executing calls to the Kernel. This | |
127 | will enable many interactive elements to be added by users in notebooks. |
|
127 | will enable many interactive elements to be added by users in notebooks. | |
128 |
|
128 | |||
129 | An example of this capability has been provided as a proof of concept in |
|
129 | An example of this capability has been provided as a proof of concept in | |
130 | :file:`examples/widgets` that lets you directly communicate with one or more |
|
130 | :file:`examples/widgets` that lets you directly communicate with one or more | |
131 | parallel engines, acting as a mini-console for parallel debugging and |
|
131 | parallel engines, acting as a mini-console for parallel debugging and | |
132 | introspection. |
|
132 | introspection. | |
133 |
|
133 | |||
134 |
|
134 | |||
135 | Improved tooltips |
|
135 | Improved tooltips | |
136 | ~~~~~~~~~~~~~~~~~ |
|
136 | ~~~~~~~~~~~~~~~~~ | |
137 |
|
137 | |||
138 | The object tooltips have gained some new functionality. By pressing tab several |
|
138 | The object tooltips have gained some new functionality. By pressing tab several | |
139 | times, you can expand them to see more of a docstring, keep them visible as you |
|
139 | times, you can expand them to see more of a docstring, keep them visible as you | |
140 | fill in a function's parameters, or transfer the information to the pager at the |
|
140 | fill in a function's parameters, or transfer the information to the pager at the | |
141 | bottom of the screen. For the details, look at the example notebook |
|
141 | bottom of the screen. For the details, look at the example notebook | |
142 | :file:`01_notebook_introduction.ipynb`. |
|
142 | :file:`01_notebook_introduction.ipynb`. | |
143 |
|
143 | |||
144 | .. figure:: ../_images/ipy_013_notebook_tooltip.png |
|
144 | .. figure:: ../_images/ipy_013_notebook_tooltip.png | |
145 | :width: 460px |
|
145 | :width: 460px | |
146 | :alt: Improved tooltips in the notebook. |
|
146 | :alt: Improved tooltips in the notebook. | |
147 | :align: center |
|
147 | :align: center | |
148 | :target: ../_images/ipy_013_notebook_tooltip.png |
|
148 | :target: ../_images/ipy_013_notebook_tooltip.png | |
149 |
|
149 | |||
150 | The new notebook tooltips. |
|
150 | The new notebook tooltips. | |
151 |
|
151 | |||
152 | Other improvements to the Notebook |
|
152 | Other improvements to the Notebook | |
153 | ---------------------------------- |
|
153 | ---------------------------------- | |
154 |
|
154 | |||
155 | These are some other notable small improvements to the notebook, in addition to |
|
155 | These are some other notable small improvements to the notebook, in addition to | |
156 | many bug fixes and minor changes to add polish and robustness throughout: |
|
156 | many bug fixes and minor changes to add polish and robustness throughout: | |
157 |
|
157 | |||
158 | * The notebook pager (the area at the bottom) is now resizeable by dragging its |
|
158 | * The notebook pager (the area at the bottom) is now resizeable by dragging its | |
159 | divider handle, a feature that had been requested many times by just about |
|
159 | divider handle, a feature that had been requested many times by just about | |
160 | anyone who had used the notebook system. :ghpull:`1705`. |
|
160 | anyone who had used the notebook system. :ghpull:`1705`. | |
161 |
|
161 | |||
162 | * It is now possible to open notebooks directly from the command line; for |
|
162 | * It is now possible to open notebooks directly from the command line; for | |
163 | example: ``ipython notebook path/`` will automatically set ``path/`` as the |
|
163 | example: ``ipython notebook path/`` will automatically set ``path/`` as the | |
164 | notebook directory, and ``ipython notebook path/foo.ipynb`` will further |
|
164 | notebook directory, and ``ipython notebook path/foo.ipynb`` will further | |
165 | start with the ``foo.ipynb`` notebook opened. :ghpull:`1686`. |
|
165 | start with the ``foo.ipynb`` notebook opened. :ghpull:`1686`. | |
166 |
|
166 | |||
167 | * If a notebook directory is specified with ``--notebook-dir`` (or with the |
|
167 | * If a notebook directory is specified with ``--notebook-dir`` (or with the | |
168 | corresponding configuration flag ``NotebookManager.notebook_dir``), all |
|
168 | corresponding configuration flag ``NotebookManager.notebook_dir``), all | |
169 | kernels start in this directory. |
|
169 | kernels start in this directory. | |
170 |
|
170 | |||
171 | * Fix codemirror clearing of cells with ``Ctrl-Z``; :ghpull:`1965`. |
|
171 | * Fix codemirror clearing of cells with ``Ctrl-Z``; :ghpull:`1965`. | |
172 |
|
172 | |||
173 | * Text (markdown) cells now line wrap correctly in the notebook, making them |
|
173 | * Text (markdown) cells now line wrap correctly in the notebook, making them | |
174 | much easier to edit :ghpull:`1330`. |
|
174 | much easier to edit :ghpull:`1330`. | |
175 |
|
175 | |||
176 | * PNG and JPEG figures returned from plots can be interactively resized in the |
|
176 | * PNG and JPEG figures returned from plots can be interactively resized in the | |
177 | notebook, by dragging them from their lower left corner. :ghpull:`1832`. |
|
177 | notebook, by dragging them from their lower left corner. :ghpull:`1832`. | |
178 |
|
178 | |||
179 | * Clear ``In []`` prompt numbers on "Clear All Output". For more |
|
179 | * Clear ``In []`` prompt numbers on "Clear All Output". For more | |
180 | version-control-friendly ``.ipynb`` files, we now strip all prompt numbers |
|
180 | version-control-friendly ``.ipynb`` files, we now strip all prompt numbers | |
181 | when doing a "Clear all output". This reduces the amount of noise in |
|
181 | when doing a "Clear all output". This reduces the amount of noise in | |
182 | commit-to-commit diffs that would otherwise show the (highly variable) prompt |
|
182 | commit-to-commit diffs that would otherwise show the (highly variable) prompt | |
183 | number changes. :ghpull:`1621`. |
|
183 | number changes. :ghpull:`1621`. | |
184 |
|
184 | |||
185 | * The notebook server now requires *two* consecutive ``Ctrl-C`` within 5 |
|
185 | * The notebook server now requires *two* consecutive ``Ctrl-C`` within 5 | |
186 | seconds (or an interactive confirmation) to terminate operation. This makes |
|
186 | seconds (or an interactive confirmation) to terminate operation. This makes | |
187 | it less likely that you will accidentally kill a long-running server by |
|
187 | it less likely that you will accidentally kill a long-running server by | |
188 | typing ``Ctrl-C`` in the wrong terminal. :ghpull:`1609`. |
|
188 | typing ``Ctrl-C`` in the wrong terminal. :ghpull:`1609`. | |
189 |
|
189 | |||
190 | * Using ``Ctrl-S`` (or ``Cmd-S`` on a Mac) actually saves the notebook rather |
|
190 | * Using ``Ctrl-S`` (or ``Cmd-S`` on a Mac) actually saves the notebook rather | |
191 | than providing the fairly useless browser html save dialog. :ghpull:`1334`. |
|
191 | than providing the fairly useless browser html save dialog. :ghpull:`1334`. | |
192 |
|
192 | |||
193 | * Allow accessing local files from the notebook (in urls), by serving any local |
|
193 | * Allow accessing local files from the notebook (in urls), by serving any local | |
194 | file as the url ``files/<relativepath>``. This makes it possible to, for |
|
194 | file as the url ``files/<relativepath>``. This makes it possible to, for | |
195 | example, embed local images in a notebook. :ghpull:`1211`. |
|
195 | example, embed local images in a notebook. :ghpull:`1211`. | |
196 |
|
196 | |||
197 |
|
197 | |||
198 | Cell magics |
|
198 | Cell magics | |
199 | ----------- |
|
199 | ----------- | |
200 |
|
200 | |||
201 | We have completely refactored the magic system, finally moving the magic |
|
201 | We have completely refactored the magic system, finally moving the magic | |
202 | objects to standalone, independent objects instead of being the mixin class |
|
202 | objects to standalone, independent objects instead of being the mixin class | |
203 | we'd had since the beginning of IPython (:ghpull:`1732`). Now, a separate base |
|
203 | we'd had since the beginning of IPython (:ghpull:`1732`). Now, a separate base | |
204 | class is provided in :class:`IPython.core.magic.Magics` that users can subclass |
|
204 | class is provided in :class:`IPython.core.magic.Magics` that users can subclass | |
205 | to create their own magics. Decorators are also provided to create magics from |
|
205 | to create their own magics. Decorators are also provided to create magics from | |
206 | simple functions without the need for object orientation. Please see the |
|
206 | simple functions without the need for object orientation. Please see the | |
207 | :ref:`magic` docs for further details. |
|
207 | :ref:`magic` docs for further details. | |
208 |
|
208 | |||
209 | All builtin magics now exist in a few subclasses that group together related |
|
209 | All builtin magics now exist in a few subclasses that group together related | |
210 | functionality, and the new :mod:`IPython.core.magics` package has been created |
|
210 | functionality, and the new :mod:`IPython.core.magics` package has been created | |
211 | to organize this into smaller files. |
|
211 | to organize this into smaller files. | |
212 |
|
212 | |||
213 | This cleanup was the last major piece of deep refactoring needed from the |
|
213 | This cleanup was the last major piece of deep refactoring needed from the | |
214 | original 2001 codebase. |
|
214 | original 2001 codebase. | |
215 |
|
215 | |||
216 | We have also introduced a new type of magic function, prefixed with `%%` |
|
216 | We have also introduced a new type of magic function, prefixed with `%%` | |
217 | instead of `%`, which operates at the whole-cell level. A cell magic receives |
|
217 | instead of `%`, which operates at the whole-cell level. A cell magic receives | |
218 | two arguments: the line it is called on (like a line magic) and the body of the |
|
218 | two arguments: the line it is called on (like a line magic) and the body of the | |
219 | cell below it. |
|
219 | cell below it. | |
220 |
|
220 | |||
221 | Cell magics are most natural in the notebook, but they also work in the |
|
221 | Cell magics are most natural in the notebook, but they also work in the | |
222 | terminal and qt console, with the usual approach of using a blank line to |
|
222 | terminal and qt console, with the usual approach of using a blank line to | |
223 | signal cell termination. |
|
223 | signal cell termination. | |
224 |
|
224 | |||
225 | For example, to time the execution of several statements:: |
|
225 | For example, to time the execution of several statements:: | |
226 |
|
226 | |||
227 | %%timeit x = 0 # setup |
|
227 | %%timeit x = 0 # setup | |
228 | for i in range(100000): |
|
228 | for i in range(100000): | |
229 | x += i**2 |
|
229 | x += i**2 | |
230 |
|
230 | |||
231 | This is particularly useful to integrate code in another language, and cell |
|
231 | This is particularly useful to integrate code in another language, and cell | |
232 | magics already exist for shell scripts, Cython, R and Octave. Using ``%%script |
|
232 | magics already exist for shell scripts, Cython, R and Octave. Using ``%%script | |
233 | /usr/bin/foo``, you can run a cell in any interpreter that accepts code via |
|
233 | /usr/bin/foo``, you can run a cell in any interpreter that accepts code via | |
234 | stdin. |
|
234 | stdin. | |
235 |
|
235 | |||
236 | Another handy cell magic makes it easy to write short text files: ``%%file |
|
236 | Another handy cell magic makes it easy to write short text files: ``%%file | |
237 | ~/save/to/here.txt``. |
|
237 | ~/save/to/here.txt``. | |
238 |
|
238 | |||
239 | The following cell magics are now included by default; all those that use |
|
239 | The following cell magics are now included by default; all those that use | |
240 | special interpreters (Perl, Ruby, bash, etc.) assume you have the requisite |
|
240 | special interpreters (Perl, Ruby, bash, etc.) assume you have the requisite | |
241 | interpreter installed: |
|
241 | interpreter installed: | |
242 |
|
242 | |||
243 | * ``%%!``: run cell body with the underlying OS shell; this is similar to |
|
243 | * ``%%!``: run cell body with the underlying OS shell; this is similar to | |
244 | prefixing every line in the cell with ``!``. |
|
244 | prefixing every line in the cell with ``!``. | |
245 |
|
245 | |||
246 | * ``%%bash``: run cell body under bash. |
|
246 | * ``%%bash``: run cell body under bash. | |
247 |
|
247 | |||
248 | * ``%%capture``: capture the output of the code in the cell (and stderr as |
|
248 | * ``%%capture``: capture the output of the code in the cell (and stderr as | |
249 | well). Useful to run codes that produce too much output that you don't even |
|
249 | well). Useful to run codes that produce too much output that you don't even | |
250 | want scrolled. |
|
250 | want scrolled. | |
251 |
|
251 | |||
252 | * ``%%file``: save cell body as a file. |
|
252 | * ``%%file``: save cell body as a file. | |
253 |
|
253 | |||
254 | * ``%%perl``: run cell body using Perl. |
|
254 | * ``%%perl``: run cell body using Perl. | |
255 |
|
255 | |||
256 | * ``%%prun``: run cell body with profiler (cell extension of ``%prun``). |
|
256 | * ``%%prun``: run cell body with profiler (cell extension of ``%prun``). | |
257 |
|
257 | |||
258 | * ``%%python3``: run cell body using Python 3. |
|
258 | * ``%%python3``: run cell body using Python 3. | |
259 |
|
259 | |||
260 | * ``%%ruby``: run cell body using Ruby. |
|
260 | * ``%%ruby``: run cell body using Ruby. | |
261 |
|
261 | |||
262 | * ``%%script``: run cell body with the script specified in the first line. |
|
262 | * ``%%script``: run cell body with the script specified in the first line. | |
263 |
|
263 | |||
264 | * ``%%sh``: run cell body using sh. |
|
264 | * ``%%sh``: run cell body using sh. | |
265 |
|
265 | |||
266 | * ``%%sx``: run cell with system shell and capture process output (cell |
|
266 | * ``%%sx``: run cell with system shell and capture process output (cell | |
267 | extension of ``%sx``). |
|
267 | extension of ``%sx``). | |
268 |
|
268 | |||
269 | * ``%%system``: run cell with system shell (``%%!`` is an alias to this). |
|
269 | * ``%%system``: run cell with system shell (``%%!`` is an alias to this). | |
270 |
|
270 | |||
271 | * ``%%timeit``: time the execution of the cell (extension of ``%timeit``). |
|
271 | * ``%%timeit``: time the execution of the cell (extension of ``%timeit``). | |
272 |
|
272 | |||
273 | This is what some of the script-related magics look like in action: |
|
273 | This is what some of the script-related magics look like in action: | |
274 |
|
274 | |||
275 | .. image:: ../_images/ipy_013_notebook_script_cells.png |
|
275 | .. image:: ../_images/ipy_013_notebook_script_cells.png | |
276 | :width: 460px |
|
276 | :width: 460px | |
277 | :alt: Cluster management from the notebook dashboard |
|
277 | :alt: Cluster management from the notebook dashboard | |
278 | :align: center |
|
278 | :align: center | |
279 | :target: ../_images/ipy_013_notebook_script_cells.png |
|
279 | :target: ../_images/ipy_013_notebook_script_cells.png | |
280 |
|
280 | |||
281 | In addition, we have also a number of :ref:`extensions <extensions_overview>` |
|
281 | In addition, we have also a number of :ref:`extensions <extensions_overview>` | |
282 | that provide specialized magics. These typically require additional software |
|
282 | that provide specialized magics. These typically require additional software | |
283 | to run and must be manually loaded via ``%load_ext <extension name>``, but are |
|
283 | to run and must be manually loaded via ``%load_ext <extension name>``, but are | |
284 | extremely useful. The following extensions are provided: |
|
284 | extremely useful. The following extensions are provided: | |
285 |
|
285 | |||
286 |
**Cython magics** (extension |
|
286 | **Cython magics** (extension ``cythonmagic``) | |
287 | This extension provides magics to automatically build and compile Python |
|
287 | This extension provides magics to automatically build and compile Python | |
288 | extension modules using the Cython_ language. You must install Cython |
|
288 | extension modules using the Cython_ language. You must install Cython | |
289 | separately, as well as a C compiler, for this to work. The examples |
|
289 | separately, as well as a C compiler, for this to work. The examples | |
290 | directory in the source distribution ships with a full notebook |
|
290 | directory in the source distribution ships with a full notebook | |
291 | demonstrating these capabilities: |
|
291 | demonstrating these capabilities: | |
292 |
|
292 | |||
293 | .. image:: ../_images/ipy_013_notebook_cythonmagic.png |
|
293 | .. image:: ../_images/ipy_013_notebook_cythonmagic.png | |
294 | :width: 460px |
|
294 | :width: 460px | |
295 | :alt: Cython magic |
|
295 | :alt: Cython magic | |
296 | :align: center |
|
296 | :align: center | |
297 | :target: ../_images/ipy_013_notebook_cythonmagic.png |
|
297 | :target: ../_images/ipy_013_notebook_cythonmagic.png | |
298 |
|
298 | |||
299 | .. _cython: http://cython.org |
|
299 | .. _cython: http://cython.org | |
300 |
|
300 | |||
301 | **Octave magics** (extension ``octavemagic``) |
|
301 | **Octave magics** (extension ``octavemagic``) | |
302 | This extension provides several magics that support calling code written in |
|
302 | This extension provides several magics that support calling code written in | |
303 | the Octave_ language for numerical computing. You can execute single-lines |
|
303 | the Octave_ language for numerical computing. You can execute single-lines | |
304 | or whole blocks of Octave code, capture both output and figures inline |
|
304 | or whole blocks of Octave code, capture both output and figures inline | |
305 | (just like matplotlib plots), and have variables automatically converted |
|
305 | (just like matplotlib plots), and have variables automatically converted | |
306 | between the two languages. To use this extension, you must have Octave |
|
306 | between the two languages. To use this extension, you must have Octave | |
307 | installed as well as the oct2py_ package. The examples |
|
307 | installed as well as the oct2py_ package. The examples | |
308 | directory in the source distribution ships with a full notebook |
|
308 | directory in the source distribution ships with a full notebook | |
309 | demonstrating these capabilities: |
|
309 | demonstrating these capabilities: | |
310 |
|
310 | |||
311 | .. image:: ../_images/ipy_013_notebook_octavemagic.png |
|
311 | .. image:: ../_images/ipy_013_notebook_octavemagic.png | |
312 | :width: 460px |
|
312 | :width: 460px | |
313 | :alt: Octave magic |
|
313 | :alt: Octave magic | |
314 | :align: center |
|
314 | :align: center | |
315 | :target: ../_images/ipy_013_notebook_octavemagic.png |
|
315 | :target: ../_images/ipy_013_notebook_octavemagic.png | |
316 |
|
316 | |||
317 | .. _octave: http://www.gnu.org/software/octave |
|
317 | .. _octave: http://www.gnu.org/software/octave | |
318 | .. _oct2py: http://pypi.python.org/pypi/oct2py |
|
318 | .. _oct2py: http://pypi.python.org/pypi/oct2py | |
319 |
|
319 | |||
320 | **R magics** (extension ``rmagic``) |
|
320 | **R magics** (extension ``rmagic``) | |
321 | This extension provides several magics that support calling code written in |
|
321 | This extension provides several magics that support calling code written in | |
322 | the R_ language for statistical data analysis. You can execute |
|
322 | the R_ language for statistical data analysis. You can execute | |
323 | single-lines or whole blocks of R code, capture both output and figures |
|
323 | single-lines or whole blocks of R code, capture both output and figures | |
324 | inline (just like matplotlib plots), and have variables automatically |
|
324 | inline (just like matplotlib plots), and have variables automatically | |
325 | converted between the two languages. To use this extension, you must have |
|
325 | converted between the two languages. To use this extension, you must have | |
326 | R installed as well as the rpy2_ package that bridges Python and R. The |
|
326 | R installed as well as the rpy2_ package that bridges Python and R. The | |
327 | examples directory in the source distribution ships with a full notebook |
|
327 | examples directory in the source distribution ships with a full notebook | |
328 | demonstrating these capabilities: |
|
328 | demonstrating these capabilities: | |
329 |
|
329 | |||
330 | .. image:: ../_images/ipy_013_notebook_rmagic.png |
|
330 | .. image:: ../_images/ipy_013_notebook_rmagic.png | |
331 | :width: 460px |
|
331 | :width: 460px | |
332 | :alt: R magic |
|
332 | :alt: R magic | |
333 | :align: center |
|
333 | :align: center | |
334 | :target: ../_images/ipy_013_notebook_rmagic.png |
|
334 | :target: ../_images/ipy_013_notebook_rmagic.png | |
335 |
|
335 | |||
336 | .. _R: http://www.r-project.org |
|
336 | .. _R: http://www.r-project.org | |
337 | .. _rpy2: http://rpy.sourceforge.net/rpy2.html |
|
337 | .. _rpy2: http://rpy.sourceforge.net/rpy2.html | |
338 |
|
338 | |||
339 |
|
339 | |||
340 | Tab completer improvements |
|
340 | Tab completer improvements | |
341 | -------------------------- |
|
341 | -------------------------- | |
342 |
|
342 | |||
343 | Useful tab-completion based on live inspection of objects is one of the most |
|
343 | Useful tab-completion based on live inspection of objects is one of the most | |
344 | popular features of IPython. To make this process even more user-friendly, the |
|
344 | popular features of IPython. To make this process even more user-friendly, the | |
345 | completers of both the Qt console and the Notebook have been reworked. |
|
345 | completers of both the Qt console and the Notebook have been reworked. | |
346 |
|
346 | |||
347 | The Qt console comes with a new ncurses-like tab completer, activated by |
|
347 | The Qt console comes with a new ncurses-like tab completer, activated by | |
348 | default, which lets you cycle through the available completions by pressing tab, |
|
348 | default, which lets you cycle through the available completions by pressing tab, | |
349 | or select a completion with the arrow keys (:ghpull:`1851`). |
|
349 | or select a completion with the arrow keys (:ghpull:`1851`). | |
350 |
|
350 | |||
351 | .. figure:: ../_images/ipy_013_qtconsole_completer.png |
|
351 | .. figure:: ../_images/ipy_013_qtconsole_completer.png | |
352 | :width: 460px |
|
352 | :width: 460px | |
353 | :alt: ncurses-like completer, with highlighted selection. |
|
353 | :alt: ncurses-like completer, with highlighted selection. | |
354 | :align: center |
|
354 | :align: center | |
355 | :target: ../_images/ipy_013_qtconsole_completer.png |
|
355 | :target: ../_images/ipy_013_qtconsole_completer.png | |
356 |
|
356 | |||
357 | The new improved Qt console's ncurses-like completer allows to easily |
|
357 | The new improved Qt console's ncurses-like completer allows to easily | |
358 | navigate thought long list of completions. |
|
358 | navigate thought long list of completions. | |
359 |
|
359 | |||
360 | In the notebook, completions are now sourced both from object introspection and |
|
360 | In the notebook, completions are now sourced both from object introspection and | |
361 | analysis of surrounding code, so limited completions can be offered for |
|
361 | analysis of surrounding code, so limited completions can be offered for | |
362 | variables defined in the current cell, or while the kernel is busy |
|
362 | variables defined in the current cell, or while the kernel is busy | |
363 | (:ghpull:`1711`). |
|
363 | (:ghpull:`1711`). | |
364 |
|
364 | |||
365 |
|
365 | |||
366 | We have implemented a new configurable flag to control tab completion on |
|
366 | We have implemented a new configurable flag to control tab completion on | |
367 | modules that provide the ``__all__`` attribute:: |
|
367 | modules that provide the ``__all__`` attribute:: | |
368 |
|
368 | |||
369 | IPCompleter.limit_to__all__= Boolean |
|
369 | IPCompleter.limit_to__all__= Boolean | |
370 |
|
370 | |||
371 | This instructs the completer to honor ``__all__`` for the completion. |
|
371 | This instructs the completer to honor ``__all__`` for the completion. | |
372 | Specifically, when completing on ``object.<tab>``, if True: only those names |
|
372 | Specifically, when completing on ``object.<tab>``, if True: only those names | |
373 | in ``obj.__all__`` will be included. When False [default]: the ``__all__`` |
|
373 | in ``obj.__all__`` will be included. When False [default]: the ``__all__`` | |
374 | attribute is ignored. :ghpull:`1529`. |
|
374 | attribute is ignored. :ghpull:`1529`. | |
375 |
|
375 | |||
376 |
|
376 | |||
377 | Improvements to the Qt console |
|
377 | Improvements to the Qt console | |
378 | ------------------------------ |
|
378 | ------------------------------ | |
379 |
|
379 | |||
380 | The Qt console continues to receive improvements and refinements, despite the |
|
380 | The Qt console continues to receive improvements and refinements, despite the | |
381 | fact that it is by now a fairly mature and robust component. Lots of small |
|
381 | fact that it is by now a fairly mature and robust component. Lots of small | |
382 | polish has gone into it, here are a few highlights: |
|
382 | polish has gone into it, here are a few highlights: | |
383 |
|
383 | |||
384 | * A number of changes were made to the underlying code for easier integration |
|
384 | * A number of changes were made to the underlying code for easier integration | |
385 | into other projects such as Spyder_ (:ghpull:`2007`, :ghpull:`2024`). |
|
385 | into other projects such as Spyder_ (:ghpull:`2007`, :ghpull:`2024`). | |
386 |
|
386 | |||
387 | * Improved menus with a new Magic menu that is organized by magic groups (this |
|
387 | * Improved menus with a new Magic menu that is organized by magic groups (this | |
388 | was made possible by the reorganization of the magic system |
|
388 | was made possible by the reorganization of the magic system | |
389 | internals). :ghpull:`1782`. |
|
389 | internals). :ghpull:`1782`. | |
390 |
|
390 | |||
391 | * Allow for restarting kernels without clearing the qtconsole, while leaving a |
|
391 | * Allow for restarting kernels without clearing the qtconsole, while leaving a | |
392 | visible indication that the kernel has restarted. :ghpull:`1681`. |
|
392 | visible indication that the kernel has restarted. :ghpull:`1681`. | |
393 |
|
393 | |||
394 | * Allow the native display of jpeg images in the qtconsole. :ghpull:`1643`. |
|
394 | * Allow the native display of jpeg images in the qtconsole. :ghpull:`1643`. | |
395 |
|
395 | |||
396 | .. _spyder: https://code.google.com/p/spyderlib |
|
396 | .. _spyder: https://code.google.com/p/spyderlib | |
397 |
|
397 | |||
398 |
|
398 | |||
399 |
|
399 | |||
400 | Parallel |
|
400 | Parallel | |
401 | -------- |
|
401 | -------- | |
402 |
|
402 | |||
403 | The parallel tools have been improved and fine-tuned on multiple fronts. Now, |
|
403 | The parallel tools have been improved and fine-tuned on multiple fronts. Now, | |
404 | the creation of an :class:`IPython.parallel.Client` object automatically |
|
404 | the creation of an :class:`IPython.parallel.Client` object automatically | |
405 | activates a line and cell magic function ``px`` that sends its code to all the |
|
405 | activates a line and cell magic function ``px`` that sends its code to all the | |
406 | engines. Further magics can be easily created with the :meth:`.Client.activate` |
|
406 | engines. Further magics can be easily created with the :meth:`.Client.activate` | |
407 | method, to conveniently execute code on any subset of engines. :ghpull:`1893`. |
|
407 | method, to conveniently execute code on any subset of engines. :ghpull:`1893`. | |
408 |
|
408 | |||
409 | The ``%%px`` cell magic can also be given an optional targets argument, as well |
|
409 | The ``%%px`` cell magic can also be given an optional targets argument, as well | |
410 | as a ``--out`` argument for storing its output. |
|
410 | as a ``--out`` argument for storing its output. | |
411 |
|
411 | |||
412 | A new magic has also been added, ``%pxconfig``, that lets you configure various |
|
412 | A new magic has also been added, ``%pxconfig``, that lets you configure various | |
413 | defaults of the parallel magics. As usual, type ``%pxconfig?`` for details. |
|
413 | defaults of the parallel magics. As usual, type ``%pxconfig?`` for details. | |
414 |
|
414 | |||
415 | The exception reporting in parallel contexts has been improved to be easier to |
|
415 | The exception reporting in parallel contexts has been improved to be easier to | |
416 | read. Now, IPython directly reports the remote exceptions without showing any |
|
416 | read. Now, IPython directly reports the remote exceptions without showing any | |
417 | of the internal execution parts: |
|
417 | of the internal execution parts: | |
418 |
|
418 | |||
419 | .. image:: ../_images/ipy_013_par_tb.png |
|
419 | .. image:: ../_images/ipy_013_par_tb.png | |
420 | :width: 460px |
|
420 | :width: 460px | |
421 | :alt: Improved parallel exceptions. |
|
421 | :alt: Improved parallel exceptions. | |
422 | :align: center |
|
422 | :align: center | |
423 | :target: ../_images/ipy_013_par_tb.png |
|
423 | :target: ../_images/ipy_013_par_tb.png | |
424 |
|
424 | |||
425 | The parallel tools now default to using ``NoDB`` as the storage backend for |
|
425 | The parallel tools now default to using ``NoDB`` as the storage backend for | |
426 | intermediate results. This means that the default usage case will have a |
|
426 | intermediate results. This means that the default usage case will have a | |
427 | significantly reduced memory footprint, though certain advanced features are |
|
427 | significantly reduced memory footprint, though certain advanced features are | |
428 | not available with this backend. For more details, see :ref:`parallel_db`. |
|
428 | not available with this backend. | |
429 |
|
429 | |||
430 | The parallel magics now display all output, so you can do parallel plotting or |
|
430 | The parallel magics now display all output, so you can do parallel plotting or | |
431 | other actions with complex display. The ``px`` magic has now both line and cell |
|
431 | other actions with complex display. The ``px`` magic has now both line and cell | |
432 | modes, and in cell mode finer control has been added about how to collate |
|
432 | modes, and in cell mode finer control has been added about how to collate | |
433 | output from multiple engines. :ghpull:`1768`. |
|
433 | output from multiple engines. :ghpull:`1768`. | |
434 |
|
434 | |||
435 | There have also been incremental improvements to the SSH launchers: |
|
435 | There have also been incremental improvements to the SSH launchers: | |
436 |
|
436 | |||
437 | * add to_send/fetch steps for moving connection files around. |
|
437 | * add to_send/fetch steps for moving connection files around. | |
438 |
|
438 | |||
439 | * add SSHProxyEngineSetLauncher, for invoking to `ipcluster engines` on a |
|
439 | * add SSHProxyEngineSetLauncher, for invoking to `ipcluster engines` on a | |
440 | remote host. This can be used to start a set of engines via PBS/SGE/MPI |
|
440 | remote host. This can be used to start a set of engines via PBS/SGE/MPI | |
441 | *remotely*. |
|
441 | *remotely*. | |
442 |
|
442 | |||
443 | This makes the SSHLauncher usable on machines without shared filesystems. |
|
443 | This makes the SSHLauncher usable on machines without shared filesystems. | |
444 |
|
444 | |||
445 | A number of 'sugar' methods/properties were added to AsyncResult that are |
|
445 | A number of 'sugar' methods/properties were added to AsyncResult that are | |
446 | quite useful (:ghpull:`1548`) for everday work: |
|
446 | quite useful (:ghpull:`1548`) for everday work: | |
447 |
|
447 | |||
448 | * ``ar.wall_time`` = received - submitted |
|
448 | * ``ar.wall_time`` = received - submitted | |
449 | * ``ar.serial_time`` = sum of serial computation time |
|
449 | * ``ar.serial_time`` = sum of serial computation time | |
450 | * ``ar.elapsed`` = time since submission (wall_time if done) |
|
450 | * ``ar.elapsed`` = time since submission (wall_time if done) | |
451 | * ``ar.progress`` = (int) number of sub-tasks that have completed |
|
451 | * ``ar.progress`` = (int) number of sub-tasks that have completed | |
452 | * ``len(ar)`` = # of tasks |
|
452 | * ``len(ar)`` = # of tasks | |
453 | * ``ar.wait_interactive()``: prints progress |
|
453 | * ``ar.wait_interactive()``: prints progress | |
454 |
|
454 | |||
455 | Added :meth:`.Client.spin_thread` / :meth:`~.Client.stop_spin_thread` for |
|
455 | Added :meth:`.Client.spin_thread` / :meth:`~.Client.stop_spin_thread` for | |
456 | running spin in a background thread, to keep zmq queue clear. This can be used |
|
456 | running spin in a background thread, to keep zmq queue clear. This can be used | |
457 | to ensure that timing information is as accurate as possible (at the cost of |
|
457 | to ensure that timing information is as accurate as possible (at the cost of | |
458 | having a background thread active). |
|
458 | having a background thread active). | |
459 |
|
459 | |||
460 | Set TaskScheduler.hwm default to 1 instead of 0. 1 has more |
|
460 | Set TaskScheduler.hwm default to 1 instead of 0. 1 has more | |
461 | predictable/intuitive behavior, if often slower, and thus a more logical |
|
461 | predictable/intuitive behavior, if often slower, and thus a more logical | |
462 | default. Users whose workloads require maximum throughput and are largely |
|
462 | default. Users whose workloads require maximum throughput and are largely | |
463 | homogeneous in time per task can make the optimization themselves, but now the |
|
463 | homogeneous in time per task can make the optimization themselves, but now the | |
464 | behavior will be less surprising to new users. :ghpull:`1294`. |
|
464 | behavior will be less surprising to new users. :ghpull:`1294`. | |
465 |
|
465 | |||
466 |
|
466 | |||
467 | Kernel/Engine unification |
|
467 | Kernel/Engine unification | |
468 | ------------------------- |
|
468 | ------------------------- | |
469 |
|
469 | |||
470 | This is mostly work 'under the hood', but it is actually a *major* achievement |
|
470 | This is mostly work 'under the hood', but it is actually a *major* achievement | |
471 | for the project that has deep implications in the long term: at last, we have |
|
471 | for the project that has deep implications in the long term: at last, we have | |
472 | unified the main object that executes as the user's interactive shell (which we |
|
472 | unified the main object that executes as the user's interactive shell (which we | |
473 | refer to as the *IPython kernel*) with the objects that run in all the worker |
|
473 | refer to as the *IPython kernel*) with the objects that run in all the worker | |
474 | nodes of the parallel computing facilities (the *IPython engines*). Ever since |
|
474 | nodes of the parallel computing facilities (the *IPython engines*). Ever since | |
475 | the first implementation of IPython's parallel code back in 2006, we had wanted |
|
475 | the first implementation of IPython's parallel code back in 2006, we had wanted | |
476 | to have these two roles be played by the same machinery, but a number of |
|
476 | to have these two roles be played by the same machinery, but a number of | |
477 | technical reasons had prevented that from being true. |
|
477 | technical reasons had prevented that from being true. | |
478 |
|
478 | |||
479 | In this release we have now merged them, and this has a number of important |
|
479 | In this release we have now merged them, and this has a number of important | |
480 | consequences: |
|
480 | consequences: | |
481 |
|
481 | |||
482 | * It is now possible to connect any of our clients (qtconsole or terminal |
|
482 | * It is now possible to connect any of our clients (qtconsole or terminal | |
483 | console) to any individual parallel engine, with the *exact* behavior of |
|
483 | console) to any individual parallel engine, with the *exact* behavior of | |
484 | working at a 'regular' IPython console/qtconsole. This makes debugging, |
|
484 | working at a 'regular' IPython console/qtconsole. This makes debugging, | |
485 | plotting, etc. in parallel scenarios vastly easier. |
|
485 | plotting, etc. in parallel scenarios vastly easier. | |
486 |
|
486 | |||
487 | * Parallel engines can always execute arbitrary 'IPython code', that is, code |
|
487 | * Parallel engines can always execute arbitrary 'IPython code', that is, code | |
488 | that has magics, shell extensions, etc. In combination with the ``%%px`` |
|
488 | that has magics, shell extensions, etc. In combination with the ``%%px`` | |
489 | magics, it is thus extremely natural for example to send to all engines a |
|
489 | magics, it is thus extremely natural for example to send to all engines a | |
490 | block of Cython or R code to be executed via the new Cython and R magics. For |
|
490 | block of Cython or R code to be executed via the new Cython and R magics. For | |
491 | example, this snippet would send the R block to all active engines in a |
|
491 | example, this snippet would send the R block to all active engines in a | |
492 | cluster:: |
|
492 | cluster:: | |
493 |
|
493 | |||
494 | %%px |
|
494 | %%px | |
495 | %%R |
|
495 | %%R | |
496 | ... R code goes here |
|
496 | ... R code goes here | |
497 |
|
497 | |||
498 | * It is possible to embed not only an interactive shell with the |
|
498 | * It is possible to embed not only an interactive shell with the | |
499 | :func:`IPython.embed` call as always, but now you can also embed a *kernel* |
|
499 | :func:`IPython.embed` call as always, but now you can also embed a *kernel* | |
500 | with :func:`IPython.embed_kernel()`. Embedding an IPython kernel in an |
|
500 | with :func:`IPython.embed_kernel()`. Embedding an IPython kernel in an | |
501 | application is useful when you want to use :func:`IPython.embed` but don't |
|
501 | application is useful when you want to use :func:`IPython.embed` but don't | |
502 | have a terminal attached on stdin and stdout. |
|
502 | have a terminal attached on stdin and stdout. | |
503 |
|
503 | |||
504 | * The new :func:`IPython.parallel.bind_kernel` allows you to promote Engines to |
|
504 | * The new :func:`IPython.parallel.bind_kernel` allows you to promote Engines to | |
505 | listening Kernels, and connect QtConsoles to an Engine and debug it |
|
505 | listening Kernels, and connect QtConsoles to an Engine and debug it | |
506 | directly. |
|
506 | directly. | |
507 |
|
507 | |||
508 | In addition, having a single core object through our entire architecture also |
|
508 | In addition, having a single core object through our entire architecture also | |
509 | makes the project conceptually cleaner, easier to maintain and more robust. |
|
509 | makes the project conceptually cleaner, easier to maintain and more robust. | |
510 | This took a lot of work to get in place, but we are thrilled to have this major |
|
510 | This took a lot of work to get in place, but we are thrilled to have this major | |
511 | piece of architecture finally where we'd always wanted it to be. |
|
511 | piece of architecture finally where we'd always wanted it to be. | |
512 |
|
512 | |||
513 |
|
513 | |||
514 | Official Public API |
|
514 | Official Public API | |
515 | ------------------- |
|
515 | ------------------- | |
516 |
|
516 | |||
517 | We have begun organizing our API for easier public use, with an eye towards an |
|
517 | We have begun organizing our API for easier public use, with an eye towards an | |
518 | official IPython 1.0 release which will firmly maintain this API compatible for |
|
518 | official IPython 1.0 release which will firmly maintain this API compatible for | |
519 | its entire lifecycle. There is now an :mod:`IPython.display` module that |
|
519 | its entire lifecycle. There is now an :mod:`IPython.display` module that | |
520 | aggregates all display routines, and the :mod:`traitlets.config` namespace has |
|
520 | aggregates all display routines, and the :mod:`traitlets.config` namespace has | |
521 | all public configuration tools. We will continue improving our public API |
|
521 | all public configuration tools. We will continue improving our public API | |
522 | layout so that users only need to import names one level deeper than the main |
|
522 | layout so that users only need to import names one level deeper than the main | |
523 | ``IPython`` package to access all public namespaces. |
|
523 | ``IPython`` package to access all public namespaces. | |
524 |
|
524 | |||
525 |
|
525 | |||
526 | IPython notebook file icons |
|
526 | IPython notebook file icons | |
527 | --------------------------- |
|
527 | --------------------------- | |
528 |
|
528 | |||
529 | The directory ``docs/resources`` in the source distribution contains SVG and |
|
529 | The directory ``docs/resources`` in the source distribution contains SVG and | |
530 | PNG versions of our file icons, as well as an ``Info.plist.example`` file with |
|
530 | PNG versions of our file icons, as well as an ``Info.plist.example`` file with | |
531 | instructions to install them on Mac OSX. This is a first draft of our icons, |
|
531 | instructions to install them on Mac OSX. This is a first draft of our icons, | |
532 | and we encourage contributions from users with graphic talent to improve them |
|
532 | and we encourage contributions from users with graphic talent to improve them | |
533 |
in the future |
|
533 | in the future. | |
534 |
|
||||
535 | .. image:: ../../resources/ipynb_icon_128x128.png |
|
|||
536 | :alt: IPython notebook file icon. |
|
|||
537 |
|
534 | |||
538 |
|
535 | |||
539 | New top-level `locate` command |
|
536 | New top-level `locate` command | |
540 | ------------------------------ |
|
537 | ------------------------------ | |
541 |
|
538 | |||
542 | Add `locate` entry points; these would be useful for quickly locating IPython |
|
539 | Add `locate` entry points; these would be useful for quickly locating IPython | |
543 | directories and profiles from other (non-Python) applications. :ghpull:`1762`. |
|
540 | directories and profiles from other (non-Python) applications. :ghpull:`1762`. | |
544 |
|
541 | |||
545 | Examples:: |
|
542 | Examples:: | |
546 |
|
543 | |||
547 | $> ipython locate |
|
544 | $> ipython locate | |
548 | /Users/me/.ipython |
|
545 | /Users/me/.ipython | |
549 |
|
546 | |||
550 | $> ipython locate profile foo |
|
547 | $> ipython locate profile foo | |
551 | /Users/me/.ipython/profile_foo |
|
548 | /Users/me/.ipython/profile_foo | |
552 |
|
549 | |||
553 | $> ipython locate profile |
|
550 | $> ipython locate profile | |
554 | /Users/me/.ipython/profile_default |
|
551 | /Users/me/.ipython/profile_default | |
555 |
|
552 | |||
556 | $> ipython locate profile dne |
|
553 | $> ipython locate profile dne | |
557 | [ProfileLocate] Profile u'dne' not found. |
|
554 | [ProfileLocate] Profile u'dne' not found. | |
558 |
|
555 | |||
559 |
|
556 | |||
560 | Other new features and improvements |
|
557 | Other new features and improvements | |
561 | ----------------------------------- |
|
558 | ----------------------------------- | |
562 |
|
559 | |||
563 | * **%install_ext**: A new magic function to install an IPython extension from |
|
560 | * **%install_ext**: A new magic function to install an IPython extension from | |
564 | a URL. E.g. ``%install_ext |
|
561 | a URL. E.g. ``%install_ext | |
565 | https://bitbucket.org/birkenfeld/ipython-physics/raw/default/physics.py``. |
|
562 | https://bitbucket.org/birkenfeld/ipython-physics/raw/default/physics.py``. | |
566 |
|
563 | |||
567 | * The ``%loadpy`` magic is no longer restricted to Python files, and has been |
|
564 | * The ``%loadpy`` magic is no longer restricted to Python files, and has been | |
568 | renamed ``%load``. The old name remains as an alias. |
|
565 | renamed ``%load``. The old name remains as an alias. | |
569 |
|
566 | |||
570 | * New command line arguments will help external programs find IPython folders: |
|
567 | * New command line arguments will help external programs find IPython folders: | |
571 | ``ipython locate`` finds the user's IPython directory, and ``ipython locate |
|
568 | ``ipython locate`` finds the user's IPython directory, and ``ipython locate | |
572 | profile foo`` finds the folder for the 'foo' profile (if it exists). |
|
569 | profile foo`` finds the folder for the 'foo' profile (if it exists). | |
573 |
|
570 | |||
574 | * The :envvar:`IPYTHON_DIR` environment variable, introduced in the Great |
|
571 | * The :envvar:`IPYTHON_DIR` environment variable, introduced in the Great | |
575 | Reorganization of 0.11 and existing only in versions 0.11-0.13, has been |
|
572 | Reorganization of 0.11 and existing only in versions 0.11-0.13, has been | |
576 | deprecated. As described in :ghpull:`1167`, the complexity and confusion of |
|
573 | deprecated. As described in :ghpull:`1167`, the complexity and confusion of | |
577 | migrating to this variable is not worth the aesthetic improvement. Please use |
|
574 | migrating to this variable is not worth the aesthetic improvement. Please use | |
578 | the historical :envvar:`IPYTHONDIR` environment variable instead. |
|
575 | the historical :envvar:`IPYTHONDIR` environment variable instead. | |
579 |
|
576 | |||
580 | * The default value of *interactivity* passed from |
|
577 | * The default value of *interactivity* passed from | |
581 | :meth:`~IPython.core.interactiveshell.InteractiveShell.run_cell` to |
|
578 | :meth:`~IPython.core.interactiveshell.InteractiveShell.run_cell` to | |
582 | :meth:`~IPython.core.interactiveshell.InteractiveShell.run_ast_nodes` |
|
579 | :meth:`~IPython.core.interactiveshell.InteractiveShell.run_ast_nodes` | |
583 | is now configurable. |
|
580 | is now configurable. | |
584 |
|
581 | |||
585 | * New ``%alias_magic`` function to conveniently create aliases of existing |
|
582 | * New ``%alias_magic`` function to conveniently create aliases of existing | |
586 | magics, if you prefer to have shorter names for personal use. |
|
583 | magics, if you prefer to have shorter names for personal use. | |
587 |
|
584 | |||
588 | * We ship unminified versions of the JavaScript libraries we use, to better |
|
585 | * We ship unminified versions of the JavaScript libraries we use, to better | |
589 | comply with Debian's packaging policies. |
|
586 | comply with Debian's packaging policies. | |
590 |
|
587 | |||
591 | * Simplify the information presented by ``obj?/obj??`` to eliminate a few |
|
588 | * Simplify the information presented by ``obj?/obj??`` to eliminate a few | |
592 | redundant fields when possible. :ghpull:`2038`. |
|
589 | redundant fields when possible. :ghpull:`2038`. | |
593 |
|
590 | |||
594 | * Improved continuous integration for IPython. We now have automated test runs |
|
591 | * Improved continuous integration for IPython. We now have automated test runs | |
595 | on `Shining Panda <https://jenkins.shiningpanda.com/ipython>`_ and `Travis-CI |
|
592 | on `Shining Panda <https://jenkins.shiningpanda.com/ipython>`_ and `Travis-CI | |
596 | <http://travis-ci.org/#!/ipython/ipython>`_, as well as `Tox support |
|
593 | <http://travis-ci.org/#!/ipython/ipython>`_, as well as `Tox support | |
597 | <http://tox.testrun.org>`_. |
|
594 | <http://tox.testrun.org>`_. | |
598 |
|
595 | |||
599 | * The `vim-ipython`_ functionality (externally developed) has been updated to |
|
596 | * The `vim-ipython`_ functionality (externally developed) has been updated to | |
600 | the latest version. |
|
597 | the latest version. | |
601 |
|
598 | |||
602 | .. _vim-ipython: https://github.com/ivanov/vim-ipython |
|
599 | .. _vim-ipython: https://github.com/ivanov/vim-ipython | |
603 |
|
600 | |||
604 | * The ``%save`` magic now has a ``-f`` flag to force overwriting, which makes |
|
601 | * The ``%save`` magic now has a ``-f`` flag to force overwriting, which makes | |
605 | it much more usable in the notebook where it is not possible to reply to |
|
602 | it much more usable in the notebook where it is not possible to reply to | |
606 | interactive questions from the kernel. :ghpull:`1937`. |
|
603 | interactive questions from the kernel. :ghpull:`1937`. | |
607 |
|
604 | |||
608 | * Use dvipng to format sympy.Matrix, enabling display of matrices in the Qt |
|
605 | * Use dvipng to format sympy.Matrix, enabling display of matrices in the Qt | |
609 | console with the sympy printing extension. :ghpull:`1861`. |
|
606 | console with the sympy printing extension. :ghpull:`1861`. | |
610 |
|
607 | |||
611 | * Our messaging protocol now has a reasonable test suite, helping ensure that |
|
608 | * Our messaging protocol now has a reasonable test suite, helping ensure that | |
612 | we don't accidentally deviate from the spec and possibly break third-party |
|
609 | we don't accidentally deviate from the spec and possibly break third-party | |
613 | applications that may have been using it. We encourage users to contribute |
|
610 | applications that may have been using it. We encourage users to contribute | |
614 | more stringent tests to this part of the test suite. :ghpull:`1627`. |
|
611 | more stringent tests to this part of the test suite. :ghpull:`1627`. | |
615 |
|
612 | |||
616 | * Use LaTeX to display, on output, various built-in types with the SymPy |
|
613 | * Use LaTeX to display, on output, various built-in types with the SymPy | |
617 | printing extension. :ghpull:`1399`. |
|
614 | printing extension. :ghpull:`1399`. | |
618 |
|
615 | |||
619 | * Add Gtk3 event loop integration and example. :ghpull:`1588`. |
|
616 | * Add Gtk3 event loop integration and example. :ghpull:`1588`. | |
620 |
|
617 | |||
621 | * ``clear_output`` improvements, which allow things like progress bars and other |
|
618 | * ``clear_output`` improvements, which allow things like progress bars and other | |
622 | simple animations to work well in the notebook (:ghpull:`1563`): |
|
619 | simple animations to work well in the notebook (:ghpull:`1563`): | |
623 |
|
620 | |||
624 | * `clear_output()` clears the line, even in terminal IPython, the QtConsole |
|
621 | * `clear_output()` clears the line, even in terminal IPython, the QtConsole | |
625 | and plain Python as well, by printing `\r` to streams. |
|
622 | and plain Python as well, by printing `\r` to streams. | |
626 |
|
623 | |||
627 | * `clear_output()` avoids the flicker in the notebook by adding a delay, |
|
624 | * `clear_output()` avoids the flicker in the notebook by adding a delay, | |
628 | and firing immediately upon the next actual display message. |
|
625 | and firing immediately upon the next actual display message. | |
629 |
|
626 | |||
630 | * `display_javascript` hides its `output_area` element, so using display to |
|
627 | * `display_javascript` hides its `output_area` element, so using display to | |
631 | run a bunch of javascript doesn't result in ever-growing vertical space. |
|
628 | run a bunch of javascript doesn't result in ever-growing vertical space. | |
632 |
|
629 | |||
633 | * Add simple support for running inside a virtualenv. While this doesn't |
|
630 | * Add simple support for running inside a virtualenv. While this doesn't | |
634 | supplant proper installation (as users should do), it helps ad-hoc calling of |
|
631 | supplant proper installation (as users should do), it helps ad-hoc calling of | |
635 | IPython from inside a virtualenv. :ghpull:`1388`. |
|
632 | IPython from inside a virtualenv. :ghpull:`1388`. | |
636 |
|
633 | |||
637 |
|
634 | |||
638 | Major Bugs fixed |
|
635 | Major Bugs fixed | |
639 | ---------------- |
|
636 | ---------------- | |
640 |
|
637 | |||
641 | In this cycle, we have :ref:`closed over 740 issues <issues_list_013>`, but a |
|
638 | In this cycle, we have :ref:`closed over 740 issues <issues_list_013>`, but a | |
642 | few major ones merit special mention: |
|
639 | few major ones merit special mention: | |
643 |
|
640 | |||
644 | * The ``%pastebin`` magic has been updated to point to gist.github.com, since |
|
641 | * The ``%pastebin`` magic has been updated to point to gist.github.com, since | |
645 | unfortunately http://paste.pocoo.org has closed down. We also added a -d flag |
|
642 | unfortunately http://paste.pocoo.org has closed down. We also added a -d flag | |
646 | for the user to provide a gist description string. :ghpull:`1670`. |
|
643 | for the user to provide a gist description string. :ghpull:`1670`. | |
647 |
|
644 | |||
648 | * Fix ``%paste`` that would reject certain valid inputs. :ghpull:`1258`. |
|
645 | * Fix ``%paste`` that would reject certain valid inputs. :ghpull:`1258`. | |
649 |
|
646 | |||
650 | * Fix sending and receiving of Numpy structured arrays (those with composite |
|
647 | * Fix sending and receiving of Numpy structured arrays (those with composite | |
651 | dtypes, often used as recarrays). :ghpull:`2034`. |
|
648 | dtypes, often used as recarrays). :ghpull:`2034`. | |
652 |
|
649 | |||
653 | * Reconnect when the websocket connection closes unexpectedly. :ghpull:`1577`. |
|
650 | * Reconnect when the websocket connection closes unexpectedly. :ghpull:`1577`. | |
654 |
|
651 | |||
655 | * Fix truncated representation of objects in the debugger by showing at least |
|
652 | * Fix truncated representation of objects in the debugger by showing at least | |
656 | 80 characters' worth of information. :ghpull:`1793`. |
|
653 | 80 characters' worth of information. :ghpull:`1793`. | |
657 |
|
654 | |||
658 | * Fix logger to be Unicode-aware: logging could crash ipython if there was |
|
655 | * Fix logger to be Unicode-aware: logging could crash ipython if there was | |
659 | unicode in the input. :ghpull:`1792`. |
|
656 | unicode in the input. :ghpull:`1792`. | |
660 |
|
657 | |||
661 | * Fix images missing from XML/SVG export in the Qt console. :ghpull:`1449`. |
|
658 | * Fix images missing from XML/SVG export in the Qt console. :ghpull:`1449`. | |
662 |
|
659 | |||
663 | * Fix deepreload on Python 3. :ghpull:`1625`, as well as having a much cleaner |
|
660 | * Fix deepreload on Python 3. :ghpull:`1625`, as well as having a much cleaner | |
664 | and more robust implementation of deepreload in general. :ghpull:`1457`. |
|
661 | and more robust implementation of deepreload in general. :ghpull:`1457`. | |
665 |
|
662 | |||
666 |
|
663 | |||
667 | Backwards incompatible changes |
|
664 | Backwards incompatible changes | |
668 | ------------------------------ |
|
665 | ------------------------------ | |
669 |
|
666 | |||
670 | * The exception :exc:`IPython.core.error.TryNext` previously accepted |
|
667 | * The exception :exc:`IPython.core.error.TryNext` previously accepted | |
671 | arguments and keyword arguments to be passed to the next implementation |
|
668 | arguments and keyword arguments to be passed to the next implementation | |
672 | of the hook. This feature was removed as it made error message propagation |
|
669 | of the hook. This feature was removed as it made error message propagation | |
673 | difficult and violated the principle of loose coupling. |
|
670 | difficult and violated the principle of loose coupling. |
@@ -1,232 +1,232 b'' | |||||
1 | #!/usr/bin/env python |
|
1 | #!/usr/bin/env python | |
2 | """Simple tools to query github.com and gather stats about issues. |
|
2 | """Simple tools to query github.com and gather stats about issues. | |
3 |
|
3 | |||
4 | To generate a report for IPython 2.0, run: |
|
4 | To generate a report for IPython 2.0, run: | |
5 |
|
5 | |||
6 | python github_stats.py --milestone 2.0 --since-tag rel-1.0.0 |
|
6 | python github_stats.py --milestone 2.0 --since-tag rel-1.0.0 | |
7 | """ |
|
7 | """ | |
8 | #----------------------------------------------------------------------------- |
|
8 | #----------------------------------------------------------------------------- | |
9 | # Imports |
|
9 | # Imports | |
10 | #----------------------------------------------------------------------------- |
|
10 | #----------------------------------------------------------------------------- | |
11 |
|
11 | |||
12 | from __future__ import print_function |
|
12 | from __future__ import print_function | |
13 |
|
13 | |||
14 | import codecs |
|
14 | import codecs | |
15 | import sys |
|
15 | import sys | |
16 |
|
16 | |||
17 | from argparse import ArgumentParser |
|
17 | from argparse import ArgumentParser | |
18 | from datetime import datetime, timedelta |
|
18 | from datetime import datetime, timedelta | |
19 | from subprocess import check_output |
|
19 | from subprocess import check_output | |
20 |
|
20 | |||
21 | from gh_api import ( |
|
21 | from gh_api import ( | |
22 | get_paged_request, make_auth_header, get_pull_request, is_pull_request, |
|
22 | get_paged_request, make_auth_header, get_pull_request, is_pull_request, | |
23 | get_milestone_id, get_issues_list, get_authors, |
|
23 | get_milestone_id, get_issues_list, get_authors, | |
24 | ) |
|
24 | ) | |
25 | #----------------------------------------------------------------------------- |
|
25 | #----------------------------------------------------------------------------- | |
26 | # Globals |
|
26 | # Globals | |
27 | #----------------------------------------------------------------------------- |
|
27 | #----------------------------------------------------------------------------- | |
28 |
|
28 | |||
29 | ISO8601 = "%Y-%m-%dT%H:%M:%SZ" |
|
29 | ISO8601 = "%Y-%m-%dT%H:%M:%SZ" | |
30 | PER_PAGE = 100 |
|
30 | PER_PAGE = 100 | |
31 |
|
31 | |||
32 | #----------------------------------------------------------------------------- |
|
32 | #----------------------------------------------------------------------------- | |
33 | # Functions |
|
33 | # Functions | |
34 | #----------------------------------------------------------------------------- |
|
34 | #----------------------------------------------------------------------------- | |
35 |
|
35 | |||
36 | def round_hour(dt): |
|
36 | def round_hour(dt): | |
37 | return dt.replace(minute=0,second=0,microsecond=0) |
|
37 | return dt.replace(minute=0,second=0,microsecond=0) | |
38 |
|
38 | |||
39 | def _parse_datetime(s): |
|
39 | def _parse_datetime(s): | |
40 | """Parse dates in the format returned by the Github API.""" |
|
40 | """Parse dates in the format returned by the Github API.""" | |
41 | if s: |
|
41 | if s: | |
42 | return datetime.strptime(s, ISO8601) |
|
42 | return datetime.strptime(s, ISO8601) | |
43 | else: |
|
43 | else: | |
44 | return datetime.fromtimestamp(0) |
|
44 | return datetime.fromtimestamp(0) | |
45 |
|
45 | |||
46 | def issues2dict(issues): |
|
46 | def issues2dict(issues): | |
47 | """Convert a list of issues to a dict, keyed by issue number.""" |
|
47 | """Convert a list of issues to a dict, keyed by issue number.""" | |
48 | idict = {} |
|
48 | idict = {} | |
49 | for i in issues: |
|
49 | for i in issues: | |
50 | idict[i['number']] = i |
|
50 | idict[i['number']] = i | |
51 | return idict |
|
51 | return idict | |
52 |
|
52 | |||
53 | def split_pulls(all_issues, project="ipython/ipython"): |
|
53 | def split_pulls(all_issues, project="ipython/ipython"): | |
54 | """split a list of closed issues into non-PR Issues and Pull Requests""" |
|
54 | """split a list of closed issues into non-PR Issues and Pull Requests""" | |
55 | pulls = [] |
|
55 | pulls = [] | |
56 | issues = [] |
|
56 | issues = [] | |
57 | for i in all_issues: |
|
57 | for i in all_issues: | |
58 | if is_pull_request(i): |
|
58 | if is_pull_request(i): | |
59 | pull = get_pull_request(project, i['number'], auth=True) |
|
59 | pull = get_pull_request(project, i['number'], auth=True) | |
60 | pulls.append(pull) |
|
60 | pulls.append(pull) | |
61 | else: |
|
61 | else: | |
62 | issues.append(i) |
|
62 | issues.append(i) | |
63 | return issues, pulls |
|
63 | return issues, pulls | |
64 |
|
64 | |||
65 |
|
65 | |||
66 | def issues_closed_since(period=timedelta(days=365), project="ipython/ipython", pulls=False): |
|
66 | def issues_closed_since(period=timedelta(days=365), project="ipython/ipython", pulls=False): | |
67 | """Get all issues closed since a particular point in time. period |
|
67 | """Get all issues closed since a particular point in time. period | |
68 | can either be a datetime object, or a timedelta object. In the |
|
68 | can either be a datetime object, or a timedelta object. In the | |
69 | latter case, it is used as a time before the present. |
|
69 | latter case, it is used as a time before the present. | |
70 | """ |
|
70 | """ | |
71 |
|
71 | |||
72 | which = 'pulls' if pulls else 'issues' |
|
72 | which = 'pulls' if pulls else 'issues' | |
73 |
|
73 | |||
74 | if isinstance(period, timedelta): |
|
74 | if isinstance(period, timedelta): | |
75 | since = round_hour(datetime.utcnow() - period) |
|
75 | since = round_hour(datetime.utcnow() - period) | |
76 | else: |
|
76 | else: | |
77 | since = period |
|
77 | since = period | |
78 | url = "https://api.github.com/repos/%s/%s?state=closed&sort=updated&since=%s&per_page=%i" % (project, which, since.strftime(ISO8601), PER_PAGE) |
|
78 | url = "https://api.github.com/repos/%s/%s?state=closed&sort=updated&since=%s&per_page=%i" % (project, which, since.strftime(ISO8601), PER_PAGE) | |
79 | allclosed = get_paged_request(url, headers=make_auth_header()) |
|
79 | allclosed = get_paged_request(url, headers=make_auth_header()) | |
80 |
|
80 | |||
81 | filtered = [ i for i in allclosed if _parse_datetime(i['closed_at']) > since ] |
|
81 | filtered = [ i for i in allclosed if _parse_datetime(i['closed_at']) > since ] | |
82 | if pulls: |
|
82 | if pulls: | |
83 | filtered = [ i for i in filtered if _parse_datetime(i['merged_at']) > since ] |
|
83 | filtered = [ i for i in filtered if _parse_datetime(i['merged_at']) > since ] | |
84 | # filter out PRs not against master (backports) |
|
84 | # filter out PRs not against master (backports) | |
85 | filtered = [ i for i in filtered if i['base']['ref'] == 'master' ] |
|
85 | filtered = [ i for i in filtered if i['base']['ref'] == 'master' ] | |
86 | else: |
|
86 | else: | |
87 | filtered = [ i for i in filtered if not is_pull_request(i) ] |
|
87 | filtered = [ i for i in filtered if not is_pull_request(i) ] | |
88 |
|
88 | |||
89 | return filtered |
|
89 | return filtered | |
90 |
|
90 | |||
91 |
|
91 | |||
92 | def sorted_by_field(issues, field='closed_at', reverse=False): |
|
92 | def sorted_by_field(issues, field='closed_at', reverse=False): | |
93 | """Return a list of issues sorted by closing date date.""" |
|
93 | """Return a list of issues sorted by closing date date.""" | |
94 | return sorted(issues, key = lambda i:i[field], reverse=reverse) |
|
94 | return sorted(issues, key = lambda i:i[field], reverse=reverse) | |
95 |
|
95 | |||
96 |
|
96 | |||
97 | def report(issues, show_urls=False): |
|
97 | def report(issues, show_urls=False): | |
98 | """Summary report about a list of issues, printing number and title.""" |
|
98 | """Summary report about a list of issues, printing number and title.""" | |
99 | if show_urls: |
|
99 | if show_urls: | |
100 | for i in issues: |
|
100 | for i in issues: | |
101 | role = 'ghpull' if 'merged_at' in i else 'ghissue' |
|
101 | role = 'ghpull' if 'merged_at' in i else 'ghissue' | |
102 | print(u'* :%s:`%d`: %s' % (role, i['number'], |
|
102 | print(u'* :%s:`%d`: %s' % (role, i['number'], | |
103 | i['title'].replace(u'`', u'``'))) |
|
103 | i['title'].replace(u'`', u'``'))) | |
104 | else: |
|
104 | else: | |
105 | for i in issues: |
|
105 | for i in issues: | |
106 | print(u'* %d: %s' % (i['number'], i['title'].replace(u'`', u'``'))) |
|
106 | print(u'* %d: %s' % (i['number'], i['title'].replace(u'`', u'``'))) | |
107 |
|
107 | |||
108 | #----------------------------------------------------------------------------- |
|
108 | #----------------------------------------------------------------------------- | |
109 | # Main script |
|
109 | # Main script | |
110 | #----------------------------------------------------------------------------- |
|
110 | #----------------------------------------------------------------------------- | |
111 |
|
111 | |||
112 | if __name__ == "__main__": |
|
112 | if __name__ == "__main__": | |
113 | # deal with unicode |
|
113 | # deal with unicode | |
114 | if sys.version_info < (3,): |
|
114 | if sys.version_info < (3,): | |
115 | sys.stdout = codecs.getwriter('utf8')(sys.stdout) |
|
115 | sys.stdout = codecs.getwriter('utf8')(sys.stdout) | |
116 |
|
116 | |||
117 | # Whether to add reST urls for all issues in printout. |
|
117 | # Whether to add reST urls for all issues in printout. | |
118 | show_urls = True |
|
118 | show_urls = True | |
119 |
|
119 | |||
120 | parser = ArgumentParser() |
|
120 | parser = ArgumentParser() | |
121 | parser.add_argument('--since-tag', type=str, |
|
121 | parser.add_argument('--since-tag', type=str, | |
122 | help="The git tag to use for the starting point (typically the last major release)." |
|
122 | help="The git tag to use for the starting point (typically the last major release)." | |
123 | ) |
|
123 | ) | |
124 | parser.add_argument('--milestone', type=str, |
|
124 | parser.add_argument('--milestone', type=str, | |
125 | help="The GitHub milestone to use for filtering issues [optional]." |
|
125 | help="The GitHub milestone to use for filtering issues [optional]." | |
126 | ) |
|
126 | ) | |
127 | parser.add_argument('--days', type=int, |
|
127 | parser.add_argument('--days', type=int, | |
128 | help="The number of days of data to summarize (use this or --since-tag)." |
|
128 | help="The number of days of data to summarize (use this or --since-tag)." | |
129 | ) |
|
129 | ) | |
130 | parser.add_argument('--project', type=str, default="ipython/ipython", |
|
130 | parser.add_argument('--project', type=str, default="ipython/ipython", | |
131 | help="The project to summarize." |
|
131 | help="The project to summarize." | |
132 | ) |
|
132 | ) | |
133 | parser.add_argument('--links', action='store_true', default=False, |
|
133 | parser.add_argument('--links', action='store_true', default=False, | |
134 | help="Include links to all closed Issues and PRs in the output." |
|
134 | help="Include links to all closed Issues and PRs in the output." | |
135 | ) |
|
135 | ) | |
136 |
|
136 | |||
137 | opts = parser.parse_args() |
|
137 | opts = parser.parse_args() | |
138 | tag = opts.since_tag |
|
138 | tag = opts.since_tag | |
139 |
|
139 | |||
140 | # set `since` from days or git tag |
|
140 | # set `since` from days or git tag | |
141 | if opts.days: |
|
141 | if opts.days: | |
142 | since = datetime.utcnow() - timedelta(days=opts.days) |
|
142 | since = datetime.utcnow() - timedelta(days=opts.days) | |
143 | else: |
|
143 | else: | |
144 | if not tag: |
|
144 | if not tag: | |
145 | tag = check_output(['git', 'describe', '--abbrev=0']).strip().decode('utf8') |
|
145 | tag = check_output(['git', 'describe', '--abbrev=0']).strip().decode('utf8') | |
146 | cmd = ['git', 'log', '-1', '--format=%ai', tag] |
|
146 | cmd = ['git', 'log', '-1', '--format=%ai', tag] | |
147 | tagday, tz = check_output(cmd).strip().decode('utf8').rsplit(' ', 1) |
|
147 | tagday, tz = check_output(cmd).strip().decode('utf8').rsplit(' ', 1) | |
148 | since = datetime.strptime(tagday, "%Y-%m-%d %H:%M:%S") |
|
148 | since = datetime.strptime(tagday, "%Y-%m-%d %H:%M:%S") | |
149 | h = int(tz[1:3]) |
|
149 | h = int(tz[1:3]) | |
150 | m = int(tz[3:]) |
|
150 | m = int(tz[3:]) | |
151 | td = timedelta(hours=h, minutes=m) |
|
151 | td = timedelta(hours=h, minutes=m) | |
152 | if tz[0] == '-': |
|
152 | if tz[0] == '-': | |
153 | since += td |
|
153 | since += td | |
154 | else: |
|
154 | else: | |
155 | since -= td |
|
155 | since -= td | |
156 |
|
156 | |||
157 | since = round_hour(since) |
|
157 | since = round_hour(since) | |
158 |
|
158 | |||
159 | milestone = opts.milestone |
|
159 | milestone = opts.milestone | |
160 | project = opts.project |
|
160 | project = opts.project | |
161 |
|
161 | |||
162 | print("fetching GitHub stats since %s (tag: %s, milestone: %s)" % (since, tag, milestone), file=sys.stderr) |
|
162 | print("fetching GitHub stats since %s (tag: %s, milestone: %s)" % (since, tag, milestone), file=sys.stderr) | |
163 | if milestone: |
|
163 | if milestone: | |
164 | milestone_id = get_milestone_id(project=project, milestone=milestone, |
|
164 | milestone_id = get_milestone_id(project=project, milestone=milestone, | |
165 | auth=True) |
|
165 | auth=True) | |
166 | issues_and_pulls = get_issues_list(project=project, |
|
166 | issues_and_pulls = get_issues_list(project=project, | |
167 | milestone=milestone_id, |
|
167 | milestone=milestone_id, | |
168 | state='closed', |
|
168 | state='closed', | |
169 | auth=True, |
|
169 | auth=True, | |
170 | ) |
|
170 | ) | |
171 | issues, pulls = split_pulls(issues_and_pulls) |
|
171 | issues, pulls = split_pulls(issues_and_pulls) | |
172 | else: |
|
172 | else: | |
173 | issues = issues_closed_since(since, project=project, pulls=False) |
|
173 | issues = issues_closed_since(since, project=project, pulls=False) | |
174 | pulls = issues_closed_since(since, project=project, pulls=True) |
|
174 | pulls = issues_closed_since(since, project=project, pulls=True) | |
175 |
|
175 | |||
176 | # For regular reports, it's nice to show them in reverse chronological order |
|
176 | # For regular reports, it's nice to show them in reverse chronological order | |
177 | issues = sorted_by_field(issues, reverse=True) |
|
177 | issues = sorted_by_field(issues, reverse=True) | |
178 | pulls = sorted_by_field(pulls, reverse=True) |
|
178 | pulls = sorted_by_field(pulls, reverse=True) | |
179 |
|
179 | |||
180 | n_issues, n_pulls = map(len, (issues, pulls)) |
|
180 | n_issues, n_pulls = map(len, (issues, pulls)) | |
181 | n_total = n_issues + n_pulls |
|
181 | n_total = n_issues + n_pulls | |
182 |
|
182 | |||
183 | # Print summary report we can directly include into release notes. |
|
183 | # Print summary report we can directly include into release notes. | |
184 |
|
184 | |||
185 | print() |
|
185 | print() | |
186 | since_day = since.strftime("%Y/%m/%d") |
|
186 | since_day = since.strftime("%Y/%m/%d") | |
187 | today = datetime.today().strftime("%Y/%m/%d") |
|
187 | today = datetime.today().strftime("%Y/%m/%d") | |
188 | print("GitHub stats for %s - %s (tag: %s)" % (since_day, today, tag)) |
|
188 | print("GitHub stats for %s - %s (tag: %s)" % (since_day, today, tag)) | |
189 | print() |
|
189 | print() | |
190 | print("These lists are automatically generated, and may be incomplete or contain duplicates.") |
|
190 | print("These lists are automatically generated, and may be incomplete or contain duplicates.") | |
191 | print() |
|
191 | print() | |
192 |
|
192 | |||
193 | ncommits = 0 |
|
193 | ncommits = 0 | |
194 | all_authors = [] |
|
194 | all_authors = [] | |
195 | if tag: |
|
195 | if tag: | |
196 | # print git info, in addition to GitHub info: |
|
196 | # print git info, in addition to GitHub info: | |
197 | since_tag = tag+'..' |
|
197 | since_tag = tag+'..' | |
198 | cmd = ['git', 'log', '--oneline', since_tag] |
|
198 | cmd = ['git', 'log', '--oneline', since_tag] | |
199 | ncommits += len(check_output(cmd).splitlines()) |
|
199 | ncommits += len(check_output(cmd).splitlines()) | |
200 |
|
200 | |||
201 | author_cmd = ['git', 'log', '--use-mailmap', "--format=* %aN", since_tag] |
|
201 | author_cmd = ['git', 'log', '--use-mailmap', "--format=* %aN", since_tag] | |
202 | all_authors.extend(check_output(author_cmd).decode('utf-8', 'replace').splitlines()) |
|
202 | all_authors.extend(check_output(author_cmd).decode('utf-8', 'replace').splitlines()) | |
203 |
|
203 | |||
204 | pr_authors = [] |
|
204 | pr_authors = [] | |
205 | for pr in pulls: |
|
205 | for pr in pulls: | |
206 | pr_authors.extend(get_authors(pr)) |
|
206 | pr_authors.extend(get_authors(pr)) | |
207 | ncommits = len(pr_authors) + ncommits - len(pulls) |
|
207 | ncommits = len(pr_authors) + ncommits - len(pulls) | |
208 | author_cmd = ['git', 'check-mailmap'] + pr_authors |
|
208 | author_cmd = ['git', 'check-mailmap'] + pr_authors | |
209 | with_email = check_output(author_cmd).decode('utf-8', 'replace').splitlines() |
|
209 | with_email = check_output(author_cmd).decode('utf-8', 'replace').splitlines() | |
210 | all_authors.extend([ u'* ' + a.split(' <')[0] for a in with_email ]) |
|
210 | all_authors.extend([ u'* ' + a.split(' <')[0] for a in with_email ]) | |
211 | unique_authors = sorted(set(all_authors), key=lambda s: s.lower()) |
|
211 | unique_authors = sorted(set(all_authors), key=lambda s: s.lower()) | |
212 |
|
212 | |||
213 | print("We closed %d issues and merged %d pull requests." % (n_issues, n_pulls)) |
|
213 | print("We closed %d issues and merged %d pull requests." % (n_issues, n_pulls)) | |
214 | if milestone: |
|
214 | if milestone: | |
215 | print("The full list can be seen `on GitHub <https://github.com/%s/milestone/%s>`" |
|
215 | print("The full list can be seen `on GitHub <https://github.com/%s/milestone/%s>`__" | |
216 | % (project, milestone) |
|
216 | % (project, milestone) | |
217 | ) |
|
217 | ) | |
218 |
|
218 | |||
219 | print() |
|
219 | print() | |
220 | print("The following %i authors contributed %i commits." % (len(unique_authors), ncommits)) |
|
220 | print("The following %i authors contributed %i commits." % (len(unique_authors), ncommits)) | |
221 | print() |
|
221 | print() | |
222 | print('\n'.join(unique_authors)) |
|
222 | print('\n'.join(unique_authors)) | |
223 |
|
223 | |||
224 | if opts.links: |
|
224 | if opts.links: | |
225 | print() |
|
225 | print() | |
226 | print("GitHub issues and pull requests:") |
|
226 | print("GitHub issues and pull requests:") | |
227 | print() |
|
227 | print() | |
228 | print('Pull Requests (%d):\n' % n_pulls) |
|
228 | print('Pull Requests (%d):\n' % n_pulls) | |
229 | report(pulls, show_urls) |
|
229 | report(pulls, show_urls) | |
230 | print() |
|
230 | print() | |
231 | print('Issues (%d):\n' % n_issues) |
|
231 | print('Issues (%d):\n' % n_issues) | |
232 | report(issues, show_urls) |
|
232 | report(issues, show_urls) |
General Comments 0
You need to be logged in to leave comments.
Login now