##// END OF EJS Templates
remove python2 specific cast_unicode_py2 function
Srinivas Reddy Thatiparthy -
Show More
@@ -1,1934 +1,1933 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """Completion for IPython.
2 """Completion for IPython.
3
3
4 This module started as fork of the rlcompleter module in the Python standard
4 This module started as 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,
6 upstream and were accepted as of Python 2.3,
7
7
8 This module now support a wide variety of completion mechanism both available
8 This module now support a wide variety of completion mechanism both available
9 for normal classic Python code, as well as completer for IPython specific
9 for normal classic Python code, as well as completer for IPython specific
10 Syntax like magics.
10 Syntax like magics.
11
11
12 Latex and Unicode completion
12 Latex and Unicode completion
13 ============================
13 ============================
14
14
15 IPython and compatible frontends not only can complete your code, but can help
15 IPython and compatible frontends not only can complete your code, but can help
16 you to input a wide range of characters. In particular we allow you to insert
16 you to input a wide range of characters. In particular we allow you to insert
17 a unicode character using the tab completion mechanism.
17 a unicode character using the tab completion mechanism.
18
18
19 Forward latex/unicode completion
19 Forward latex/unicode completion
20 --------------------------------
20 --------------------------------
21
21
22 Forward completion allows you to easily type a unicode character using its latex
22 Forward completion allows you to easily type a unicode character using its latex
23 name, or unicode long description. To do so type a backslash follow by the
23 name, or unicode long description. To do so type a backslash follow by the
24 relevant name and press tab:
24 relevant name and press tab:
25
25
26
26
27 Using latex completion:
27 Using latex completion:
28
28
29 .. code::
29 .. code::
30
30
31 \\alpha<tab>
31 \\alpha<tab>
32 Ξ±
32 Ξ±
33
33
34 or using unicode completion:
34 or using unicode completion:
35
35
36
36
37 .. code::
37 .. code::
38
38
39 \\greek small letter alpha<tab>
39 \\greek small letter alpha<tab>
40 Ξ±
40 Ξ±
41
41
42
42
43 Only valid Python identifiers will complete. Combining characters (like arrow or
43 Only valid Python identifiers will complete. Combining characters (like arrow or
44 dots) are also available, unlike latex they need to be put after the their
44 dots) are also available, unlike latex they need to be put after the their
45 counterpart that is to say, `F\\\\vec<tab>` is correct, not `\\\\vec<tab>F`.
45 counterpart that is to say, `F\\\\vec<tab>` is correct, not `\\\\vec<tab>F`.
46
46
47 Some browsers are known to display combining characters incorrectly.
47 Some browsers are known to display combining characters incorrectly.
48
48
49 Backward latex completion
49 Backward latex completion
50 -------------------------
50 -------------------------
51
51
52 It is sometime challenging to know how to type a character, if you are using
52 It is sometime challenging to know how to type a character, if you are using
53 IPython, or any compatible frontend you can prepend backslash to the character
53 IPython, or any compatible frontend you can prepend backslash to the character
54 and press `<tab>` to expand it to its latex form.
54 and press `<tab>` to expand it to its latex form.
55
55
56 .. code::
56 .. code::
57
57
58 \\Ξ±<tab>
58 \\Ξ±<tab>
59 \\alpha
59 \\alpha
60
60
61
61
62 Both forward and backward completions can be deactivated by setting the
62 Both forward and backward completions can be deactivated by setting the
63 ``Completer.backslash_combining_completions`` option to ``False``.
63 ``Completer.backslash_combining_completions`` option to ``False``.
64
64
65
65
66 Experimental
66 Experimental
67 ============
67 ============
68
68
69 Starting with IPython 6.0, this module can make use of the Jedi library to
69 Starting with IPython 6.0, this module can make use of the Jedi library to
70 generate completions both using static analysis of the code, and dynamically
70 generate completions both using static analysis of the code, and dynamically
71 inspecting multiple namespaces. The APIs attached to this new mechanism is
71 inspecting multiple namespaces. The APIs attached to this new mechanism is
72 unstable and will raise unless use in an :any:`provisionalcompleter` context
72 unstable and will raise unless use in an :any:`provisionalcompleter` context
73 manager.
73 manager.
74
74
75 You will find that the following are experimental:
75 You will find that the following are experimental:
76
76
77 - :any:`provisionalcompleter`
77 - :any:`provisionalcompleter`
78 - :any:`IPCompleter.completions`
78 - :any:`IPCompleter.completions`
79 - :any:`Completion`
79 - :any:`Completion`
80 - :any:`rectify_completions`
80 - :any:`rectify_completions`
81
81
82 .. note::
82 .. note::
83
83
84 better name for :any:`rectify_completions` ?
84 better name for :any:`rectify_completions` ?
85
85
86 We welcome any feedback on these new API, and we also encourage you to try this
86 We welcome any feedback on these new API, and we also encourage you to try this
87 module in debug mode (start IPython with ``--Completer.debug=True``) in order
87 module in debug mode (start IPython with ``--Completer.debug=True``) in order
88 to have extra logging information is :any:`jedi` is crashing, or if current
88 to have extra logging information is :any:`jedi` is crashing, or if current
89 IPython completer pending deprecations are returning results not yet handled
89 IPython completer pending deprecations are returning results not yet handled
90 by :any:`jedi`.
90 by :any:`jedi`.
91
91
92 Using Jedi for tab completion allow snippets like the following to work without
92 Using Jedi for tab completion allow snippets like the following to work without
93 having to execute any code:
93 having to execute any code:
94
94
95 >>> myvar = ['hello', 42]
95 >>> myvar = ['hello', 42]
96 ... myvar[1].bi<tab>
96 ... myvar[1].bi<tab>
97
97
98 Tab completion will be able to infer that ``myvar[1]`` is a real number without
98 Tab completion will be able to infer that ``myvar[1]`` is a real number without
99 executing any code unlike the previously available ``IPCompleter.greedy``
99 executing any code unlike the previously available ``IPCompleter.greedy``
100 option.
100 option.
101
101
102 Be sure to update :any:`jedi` to the latest stable version or to try the
102 Be sure to update :any:`jedi` to the latest stable version or to try the
103 current development version to get better completions.
103 current development version to get better completions.
104 """
104 """
105
105
106 # skip module docstests
106 # skip module docstests
107 skip_doctest = True
107 skip_doctest = True
108
108
109 # Copyright (c) IPython Development Team.
109 # Copyright (c) IPython Development Team.
110 # Distributed under the terms of the Modified BSD License.
110 # Distributed under the terms of the Modified BSD License.
111 #
111 #
112 # Some of this code originated from rlcompleter in the Python standard library
112 # Some of this code originated from rlcompleter in the Python standard library
113 # Copyright (C) 2001 Python Software Foundation, www.python.org
113 # Copyright (C) 2001 Python Software Foundation, www.python.org
114
114
115
115
116 import __main__
116 import __main__
117 import builtins as builtin_mod
117 import builtins as builtin_mod
118 import glob
118 import glob
119 import time
119 import time
120 import inspect
120 import inspect
121 import itertools
121 import itertools
122 import keyword
122 import keyword
123 import os
123 import os
124 import re
124 import re
125 import sys
125 import sys
126 import unicodedata
126 import unicodedata
127 import string
127 import string
128 import warnings
128 import warnings
129
129
130 from contextlib import contextmanager
130 from contextlib import contextmanager
131 from importlib import import_module
131 from importlib import import_module
132 from typing import Iterator, List
132 from typing import Iterator, List
133 from types import SimpleNamespace
133 from types import SimpleNamespace
134
134
135 from traitlets.config.configurable import Configurable
135 from traitlets.config.configurable import Configurable
136 from IPython.core.error import TryNext
136 from IPython.core.error import TryNext
137 from IPython.core.inputsplitter import ESC_MAGIC
137 from IPython.core.inputsplitter import ESC_MAGIC
138 from IPython.core.latex_symbols import latex_symbols, reverse_latex_symbol
138 from IPython.core.latex_symbols import latex_symbols, reverse_latex_symbol
139 from IPython.utils import generics
139 from IPython.utils import generics
140 from IPython.utils.dir2 import dir2, get_real_method
140 from IPython.utils.dir2 import dir2, get_real_method
141 from IPython.utils.process import arg_split
141 from IPython.utils.process import arg_split
142 from IPython.utils.py3compat import cast_unicode_py2
143 from traitlets import Bool, Enum, observe, Int
142 from traitlets import Bool, Enum, observe, Int
144
143
145 try:
144 try:
146 import jedi
145 import jedi
147 import jedi.api.helpers
146 import jedi.api.helpers
148 JEDI_INSTALLED = True
147 JEDI_INSTALLED = True
149 except ImportError:
148 except ImportError:
150 JEDI_INSTALLED = False
149 JEDI_INSTALLED = False
151 #-----------------------------------------------------------------------------
150 #-----------------------------------------------------------------------------
152 # Globals
151 # Globals
153 #-----------------------------------------------------------------------------
152 #-----------------------------------------------------------------------------
154
153
155 # Public API
154 # Public API
156 __all__ = ['Completer','IPCompleter']
155 __all__ = ['Completer','IPCompleter']
157
156
158 if sys.platform == 'win32':
157 if sys.platform == 'win32':
159 PROTECTABLES = ' '
158 PROTECTABLES = ' '
160 else:
159 else:
161 PROTECTABLES = ' ()[]{}?=\\|;:\'#*"^&'
160 PROTECTABLES = ' ()[]{}?=\\|;:\'#*"^&'
162
161
163
162
164 _deprecation_readline_sentinel = object()
163 _deprecation_readline_sentinel = object()
165
164
166
165
167 class ProvisionalCompleterWarning(FutureWarning):
166 class ProvisionalCompleterWarning(FutureWarning):
168 """
167 """
169 Exception raise by an experimental feature in this module.
168 Exception raise by an experimental feature in this module.
170
169
171 Wrap code in :any:`provisionalcompleter` context manager if you
170 Wrap code in :any:`provisionalcompleter` context manager if you
172 are certain you want to use an unstable feature.
171 are certain you want to use an unstable feature.
173 """
172 """
174 pass
173 pass
175
174
176 warnings.filterwarnings('error', category=ProvisionalCompleterWarning)
175 warnings.filterwarnings('error', category=ProvisionalCompleterWarning)
177
176
178 @contextmanager
177 @contextmanager
179 def provisionalcompleter(action='ignore'):
178 def provisionalcompleter(action='ignore'):
180 """
179 """
181
180
182
181
183 This contest manager has to be used in any place where unstable completer
182 This contest manager has to be used in any place where unstable completer
184 behavior and API may be called.
183 behavior and API may be called.
185
184
186 >>> with provisionalcompleter():
185 >>> with provisionalcompleter():
187 ... completer.do_experimetal_things() # works
186 ... completer.do_experimetal_things() # works
188
187
189 >>> completer.do_experimental_things() # raises.
188 >>> completer.do_experimental_things() # raises.
190
189
191 .. note:: Unstable
190 .. note:: Unstable
192
191
193 By using this context manager you agree that the API in use may change
192 By using this context manager you agree that the API in use may change
194 without warning, and that you won't complain if they do so.
193 without warning, and that you won't complain if they do so.
195
194
196 You also understand that if the API is not to you liking you should report
195 You also understand that if the API is not to you liking you should report
197 a bug to explain your use case upstream and improve the API and will loose
196 a bug to explain your use case upstream and improve the API and will loose
198 credibility if you complain after the API is make stable.
197 credibility if you complain after the API is make stable.
199
198
200 We'll be happy to get your feedback , feature request and improvement on
199 We'll be happy to get your feedback , feature request and improvement on
201 any of the unstable APIs !
200 any of the unstable APIs !
202 """
201 """
203 with warnings.catch_warnings():
202 with warnings.catch_warnings():
204 warnings.filterwarnings(action, category=ProvisionalCompleterWarning)
203 warnings.filterwarnings(action, category=ProvisionalCompleterWarning)
205 yield
204 yield
206
205
207
206
208 def has_open_quotes(s):
207 def has_open_quotes(s):
209 """Return whether a string has open quotes.
208 """Return whether a string has open quotes.
210
209
211 This simply counts whether the number of quote characters of either type in
210 This simply counts whether the number of quote characters of either type in
212 the string is odd.
211 the string is odd.
213
212
214 Returns
213 Returns
215 -------
214 -------
216 If there is an open quote, the quote character is returned. Else, return
215 If there is an open quote, the quote character is returned. Else, return
217 False.
216 False.
218 """
217 """
219 # We check " first, then ', so complex cases with nested quotes will get
218 # We check " first, then ', so complex cases with nested quotes will get
220 # the " to take precedence.
219 # the " to take precedence.
221 if s.count('"') % 2:
220 if s.count('"') % 2:
222 return '"'
221 return '"'
223 elif s.count("'") % 2:
222 elif s.count("'") % 2:
224 return "'"
223 return "'"
225 else:
224 else:
226 return False
225 return False
227
226
228
227
229 def protect_filename(s, protectables=PROTECTABLES):
228 def protect_filename(s, protectables=PROTECTABLES):
230 """Escape a string to protect certain characters."""
229 """Escape a string to protect certain characters."""
231 if set(s) & set(protectables):
230 if set(s) & set(protectables):
232 if sys.platform == "win32":
231 if sys.platform == "win32":
233 return '"' + s + '"'
232 return '"' + s + '"'
234 else:
233 else:
235 return "".join(("\\" + c if c in protectables else c) for c in s)
234 return "".join(("\\" + c if c in protectables else c) for c in s)
236 else:
235 else:
237 return s
236 return s
238
237
239
238
240 def expand_user(path):
239 def expand_user(path):
241 """Expand ``~``-style usernames in strings.
240 """Expand ``~``-style usernames in strings.
242
241
243 This is similar to :func:`os.path.expanduser`, but it computes and returns
242 This is similar to :func:`os.path.expanduser`, but it computes and returns
244 extra information that will be useful if the input was being used in
243 extra information that will be useful if the input was being used in
245 computing completions, and you wish to return the completions with the
244 computing completions, and you wish to return the completions with the
246 original '~' instead of its expanded value.
245 original '~' instead of its expanded value.
247
246
248 Parameters
247 Parameters
249 ----------
248 ----------
250 path : str
249 path : str
251 String to be expanded. If no ~ is present, the output is the same as the
250 String to be expanded. If no ~ is present, the output is the same as the
252 input.
251 input.
253
252
254 Returns
253 Returns
255 -------
254 -------
256 newpath : str
255 newpath : str
257 Result of ~ expansion in the input path.
256 Result of ~ expansion in the input path.
258 tilde_expand : bool
257 tilde_expand : bool
259 Whether any expansion was performed or not.
258 Whether any expansion was performed or not.
260 tilde_val : str
259 tilde_val : str
261 The value that ~ was replaced with.
260 The value that ~ was replaced with.
262 """
261 """
263 # Default values
262 # Default values
264 tilde_expand = False
263 tilde_expand = False
265 tilde_val = ''
264 tilde_val = ''
266 newpath = path
265 newpath = path
267
266
268 if path.startswith('~'):
267 if path.startswith('~'):
269 tilde_expand = True
268 tilde_expand = True
270 rest = len(path)-1
269 rest = len(path)-1
271 newpath = os.path.expanduser(path)
270 newpath = os.path.expanduser(path)
272 if rest:
271 if rest:
273 tilde_val = newpath[:-rest]
272 tilde_val = newpath[:-rest]
274 else:
273 else:
275 tilde_val = newpath
274 tilde_val = newpath
276
275
277 return newpath, tilde_expand, tilde_val
276 return newpath, tilde_expand, tilde_val
278
277
279
278
280 def compress_user(path, tilde_expand, tilde_val):
279 def compress_user(path, tilde_expand, tilde_val):
281 """Does the opposite of expand_user, with its outputs.
280 """Does the opposite of expand_user, with its outputs.
282 """
281 """
283 if tilde_expand:
282 if tilde_expand:
284 return path.replace(tilde_val, '~')
283 return path.replace(tilde_val, '~')
285 else:
284 else:
286 return path
285 return path
287
286
288
287
289 def completions_sorting_key(word):
288 def completions_sorting_key(word):
290 """key for sorting completions
289 """key for sorting completions
291
290
292 This does several things:
291 This does several things:
293
292
294 - Lowercase all completions, so they are sorted alphabetically with
293 - Lowercase all completions, so they are sorted alphabetically with
295 upper and lower case words mingled
294 upper and lower case words mingled
296 - Demote any completions starting with underscores to the end
295 - Demote any completions starting with underscores to the end
297 - Insert any %magic and %%cellmagic completions in the alphabetical order
296 - Insert any %magic and %%cellmagic completions in the alphabetical order
298 by their name
297 by their name
299 """
298 """
300 # Case insensitive sort
299 # Case insensitive sort
301 word = word.lower()
300 word = word.lower()
302
301
303 prio1, prio2 = 0, 0
302 prio1, prio2 = 0, 0
304
303
305 if word.startswith('__'):
304 if word.startswith('__'):
306 prio1 = 2
305 prio1 = 2
307 elif word.startswith('_'):
306 elif word.startswith('_'):
308 prio1 = 1
307 prio1 = 1
309
308
310 if word.endswith('='):
309 if word.endswith('='):
311 prio1 = -1
310 prio1 = -1
312
311
313 if word.startswith('%%'):
312 if word.startswith('%%'):
314 # If there's another % in there, this is something else, so leave it alone
313 # If there's another % in there, this is something else, so leave it alone
315 if not "%" in word[2:]:
314 if not "%" in word[2:]:
316 word = word[2:]
315 word = word[2:]
317 prio2 = 2
316 prio2 = 2
318 elif word.startswith('%'):
317 elif word.startswith('%'):
319 if not "%" in word[1:]:
318 if not "%" in word[1:]:
320 word = word[1:]
319 word = word[1:]
321 prio2 = 1
320 prio2 = 1
322
321
323 return prio1, word, prio2
322 return prio1, word, prio2
324
323
325
324
326 class _FakeJediCompletion:
325 class _FakeJediCompletion:
327 """
326 """
328 This is a workaround to communicate to the UI that Jedi has crashed and to
327 This is a workaround to communicate to the UI that Jedi has crashed and to
329 report a bug. Will be used only id :any:`IPCompleter.debug` is set to true.
328 report a bug. Will be used only id :any:`IPCompleter.debug` is set to true.
330
329
331 Added in IPython 6.0 so should likely be removed for 7.0
330 Added in IPython 6.0 so should likely be removed for 7.0
332
331
333 """
332 """
334
333
335 def __init__(self, name):
334 def __init__(self, name):
336
335
337 self.name = name
336 self.name = name
338 self.complete = name
337 self.complete = name
339 self.type = 'crashed'
338 self.type = 'crashed'
340 self.name_with_symbols = name
339 self.name_with_symbols = name
341
340
342 def __repr__(self):
341 def __repr__(self):
343 return '<Fake completion object jedi has crashed>'
342 return '<Fake completion object jedi has crashed>'
344
343
345
344
346 class Completion:
345 class Completion:
347 """
346 """
348 Completion object used and return by IPython completers.
347 Completion object used and return by IPython completers.
349
348
350 .. warning:: Unstable
349 .. warning:: Unstable
351
350
352 This function is unstable, API may change without warning.
351 This function is unstable, API may change without warning.
353 It will also raise unless use in proper context manager.
352 It will also raise unless use in proper context manager.
354
353
355 This act as a middle ground :any:`Completion` object between the
354 This act as a middle ground :any:`Completion` object between the
356 :any:`jedi.api.classes.Completion` object and the Prompt Toolkit completion
355 :any:`jedi.api.classes.Completion` object and the Prompt Toolkit completion
357 object. While Jedi need a lot of information about evaluator and how the
356 object. While Jedi need a lot of information about evaluator and how the
358 code should be ran/inspected, PromptToolkit (and other frontend) mostly
357 code should be ran/inspected, PromptToolkit (and other frontend) mostly
359 need user facing information.
358 need user facing information.
360
359
361 - Which range should be replaced replaced by what.
360 - Which range should be replaced replaced by what.
362 - Some metadata (like completion type), or meta informations to displayed to
361 - Some metadata (like completion type), or meta informations to displayed to
363 the use user.
362 the use user.
364
363
365 For debugging purpose we can also store the origin of the completion (``jedi``,
364 For debugging purpose we can also store the origin of the completion (``jedi``,
366 ``IPython.python_matches``, ``IPython.magics_matches``...).
365 ``IPython.python_matches``, ``IPython.magics_matches``...).
367 """
366 """
368
367
369 def __init__(self, start: int, end: int, text: str, *, type: str=None, _origin=''):
368 def __init__(self, start: int, end: int, text: str, *, type: str=None, _origin=''):
370 warnings.warn("``Completion`` is a provisional API (as of IPython 6.0). "
369 warnings.warn("``Completion`` is a provisional API (as of IPython 6.0). "
371 "It may change without warnings. "
370 "It may change without warnings. "
372 "Use in corresponding context manager.",
371 "Use in corresponding context manager.",
373 category=ProvisionalCompleterWarning, stacklevel=2)
372 category=ProvisionalCompleterWarning, stacklevel=2)
374
373
375 self.start = start
374 self.start = start
376 self.end = end
375 self.end = end
377 self.text = text
376 self.text = text
378 self.type = type
377 self.type = type
379 self._origin = _origin
378 self._origin = _origin
380
379
381 def __repr__(self):
380 def __repr__(self):
382 return '<Completion start=%s end=%s text=%r type=%r>' % (self.start, self.end, self.text, self.type or '?')
381 return '<Completion start=%s end=%s text=%r type=%r>' % (self.start, self.end, self.text, self.type or '?')
383
382
384 def __eq__(self, other)->Bool:
383 def __eq__(self, other)->Bool:
385 """
384 """
386 Equality and hash do not hash the type (as some completer may not be
385 Equality and hash do not hash the type (as some completer may not be
387 able to infer the type), but are use to (partially) de-duplicate
386 able to infer the type), but are use to (partially) de-duplicate
388 completion.
387 completion.
389
388
390 Completely de-duplicating completion is a bit tricker that just
389 Completely de-duplicating completion is a bit tricker that just
391 comparing as it depends on surrounding text, which Completions are not
390 comparing as it depends on surrounding text, which Completions are not
392 aware of.
391 aware of.
393 """
392 """
394 return self.start == other.start and \
393 return self.start == other.start and \
395 self.end == other.end and \
394 self.end == other.end and \
396 self.text == other.text
395 self.text == other.text
397
396
398 def __hash__(self):
397 def __hash__(self):
399 return hash((self.start, self.end, self.text))
398 return hash((self.start, self.end, self.text))
400
399
401
400
402 _IC = Iterator[Completion]
401 _IC = Iterator[Completion]
403
402
404
403
405 def _deduplicate_completions(text: str, completions: _IC)-> _IC:
404 def _deduplicate_completions(text: str, completions: _IC)-> _IC:
406 """
405 """
407 Deduplicate a set of completions.
406 Deduplicate a set of completions.
408
407
409 .. warning:: Unstable
408 .. warning:: Unstable
410
409
411 This function is unstable, API may change without warning.
410 This function is unstable, API may change without warning.
412
411
413 Parameters
412 Parameters
414 ----------
413 ----------
415 text: str
414 text: str
416 text that should be completed.
415 text that should be completed.
417 completions: Iterator[Completion]
416 completions: Iterator[Completion]
418 iterator over the completions to deduplicate
417 iterator over the completions to deduplicate
419
418
420
419
421 Completions coming from multiple sources, may be different but end up having
420 Completions coming from multiple sources, may be different but end up having
422 the same effect when applied to ``text``. If this is the case, this will
421 the same effect when applied to ``text``. If this is the case, this will
423 consider completions as equal and only emit the first encountered.
422 consider completions as equal and only emit the first encountered.
424
423
425 Not folded in `completions()` yet for debugging purpose, and to detect when
424 Not folded in `completions()` yet for debugging purpose, and to detect when
426 the IPython completer does return things that Jedi does not, but should be
425 the IPython completer does return things that Jedi does not, but should be
427 at some point.
426 at some point.
428 """
427 """
429 completions = list(completions)
428 completions = list(completions)
430 if not completions:
429 if not completions:
431 return
430 return
432
431
433 new_start = min(c.start for c in completions)
432 new_start = min(c.start for c in completions)
434 new_end = max(c.end for c in completions)
433 new_end = max(c.end for c in completions)
435
434
436 seen = set()
435 seen = set()
437 for c in completions:
436 for c in completions:
438 new_text = text[new_start:c.start] + c.text + text[c.end:new_end]
437 new_text = text[new_start:c.start] + c.text + text[c.end:new_end]
439 if new_text not in seen:
438 if new_text not in seen:
440 yield c
439 yield c
441 seen.add(new_text)
440 seen.add(new_text)
442
441
443
442
444 def rectify_completions(text: str, completions: _IC, *, _debug=False)->_IC:
443 def rectify_completions(text: str, completions: _IC, *, _debug=False)->_IC:
445 """
444 """
446 Rectify a set of completions to all have the same ``start`` and ``end``
445 Rectify a set of completions to all have the same ``start`` and ``end``
447
446
448 .. warning:: Unstable
447 .. warning:: Unstable
449
448
450 This function is unstable, API may change without warning.
449 This function is unstable, API may change without warning.
451 It will also raise unless use in proper context manager.
450 It will also raise unless use in proper context manager.
452
451
453 Parameters
452 Parameters
454 ----------
453 ----------
455 text: str
454 text: str
456 text that should be completed.
455 text that should be completed.
457 completions: Iterator[Completion]
456 completions: Iterator[Completion]
458 iterator over the completions to rectify
457 iterator over the completions to rectify
459
458
460
459
461 :any:`jedi.api.classes.Completion` s returned by Jedi may not have the same start and end, though
460 :any:`jedi.api.classes.Completion` s returned by Jedi may not have the same start and end, though
462 the Jupyter Protocol requires them to behave like so. This will readjust
461 the Jupyter Protocol requires them to behave like so. This will readjust
463 the completion to have the same ``start`` and ``end`` by padding both
462 the completion to have the same ``start`` and ``end`` by padding both
464 extremities with surrounding text.
463 extremities with surrounding text.
465
464
466 During stabilisation should support a ``_debug`` option to log which
465 During stabilisation should support a ``_debug`` option to log which
467 completion are return by the IPython completer and not found in Jedi in
466 completion are return by the IPython completer and not found in Jedi in
468 order to make upstream bug report.
467 order to make upstream bug report.
469 """
468 """
470 warnings.warn("`rectify_completions` is a provisional API (as of IPython 6.0). "
469 warnings.warn("`rectify_completions` is a provisional API (as of IPython 6.0). "
471 "It may change without warnings. "
470 "It may change without warnings. "
472 "Use in corresponding context manager.",
471 "Use in corresponding context manager.",
473 category=ProvisionalCompleterWarning, stacklevel=2)
472 category=ProvisionalCompleterWarning, stacklevel=2)
474
473
475 completions = list(completions)
474 completions = list(completions)
476 if not completions:
475 if not completions:
477 return
476 return
478 starts = (c.start for c in completions)
477 starts = (c.start for c in completions)
479 ends = (c.end for c in completions)
478 ends = (c.end for c in completions)
480
479
481 new_start = min(starts)
480 new_start = min(starts)
482 new_end = max(ends)
481 new_end = max(ends)
483
482
484 seen_jedi = set()
483 seen_jedi = set()
485 seen_python_matches = set()
484 seen_python_matches = set()
486 for c in completions:
485 for c in completions:
487 new_text = text[new_start:c.start] + c.text + text[c.end:new_end]
486 new_text = text[new_start:c.start] + c.text + text[c.end:new_end]
488 if c._origin == 'jedi':
487 if c._origin == 'jedi':
489 seen_jedi.add(new_text)
488 seen_jedi.add(new_text)
490 elif c._origin == 'IPCompleter.python_matches':
489 elif c._origin == 'IPCompleter.python_matches':
491 seen_python_matches.add(new_text)
490 seen_python_matches.add(new_text)
492 yield Completion(new_start, new_end, new_text, type=c.type, _origin=c._origin)
491 yield Completion(new_start, new_end, new_text, type=c.type, _origin=c._origin)
493 diff = seen_python_matches.difference(seen_jedi)
492 diff = seen_python_matches.difference(seen_jedi)
494 if diff and _debug:
493 if diff and _debug:
495 print('IPython.python matches have extras:', diff)
494 print('IPython.python matches have extras:', diff)
496
495
497
496
498 if sys.platform == 'win32':
497 if sys.platform == 'win32':
499 DELIMS = ' \t\n`!@#$^&*()=+[{]}|;\'",<>?'
498 DELIMS = ' \t\n`!@#$^&*()=+[{]}|;\'",<>?'
500 else:
499 else:
501 DELIMS = ' \t\n`!@#$^&*()=+[{]}\\|;:\'",<>?'
500 DELIMS = ' \t\n`!@#$^&*()=+[{]}\\|;:\'",<>?'
502
501
503 GREEDY_DELIMS = ' =\r\n'
502 GREEDY_DELIMS = ' =\r\n'
504
503
505
504
506 class CompletionSplitter(object):
505 class CompletionSplitter(object):
507 """An object to split an input line in a manner similar to readline.
506 """An object to split an input line in a manner similar to readline.
508
507
509 By having our own implementation, we can expose readline-like completion in
508 By having our own implementation, we can expose readline-like completion in
510 a uniform manner to all frontends. This object only needs to be given the
509 a uniform manner to all frontends. This object only needs to be given the
511 line of text to be split and the cursor position on said line, and it
510 line of text to be split and the cursor position on said line, and it
512 returns the 'word' to be completed on at the cursor after splitting the
511 returns the 'word' to be completed on at the cursor after splitting the
513 entire line.
512 entire line.
514
513
515 What characters are used as splitting delimiters can be controlled by
514 What characters are used as splitting delimiters can be controlled by
516 setting the ``delims`` attribute (this is a property that internally
515 setting the ``delims`` attribute (this is a property that internally
517 automatically builds the necessary regular expression)"""
516 automatically builds the necessary regular expression)"""
518
517
519 # Private interface
518 # Private interface
520
519
521 # A string of delimiter characters. The default value makes sense for
520 # A string of delimiter characters. The default value makes sense for
522 # IPython's most typical usage patterns.
521 # IPython's most typical usage patterns.
523 _delims = DELIMS
522 _delims = DELIMS
524
523
525 # The expression (a normal string) to be compiled into a regular expression
524 # The expression (a normal string) to be compiled into a regular expression
526 # for actual splitting. We store it as an attribute mostly for ease of
525 # for actual splitting. We store it as an attribute mostly for ease of
527 # debugging, since this type of code can be so tricky to debug.
526 # debugging, since this type of code can be so tricky to debug.
528 _delim_expr = None
527 _delim_expr = None
529
528
530 # The regular expression that does the actual splitting
529 # The regular expression that does the actual splitting
531 _delim_re = None
530 _delim_re = None
532
531
533 def __init__(self, delims=None):
532 def __init__(self, delims=None):
534 delims = CompletionSplitter._delims if delims is None else delims
533 delims = CompletionSplitter._delims if delims is None else delims
535 self.delims = delims
534 self.delims = delims
536
535
537 @property
536 @property
538 def delims(self):
537 def delims(self):
539 """Return the string of delimiter characters."""
538 """Return the string of delimiter characters."""
540 return self._delims
539 return self._delims
541
540
542 @delims.setter
541 @delims.setter
543 def delims(self, delims):
542 def delims(self, delims):
544 """Set the delimiters for line splitting."""
543 """Set the delimiters for line splitting."""
545 expr = '[' + ''.join('\\'+ c for c in delims) + ']'
544 expr = '[' + ''.join('\\'+ c for c in delims) + ']'
546 self._delim_re = re.compile(expr)
545 self._delim_re = re.compile(expr)
547 self._delims = delims
546 self._delims = delims
548 self._delim_expr = expr
547 self._delim_expr = expr
549
548
550 def split_line(self, line, cursor_pos=None):
549 def split_line(self, line, cursor_pos=None):
551 """Split a line of text with a cursor at the given position.
550 """Split a line of text with a cursor at the given position.
552 """
551 """
553 l = line if cursor_pos is None else line[:cursor_pos]
552 l = line if cursor_pos is None else line[:cursor_pos]
554 return self._delim_re.split(l)[-1]
553 return self._delim_re.split(l)[-1]
555
554
556
555
557
556
558 class Completer(Configurable):
557 class Completer(Configurable):
559
558
560 greedy = Bool(False,
559 greedy = Bool(False,
561 help="""Activate greedy completion
560 help="""Activate greedy completion
562 PENDING DEPRECTION. this is now mostly taken care of with Jedi.
561 PENDING DEPRECTION. this is now mostly taken care of with Jedi.
563
562
564 This will enable completion on elements of lists, results of function calls, etc.,
563 This will enable completion on elements of lists, results of function calls, etc.,
565 but can be unsafe because the code is actually evaluated on TAB.
564 but can be unsafe because the code is actually evaluated on TAB.
566 """
565 """
567 ).tag(config=True)
566 ).tag(config=True)
568
567
569 use_jedi = Bool(default_value=JEDI_INSTALLED,
568 use_jedi = Bool(default_value=JEDI_INSTALLED,
570 help="Experimental: Use Jedi to generate autocompletions. "
569 help="Experimental: Use Jedi to generate autocompletions. "
571 "Default to True if jedi is installed").tag(config=True)
570 "Default to True if jedi is installed").tag(config=True)
572
571
573 jedi_compute_type_timeout = Int(default_value=400,
572 jedi_compute_type_timeout = Int(default_value=400,
574 help="""Experimental: restrict time (in milliseconds) during which Jedi can compute types.
573 help="""Experimental: restrict time (in milliseconds) during which Jedi can compute types.
575 Set to 0 to stop computing types. Non-zero value lower than 100ms may hurt
574 Set to 0 to stop computing types. Non-zero value lower than 100ms may hurt
576 performance by preventing jedi to build its cache.
575 performance by preventing jedi to build its cache.
577 """).tag(config=True)
576 """).tag(config=True)
578
577
579 debug = Bool(default_value=False,
578 debug = Bool(default_value=False,
580 help='Enable debug for the Completer. Mostly print extra '
579 help='Enable debug for the Completer. Mostly print extra '
581 'information for experimental jedi integration.')\
580 'information for experimental jedi integration.')\
582 .tag(config=True)
581 .tag(config=True)
583
582
584 backslash_combining_completions = Bool(True,
583 backslash_combining_completions = Bool(True,
585 help="Enable unicode completions, e.g. \\alpha<tab> . "
584 help="Enable unicode completions, e.g. \\alpha<tab> . "
586 "Includes completion of latex commands, unicode names, and expanding "
585 "Includes completion of latex commands, unicode names, and expanding "
587 "unicode characters back to latex commands.").tag(config=True)
586 "unicode characters back to latex commands.").tag(config=True)
588
587
589
588
590
589
591 def __init__(self, namespace=None, global_namespace=None, **kwargs):
590 def __init__(self, namespace=None, global_namespace=None, **kwargs):
592 """Create a new completer for the command line.
591 """Create a new completer for the command line.
593
592
594 Completer(namespace=ns, global_namespace=ns2) -> completer instance.
593 Completer(namespace=ns, global_namespace=ns2) -> completer instance.
595
594
596 If unspecified, the default namespace where completions are performed
595 If unspecified, the default namespace where completions are performed
597 is __main__ (technically, __main__.__dict__). Namespaces should be
596 is __main__ (technically, __main__.__dict__). Namespaces should be
598 given as dictionaries.
597 given as dictionaries.
599
598
600 An optional second namespace can be given. This allows the completer
599 An optional second namespace can be given. This allows the completer
601 to handle cases where both the local and global scopes need to be
600 to handle cases where both the local and global scopes need to be
602 distinguished.
601 distinguished.
603 """
602 """
604
603
605 # Don't bind to namespace quite yet, but flag whether the user wants a
604 # Don't bind to namespace quite yet, but flag whether the user wants a
606 # specific namespace or to use __main__.__dict__. This will allow us
605 # specific namespace or to use __main__.__dict__. This will allow us
607 # to bind to __main__.__dict__ at completion time, not now.
606 # to bind to __main__.__dict__ at completion time, not now.
608 if namespace is None:
607 if namespace is None:
609 self.use_main_ns = True
608 self.use_main_ns = True
610 else:
609 else:
611 self.use_main_ns = False
610 self.use_main_ns = False
612 self.namespace = namespace
611 self.namespace = namespace
613
612
614 # The global namespace, if given, can be bound directly
613 # The global namespace, if given, can be bound directly
615 if global_namespace is None:
614 if global_namespace is None:
616 self.global_namespace = {}
615 self.global_namespace = {}
617 else:
616 else:
618 self.global_namespace = global_namespace
617 self.global_namespace = global_namespace
619
618
620 super(Completer, self).__init__(**kwargs)
619 super(Completer, self).__init__(**kwargs)
621
620
622 def complete(self, text, state):
621 def complete(self, text, state):
623 """Return the next possible completion for 'text'.
622 """Return the next possible completion for 'text'.
624
623
625 This is called successively with state == 0, 1, 2, ... until it
624 This is called successively with state == 0, 1, 2, ... until it
626 returns None. The completion should begin with 'text'.
625 returns None. The completion should begin with 'text'.
627
626
628 """
627 """
629 if self.use_main_ns:
628 if self.use_main_ns:
630 self.namespace = __main__.__dict__
629 self.namespace = __main__.__dict__
631
630
632 if state == 0:
631 if state == 0:
633 if "." in text:
632 if "." in text:
634 self.matches = self.attr_matches(text)
633 self.matches = self.attr_matches(text)
635 else:
634 else:
636 self.matches = self.global_matches(text)
635 self.matches = self.global_matches(text)
637 try:
636 try:
638 return self.matches[state]
637 return self.matches[state]
639 except IndexError:
638 except IndexError:
640 return None
639 return None
641
640
642 def global_matches(self, text):
641 def global_matches(self, text):
643 """Compute matches when text is a simple name.
642 """Compute matches when text is a simple name.
644
643
645 Return a list of all keywords, built-in functions and names currently
644 Return a list of all keywords, built-in functions and names currently
646 defined in self.namespace or self.global_namespace that match.
645 defined in self.namespace or self.global_namespace that match.
647
646
648 """
647 """
649 matches = []
648 matches = []
650 match_append = matches.append
649 match_append = matches.append
651 n = len(text)
650 n = len(text)
652 for lst in [keyword.kwlist,
651 for lst in [keyword.kwlist,
653 builtin_mod.__dict__.keys(),
652 builtin_mod.__dict__.keys(),
654 self.namespace.keys(),
653 self.namespace.keys(),
655 self.global_namespace.keys()]:
654 self.global_namespace.keys()]:
656 for word in lst:
655 for word in lst:
657 if word[:n] == text and word != "__builtins__":
656 if word[:n] == text and word != "__builtins__":
658 match_append(word)
657 match_append(word)
659
658
660 snake_case_re = re.compile(r"[^_]+(_[^_]+)+?\Z")
659 snake_case_re = re.compile(r"[^_]+(_[^_]+)+?\Z")
661 for lst in [self.namespace.keys(),
660 for lst in [self.namespace.keys(),
662 self.global_namespace.keys()]:
661 self.global_namespace.keys()]:
663 shortened = {"_".join([sub[0] for sub in word.split('_')]) : word
662 shortened = {"_".join([sub[0] for sub in word.split('_')]) : word
664 for word in lst if snake_case_re.match(word)}
663 for word in lst if snake_case_re.match(word)}
665 for word in shortened.keys():
664 for word in shortened.keys():
666 if word[:n] == text and word != "__builtins__":
665 if word[:n] == text and word != "__builtins__":
667 match_append(shortened[word])
666 match_append(shortened[word])
668 return [cast_unicode_py2(m) for m in matches]
667 return matches
669
668
670 def attr_matches(self, text):
669 def attr_matches(self, text):
671 """Compute matches when text contains a dot.
670 """Compute matches when text contains a dot.
672
671
673 Assuming the text is of the form NAME.NAME....[NAME], and is
672 Assuming the text is of the form NAME.NAME....[NAME], and is
674 evaluatable in self.namespace or self.global_namespace, it will be
673 evaluatable in self.namespace or self.global_namespace, it will be
675 evaluated and its attributes (as revealed by dir()) are used as
674 evaluated and its attributes (as revealed by dir()) are used as
676 possible completions. (For class instances, class members are are
675 possible completions. (For class instances, class members are are
677 also considered.)
676 also considered.)
678
677
679 WARNING: this can still invoke arbitrary C code, if an object
678 WARNING: this can still invoke arbitrary C code, if an object
680 with a __getattr__ hook is evaluated.
679 with a __getattr__ hook is evaluated.
681
680
682 """
681 """
683
682
684 # Another option, seems to work great. Catches things like ''.<tab>
683 # Another option, seems to work great. Catches things like ''.<tab>
685 m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text)
684 m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text)
686
685
687 if m:
686 if m:
688 expr, attr = m.group(1, 3)
687 expr, attr = m.group(1, 3)
689 elif self.greedy:
688 elif self.greedy:
690 m2 = re.match(r"(.+)\.(\w*)$", self.line_buffer)
689 m2 = re.match(r"(.+)\.(\w*)$", self.line_buffer)
691 if not m2:
690 if not m2:
692 return []
691 return []
693 expr, attr = m2.group(1,2)
692 expr, attr = m2.group(1,2)
694 else:
693 else:
695 return []
694 return []
696
695
697 try:
696 try:
698 obj = eval(expr, self.namespace)
697 obj = eval(expr, self.namespace)
699 except:
698 except:
700 try:
699 try:
701 obj = eval(expr, self.global_namespace)
700 obj = eval(expr, self.global_namespace)
702 except:
701 except:
703 return []
702 return []
704
703
705 if self.limit_to__all__ and hasattr(obj, '__all__'):
704 if self.limit_to__all__ and hasattr(obj, '__all__'):
706 words = get__all__entries(obj)
705 words = get__all__entries(obj)
707 else:
706 else:
708 words = dir2(obj)
707 words = dir2(obj)
709
708
710 try:
709 try:
711 words = generics.complete_object(obj, words)
710 words = generics.complete_object(obj, words)
712 except TryNext:
711 except TryNext:
713 pass
712 pass
714 except AssertionError:
713 except AssertionError:
715 raise
714 raise
716 except Exception:
715 except Exception:
717 # Silence errors from completion function
716 # Silence errors from completion function
718 #raise # dbg
717 #raise # dbg
719 pass
718 pass
720 # Build match list to return
719 # Build match list to return
721 n = len(attr)
720 n = len(attr)
722 return [u"%s.%s" % (expr, w) for w in words if w[:n] == attr ]
721 return [u"%s.%s" % (expr, w) for w in words if w[:n] == attr ]
723
722
724
723
725 def get__all__entries(obj):
724 def get__all__entries(obj):
726 """returns the strings in the __all__ attribute"""
725 """returns the strings in the __all__ attribute"""
727 try:
726 try:
728 words = getattr(obj, '__all__')
727 words = getattr(obj, '__all__')
729 except:
728 except:
730 return []
729 return []
731
730
732 return [cast_unicode_py2(w) for w in words if isinstance(w, str)]
731 return [w for w in words if isinstance(w, str)]
733
732
734
733
735 def match_dict_keys(keys: List[str], prefix: str, delims: str):
734 def match_dict_keys(keys: List[str], prefix: str, delims: str):
736 """Used by dict_key_matches, matching the prefix to a list of keys
735 """Used by dict_key_matches, matching the prefix to a list of keys
737
736
738 Parameters
737 Parameters
739 ==========
738 ==========
740 keys:
739 keys:
741 list of keys in dictionary currently being completed.
740 list of keys in dictionary currently being completed.
742 prefix:
741 prefix:
743 Part of the text already typed by the user. e.g. `mydict[b'fo`
742 Part of the text already typed by the user. e.g. `mydict[b'fo`
744 delims:
743 delims:
745 String of delimiters to consider when finding the current key.
744 String of delimiters to consider when finding the current key.
746
745
747 Returns
746 Returns
748 =======
747 =======
749
748
750 A tuple of three elements: ``quote``, ``token_start``, ``matched``, with
749 A tuple of three elements: ``quote``, ``token_start``, ``matched``, with
751 ``quote`` being the quote that need to be used to close current string.
750 ``quote`` being the quote that need to be used to close current string.
752 ``token_start`` the position where the replacement should start occurring,
751 ``token_start`` the position where the replacement should start occurring,
753 ``matches`` a list of replacement/completion
752 ``matches`` a list of replacement/completion
754
753
755 """
754 """
756 if not prefix:
755 if not prefix:
757 return None, 0, [repr(k) for k in keys
756 return None, 0, [repr(k) for k in keys
758 if isinstance(k, (str, bytes))]
757 if isinstance(k, (str, bytes))]
759 quote_match = re.search('["\']', prefix)
758 quote_match = re.search('["\']', prefix)
760 quote = quote_match.group()
759 quote = quote_match.group()
761 try:
760 try:
762 prefix_str = eval(prefix + quote, {})
761 prefix_str = eval(prefix + quote, {})
763 except Exception:
762 except Exception:
764 return None, 0, []
763 return None, 0, []
765
764
766 pattern = '[^' + ''.join('\\' + c for c in delims) + ']*$'
765 pattern = '[^' + ''.join('\\' + c for c in delims) + ']*$'
767 token_match = re.search(pattern, prefix, re.UNICODE)
766 token_match = re.search(pattern, prefix, re.UNICODE)
768 token_start = token_match.start()
767 token_start = token_match.start()
769 token_prefix = token_match.group()
768 token_prefix = token_match.group()
770
769
771 matched = []
770 matched = []
772 for key in keys:
771 for key in keys:
773 try:
772 try:
774 if not key.startswith(prefix_str):
773 if not key.startswith(prefix_str):
775 continue
774 continue
776 except (AttributeError, TypeError, UnicodeError):
775 except (AttributeError, TypeError, UnicodeError):
777 # Python 3+ TypeError on b'a'.startswith('a') or vice-versa
776 # Python 3+ TypeError on b'a'.startswith('a') or vice-versa
778 continue
777 continue
779
778
780 # reformat remainder of key to begin with prefix
779 # reformat remainder of key to begin with prefix
781 rem = key[len(prefix_str):]
780 rem = key[len(prefix_str):]
782 # force repr wrapped in '
781 # force repr wrapped in '
783 rem_repr = repr(rem + '"') if isinstance(rem, str) else repr(rem + b'"')
782 rem_repr = repr(rem + '"') if isinstance(rem, str) else repr(rem + b'"')
784 if rem_repr.startswith('u') and prefix[0] not in 'uU':
783 if rem_repr.startswith('u') and prefix[0] not in 'uU':
785 # Found key is unicode, but prefix is Py2 string.
784 # Found key is unicode, but prefix is Py2 string.
786 # Therefore attempt to interpret key as string.
785 # Therefore attempt to interpret key as string.
787 try:
786 try:
788 rem_repr = repr(rem.encode('ascii') + '"')
787 rem_repr = repr(rem.encode('ascii') + '"')
789 except UnicodeEncodeError:
788 except UnicodeEncodeError:
790 continue
789 continue
791
790
792 rem_repr = rem_repr[1 + rem_repr.index("'"):-2]
791 rem_repr = rem_repr[1 + rem_repr.index("'"):-2]
793 if quote == '"':
792 if quote == '"':
794 # The entered prefix is quoted with ",
793 # The entered prefix is quoted with ",
795 # but the match is quoted with '.
794 # but the match is quoted with '.
796 # A contained " hence needs escaping for comparison:
795 # A contained " hence needs escaping for comparison:
797 rem_repr = rem_repr.replace('"', '\\"')
796 rem_repr = rem_repr.replace('"', '\\"')
798
797
799 # then reinsert prefix from start of token
798 # then reinsert prefix from start of token
800 matched.append('%s%s' % (token_prefix, rem_repr))
799 matched.append('%s%s' % (token_prefix, rem_repr))
801 return quote, token_start, matched
800 return quote, token_start, matched
802
801
803
802
804 def cursor_to_position(text:int, line:int, column:int)->int:
803 def cursor_to_position(text:int, line:int, column:int)->int:
805 """
804 """
806
805
807 Convert the (line,column) position of the cursor in text to an offset in a
806 Convert the (line,column) position of the cursor in text to an offset in a
808 string.
807 string.
809
808
810 Parameters
809 Parameters
811 ----------
810 ----------
812
811
813 text : str
812 text : str
814 The text in which to calculate the cursor offset
813 The text in which to calculate the cursor offset
815 line : int
814 line : int
816 Line of the cursor; 0-indexed
815 Line of the cursor; 0-indexed
817 column : int
816 column : int
818 Column of the cursor 0-indexed
817 Column of the cursor 0-indexed
819
818
820 Return
819 Return
821 ------
820 ------
822 Position of the cursor in ``text``, 0-indexed.
821 Position of the cursor in ``text``, 0-indexed.
823
822
824 See Also
823 See Also
825 --------
824 --------
826 position_to_cursor: reciprocal of this function
825 position_to_cursor: reciprocal of this function
827
826
828 """
827 """
829 lines = text.split('\n')
828 lines = text.split('\n')
830 assert line <= len(lines), '{} <= {}'.format(str(line), str(len(lines)))
829 assert line <= len(lines), '{} <= {}'.format(str(line), str(len(lines)))
831
830
832 return sum(len(l) + 1 for l in lines[:line]) + column
831 return sum(len(l) + 1 for l in lines[:line]) + column
833
832
834 def position_to_cursor(text:str, offset:int)->(int, int):
833 def position_to_cursor(text:str, offset:int)->(int, int):
835 """
834 """
836 Convert the position of the cursor in text (0 indexed) to a line
835 Convert the position of the cursor in text (0 indexed) to a line
837 number(0-indexed) and a column number (0-indexed) pair
836 number(0-indexed) and a column number (0-indexed) pair
838
837
839 Position should be a valid position in ``text``.
838 Position should be a valid position in ``text``.
840
839
841 Parameters
840 Parameters
842 ----------
841 ----------
843
842
844 text : str
843 text : str
845 The text in which to calculate the cursor offset
844 The text in which to calculate the cursor offset
846 offset : int
845 offset : int
847 Position of the cursor in ``text``, 0-indexed.
846 Position of the cursor in ``text``, 0-indexed.
848
847
849 Return
848 Return
850 ------
849 ------
851 (line, column) : (int, int)
850 (line, column) : (int, int)
852 Line of the cursor; 0-indexed, column of the cursor 0-indexed
851 Line of the cursor; 0-indexed, column of the cursor 0-indexed
853
852
854
853
855 See Also
854 See Also
856 --------
855 --------
857 cursor_to_position : reciprocal of this function
856 cursor_to_position : reciprocal of this function
858
857
859
858
860 """
859 """
861
860
862 assert 0 < offset <= len(text) , "0 < %s <= %s" % (offset , len(text))
861 assert 0 < offset <= len(text) , "0 < %s <= %s" % (offset , len(text))
863
862
864 before = text[:offset]
863 before = text[:offset]
865 blines = before.split('\n') # ! splitnes trim trailing \n
864 blines = before.split('\n') # ! splitnes trim trailing \n
866 line = before.count('\n')
865 line = before.count('\n')
867 col = len(blines[-1])
866 col = len(blines[-1])
868 return line, col
867 return line, col
869
868
870
869
871 def _safe_isinstance(obj, module, class_name):
870 def _safe_isinstance(obj, module, class_name):
872 """Checks if obj is an instance of module.class_name if loaded
871 """Checks if obj is an instance of module.class_name if loaded
873 """
872 """
874 return (module in sys.modules and
873 return (module in sys.modules and
875 isinstance(obj, getattr(import_module(module), class_name)))
874 isinstance(obj, getattr(import_module(module), class_name)))
876
875
877
876
878 def back_unicode_name_matches(text):
877 def back_unicode_name_matches(text):
879 u"""Match unicode characters back to unicode name
878 u"""Match unicode characters back to unicode name
880
879
881 This does ``β˜ƒ`` -> ``\\snowman``
880 This does ``β˜ƒ`` -> ``\\snowman``
882
881
883 Note that snowman is not a valid python3 combining character but will be expanded.
882 Note that snowman is not a valid python3 combining character but will be expanded.
884 Though it will not recombine back to the snowman character by the completion machinery.
883 Though it will not recombine back to the snowman character by the completion machinery.
885
884
886 This will not either back-complete standard sequences like \\n, \\b ...
885 This will not either back-complete standard sequences like \\n, \\b ...
887
886
888 Used on Python 3 only.
887 Used on Python 3 only.
889 """
888 """
890 if len(text)<2:
889 if len(text)<2:
891 return u'', ()
890 return u'', ()
892 maybe_slash = text[-2]
891 maybe_slash = text[-2]
893 if maybe_slash != '\\':
892 if maybe_slash != '\\':
894 return u'', ()
893 return u'', ()
895
894
896 char = text[-1]
895 char = text[-1]
897 # no expand on quote for completion in strings.
896 # no expand on quote for completion in strings.
898 # nor backcomplete standard ascii keys
897 # nor backcomplete standard ascii keys
899 if char in string.ascii_letters or char in ['"',"'"]:
898 if char in string.ascii_letters or char in ['"',"'"]:
900 return u'', ()
899 return u'', ()
901 try :
900 try :
902 unic = unicodedata.name(char)
901 unic = unicodedata.name(char)
903 return '\\'+char,['\\'+unic]
902 return '\\'+char,['\\'+unic]
904 except KeyError:
903 except KeyError:
905 pass
904 pass
906 return u'', ()
905 return u'', ()
907
906
908 def back_latex_name_matches(text:str):
907 def back_latex_name_matches(text:str):
909 """Match latex characters back to unicode name
908 """Match latex characters back to unicode name
910
909
911 This does ``\\β„΅`` -> ``\\aleph``
910 This does ``\\β„΅`` -> ``\\aleph``
912
911
913 Used on Python 3 only.
912 Used on Python 3 only.
914 """
913 """
915 if len(text)<2:
914 if len(text)<2:
916 return u'', ()
915 return u'', ()
917 maybe_slash = text[-2]
916 maybe_slash = text[-2]
918 if maybe_slash != '\\':
917 if maybe_slash != '\\':
919 return u'', ()
918 return u'', ()
920
919
921
920
922 char = text[-1]
921 char = text[-1]
923 # no expand on quote for completion in strings.
922 # no expand on quote for completion in strings.
924 # nor backcomplete standard ascii keys
923 # nor backcomplete standard ascii keys
925 if char in string.ascii_letters or char in ['"',"'"]:
924 if char in string.ascii_letters or char in ['"',"'"]:
926 return u'', ()
925 return u'', ()
927 try :
926 try :
928 latex = reverse_latex_symbol[char]
927 latex = reverse_latex_symbol[char]
929 # '\\' replace the \ as well
928 # '\\' replace the \ as well
930 return '\\'+char,[latex]
929 return '\\'+char,[latex]
931 except KeyError:
930 except KeyError:
932 pass
931 pass
933 return u'', ()
932 return u'', ()
934
933
935
934
936 class IPCompleter(Completer):
935 class IPCompleter(Completer):
937 """Extension of the completer class with IPython-specific features"""
936 """Extension of the completer class with IPython-specific features"""
938
937
939 @observe('greedy')
938 @observe('greedy')
940 def _greedy_changed(self, change):
939 def _greedy_changed(self, change):
941 """update the splitter and readline delims when greedy is changed"""
940 """update the splitter and readline delims when greedy is changed"""
942 if change['new']:
941 if change['new']:
943 self.splitter.delims = GREEDY_DELIMS
942 self.splitter.delims = GREEDY_DELIMS
944 else:
943 else:
945 self.splitter.delims = DELIMS
944 self.splitter.delims = DELIMS
946
945
947 merge_completions = Bool(True,
946 merge_completions = Bool(True,
948 help="""Whether to merge completion results into a single list
947 help="""Whether to merge completion results into a single list
949
948
950 If False, only the completion results from the first non-empty
949 If False, only the completion results from the first non-empty
951 completer will be returned.
950 completer will be returned.
952 """
951 """
953 ).tag(config=True)
952 ).tag(config=True)
954 omit__names = Enum((0,1,2), default_value=2,
953 omit__names = Enum((0,1,2), default_value=2,
955 help="""Instruct the completer to omit private method names
954 help="""Instruct the completer to omit private method names
956
955
957 Specifically, when completing on ``object.<tab>``.
956 Specifically, when completing on ``object.<tab>``.
958
957
959 When 2 [default]: all names that start with '_' will be excluded.
958 When 2 [default]: all names that start with '_' will be excluded.
960
959
961 When 1: all 'magic' names (``__foo__``) will be excluded.
960 When 1: all 'magic' names (``__foo__``) will be excluded.
962
961
963 When 0: nothing will be excluded.
962 When 0: nothing will be excluded.
964 """
963 """
965 ).tag(config=True)
964 ).tag(config=True)
966 limit_to__all__ = Bool(False,
965 limit_to__all__ = Bool(False,
967 help="""
966 help="""
968 DEPRECATED as of version 5.0.
967 DEPRECATED as of version 5.0.
969
968
970 Instruct the completer to use __all__ for the completion
969 Instruct the completer to use __all__ for the completion
971
970
972 Specifically, when completing on ``object.<tab>``.
971 Specifically, when completing on ``object.<tab>``.
973
972
974 When True: only those names in obj.__all__ will be included.
973 When True: only those names in obj.__all__ will be included.
975
974
976 When False [default]: the __all__ attribute is ignored
975 When False [default]: the __all__ attribute is ignored
977 """,
976 """,
978 ).tag(config=True)
977 ).tag(config=True)
979
978
980 @observe('limit_to__all__')
979 @observe('limit_to__all__')
981 def _limit_to_all_changed(self, change):
980 def _limit_to_all_changed(self, change):
982 warnings.warn('`IPython.core.IPCompleter.limit_to__all__` configuration '
981 warnings.warn('`IPython.core.IPCompleter.limit_to__all__` configuration '
983 'value has been deprecated since IPython 5.0, will be made to have '
982 'value has been deprecated since IPython 5.0, will be made to have '
984 'no effects and then removed in future version of IPython.',
983 'no effects and then removed in future version of IPython.',
985 UserWarning)
984 UserWarning)
986
985
987 def __init__(self, shell=None, namespace=None, global_namespace=None,
986 def __init__(self, shell=None, namespace=None, global_namespace=None,
988 use_readline=_deprecation_readline_sentinel, config=None, **kwargs):
987 use_readline=_deprecation_readline_sentinel, config=None, **kwargs):
989 """IPCompleter() -> completer
988 """IPCompleter() -> completer
990
989
991 Return a completer object.
990 Return a completer object.
992
991
993 Parameters
992 Parameters
994 ----------
993 ----------
995
994
996 shell
995 shell
997 a pointer to the ipython shell itself. This is needed
996 a pointer to the ipython shell itself. This is needed
998 because this completer knows about magic functions, and those can
997 because this completer knows about magic functions, and those can
999 only be accessed via the ipython instance.
998 only be accessed via the ipython instance.
1000
999
1001 namespace : dict, optional
1000 namespace : dict, optional
1002 an optional dict where completions are performed.
1001 an optional dict where completions are performed.
1003
1002
1004 global_namespace : dict, optional
1003 global_namespace : dict, optional
1005 secondary optional dict for completions, to
1004 secondary optional dict for completions, to
1006 handle cases (such as IPython embedded inside functions) where
1005 handle cases (such as IPython embedded inside functions) where
1007 both Python scopes are visible.
1006 both Python scopes are visible.
1008
1007
1009 use_readline : bool, optional
1008 use_readline : bool, optional
1010 DEPRECATED, ignored since IPython 6.0, will have no effects
1009 DEPRECATED, ignored since IPython 6.0, will have no effects
1011 """
1010 """
1012
1011
1013 self.magic_escape = ESC_MAGIC
1012 self.magic_escape = ESC_MAGIC
1014 self.splitter = CompletionSplitter()
1013 self.splitter = CompletionSplitter()
1015
1014
1016 if use_readline is not _deprecation_readline_sentinel:
1015 if use_readline is not _deprecation_readline_sentinel:
1017 warnings.warn('The `use_readline` parameter is deprecated and ignored since IPython 6.0.',
1016 warnings.warn('The `use_readline` parameter is deprecated and ignored since IPython 6.0.',
1018 DeprecationWarning, stacklevel=2)
1017 DeprecationWarning, stacklevel=2)
1019
1018
1020 # _greedy_changed() depends on splitter and readline being defined:
1019 # _greedy_changed() depends on splitter and readline being defined:
1021 Completer.__init__(self, namespace=namespace, global_namespace=global_namespace,
1020 Completer.__init__(self, namespace=namespace, global_namespace=global_namespace,
1022 config=config, **kwargs)
1021 config=config, **kwargs)
1023
1022
1024 # List where completion matches will be stored
1023 # List where completion matches will be stored
1025 self.matches = []
1024 self.matches = []
1026 self.shell = shell
1025 self.shell = shell
1027 # Regexp to split filenames with spaces in them
1026 # Regexp to split filenames with spaces in them
1028 self.space_name_re = re.compile(r'([^\\] )')
1027 self.space_name_re = re.compile(r'([^\\] )')
1029 # Hold a local ref. to glob.glob for speed
1028 # Hold a local ref. to glob.glob for speed
1030 self.glob = glob.glob
1029 self.glob = glob.glob
1031
1030
1032 # Determine if we are running on 'dumb' terminals, like (X)Emacs
1031 # Determine if we are running on 'dumb' terminals, like (X)Emacs
1033 # buffers, to avoid completion problems.
1032 # buffers, to avoid completion problems.
1034 term = os.environ.get('TERM','xterm')
1033 term = os.environ.get('TERM','xterm')
1035 self.dumb_terminal = term in ['dumb','emacs']
1034 self.dumb_terminal = term in ['dumb','emacs']
1036
1035
1037 # Special handling of backslashes needed in win32 platforms
1036 # Special handling of backslashes needed in win32 platforms
1038 if sys.platform == "win32":
1037 if sys.platform == "win32":
1039 self.clean_glob = self._clean_glob_win32
1038 self.clean_glob = self._clean_glob_win32
1040 else:
1039 else:
1041 self.clean_glob = self._clean_glob
1040 self.clean_glob = self._clean_glob
1042
1041
1043 #regexp to parse docstring for function signature
1042 #regexp to parse docstring for function signature
1044 self.docstring_sig_re = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
1043 self.docstring_sig_re = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
1045 self.docstring_kwd_re = re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
1044 self.docstring_kwd_re = re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
1046 #use this if positional argument name is also needed
1045 #use this if positional argument name is also needed
1047 #= re.compile(r'[\s|\[]*(\w+)(?:\s*=?\s*.*)')
1046 #= re.compile(r'[\s|\[]*(\w+)(?:\s*=?\s*.*)')
1048
1047
1049 # All active matcher routines for completion
1048 # All active matcher routines for completion
1050 self.matchers = [
1049 self.matchers = [
1051 self.python_matches,
1050 self.python_matches,
1052 self.file_matches,
1051 self.file_matches,
1053 self.magic_config_matches,
1052 self.magic_config_matches,
1054 self.magic_matches,
1053 self.magic_matches,
1055 self.python_func_kw_matches,
1054 self.python_func_kw_matches,
1056 self.dict_key_matches,
1055 self.dict_key_matches,
1057 ]
1056 ]
1058
1057
1059 # This is set externally by InteractiveShell
1058 # This is set externally by InteractiveShell
1060 self.custom_completers = None
1059 self.custom_completers = None
1061
1060
1062 def all_completions(self, text):
1061 def all_completions(self, text):
1063 """
1062 """
1064 Wrapper around the complete method for the benefit of emacs.
1063 Wrapper around the complete method for the benefit of emacs.
1065 """
1064 """
1066 return self.complete(text)[1]
1065 return self.complete(text)[1]
1067
1066
1068 def _clean_glob(self, text):
1067 def _clean_glob(self, text):
1069 return self.glob("%s*" % text)
1068 return self.glob("%s*" % text)
1070
1069
1071 def _clean_glob_win32(self,text):
1070 def _clean_glob_win32(self,text):
1072 return [f.replace("\\","/")
1071 return [f.replace("\\","/")
1073 for f in self.glob("%s*" % text)]
1072 for f in self.glob("%s*" % text)]
1074
1073
1075 def file_matches(self, text):
1074 def file_matches(self, text):
1076 """Match filenames, expanding ~USER type strings.
1075 """Match filenames, expanding ~USER type strings.
1077
1076
1078 Most of the seemingly convoluted logic in this completer is an
1077 Most of the seemingly convoluted logic in this completer is an
1079 attempt to handle filenames with spaces in them. And yet it's not
1078 attempt to handle filenames with spaces in them. And yet it's not
1080 quite perfect, because Python's readline doesn't expose all of the
1079 quite perfect, because Python's readline doesn't expose all of the
1081 GNU readline details needed for this to be done correctly.
1080 GNU readline details needed for this to be done correctly.
1082
1081
1083 For a filename with a space in it, the printed completions will be
1082 For a filename with a space in it, the printed completions will be
1084 only the parts after what's already been typed (instead of the
1083 only the parts after what's already been typed (instead of the
1085 full completions, as is normally done). I don't think with the
1084 full completions, as is normally done). I don't think with the
1086 current (as of Python 2.3) Python readline it's possible to do
1085 current (as of Python 2.3) Python readline it's possible to do
1087 better."""
1086 better."""
1088
1087
1089 # chars that require escaping with backslash - i.e. chars
1088 # chars that require escaping with backslash - i.e. chars
1090 # that readline treats incorrectly as delimiters, but we
1089 # that readline treats incorrectly as delimiters, but we
1091 # don't want to treat as delimiters in filename matching
1090 # don't want to treat as delimiters in filename matching
1092 # when escaped with backslash
1091 # when escaped with backslash
1093 if text.startswith('!'):
1092 if text.startswith('!'):
1094 text = text[1:]
1093 text = text[1:]
1095 text_prefix = u'!'
1094 text_prefix = u'!'
1096 else:
1095 else:
1097 text_prefix = u''
1096 text_prefix = u''
1098
1097
1099 text_until_cursor = self.text_until_cursor
1098 text_until_cursor = self.text_until_cursor
1100 # track strings with open quotes
1099 # track strings with open quotes
1101 open_quotes = has_open_quotes(text_until_cursor)
1100 open_quotes = has_open_quotes(text_until_cursor)
1102
1101
1103 if '(' in text_until_cursor or '[' in text_until_cursor:
1102 if '(' in text_until_cursor or '[' in text_until_cursor:
1104 lsplit = text
1103 lsplit = text
1105 else:
1104 else:
1106 try:
1105 try:
1107 # arg_split ~ shlex.split, but with unicode bugs fixed by us
1106 # arg_split ~ shlex.split, but with unicode bugs fixed by us
1108 lsplit = arg_split(text_until_cursor)[-1]
1107 lsplit = arg_split(text_until_cursor)[-1]
1109 except ValueError:
1108 except ValueError:
1110 # typically an unmatched ", or backslash without escaped char.
1109 # typically an unmatched ", or backslash without escaped char.
1111 if open_quotes:
1110 if open_quotes:
1112 lsplit = text_until_cursor.split(open_quotes)[-1]
1111 lsplit = text_until_cursor.split(open_quotes)[-1]
1113 else:
1112 else:
1114 return []
1113 return []
1115 except IndexError:
1114 except IndexError:
1116 # tab pressed on empty line
1115 # tab pressed on empty line
1117 lsplit = ""
1116 lsplit = ""
1118
1117
1119 if not open_quotes and lsplit != protect_filename(lsplit):
1118 if not open_quotes and lsplit != protect_filename(lsplit):
1120 # if protectables are found, do matching on the whole escaped name
1119 # if protectables are found, do matching on the whole escaped name
1121 has_protectables = True
1120 has_protectables = True
1122 text0,text = text,lsplit
1121 text0,text = text,lsplit
1123 else:
1122 else:
1124 has_protectables = False
1123 has_protectables = False
1125 text = os.path.expanduser(text)
1124 text = os.path.expanduser(text)
1126
1125
1127 if text == "":
1126 if text == "":
1128 return [text_prefix + cast_unicode_py2(protect_filename(f)) for f in self.glob("*")]
1127 return [text_prefix + protect_filename(f) for f in self.glob("*")]
1129
1128
1130 # Compute the matches from the filesystem
1129 # Compute the matches from the filesystem
1131 if sys.platform == 'win32':
1130 if sys.platform == 'win32':
1132 m0 = self.clean_glob(text)
1131 m0 = self.clean_glob(text)
1133 else:
1132 else:
1134 m0 = self.clean_glob(text.replace('\\', ''))
1133 m0 = self.clean_glob(text.replace('\\', ''))
1135
1134
1136 if has_protectables:
1135 if has_protectables:
1137 # If we had protectables, we need to revert our changes to the
1136 # If we had protectables, we need to revert our changes to the
1138 # beginning of filename so that we don't double-write the part
1137 # beginning of filename so that we don't double-write the part
1139 # of the filename we have so far
1138 # of the filename we have so far
1140 len_lsplit = len(lsplit)
1139 len_lsplit = len(lsplit)
1141 matches = [text_prefix + text0 +
1140 matches = [text_prefix + text0 +
1142 protect_filename(f[len_lsplit:]) for f in m0]
1141 protect_filename(f[len_lsplit:]) for f in m0]
1143 else:
1142 else:
1144 if open_quotes:
1143 if open_quotes:
1145 # if we have a string with an open quote, we don't need to
1144 # if we have a string with an open quote, we don't need to
1146 # protect the names beyond the quote (and we _shouldn't_, as
1145 # protect the names beyond the quote (and we _shouldn't_, as
1147 # it would cause bugs when the filesystem call is made).
1146 # it would cause bugs when the filesystem call is made).
1148 matches = m0 if sys.platform == "win32" else\
1147 matches = m0 if sys.platform == "win32" else\
1149 [protect_filename(f, open_quotes) for f in m0]
1148 [protect_filename(f, open_quotes) for f in m0]
1150 else:
1149 else:
1151 matches = [text_prefix +
1150 matches = [text_prefix +
1152 protect_filename(f) for f in m0]
1151 protect_filename(f) for f in m0]
1153
1152
1154 # Mark directories in input list by appending '/' to their names.
1153 # Mark directories in input list by appending '/' to their names.
1155 return [cast_unicode_py2(x+'/') if os.path.isdir(x) else x for x in matches]
1154 return [x+'/' if os.path.isdir(x) else x for x in matches]
1156
1155
1157 def magic_matches(self, text):
1156 def magic_matches(self, text):
1158 """Match magics"""
1157 """Match magics"""
1159 # Get all shell magics now rather than statically, so magics loaded at
1158 # Get all shell magics now rather than statically, so magics loaded at
1160 # runtime show up too.
1159 # runtime show up too.
1161 lsm = self.shell.magics_manager.lsmagic()
1160 lsm = self.shell.magics_manager.lsmagic()
1162 line_magics = lsm['line']
1161 line_magics = lsm['line']
1163 cell_magics = lsm['cell']
1162 cell_magics = lsm['cell']
1164 pre = self.magic_escape
1163 pre = self.magic_escape
1165 pre2 = pre+pre
1164 pre2 = pre+pre
1166
1165
1167 # Completion logic:
1166 # Completion logic:
1168 # - user gives %%: only do cell magics
1167 # - user gives %%: only do cell magics
1169 # - user gives %: do both line and cell magics
1168 # - user gives %: do both line and cell magics
1170 # - no prefix: do both
1169 # - no prefix: do both
1171 # In other words, line magics are skipped if the user gives %% explicitly
1170 # In other words, line magics are skipped if the user gives %% explicitly
1172 #
1171 #
1173 # We also exclude magics that match any currently visible names:
1172 # We also exclude magics that match any currently visible names:
1174 # https://github.com/ipython/ipython/issues/4877
1173 # https://github.com/ipython/ipython/issues/4877
1175 bare_text = text.lstrip(pre)
1174 bare_text = text.lstrip(pre)
1176 global_matches = self.global_matches(bare_text)
1175 global_matches = self.global_matches(bare_text)
1177 matches = lambda magic: magic.startswith(bare_text) \
1176 matches = lambda magic: magic.startswith(bare_text) \
1178 and magic not in global_matches
1177 and magic not in global_matches
1179 comp = [ pre2+m for m in cell_magics if matches(m)]
1178 comp = [ pre2+m for m in cell_magics if matches(m)]
1180 if not text.startswith(pre2):
1179 if not text.startswith(pre2):
1181 comp += [ pre+m for m in line_magics if matches(m)]
1180 comp += [ pre+m for m in line_magics if matches(m)]
1182
1181
1183 return [cast_unicode_py2(c) for c in comp]
1182 return comp
1184
1183
1185 def magic_config_matches(self, text):
1184 def magic_config_matches(self, text):
1186 """ Match class names and attributes for %config magic """
1185 """ Match class names and attributes for %config magic """
1187 # use line buffer instead of text (which is a word)
1186 # use line buffer instead of text (which is a word)
1188 texts = self.line_buffer.strip().split()
1187 texts = self.line_buffer.strip().split()
1189
1188
1190 if len(texts) > 0 and \
1189 if len(texts) > 0 and \
1191 ('config'.startswith(texts[0]) or '%config'.startswith(texts[0])):
1190 ('config'.startswith(texts[0]) or '%config'.startswith(texts[0])):
1192 # get all configuration classes
1191 # get all configuration classes
1193 classes = sorted(set([ c for c in self.shell.configurables
1192 classes = sorted(set([ c for c in self.shell.configurables
1194 if c.__class__.class_traits(config=True)
1193 if c.__class__.class_traits(config=True)
1195 ]), key=lambda x: x.__class__.__name__)
1194 ]), key=lambda x: x.__class__.__name__)
1196 classnames = [ c.__class__.__name__ for c in classes ]
1195 classnames = [ c.__class__.__name__ for c in classes ]
1197
1196
1198 # return all classnames if config or %config is given
1197 # return all classnames if config or %config is given
1199 if len(texts) == 1:
1198 if len(texts) == 1:
1200 return classnames
1199 return classnames
1201
1200
1202 # match classname
1201 # match classname
1203 classname_texts = texts[1].split('.')
1202 classname_texts = texts[1].split('.')
1204 classname = classname_texts[0]
1203 classname = classname_texts[0]
1205 classname_matches = [ c for c in classnames
1204 classname_matches = [ c for c in classnames
1206 if c.startswith(classname) ]
1205 if c.startswith(classname) ]
1207
1206
1208 # return matched classes or the matched class with attributes
1207 # return matched classes or the matched class with attributes
1209 if texts[1].find('.') < 0:
1208 if texts[1].find('.') < 0:
1210 return classname_matches
1209 return classname_matches
1211 elif len(classname_matches) == 1 and \
1210 elif len(classname_matches) == 1 and \
1212 classname_matches[0] == classname:
1211 classname_matches[0] == classname:
1213 cls = classes[classnames.index(classname)].__class__
1212 cls = classes[classnames.index(classname)].__class__
1214 help = cls.class_get_help()
1213 help = cls.class_get_help()
1215 # strip leading '--' from cl-args:
1214 # strip leading '--' from cl-args:
1216 help = re.sub(re.compile(r'^--', re.MULTILINE), '', help)
1215 help = re.sub(re.compile(r'^--', re.MULTILINE), '', help)
1217 return [ attr.split('=')[0]
1216 return [ attr.split('=')[0]
1218 for attr in help.strip().splitlines()
1217 for attr in help.strip().splitlines()
1219 if attr.startswith(texts[1]) ]
1218 if attr.startswith(texts[1]) ]
1220 return []
1219 return []
1221
1220
1222 def _jedi_matches(self, cursor_column:int, cursor_line:int, text:str):
1221 def _jedi_matches(self, cursor_column:int, cursor_line:int, text:str):
1223 """
1222 """
1224
1223
1225 Return a list of :any:`jedi.api.Completions` object from a ``text`` and
1224 Return a list of :any:`jedi.api.Completions` object from a ``text`` and
1226 cursor position.
1225 cursor position.
1227
1226
1228 Parameters
1227 Parameters
1229 ----------
1228 ----------
1230 cursor_column : int
1229 cursor_column : int
1231 column position of the cursor in ``text``, 0-indexed.
1230 column position of the cursor in ``text``, 0-indexed.
1232 cursor_line : int
1231 cursor_line : int
1233 line position of the cursor in ``text``, 0-indexed
1232 line position of the cursor in ``text``, 0-indexed
1234 text : str
1233 text : str
1235 text to complete
1234 text to complete
1236
1235
1237 Debugging
1236 Debugging
1238 ---------
1237 ---------
1239
1238
1240 If ``IPCompleter.debug`` is ``True`` may return a :any:`_FakeJediCompletion`
1239 If ``IPCompleter.debug`` is ``True`` may return a :any:`_FakeJediCompletion`
1241 object containing a string with the Jedi debug information attached.
1240 object containing a string with the Jedi debug information attached.
1242 """
1241 """
1243 namespaces = [self.namespace]
1242 namespaces = [self.namespace]
1244 if self.global_namespace is not None:
1243 if self.global_namespace is not None:
1245 namespaces.append(self.global_namespace)
1244 namespaces.append(self.global_namespace)
1246
1245
1247 completion_filter = lambda x:x
1246 completion_filter = lambda x:x
1248 # cursor_pos is an it, jedi wants line and column
1247 # cursor_pos is an it, jedi wants line and column
1249 offset = cursor_to_position(text, cursor_line, cursor_column)
1248 offset = cursor_to_position(text, cursor_line, cursor_column)
1250 # filter output if we are completing for object members
1249 # filter output if we are completing for object members
1251 if offset:
1250 if offset:
1252 pre = text[offset-1]
1251 pre = text[offset-1]
1253 if pre == '.':
1252 if pre == '.':
1254 if self.omit__names == 2:
1253 if self.omit__names == 2:
1255 completion_filter = lambda c:not c.name.startswith('_')
1254 completion_filter = lambda c:not c.name.startswith('_')
1256 elif self.omit__names == 1:
1255 elif self.omit__names == 1:
1257 completion_filter = lambda c:not (c.name.startswith('__') and c.name.endswith('__'))
1256 completion_filter = lambda c:not (c.name.startswith('__') and c.name.endswith('__'))
1258 elif self.omit__names == 0:
1257 elif self.omit__names == 0:
1259 completion_filter = lambda x:x
1258 completion_filter = lambda x:x
1260 else:
1259 else:
1261 raise ValueError("Don't understand self.omit__names == {}".format(self.omit__names))
1260 raise ValueError("Don't understand self.omit__names == {}".format(self.omit__names))
1262
1261
1263 interpreter = jedi.Interpreter(
1262 interpreter = jedi.Interpreter(
1264 text, namespaces, column=cursor_column, line=cursor_line + 1)
1263 text, namespaces, column=cursor_column, line=cursor_line + 1)
1265
1264
1266 try_jedi = False
1265 try_jedi = False
1267
1266
1268 try:
1267 try:
1269 # should we check the type of the node is Error ?
1268 # should we check the type of the node is Error ?
1270 from jedi.parser.tree import ErrorLeaf
1269 from jedi.parser.tree import ErrorLeaf
1271 next_to_last_tree = interpreter._get_module().tree_node.children[-2]
1270 next_to_last_tree = interpreter._get_module().tree_node.children[-2]
1272 completing_string = False
1271 completing_string = False
1273 if isinstance(next_to_last_tree, ErrorLeaf):
1272 if isinstance(next_to_last_tree, ErrorLeaf):
1274 completing_string = interpreter._get_module().tree_node.children[-2].value[0] in {'"', "'"}
1273 completing_string = interpreter._get_module().tree_node.children[-2].value[0] in {'"', "'"}
1275 # if we are in a string jedi is likely not the right candidate for
1274 # if we are in a string jedi is likely not the right candidate for
1276 # now. Skip it.
1275 # now. Skip it.
1277 try_jedi = not completing_string
1276 try_jedi = not completing_string
1278 except Exception as e:
1277 except Exception as e:
1279 # many of things can go wrong, we are using private API just don't crash.
1278 # many of things can go wrong, we are using private API just don't crash.
1280 if self.debug:
1279 if self.debug:
1281 print("Error detecting if completing a non-finished string :", e, '|')
1280 print("Error detecting if completing a non-finished string :", e, '|')
1282
1281
1283 if not try_jedi:
1282 if not try_jedi:
1284 return []
1283 return []
1285 try:
1284 try:
1286 return filter(completion_filter, interpreter.completions())
1285 return filter(completion_filter, interpreter.completions())
1287 except Exception as e:
1286 except Exception as e:
1288 if self.debug:
1287 if self.debug:
1289 return [_FakeJediCompletion('Oops Jedi has crashed, please report a bug with the following:\n"""\n%s\ns"""' % (e))]
1288 return [_FakeJediCompletion('Oops Jedi has crashed, please report a bug with the following:\n"""\n%s\ns"""' % (e))]
1290 else:
1289 else:
1291 return []
1290 return []
1292
1291
1293 def python_matches(self, text):
1292 def python_matches(self, text):
1294 """Match attributes or global python names"""
1293 """Match attributes or global python names"""
1295 if "." in text:
1294 if "." in text:
1296 try:
1295 try:
1297 matches = self.attr_matches(text)
1296 matches = self.attr_matches(text)
1298 if text.endswith('.') and self.omit__names:
1297 if text.endswith('.') and self.omit__names:
1299 if self.omit__names == 1:
1298 if self.omit__names == 1:
1300 # true if txt is _not_ a __ name, false otherwise:
1299 # true if txt is _not_ a __ name, false otherwise:
1301 no__name = (lambda txt:
1300 no__name = (lambda txt:
1302 re.match(r'.*\.__.*?__',txt) is None)
1301 re.match(r'.*\.__.*?__',txt) is None)
1303 else:
1302 else:
1304 # true if txt is _not_ a _ name, false otherwise:
1303 # true if txt is _not_ a _ name, false otherwise:
1305 no__name = (lambda txt:
1304 no__name = (lambda txt:
1306 re.match(r'\._.*?',txt[txt.rindex('.'):]) is None)
1305 re.match(r'\._.*?',txt[txt.rindex('.'):]) is None)
1307 matches = filter(no__name, matches)
1306 matches = filter(no__name, matches)
1308 except NameError:
1307 except NameError:
1309 # catches <undefined attributes>.<tab>
1308 # catches <undefined attributes>.<tab>
1310 matches = []
1309 matches = []
1311 else:
1310 else:
1312 matches = self.global_matches(text)
1311 matches = self.global_matches(text)
1313 return matches
1312 return matches
1314
1313
1315 def _default_arguments_from_docstring(self, doc):
1314 def _default_arguments_from_docstring(self, doc):
1316 """Parse the first line of docstring for call signature.
1315 """Parse the first line of docstring for call signature.
1317
1316
1318 Docstring should be of the form 'min(iterable[, key=func])\n'.
1317 Docstring should be of the form 'min(iterable[, key=func])\n'.
1319 It can also parse cython docstring of the form
1318 It can also parse cython docstring of the form
1320 'Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)'.
1319 'Minuit.migrad(self, int ncall=10000, resume=True, int nsplit=1)'.
1321 """
1320 """
1322 if doc is None:
1321 if doc is None:
1323 return []
1322 return []
1324
1323
1325 #care only the firstline
1324 #care only the firstline
1326 line = doc.lstrip().splitlines()[0]
1325 line = doc.lstrip().splitlines()[0]
1327
1326
1328 #p = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
1327 #p = re.compile(r'^[\w|\s.]+\(([^)]*)\).*')
1329 #'min(iterable[, key=func])\n' -> 'iterable[, key=func]'
1328 #'min(iterable[, key=func])\n' -> 'iterable[, key=func]'
1330 sig = self.docstring_sig_re.search(line)
1329 sig = self.docstring_sig_re.search(line)
1331 if sig is None:
1330 if sig is None:
1332 return []
1331 return []
1333 # iterable[, key=func]' -> ['iterable[' ,' key=func]']
1332 # iterable[, key=func]' -> ['iterable[' ,' key=func]']
1334 sig = sig.groups()[0].split(',')
1333 sig = sig.groups()[0].split(',')
1335 ret = []
1334 ret = []
1336 for s in sig:
1335 for s in sig:
1337 #re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
1336 #re.compile(r'[\s|\[]*(\w+)(?:\s*=\s*.*)')
1338 ret += self.docstring_kwd_re.findall(s)
1337 ret += self.docstring_kwd_re.findall(s)
1339 return ret
1338 return ret
1340
1339
1341 def _default_arguments(self, obj):
1340 def _default_arguments(self, obj):
1342 """Return the list of default arguments of obj if it is callable,
1341 """Return the list of default arguments of obj if it is callable,
1343 or empty list otherwise."""
1342 or empty list otherwise."""
1344 call_obj = obj
1343 call_obj = obj
1345 ret = []
1344 ret = []
1346 if inspect.isbuiltin(obj):
1345 if inspect.isbuiltin(obj):
1347 pass
1346 pass
1348 elif not (inspect.isfunction(obj) or inspect.ismethod(obj)):
1347 elif not (inspect.isfunction(obj) or inspect.ismethod(obj)):
1349 if inspect.isclass(obj):
1348 if inspect.isclass(obj):
1350 #for cython embededsignature=True the constructor docstring
1349 #for cython embededsignature=True the constructor docstring
1351 #belongs to the object itself not __init__
1350 #belongs to the object itself not __init__
1352 ret += self._default_arguments_from_docstring(
1351 ret += self._default_arguments_from_docstring(
1353 getattr(obj, '__doc__', ''))
1352 getattr(obj, '__doc__', ''))
1354 # for classes, check for __init__,__new__
1353 # for classes, check for __init__,__new__
1355 call_obj = (getattr(obj, '__init__', None) or
1354 call_obj = (getattr(obj, '__init__', None) or
1356 getattr(obj, '__new__', None))
1355 getattr(obj, '__new__', None))
1357 # for all others, check if they are __call__able
1356 # for all others, check if they are __call__able
1358 elif hasattr(obj, '__call__'):
1357 elif hasattr(obj, '__call__'):
1359 call_obj = obj.__call__
1358 call_obj = obj.__call__
1360 ret += self._default_arguments_from_docstring(
1359 ret += self._default_arguments_from_docstring(
1361 getattr(call_obj, '__doc__', ''))
1360 getattr(call_obj, '__doc__', ''))
1362
1361
1363 _keeps = (inspect.Parameter.KEYWORD_ONLY,
1362 _keeps = (inspect.Parameter.KEYWORD_ONLY,
1364 inspect.Parameter.POSITIONAL_OR_KEYWORD)
1363 inspect.Parameter.POSITIONAL_OR_KEYWORD)
1365
1364
1366 try:
1365 try:
1367 sig = inspect.signature(call_obj)
1366 sig = inspect.signature(call_obj)
1368 ret.extend(k for k, v in sig.parameters.items() if
1367 ret.extend(k for k, v in sig.parameters.items() if
1369 v.kind in _keeps)
1368 v.kind in _keeps)
1370 except ValueError:
1369 except ValueError:
1371 pass
1370 pass
1372
1371
1373 return list(set(ret))
1372 return list(set(ret))
1374
1373
1375 def python_func_kw_matches(self,text):
1374 def python_func_kw_matches(self,text):
1376 """Match named parameters (kwargs) of the last open function"""
1375 """Match named parameters (kwargs) of the last open function"""
1377
1376
1378 if "." in text: # a parameter cannot be dotted
1377 if "." in text: # a parameter cannot be dotted
1379 return []
1378 return []
1380 try: regexp = self.__funcParamsRegex
1379 try: regexp = self.__funcParamsRegex
1381 except AttributeError:
1380 except AttributeError:
1382 regexp = self.__funcParamsRegex = re.compile(r'''
1381 regexp = self.__funcParamsRegex = re.compile(r'''
1383 '.*?(?<!\\)' | # single quoted strings or
1382 '.*?(?<!\\)' | # single quoted strings or
1384 ".*?(?<!\\)" | # double quoted strings or
1383 ".*?(?<!\\)" | # double quoted strings or
1385 \w+ | # identifier
1384 \w+ | # identifier
1386 \S # other characters
1385 \S # other characters
1387 ''', re.VERBOSE | re.DOTALL)
1386 ''', re.VERBOSE | re.DOTALL)
1388 # 1. find the nearest identifier that comes before an unclosed
1387 # 1. find the nearest identifier that comes before an unclosed
1389 # parenthesis before the cursor
1388 # parenthesis before the cursor
1390 # e.g. for "foo (1+bar(x), pa<cursor>,a=1)", the candidate is "foo"
1389 # e.g. for "foo (1+bar(x), pa<cursor>,a=1)", the candidate is "foo"
1391 tokens = regexp.findall(self.text_until_cursor)
1390 tokens = regexp.findall(self.text_until_cursor)
1392 iterTokens = reversed(tokens); openPar = 0
1391 iterTokens = reversed(tokens); openPar = 0
1393
1392
1394 for token in iterTokens:
1393 for token in iterTokens:
1395 if token == ')':
1394 if token == ')':
1396 openPar -= 1
1395 openPar -= 1
1397 elif token == '(':
1396 elif token == '(':
1398 openPar += 1
1397 openPar += 1
1399 if openPar > 0:
1398 if openPar > 0:
1400 # found the last unclosed parenthesis
1399 # found the last unclosed parenthesis
1401 break
1400 break
1402 else:
1401 else:
1403 return []
1402 return []
1404 # 2. Concatenate dotted names ("foo.bar" for "foo.bar(x, pa" )
1403 # 2. Concatenate dotted names ("foo.bar" for "foo.bar(x, pa" )
1405 ids = []
1404 ids = []
1406 isId = re.compile(r'\w+$').match
1405 isId = re.compile(r'\w+$').match
1407
1406
1408 while True:
1407 while True:
1409 try:
1408 try:
1410 ids.append(next(iterTokens))
1409 ids.append(next(iterTokens))
1411 if not isId(ids[-1]):
1410 if not isId(ids[-1]):
1412 ids.pop(); break
1411 ids.pop(); break
1413 if not next(iterTokens) == '.':
1412 if not next(iterTokens) == '.':
1414 break
1413 break
1415 except StopIteration:
1414 except StopIteration:
1416 break
1415 break
1417
1416
1418 # Find all named arguments already assigned to, as to avoid suggesting
1417 # Find all named arguments already assigned to, as to avoid suggesting
1419 # them again
1418 # them again
1420 usedNamedArgs = set()
1419 usedNamedArgs = set()
1421 par_level = -1
1420 par_level = -1
1422 for token, next_token in zip(tokens, tokens[1:]):
1421 for token, next_token in zip(tokens, tokens[1:]):
1423 if token == '(':
1422 if token == '(':
1424 par_level += 1
1423 par_level += 1
1425 elif token == ')':
1424 elif token == ')':
1426 par_level -= 1
1425 par_level -= 1
1427
1426
1428 if par_level != 0:
1427 if par_level != 0:
1429 continue
1428 continue
1430
1429
1431 if next_token != '=':
1430 if next_token != '=':
1432 continue
1431 continue
1433
1432
1434 usedNamedArgs.add(token)
1433 usedNamedArgs.add(token)
1435
1434
1436 # lookup the candidate callable matches either using global_matches
1435 # lookup the candidate callable matches either using global_matches
1437 # or attr_matches for dotted names
1436 # or attr_matches for dotted names
1438 if len(ids) == 1:
1437 if len(ids) == 1:
1439 callableMatches = self.global_matches(ids[0])
1438 callableMatches = self.global_matches(ids[0])
1440 else:
1439 else:
1441 callableMatches = self.attr_matches('.'.join(ids[::-1]))
1440 callableMatches = self.attr_matches('.'.join(ids[::-1]))
1442 argMatches = []
1441 argMatches = []
1443 for callableMatch in callableMatches:
1442 for callableMatch in callableMatches:
1444 try:
1443 try:
1445 namedArgs = self._default_arguments(eval(callableMatch,
1444 namedArgs = self._default_arguments(eval(callableMatch,
1446 self.namespace))
1445 self.namespace))
1447 except:
1446 except:
1448 continue
1447 continue
1449
1448
1450 # Remove used named arguments from the list, no need to show twice
1449 # Remove used named arguments from the list, no need to show twice
1451 for namedArg in set(namedArgs) - usedNamedArgs:
1450 for namedArg in set(namedArgs) - usedNamedArgs:
1452 if namedArg.startswith(text):
1451 if namedArg.startswith(text):
1453 argMatches.append(u"%s=" %namedArg)
1452 argMatches.append(u"%s=" %namedArg)
1454 return argMatches
1453 return argMatches
1455
1454
1456 def dict_key_matches(self, text):
1455 def dict_key_matches(self, text):
1457 "Match string keys in a dictionary, after e.g. 'foo[' "
1456 "Match string keys in a dictionary, after e.g. 'foo[' "
1458 def get_keys(obj):
1457 def get_keys(obj):
1459 # Objects can define their own completions by defining an
1458 # Objects can define their own completions by defining an
1460 # _ipy_key_completions_() method.
1459 # _ipy_key_completions_() method.
1461 method = get_real_method(obj, '_ipython_key_completions_')
1460 method = get_real_method(obj, '_ipython_key_completions_')
1462 if method is not None:
1461 if method is not None:
1463 return method()
1462 return method()
1464
1463
1465 # Special case some common in-memory dict-like types
1464 # Special case some common in-memory dict-like types
1466 if isinstance(obj, dict) or\
1465 if isinstance(obj, dict) or\
1467 _safe_isinstance(obj, 'pandas', 'DataFrame'):
1466 _safe_isinstance(obj, 'pandas', 'DataFrame'):
1468 try:
1467 try:
1469 return list(obj.keys())
1468 return list(obj.keys())
1470 except Exception:
1469 except Exception:
1471 return []
1470 return []
1472 elif _safe_isinstance(obj, 'numpy', 'ndarray') or\
1471 elif _safe_isinstance(obj, 'numpy', 'ndarray') or\
1473 _safe_isinstance(obj, 'numpy', 'void'):
1472 _safe_isinstance(obj, 'numpy', 'void'):
1474 return obj.dtype.names or []
1473 return obj.dtype.names or []
1475 return []
1474 return []
1476
1475
1477 try:
1476 try:
1478 regexps = self.__dict_key_regexps
1477 regexps = self.__dict_key_regexps
1479 except AttributeError:
1478 except AttributeError:
1480 dict_key_re_fmt = r'''(?x)
1479 dict_key_re_fmt = r'''(?x)
1481 ( # match dict-referring expression wrt greedy setting
1480 ( # match dict-referring expression wrt greedy setting
1482 %s
1481 %s
1483 )
1482 )
1484 \[ # open bracket
1483 \[ # open bracket
1485 \s* # and optional whitespace
1484 \s* # and optional whitespace
1486 ([uUbB]? # string prefix (r not handled)
1485 ([uUbB]? # string prefix (r not handled)
1487 (?: # unclosed string
1486 (?: # unclosed string
1488 '(?:[^']|(?<!\\)\\')*
1487 '(?:[^']|(?<!\\)\\')*
1489 |
1488 |
1490 "(?:[^"]|(?<!\\)\\")*
1489 "(?:[^"]|(?<!\\)\\")*
1491 )
1490 )
1492 )?
1491 )?
1493 $
1492 $
1494 '''
1493 '''
1495 regexps = self.__dict_key_regexps = {
1494 regexps = self.__dict_key_regexps = {
1496 False: re.compile(dict_key_re_fmt % '''
1495 False: re.compile(dict_key_re_fmt % '''
1497 # identifiers separated by .
1496 # identifiers separated by .
1498 (?!\d)\w+
1497 (?!\d)\w+
1499 (?:\.(?!\d)\w+)*
1498 (?:\.(?!\d)\w+)*
1500 '''),
1499 '''),
1501 True: re.compile(dict_key_re_fmt % '''
1500 True: re.compile(dict_key_re_fmt % '''
1502 .+
1501 .+
1503 ''')
1502 ''')
1504 }
1503 }
1505
1504
1506 match = regexps[self.greedy].search(self.text_until_cursor)
1505 match = regexps[self.greedy].search(self.text_until_cursor)
1507 if match is None:
1506 if match is None:
1508 return []
1507 return []
1509
1508
1510 expr, prefix = match.groups()
1509 expr, prefix = match.groups()
1511 try:
1510 try:
1512 obj = eval(expr, self.namespace)
1511 obj = eval(expr, self.namespace)
1513 except Exception:
1512 except Exception:
1514 try:
1513 try:
1515 obj = eval(expr, self.global_namespace)
1514 obj = eval(expr, self.global_namespace)
1516 except Exception:
1515 except Exception:
1517 return []
1516 return []
1518
1517
1519 keys = get_keys(obj)
1518 keys = get_keys(obj)
1520 if not keys:
1519 if not keys:
1521 return keys
1520 return keys
1522 closing_quote, token_offset, matches = match_dict_keys(keys, prefix, self.splitter.delims)
1521 closing_quote, token_offset, matches = match_dict_keys(keys, prefix, self.splitter.delims)
1523 if not matches:
1522 if not matches:
1524 return matches
1523 return matches
1525
1524
1526 # get the cursor position of
1525 # get the cursor position of
1527 # - the text being completed
1526 # - the text being completed
1528 # - the start of the key text
1527 # - the start of the key text
1529 # - the start of the completion
1528 # - the start of the completion
1530 text_start = len(self.text_until_cursor) - len(text)
1529 text_start = len(self.text_until_cursor) - len(text)
1531 if prefix:
1530 if prefix:
1532 key_start = match.start(2)
1531 key_start = match.start(2)
1533 completion_start = key_start + token_offset
1532 completion_start = key_start + token_offset
1534 else:
1533 else:
1535 key_start = completion_start = match.end()
1534 key_start = completion_start = match.end()
1536
1535
1537 # grab the leading prefix, to make sure all completions start with `text`
1536 # grab the leading prefix, to make sure all completions start with `text`
1538 if text_start > key_start:
1537 if text_start > key_start:
1539 leading = ''
1538 leading = ''
1540 else:
1539 else:
1541 leading = text[text_start:completion_start]
1540 leading = text[text_start:completion_start]
1542
1541
1543 # the index of the `[` character
1542 # the index of the `[` character
1544 bracket_idx = match.end(1)
1543 bracket_idx = match.end(1)
1545
1544
1546 # append closing quote and bracket as appropriate
1545 # append closing quote and bracket as appropriate
1547 # this is *not* appropriate if the opening quote or bracket is outside
1546 # this is *not* appropriate if the opening quote or bracket is outside
1548 # the text given to this method
1547 # the text given to this method
1549 suf = ''
1548 suf = ''
1550 continuation = self.line_buffer[len(self.text_until_cursor):]
1549 continuation = self.line_buffer[len(self.text_until_cursor):]
1551 if key_start > text_start and closing_quote:
1550 if key_start > text_start and closing_quote:
1552 # quotes were opened inside text, maybe close them
1551 # quotes were opened inside text, maybe close them
1553 if continuation.startswith(closing_quote):
1552 if continuation.startswith(closing_quote):
1554 continuation = continuation[len(closing_quote):]
1553 continuation = continuation[len(closing_quote):]
1555 else:
1554 else:
1556 suf += closing_quote
1555 suf += closing_quote
1557 if bracket_idx > text_start:
1556 if bracket_idx > text_start:
1558 # brackets were opened inside text, maybe close them
1557 # brackets were opened inside text, maybe close them
1559 if not continuation.startswith(']'):
1558 if not continuation.startswith(']'):
1560 suf += ']'
1559 suf += ']'
1561
1560
1562 return [leading + k + suf for k in matches]
1561 return [leading + k + suf for k in matches]
1563
1562
1564 def unicode_name_matches(self, text):
1563 def unicode_name_matches(self, text):
1565 u"""Match Latex-like syntax for unicode characters base
1564 u"""Match Latex-like syntax for unicode characters base
1566 on the name of the character.
1565 on the name of the character.
1567
1566
1568 This does ``\\GREEK SMALL LETTER ETA`` -> ``Ξ·``
1567 This does ``\\GREEK SMALL LETTER ETA`` -> ``Ξ·``
1569
1568
1570 Works only on valid python 3 identifier, or on combining characters that
1569 Works only on valid python 3 identifier, or on combining characters that
1571 will combine to form a valid identifier.
1570 will combine to form a valid identifier.
1572
1571
1573 Used on Python 3 only.
1572 Used on Python 3 only.
1574 """
1573 """
1575 slashpos = text.rfind('\\')
1574 slashpos = text.rfind('\\')
1576 if slashpos > -1:
1575 if slashpos > -1:
1577 s = text[slashpos+1:]
1576 s = text[slashpos+1:]
1578 try :
1577 try :
1579 unic = unicodedata.lookup(s)
1578 unic = unicodedata.lookup(s)
1580 # allow combining chars
1579 # allow combining chars
1581 if ('a'+unic).isidentifier():
1580 if ('a'+unic).isidentifier():
1582 return '\\'+s,[unic]
1581 return '\\'+s,[unic]
1583 except KeyError:
1582 except KeyError:
1584 pass
1583 pass
1585 return u'', []
1584 return u'', []
1586
1585
1587
1586
1588 def latex_matches(self, text):
1587 def latex_matches(self, text):
1589 u"""Match Latex syntax for unicode characters.
1588 u"""Match Latex syntax for unicode characters.
1590
1589
1591 This does both ``\\alp`` -> ``\\alpha`` and ``\\alpha`` -> ``Ξ±``
1590 This does both ``\\alp`` -> ``\\alpha`` and ``\\alpha`` -> ``Ξ±``
1592
1591
1593 Used on Python 3 only.
1592 Used on Python 3 only.
1594 """
1593 """
1595 slashpos = text.rfind('\\')
1594 slashpos = text.rfind('\\')
1596 if slashpos > -1:
1595 if slashpos > -1:
1597 s = text[slashpos:]
1596 s = text[slashpos:]
1598 if s in latex_symbols:
1597 if s in latex_symbols:
1599 # Try to complete a full latex symbol to unicode
1598 # Try to complete a full latex symbol to unicode
1600 # \\alpha -> Ξ±
1599 # \\alpha -> Ξ±
1601 return s, [latex_symbols[s]]
1600 return s, [latex_symbols[s]]
1602 else:
1601 else:
1603 # If a user has partially typed a latex symbol, give them
1602 # If a user has partially typed a latex symbol, give them
1604 # a full list of options \al -> [\aleph, \alpha]
1603 # a full list of options \al -> [\aleph, \alpha]
1605 matches = [k for k in latex_symbols if k.startswith(s)]
1604 matches = [k for k in latex_symbols if k.startswith(s)]
1606 return s, matches
1605 return s, matches
1607 return u'', []
1606 return u'', []
1608
1607
1609 def dispatch_custom_completer(self, text):
1608 def dispatch_custom_completer(self, text):
1610 if not self.custom_completers:
1609 if not self.custom_completers:
1611 return
1610 return
1612
1611
1613 line = self.line_buffer
1612 line = self.line_buffer
1614 if not line.strip():
1613 if not line.strip():
1615 return None
1614 return None
1616
1615
1617 # Create a little structure to pass all the relevant information about
1616 # Create a little structure to pass all the relevant information about
1618 # the current completion to any custom completer.
1617 # the current completion to any custom completer.
1619 event = SimpleNamespace()
1618 event = SimpleNamespace()
1620 event.line = line
1619 event.line = line
1621 event.symbol = text
1620 event.symbol = text
1622 cmd = line.split(None,1)[0]
1621 cmd = line.split(None,1)[0]
1623 event.command = cmd
1622 event.command = cmd
1624 event.text_until_cursor = self.text_until_cursor
1623 event.text_until_cursor = self.text_until_cursor
1625
1624
1626 # for foo etc, try also to find completer for %foo
1625 # for foo etc, try also to find completer for %foo
1627 if not cmd.startswith(self.magic_escape):
1626 if not cmd.startswith(self.magic_escape):
1628 try_magic = self.custom_completers.s_matches(
1627 try_magic = self.custom_completers.s_matches(
1629 self.magic_escape + cmd)
1628 self.magic_escape + cmd)
1630 else:
1629 else:
1631 try_magic = []
1630 try_magic = []
1632
1631
1633 for c in itertools.chain(self.custom_completers.s_matches(cmd),
1632 for c in itertools.chain(self.custom_completers.s_matches(cmd),
1634 try_magic,
1633 try_magic,
1635 self.custom_completers.flat_matches(self.text_until_cursor)):
1634 self.custom_completers.flat_matches(self.text_until_cursor)):
1636 try:
1635 try:
1637 res = c(event)
1636 res = c(event)
1638 if res:
1637 if res:
1639 # first, try case sensitive match
1638 # first, try case sensitive match
1640 withcase = [cast_unicode_py2(r) for r in res if r.startswith(text)]
1639 withcase = [r for r in res if r.startswith(text)]
1641 if withcase:
1640 if withcase:
1642 return withcase
1641 return withcase
1643 # if none, then case insensitive ones are ok too
1642 # if none, then case insensitive ones are ok too
1644 text_low = text.lower()
1643 text_low = text.lower()
1645 return [cast_unicode_py2(r) for r in res if r.lower().startswith(text_low)]
1644 return [r for r in res if r.lower().startswith(text_low)]
1646 except TryNext:
1645 except TryNext:
1647 pass
1646 pass
1648
1647
1649 return None
1648 return None
1650
1649
1651 def completions(self, text: str, offset: int)->Iterator[Completion]:
1650 def completions(self, text: str, offset: int)->Iterator[Completion]:
1652 """
1651 """
1653 Returns an iterator over the possible completions
1652 Returns an iterator over the possible completions
1654
1653
1655 .. warning:: Unstable
1654 .. warning:: Unstable
1656
1655
1657 This function is unstable, API may change without warning.
1656 This function is unstable, API may change without warning.
1658 It will also raise unless use in proper context manager.
1657 It will also raise unless use in proper context manager.
1659
1658
1660 Parameters
1659 Parameters
1661 ----------
1660 ----------
1662
1661
1663 text:str
1662 text:str
1664 Full text of the current input, multi line string.
1663 Full text of the current input, multi line string.
1665 offset:int
1664 offset:int
1666 Integer representing the position of the cursor in ``text``. Offset
1665 Integer representing the position of the cursor in ``text``. Offset
1667 is 0-based indexed.
1666 is 0-based indexed.
1668
1667
1669 Yields
1668 Yields
1670 ------
1669 ------
1671 :any:`Completion` object
1670 :any:`Completion` object
1672
1671
1673
1672
1674 The cursor on a text can either be seen as being "in between"
1673 The cursor on a text can either be seen as being "in between"
1675 characters or "On" a character depending on the interface visible to
1674 characters or "On" a character depending on the interface visible to
1676 the user. For consistency the cursor being on "in between" characters X
1675 the user. For consistency the cursor being on "in between" characters X
1677 and Y is equivalent to the cursor being "on" character Y, that is to say
1676 and Y is equivalent to the cursor being "on" character Y, that is to say
1678 the character the cursor is on is considered as being after the cursor.
1677 the character the cursor is on is considered as being after the cursor.
1679
1678
1680 Combining characters may span more that one position in the
1679 Combining characters may span more that one position in the
1681 text.
1680 text.
1682
1681
1683
1682
1684 .. note::
1683 .. note::
1685
1684
1686 If ``IPCompleter.debug`` is :any:`True` will yield a ``--jedi/ipython--``
1685 If ``IPCompleter.debug`` is :any:`True` will yield a ``--jedi/ipython--``
1687 fake Completion token to distinguish completion returned by Jedi
1686 fake Completion token to distinguish completion returned by Jedi
1688 and usual IPython completion.
1687 and usual IPython completion.
1689
1688
1690 .. note::
1689 .. note::
1691
1690
1692 Completions are not completely deduplicated yet. If identical
1691 Completions are not completely deduplicated yet. If identical
1693 completions are coming from different sources this function does not
1692 completions are coming from different sources this function does not
1694 ensure that each completion object will only be present once.
1693 ensure that each completion object will only be present once.
1695 """
1694 """
1696 warnings.warn("_complete is a provisional API (as of IPython 6.0). "
1695 warnings.warn("_complete is a provisional API (as of IPython 6.0). "
1697 "It may change without warnings. "
1696 "It may change without warnings. "
1698 "Use in corresponding context manager.",
1697 "Use in corresponding context manager.",
1699 category=ProvisionalCompleterWarning, stacklevel=2)
1698 category=ProvisionalCompleterWarning, stacklevel=2)
1700
1699
1701 seen = set()
1700 seen = set()
1702 for c in self._completions(text, offset, _timeout=self.jedi_compute_type_timeout/1000):
1701 for c in self._completions(text, offset, _timeout=self.jedi_compute_type_timeout/1000):
1703 if c and (c in seen):
1702 if c and (c in seen):
1704 continue
1703 continue
1705 yield c
1704 yield c
1706 seen.add(c)
1705 seen.add(c)
1707
1706
1708 def _completions(self, full_text: str, offset: int, *, _timeout)->Iterator[Completion]:
1707 def _completions(self, full_text: str, offset: int, *, _timeout)->Iterator[Completion]:
1709 """
1708 """
1710 Core completion module.Same signature as :any:`completions`, with the
1709 Core completion module.Same signature as :any:`completions`, with the
1711 extra `timeout` parameter (in seconds).
1710 extra `timeout` parameter (in seconds).
1712
1711
1713
1712
1714 Computing jedi's completion ``.type`` can be quite expensive (it is a
1713 Computing jedi's completion ``.type`` can be quite expensive (it is a
1715 lazy property) and can require some warm-up, more warm up than just
1714 lazy property) and can require some warm-up, more warm up than just
1716 computing the ``name`` of a completion. The warm-up can be :
1715 computing the ``name`` of a completion. The warm-up can be :
1717
1716
1718 - Long warm-up the first time a module is encountered after
1717 - Long warm-up the first time a module is encountered after
1719 install/update: actually build parse/inference tree.
1718 install/update: actually build parse/inference tree.
1720
1719
1721 - first time the module is encountered in a session: load tree from
1720 - first time the module is encountered in a session: load tree from
1722 disk.
1721 disk.
1723
1722
1724 We don't want to block completions for tens of seconds so we give the
1723 We don't want to block completions for tens of seconds so we give the
1725 completer a "budget" of ``_timeout`` seconds per invocation to compute
1724 completer a "budget" of ``_timeout`` seconds per invocation to compute
1726 completions types, the completions that have not yet been computed will
1725 completions types, the completions that have not yet been computed will
1727 be marked as "unknown" an will have a chance to be computed next round
1726 be marked as "unknown" an will have a chance to be computed next round
1728 are things get cached.
1727 are things get cached.
1729
1728
1730 Keep in mind that Jedi is not the only thing treating the completion so
1729 Keep in mind that Jedi is not the only thing treating the completion so
1731 keep the timeout short-ish as if we take more than 0.3 second we still
1730 keep the timeout short-ish as if we take more than 0.3 second we still
1732 have lots of processing to do.
1731 have lots of processing to do.
1733
1732
1734 """
1733 """
1735 deadline = time.monotonic() + _timeout
1734 deadline = time.monotonic() + _timeout
1736
1735
1737
1736
1738 before = full_text[:offset]
1737 before = full_text[:offset]
1739 cursor_line, cursor_column = position_to_cursor(full_text, offset)
1738 cursor_line, cursor_column = position_to_cursor(full_text, offset)
1740
1739
1741 matched_text, matches, matches_origin, jedi_matches = self._complete(
1740 matched_text, matches, matches_origin, jedi_matches = self._complete(
1742 full_text=full_text, cursor_line=cursor_line, cursor_pos=cursor_column)
1741 full_text=full_text, cursor_line=cursor_line, cursor_pos=cursor_column)
1743
1742
1744 iter_jm = iter(jedi_matches)
1743 iter_jm = iter(jedi_matches)
1745 if _timeout:
1744 if _timeout:
1746 for jm in iter_jm:
1745 for jm in iter_jm:
1747 try:
1746 try:
1748 type_ = jm.type
1747 type_ = jm.type
1749 except Exception:
1748 except Exception:
1750 if self.debug:
1749 if self.debug:
1751 print("Error in Jedi getting type of ", jm)
1750 print("Error in Jedi getting type of ", jm)
1752 type_ = None
1751 type_ = None
1753 delta = len(jm.name_with_symbols) - len(jm.complete)
1752 delta = len(jm.name_with_symbols) - len(jm.complete)
1754 yield Completion(start=offset - delta,
1753 yield Completion(start=offset - delta,
1755 end=offset,
1754 end=offset,
1756 text=jm.name_with_symbols,
1755 text=jm.name_with_symbols,
1757 type=type_,
1756 type=type_,
1758 _origin='jedi')
1757 _origin='jedi')
1759
1758
1760 if time.monotonic() > deadline:
1759 if time.monotonic() > deadline:
1761 break
1760 break
1762
1761
1763 for jm in iter_jm:
1762 for jm in iter_jm:
1764 delta = len(jm.name_with_symbols) - len(jm.complete)
1763 delta = len(jm.name_with_symbols) - len(jm.complete)
1765 yield Completion(start=offset - delta,
1764 yield Completion(start=offset - delta,
1766 end=offset,
1765 end=offset,
1767 text=jm.name_with_symbols,
1766 text=jm.name_with_symbols,
1768 type='<unknown>', # don't compute type for speed
1767 type='<unknown>', # don't compute type for speed
1769 _origin='jedi')
1768 _origin='jedi')
1770
1769
1771
1770
1772 start_offset = before.rfind(matched_text)
1771 start_offset = before.rfind(matched_text)
1773
1772
1774 # TODO:
1773 # TODO:
1775 # Supress this, right now just for debug.
1774 # Supress this, right now just for debug.
1776 if jedi_matches and matches and self.debug:
1775 if jedi_matches and matches and self.debug:
1777 yield Completion(start=start_offset, end=offset, text='--jedi/ipython--', _origin='debug')
1776 yield Completion(start=start_offset, end=offset, text='--jedi/ipython--', _origin='debug')
1778
1777
1779 # I'm unsure if this is always true, so let's assert and see if it
1778 # I'm unsure if this is always true, so let's assert and see if it
1780 # crash
1779 # crash
1781 assert before.endswith(matched_text)
1780 assert before.endswith(matched_text)
1782 for m, t in zip(matches, matches_origin):
1781 for m, t in zip(matches, matches_origin):
1783 yield Completion(start=start_offset, end=offset, text=m, _origin=t)
1782 yield Completion(start=start_offset, end=offset, text=m, _origin=t)
1784
1783
1785
1784
1786 def complete(self, text=None, line_buffer=None, cursor_pos=None):
1785 def complete(self, text=None, line_buffer=None, cursor_pos=None):
1787 """Find completions for the given text and line context.
1786 """Find completions for the given text and line context.
1788
1787
1789 Note that both the text and the line_buffer are optional, but at least
1788 Note that both the text and the line_buffer are optional, but at least
1790 one of them must be given.
1789 one of them must be given.
1791
1790
1792 Parameters
1791 Parameters
1793 ----------
1792 ----------
1794 text : string, optional
1793 text : string, optional
1795 Text to perform the completion on. If not given, the line buffer
1794 Text to perform the completion on. If not given, the line buffer
1796 is split using the instance's CompletionSplitter object.
1795 is split using the instance's CompletionSplitter object.
1797
1796
1798 line_buffer : string, optional
1797 line_buffer : string, optional
1799 If not given, the completer attempts to obtain the current line
1798 If not given, the completer attempts to obtain the current line
1800 buffer via readline. This keyword allows clients which are
1799 buffer via readline. This keyword allows clients which are
1801 requesting for text completions in non-readline contexts to inform
1800 requesting for text completions in non-readline contexts to inform
1802 the completer of the entire text.
1801 the completer of the entire text.
1803
1802
1804 cursor_pos : int, optional
1803 cursor_pos : int, optional
1805 Index of the cursor in the full line buffer. Should be provided by
1804 Index of the cursor in the full line buffer. Should be provided by
1806 remote frontends where kernel has no access to frontend state.
1805 remote frontends where kernel has no access to frontend state.
1807
1806
1808 Returns
1807 Returns
1809 -------
1808 -------
1810 text : str
1809 text : str
1811 Text that was actually used in the completion.
1810 Text that was actually used in the completion.
1812
1811
1813 matches : list
1812 matches : list
1814 A list of completion matches.
1813 A list of completion matches.
1815
1814
1816
1815
1817 .. note::
1816 .. note::
1818
1817
1819 This API is likely to be deprecated and replaced by
1818 This API is likely to be deprecated and replaced by
1820 :any:`IPCompleter.completions` in the future.
1819 :any:`IPCompleter.completions` in the future.
1821
1820
1822
1821
1823 """
1822 """
1824 warnings.warn('`Completer.complete` is pending deprecation since '
1823 warnings.warn('`Completer.complete` is pending deprecation since '
1825 'IPython 6.0 and will be replaced by `Completer.completions`.',
1824 'IPython 6.0 and will be replaced by `Completer.completions`.',
1826 PendingDeprecationWarning)
1825 PendingDeprecationWarning)
1827 # potential todo, FOLD the 3rd throw away argument of _complete
1826 # potential todo, FOLD the 3rd throw away argument of _complete
1828 # into the first 2 one.
1827 # into the first 2 one.
1829 return self._complete(line_buffer=line_buffer, cursor_pos=cursor_pos, text=text, cursor_line=0)[:2]
1828 return self._complete(line_buffer=line_buffer, cursor_pos=cursor_pos, text=text, cursor_line=0)[:2]
1830
1829
1831 def _complete(self, *, cursor_line, cursor_pos, line_buffer=None, text=None,
1830 def _complete(self, *, cursor_line, cursor_pos, line_buffer=None, text=None,
1832 full_text=None, return_jedi_results=True) -> (str, List[str], List[object]):
1831 full_text=None, return_jedi_results=True) -> (str, List[str], List[object]):
1833 """
1832 """
1834
1833
1835 Like complete but can also returns raw jedi completions as well as the
1834 Like complete but can also returns raw jedi completions as well as the
1836 origin of the completion text. This could (and should) be made much
1835 origin of the completion text. This could (and should) be made much
1837 cleaner but that will be simpler once we drop the old (and stateful)
1836 cleaner but that will be simpler once we drop the old (and stateful)
1838 :any:`complete` API.
1837 :any:`complete` API.
1839
1838
1840
1839
1841 With current provisional API, cursor_pos act both (depending on the
1840 With current provisional API, cursor_pos act both (depending on the
1842 caller) as the offset in the ``text`` or ``line_buffer``, or as the
1841 caller) as the offset in the ``text`` or ``line_buffer``, or as the
1843 ``column`` when passing multiline strings this could/should be renamed
1842 ``column`` when passing multiline strings this could/should be renamed
1844 but would add extra noise.
1843 but would add extra noise.
1845 """
1844 """
1846
1845
1847 # if the cursor position isn't given, the only sane assumption we can
1846 # if the cursor position isn't given, the only sane assumption we can
1848 # make is that it's at the end of the line (the common case)
1847 # make is that it's at the end of the line (the common case)
1849 if cursor_pos is None:
1848 if cursor_pos is None:
1850 cursor_pos = len(line_buffer) if text is None else len(text)
1849 cursor_pos = len(line_buffer) if text is None else len(text)
1851
1850
1852 if self.use_main_ns:
1851 if self.use_main_ns:
1853 self.namespace = __main__.__dict__
1852 self.namespace = __main__.__dict__
1854
1853
1855 # if text is either None or an empty string, rely on the line buffer
1854 # if text is either None or an empty string, rely on the line buffer
1856 if (not line_buffer) and full_text:
1855 if (not line_buffer) and full_text:
1857 line_buffer = full_text.split('\n')[cursor_line]
1856 line_buffer = full_text.split('\n')[cursor_line]
1858 if not text:
1857 if not text:
1859 text = self.splitter.split_line(line_buffer, cursor_pos)
1858 text = self.splitter.split_line(line_buffer, cursor_pos)
1860
1859
1861 if self.backslash_combining_completions:
1860 if self.backslash_combining_completions:
1862 # allow deactivation of these on windows.
1861 # allow deactivation of these on windows.
1863 base_text = text if not line_buffer else line_buffer[:cursor_pos]
1862 base_text = text if not line_buffer else line_buffer[:cursor_pos]
1864 latex_text, latex_matches = self.latex_matches(base_text)
1863 latex_text, latex_matches = self.latex_matches(base_text)
1865 if latex_matches:
1864 if latex_matches:
1866 return latex_text, latex_matches, ['latex_matches']*len(latex_matches), ()
1865 return latex_text, latex_matches, ['latex_matches']*len(latex_matches), ()
1867 name_text = ''
1866 name_text = ''
1868 name_matches = []
1867 name_matches = []
1869 for meth in (self.unicode_name_matches, back_latex_name_matches, back_unicode_name_matches):
1868 for meth in (self.unicode_name_matches, back_latex_name_matches, back_unicode_name_matches):
1870 name_text, name_matches = meth(base_text)
1869 name_text, name_matches = meth(base_text)
1871 if name_text:
1870 if name_text:
1872 return name_text, name_matches, [meth.__qualname__]*len(name_matches), {}
1871 return name_text, name_matches, [meth.__qualname__]*len(name_matches), {}
1873
1872
1874
1873
1875 # If no line buffer is given, assume the input text is all there was
1874 # If no line buffer is given, assume the input text is all there was
1876 if line_buffer is None:
1875 if line_buffer is None:
1877 line_buffer = text
1876 line_buffer = text
1878
1877
1879 self.line_buffer = line_buffer
1878 self.line_buffer = line_buffer
1880 self.text_until_cursor = self.line_buffer[:cursor_pos]
1879 self.text_until_cursor = self.line_buffer[:cursor_pos]
1881
1880
1882 # Start with a clean slate of completions
1881 # Start with a clean slate of completions
1883 matches = []
1882 matches = []
1884 custom_res = self.dispatch_custom_completer(text)
1883 custom_res = self.dispatch_custom_completer(text)
1885 # FIXME: we should extend our api to return a dict with completions for
1884 # FIXME: we should extend our api to return a dict with completions for
1886 # different types of objects. The rlcomplete() method could then
1885 # different types of objects. The rlcomplete() method could then
1887 # simply collapse the dict into a list for readline, but we'd have
1886 # simply collapse the dict into a list for readline, but we'd have
1888 # richer completion semantics in other evironments.
1887 # richer completion semantics in other evironments.
1889 completions = ()
1888 completions = ()
1890 if self.use_jedi and return_jedi_results:
1889 if self.use_jedi and return_jedi_results:
1891 if not full_text:
1890 if not full_text:
1892 full_text = line_buffer
1891 full_text = line_buffer
1893 completions = self._jedi_matches(
1892 completions = self._jedi_matches(
1894 cursor_pos, cursor_line, full_text)
1893 cursor_pos, cursor_line, full_text)
1895 if custom_res is not None:
1894 if custom_res is not None:
1896 # did custom completers produce something?
1895 # did custom completers produce something?
1897 matches = [(m, 'custom') for m in custom_res]
1896 matches = [(m, 'custom') for m in custom_res]
1898 else:
1897 else:
1899 # Extend the list of completions with the results of each
1898 # Extend the list of completions with the results of each
1900 # matcher, so we return results to the user from all
1899 # matcher, so we return results to the user from all
1901 # namespaces.
1900 # namespaces.
1902 if self.merge_completions:
1901 if self.merge_completions:
1903 matches = []
1902 matches = []
1904 for matcher in self.matchers:
1903 for matcher in self.matchers:
1905 try:
1904 try:
1906 matches.extend([(m, matcher.__qualname__)
1905 matches.extend([(m, matcher.__qualname__)
1907 for m in matcher(text)])
1906 for m in matcher(text)])
1908 except:
1907 except:
1909 # Show the ugly traceback if the matcher causes an
1908 # Show the ugly traceback if the matcher causes an
1910 # exception, but do NOT crash the kernel!
1909 # exception, but do NOT crash the kernel!
1911 sys.excepthook(*sys.exc_info())
1910 sys.excepthook(*sys.exc_info())
1912 else:
1911 else:
1913 for matcher in self.matchers:
1912 for matcher in self.matchers:
1914 matches = [(m, matcher.__qualname__)
1913 matches = [(m, matcher.__qualname__)
1915 for m in matcher(text)]
1914 for m in matcher(text)]
1916 if matches:
1915 if matches:
1917 break
1916 break
1918 seen = set()
1917 seen = set()
1919 filtered_matches = set()
1918 filtered_matches = set()
1920 for m in matches:
1919 for m in matches:
1921 t, c = m
1920 t, c = m
1922 if t not in seen:
1921 if t not in seen:
1923 filtered_matches.add(m)
1922 filtered_matches.add(m)
1924 seen.add(t)
1923 seen.add(t)
1925
1924
1926 filtered_matches = sorted(
1925 filtered_matches = sorted(
1927 set(filtered_matches), key=lambda x: completions_sorting_key(x[0]))
1926 set(filtered_matches), key=lambda x: completions_sorting_key(x[0]))
1928
1927
1929 matches = [m[0] for m in filtered_matches]
1928 matches = [m[0] for m in filtered_matches]
1930 origins = [m[1] for m in filtered_matches]
1929 origins = [m[1] for m in filtered_matches]
1931
1930
1932 self.matches = matches
1931 self.matches = matches
1933
1932
1934 return text, matches, origins, completions
1933 return text, matches, origins, completions
@@ -1,321 +1,320 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Displayhook for IPython.
2 """Displayhook for IPython.
3
3
4 This defines a callable class that IPython uses for `sys.displayhook`.
4 This defines a callable class that IPython uses for `sys.displayhook`.
5 """
5 """
6
6
7 # Copyright (c) IPython Development Team.
7 # Copyright (c) IPython Development Team.
8 # Distributed under the terms of the Modified BSD License.
8 # Distributed under the terms of the Modified BSD License.
9
9
10 import builtins as builtin_mod
10 import builtins as builtin_mod
11 import sys
11 import sys
12 import io as _io
12 import io as _io
13 import tokenize
13 import tokenize
14
14
15 from traitlets.config.configurable import Configurable
15 from traitlets.config.configurable import Configurable
16 from IPython.utils.py3compat import cast_unicode_py2
17 from traitlets import Instance, Float
16 from traitlets import Instance, Float
18 from warnings import warn
17 from warnings import warn
19
18
20 # TODO: Move the various attributes (cache_size, [others now moved]). Some
19 # TODO: Move the various attributes (cache_size, [others now moved]). Some
21 # of these are also attributes of InteractiveShell. They should be on ONE object
20 # of these are also attributes of InteractiveShell. They should be on ONE object
22 # only and the other objects should ask that one object for their values.
21 # only and the other objects should ask that one object for their values.
23
22
24 class DisplayHook(Configurable):
23 class DisplayHook(Configurable):
25 """The custom IPython displayhook to replace sys.displayhook.
24 """The custom IPython displayhook to replace sys.displayhook.
26
25
27 This class does many things, but the basic idea is that it is a callable
26 This class does many things, but the basic idea is that it is a callable
28 that gets called anytime user code returns a value.
27 that gets called anytime user code returns a value.
29 """
28 """
30
29
31 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC',
30 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC',
32 allow_none=True)
31 allow_none=True)
33 exec_result = Instance('IPython.core.interactiveshell.ExecutionResult',
32 exec_result = Instance('IPython.core.interactiveshell.ExecutionResult',
34 allow_none=True)
33 allow_none=True)
35 cull_fraction = Float(0.2)
34 cull_fraction = Float(0.2)
36
35
37 def __init__(self, shell=None, cache_size=1000, **kwargs):
36 def __init__(self, shell=None, cache_size=1000, **kwargs):
38 super(DisplayHook, self).__init__(shell=shell, **kwargs)
37 super(DisplayHook, self).__init__(shell=shell, **kwargs)
39 cache_size_min = 3
38 cache_size_min = 3
40 if cache_size <= 0:
39 if cache_size <= 0:
41 self.do_full_cache = 0
40 self.do_full_cache = 0
42 cache_size = 0
41 cache_size = 0
43 elif cache_size < cache_size_min:
42 elif cache_size < cache_size_min:
44 self.do_full_cache = 0
43 self.do_full_cache = 0
45 cache_size = 0
44 cache_size = 0
46 warn('caching was disabled (min value for cache size is %s).' %
45 warn('caching was disabled (min value for cache size is %s).' %
47 cache_size_min,stacklevel=3)
46 cache_size_min,stacklevel=3)
48 else:
47 else:
49 self.do_full_cache = 1
48 self.do_full_cache = 1
50
49
51 self.cache_size = cache_size
50 self.cache_size = cache_size
52
51
53 # we need a reference to the user-level namespace
52 # we need a reference to the user-level namespace
54 self.shell = shell
53 self.shell = shell
55
54
56 self._,self.__,self.___ = '','',''
55 self._,self.__,self.___ = '','',''
57
56
58 # these are deliberately global:
57 # these are deliberately global:
59 to_user_ns = {'_':self._,'__':self.__,'___':self.___}
58 to_user_ns = {'_':self._,'__':self.__,'___':self.___}
60 self.shell.user_ns.update(to_user_ns)
59 self.shell.user_ns.update(to_user_ns)
61
60
62 @property
61 @property
63 def prompt_count(self):
62 def prompt_count(self):
64 return self.shell.execution_count
63 return self.shell.execution_count
65
64
66 #-------------------------------------------------------------------------
65 #-------------------------------------------------------------------------
67 # Methods used in __call__. Override these methods to modify the behavior
66 # Methods used in __call__. Override these methods to modify the behavior
68 # of the displayhook.
67 # of the displayhook.
69 #-------------------------------------------------------------------------
68 #-------------------------------------------------------------------------
70
69
71 def check_for_underscore(self):
70 def check_for_underscore(self):
72 """Check if the user has set the '_' variable by hand."""
71 """Check if the user has set the '_' variable by hand."""
73 # If something injected a '_' variable in __builtin__, delete
72 # If something injected a '_' variable in __builtin__, delete
74 # ipython's automatic one so we don't clobber that. gettext() in
73 # ipython's automatic one so we don't clobber that. gettext() in
75 # particular uses _, so we need to stay away from it.
74 # particular uses _, so we need to stay away from it.
76 if '_' in builtin_mod.__dict__:
75 if '_' in builtin_mod.__dict__:
77 try:
76 try:
78 user_value = self.shell.user_ns['_']
77 user_value = self.shell.user_ns['_']
79 if user_value is not self._:
78 if user_value is not self._:
80 return
79 return
81 del self.shell.user_ns['_']
80 del self.shell.user_ns['_']
82 except KeyError:
81 except KeyError:
83 pass
82 pass
84
83
85 def quiet(self):
84 def quiet(self):
86 """Should we silence the display hook because of ';'?"""
85 """Should we silence the display hook because of ';'?"""
87 # do not print output if input ends in ';'
86 # do not print output if input ends in ';'
88
87
89 try:
88 try:
90 cell = cast_unicode_py2(self.shell.history_manager.input_hist_parsed[-1])
89 cell = self.shell.history_manager.input_hist_parsed[-1]
91 except IndexError:
90 except IndexError:
92 # some uses of ipshellembed may fail here
91 # some uses of ipshellembed may fail here
93 return False
92 return False
94
93
95 sio = _io.StringIO(cell)
94 sio = _io.StringIO(cell)
96 tokens = list(tokenize.generate_tokens(sio.readline))
95 tokens = list(tokenize.generate_tokens(sio.readline))
97
96
98 for token in reversed(tokens):
97 for token in reversed(tokens):
99 if token[0] in (tokenize.ENDMARKER, tokenize.NL, tokenize.NEWLINE, tokenize.COMMENT):
98 if token[0] in (tokenize.ENDMARKER, tokenize.NL, tokenize.NEWLINE, tokenize.COMMENT):
100 continue
99 continue
101 if (token[0] == tokenize.OP) and (token[1] == ';'):
100 if (token[0] == tokenize.OP) and (token[1] == ';'):
102 return True
101 return True
103 else:
102 else:
104 return False
103 return False
105
104
106 def start_displayhook(self):
105 def start_displayhook(self):
107 """Start the displayhook, initializing resources."""
106 """Start the displayhook, initializing resources."""
108 pass
107 pass
109
108
110 def write_output_prompt(self):
109 def write_output_prompt(self):
111 """Write the output prompt.
110 """Write the output prompt.
112
111
113 The default implementation simply writes the prompt to
112 The default implementation simply writes the prompt to
114 ``sys.stdout``.
113 ``sys.stdout``.
115 """
114 """
116 # Use write, not print which adds an extra space.
115 # Use write, not print which adds an extra space.
117 sys.stdout.write(self.shell.separate_out)
116 sys.stdout.write(self.shell.separate_out)
118 outprompt = 'Out[{}]: '.format(self.shell.execution_count)
117 outprompt = 'Out[{}]: '.format(self.shell.execution_count)
119 if self.do_full_cache:
118 if self.do_full_cache:
120 sys.stdout.write(outprompt)
119 sys.stdout.write(outprompt)
121
120
122 def compute_format_data(self, result):
121 def compute_format_data(self, result):
123 """Compute format data of the object to be displayed.
122 """Compute format data of the object to be displayed.
124
123
125 The format data is a generalization of the :func:`repr` of an object.
124 The format data is a generalization of the :func:`repr` of an object.
126 In the default implementation the format data is a :class:`dict` of
125 In the default implementation the format data is a :class:`dict` of
127 key value pair where the keys are valid MIME types and the values
126 key value pair where the keys are valid MIME types and the values
128 are JSON'able data structure containing the raw data for that MIME
127 are JSON'able data structure containing the raw data for that MIME
129 type. It is up to frontends to determine pick a MIME to to use and
128 type. It is up to frontends to determine pick a MIME to to use and
130 display that data in an appropriate manner.
129 display that data in an appropriate manner.
131
130
132 This method only computes the format data for the object and should
131 This method only computes the format data for the object and should
133 NOT actually print or write that to a stream.
132 NOT actually print or write that to a stream.
134
133
135 Parameters
134 Parameters
136 ----------
135 ----------
137 result : object
136 result : object
138 The Python object passed to the display hook, whose format will be
137 The Python object passed to the display hook, whose format will be
139 computed.
138 computed.
140
139
141 Returns
140 Returns
142 -------
141 -------
143 (format_dict, md_dict) : dict
142 (format_dict, md_dict) : dict
144 format_dict is a :class:`dict` whose keys are valid MIME types and values are
143 format_dict is a :class:`dict` whose keys are valid MIME types and values are
145 JSON'able raw data for that MIME type. It is recommended that
144 JSON'able raw data for that MIME type. It is recommended that
146 all return values of this should always include the "text/plain"
145 all return values of this should always include the "text/plain"
147 MIME type representation of the object.
146 MIME type representation of the object.
148 md_dict is a :class:`dict` with the same MIME type keys
147 md_dict is a :class:`dict` with the same MIME type keys
149 of metadata associated with each output.
148 of metadata associated with each output.
150
149
151 """
150 """
152 return self.shell.display_formatter.format(result)
151 return self.shell.display_formatter.format(result)
153
152
154 # This can be set to True by the write_output_prompt method in a subclass
153 # This can be set to True by the write_output_prompt method in a subclass
155 prompt_end_newline = False
154 prompt_end_newline = False
156
155
157 def write_format_data(self, format_dict, md_dict=None):
156 def write_format_data(self, format_dict, md_dict=None):
158 """Write the format data dict to the frontend.
157 """Write the format data dict to the frontend.
159
158
160 This default version of this method simply writes the plain text
159 This default version of this method simply writes the plain text
161 representation of the object to ``sys.stdout``. Subclasses should
160 representation of the object to ``sys.stdout``. Subclasses should
162 override this method to send the entire `format_dict` to the
161 override this method to send the entire `format_dict` to the
163 frontends.
162 frontends.
164
163
165 Parameters
164 Parameters
166 ----------
165 ----------
167 format_dict : dict
166 format_dict : dict
168 The format dict for the object passed to `sys.displayhook`.
167 The format dict for the object passed to `sys.displayhook`.
169 md_dict : dict (optional)
168 md_dict : dict (optional)
170 The metadata dict to be associated with the display data.
169 The metadata dict to be associated with the display data.
171 """
170 """
172 if 'text/plain' not in format_dict:
171 if 'text/plain' not in format_dict:
173 # nothing to do
172 # nothing to do
174 return
173 return
175 # We want to print because we want to always make sure we have a
174 # We want to print because we want to always make sure we have a
176 # newline, even if all the prompt separators are ''. This is the
175 # newline, even if all the prompt separators are ''. This is the
177 # standard IPython behavior.
176 # standard IPython behavior.
178 result_repr = format_dict['text/plain']
177 result_repr = format_dict['text/plain']
179 if '\n' in result_repr:
178 if '\n' in result_repr:
180 # So that multi-line strings line up with the left column of
179 # So that multi-line strings line up with the left column of
181 # the screen, instead of having the output prompt mess up
180 # the screen, instead of having the output prompt mess up
182 # their first line.
181 # their first line.
183 # We use the prompt template instead of the expanded prompt
182 # We use the prompt template instead of the expanded prompt
184 # because the expansion may add ANSI escapes that will interfere
183 # because the expansion may add ANSI escapes that will interfere
185 # with our ability to determine whether or not we should add
184 # with our ability to determine whether or not we should add
186 # a newline.
185 # a newline.
187 if not self.prompt_end_newline:
186 if not self.prompt_end_newline:
188 # But avoid extraneous empty lines.
187 # But avoid extraneous empty lines.
189 result_repr = '\n' + result_repr
188 result_repr = '\n' + result_repr
190
189
191 print(result_repr)
190 print(result_repr)
192
191
193 def update_user_ns(self, result):
192 def update_user_ns(self, result):
194 """Update user_ns with various things like _, __, _1, etc."""
193 """Update user_ns with various things like _, __, _1, etc."""
195
194
196 # Avoid recursive reference when displaying _oh/Out
195 # Avoid recursive reference when displaying _oh/Out
197 if result is not self.shell.user_ns['_oh']:
196 if result is not self.shell.user_ns['_oh']:
198 if len(self.shell.user_ns['_oh']) >= self.cache_size and self.do_full_cache:
197 if len(self.shell.user_ns['_oh']) >= self.cache_size and self.do_full_cache:
199 self.cull_cache()
198 self.cull_cache()
200
199
201 # Don't overwrite '_' and friends if '_' is in __builtin__
200 # Don't overwrite '_' and friends if '_' is in __builtin__
202 # (otherwise we cause buggy behavior for things like gettext). and
201 # (otherwise we cause buggy behavior for things like gettext). and
203 # do not overwrite _, __ or ___ if one of these has been assigned
202 # do not overwrite _, __ or ___ if one of these has been assigned
204 # by the user.
203 # by the user.
205 update_unders = True
204 update_unders = True
206 for unders in ['_'*i for i in range(1,4)]:
205 for unders in ['_'*i for i in range(1,4)]:
207 if not unders in self.shell.user_ns:
206 if not unders in self.shell.user_ns:
208 continue
207 continue
209 if getattr(self, unders) is not self.shell.user_ns.get(unders):
208 if getattr(self, unders) is not self.shell.user_ns.get(unders):
210 update_unders = False
209 update_unders = False
211
210
212 self.___ = self.__
211 self.___ = self.__
213 self.__ = self._
212 self.__ = self._
214 self._ = result
213 self._ = result
215
214
216 if ('_' not in builtin_mod.__dict__) and (update_unders):
215 if ('_' not in builtin_mod.__dict__) and (update_unders):
217 self.shell.push({'_':self._,
216 self.shell.push({'_':self._,
218 '__':self.__,
217 '__':self.__,
219 '___':self.___}, interactive=False)
218 '___':self.___}, interactive=False)
220
219
221 # hackish access to top-level namespace to create _1,_2... dynamically
220 # hackish access to top-level namespace to create _1,_2... dynamically
222 to_main = {}
221 to_main = {}
223 if self.do_full_cache:
222 if self.do_full_cache:
224 new_result = '_%s' % self.prompt_count
223 new_result = '_%s' % self.prompt_count
225 to_main[new_result] = result
224 to_main[new_result] = result
226 self.shell.push(to_main, interactive=False)
225 self.shell.push(to_main, interactive=False)
227 self.shell.user_ns['_oh'][self.prompt_count] = result
226 self.shell.user_ns['_oh'][self.prompt_count] = result
228
227
229 def fill_exec_result(self, result):
228 def fill_exec_result(self, result):
230 if self.exec_result is not None:
229 if self.exec_result is not None:
231 self.exec_result.result = result
230 self.exec_result.result = result
232
231
233 def log_output(self, format_dict):
232 def log_output(self, format_dict):
234 """Log the output."""
233 """Log the output."""
235 if 'text/plain' not in format_dict:
234 if 'text/plain' not in format_dict:
236 # nothing to do
235 # nothing to do
237 return
236 return
238 if self.shell.logger.log_output:
237 if self.shell.logger.log_output:
239 self.shell.logger.log_write(format_dict['text/plain'], 'output')
238 self.shell.logger.log_write(format_dict['text/plain'], 'output')
240 self.shell.history_manager.output_hist_reprs[self.prompt_count] = \
239 self.shell.history_manager.output_hist_reprs[self.prompt_count] = \
241 format_dict['text/plain']
240 format_dict['text/plain']
242
241
243 def finish_displayhook(self):
242 def finish_displayhook(self):
244 """Finish up all displayhook activities."""
243 """Finish up all displayhook activities."""
245 sys.stdout.write(self.shell.separate_out2)
244 sys.stdout.write(self.shell.separate_out2)
246 sys.stdout.flush()
245 sys.stdout.flush()
247
246
248 def __call__(self, result=None):
247 def __call__(self, result=None):
249 """Printing with history cache management.
248 """Printing with history cache management.
250
249
251 This is invoked everytime the interpreter needs to print, and is
250 This is invoked everytime the interpreter needs to print, and is
252 activated by setting the variable sys.displayhook to it.
251 activated by setting the variable sys.displayhook to it.
253 """
252 """
254 self.check_for_underscore()
253 self.check_for_underscore()
255 if result is not None and not self.quiet():
254 if result is not None and not self.quiet():
256 self.start_displayhook()
255 self.start_displayhook()
257 self.write_output_prompt()
256 self.write_output_prompt()
258 format_dict, md_dict = self.compute_format_data(result)
257 format_dict, md_dict = self.compute_format_data(result)
259 self.update_user_ns(result)
258 self.update_user_ns(result)
260 self.fill_exec_result(result)
259 self.fill_exec_result(result)
261 if format_dict:
260 if format_dict:
262 self.write_format_data(format_dict, md_dict)
261 self.write_format_data(format_dict, md_dict)
263 self.log_output(format_dict)
262 self.log_output(format_dict)
264 self.finish_displayhook()
263 self.finish_displayhook()
265
264
266 def cull_cache(self):
265 def cull_cache(self):
267 """Output cache is full, cull the oldest entries"""
266 """Output cache is full, cull the oldest entries"""
268 oh = self.shell.user_ns.get('_oh', {})
267 oh = self.shell.user_ns.get('_oh', {})
269 sz = len(oh)
268 sz = len(oh)
270 cull_count = max(int(sz * self.cull_fraction), 2)
269 cull_count = max(int(sz * self.cull_fraction), 2)
271 warn('Output cache limit (currently {sz} entries) hit.\n'
270 warn('Output cache limit (currently {sz} entries) hit.\n'
272 'Flushing oldest {cull_count} entries.'.format(sz=sz, cull_count=cull_count))
271 'Flushing oldest {cull_count} entries.'.format(sz=sz, cull_count=cull_count))
273
272
274 for i, n in enumerate(sorted(oh)):
273 for i, n in enumerate(sorted(oh)):
275 if i >= cull_count:
274 if i >= cull_count:
276 break
275 break
277 self.shell.user_ns.pop('_%i' % n, None)
276 self.shell.user_ns.pop('_%i' % n, None)
278 oh.pop(n, None)
277 oh.pop(n, None)
279
278
280
279
281 def flush(self):
280 def flush(self):
282 if not self.do_full_cache:
281 if not self.do_full_cache:
283 raise ValueError("You shouldn't have reached the cache flush "
282 raise ValueError("You shouldn't have reached the cache flush "
284 "if full caching is not enabled!")
283 "if full caching is not enabled!")
285 # delete auto-generated vars from global namespace
284 # delete auto-generated vars from global namespace
286
285
287 for n in range(1,self.prompt_count + 1):
286 for n in range(1,self.prompt_count + 1):
288 key = '_'+repr(n)
287 key = '_'+repr(n)
289 try:
288 try:
290 del self.shell.user_ns[key]
289 del self.shell.user_ns[key]
291 except: pass
290 except: pass
292 # In some embedded circumstances, the user_ns doesn't have the
291 # In some embedded circumstances, the user_ns doesn't have the
293 # '_oh' key set up.
292 # '_oh' key set up.
294 oh = self.shell.user_ns.get('_oh', None)
293 oh = self.shell.user_ns.get('_oh', None)
295 if oh is not None:
294 if oh is not None:
296 oh.clear()
295 oh.clear()
297
296
298 # Release our own references to objects:
297 # Release our own references to objects:
299 self._, self.__, self.___ = '', '', ''
298 self._, self.__, self.___ = '', '', ''
300
299
301 if '_' not in builtin_mod.__dict__:
300 if '_' not in builtin_mod.__dict__:
302 self.shell.user_ns.update({'_':None,'__':None, '___':None})
301 self.shell.user_ns.update({'_':None,'__':None, '___':None})
303 import gc
302 import gc
304 # TODO: Is this really needed?
303 # TODO: Is this really needed?
305 # IronPython blocks here forever
304 # IronPython blocks here forever
306 if sys.platform != "cli":
305 if sys.platform != "cli":
307 gc.collect()
306 gc.collect()
308
307
309
308
310 class CapturingDisplayHook(object):
309 class CapturingDisplayHook(object):
311 def __init__(self, shell, outputs=None):
310 def __init__(self, shell, outputs=None):
312 self.shell = shell
311 self.shell = shell
313 if outputs is None:
312 if outputs is None:
314 outputs = []
313 outputs = []
315 self.outputs = outputs
314 self.outputs = outputs
316
315
317 def __call__(self, result=None):
316 def __call__(self, result=None):
318 if result is None:
317 if result is None:
319 return
318 return
320 format_dict, md_dict = self.shell.display_formatter.format(result)
319 format_dict, md_dict = self.shell.display_formatter.format(result)
321 self.outputs.append((format_dict, md_dict))
320 self.outputs.append((format_dict, md_dict))
@@ -1,319 +1,318 b''
1 """Implementation of magic functions related to History.
1 """Implementation of magic functions related to History.
2 """
2 """
3 #-----------------------------------------------------------------------------
3 #-----------------------------------------------------------------------------
4 # Copyright (c) 2012, IPython Development Team.
4 # Copyright (c) 2012, IPython Development Team.
5 #
5 #
6 # Distributed under the terms of the Modified BSD License.
6 # Distributed under the terms of the Modified BSD License.
7 #
7 #
8 # The full license is in the file COPYING.txt, distributed with this software.
8 # The full license is in the file COPYING.txt, distributed with this software.
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10
10
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 # Imports
12 # Imports
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15 # Stdlib
15 # Stdlib
16 import os
16 import os
17 import sys
17 import sys
18 from io import open as io_open
18 from io import open as io_open
19
19
20 # Our own packages
20 # Our own packages
21 from IPython.core.error import StdinNotImplementedError
21 from IPython.core.error import StdinNotImplementedError
22 from IPython.core.magic import Magics, magics_class, line_magic
22 from IPython.core.magic import Magics, magics_class, line_magic
23 from IPython.core.magic_arguments import (argument, magic_arguments,
23 from IPython.core.magic_arguments import (argument, magic_arguments,
24 parse_argstring)
24 parse_argstring)
25 from IPython.testing.skipdoctest import skip_doctest
25 from IPython.testing.skipdoctest import skip_doctest
26 from IPython.utils import io
26 from IPython.utils import io
27 from IPython.utils.py3compat import cast_unicode_py2
28
27
29 #-----------------------------------------------------------------------------
28 #-----------------------------------------------------------------------------
30 # Magics class implementation
29 # Magics class implementation
31 #-----------------------------------------------------------------------------
30 #-----------------------------------------------------------------------------
32
31
33
32
34 _unspecified = object()
33 _unspecified = object()
35
34
36
35
37 @magics_class
36 @magics_class
38 class HistoryMagics(Magics):
37 class HistoryMagics(Magics):
39
38
40 @magic_arguments()
39 @magic_arguments()
41 @argument(
40 @argument(
42 '-n', dest='print_nums', action='store_true', default=False,
41 '-n', dest='print_nums', action='store_true', default=False,
43 help="""
42 help="""
44 print line numbers for each input.
43 print line numbers for each input.
45 This feature is only available if numbered prompts are in use.
44 This feature is only available if numbered prompts are in use.
46 """)
45 """)
47 @argument(
46 @argument(
48 '-o', dest='get_output', action='store_true', default=False,
47 '-o', dest='get_output', action='store_true', default=False,
49 help="also print outputs for each input.")
48 help="also print outputs for each input.")
50 @argument(
49 @argument(
51 '-p', dest='pyprompts', action='store_true', default=False,
50 '-p', dest='pyprompts', action='store_true', default=False,
52 help="""
51 help="""
53 print classic '>>>' python prompts before each input.
52 print classic '>>>' python prompts before each input.
54 This is useful for making documentation, and in conjunction
53 This is useful for making documentation, and in conjunction
55 with -o, for producing doctest-ready output.
54 with -o, for producing doctest-ready output.
56 """)
55 """)
57 @argument(
56 @argument(
58 '-t', dest='raw', action='store_false', default=True,
57 '-t', dest='raw', action='store_false', default=True,
59 help="""
58 help="""
60 print the 'translated' history, as IPython understands it.
59 print the 'translated' history, as IPython understands it.
61 IPython filters your input and converts it all into valid Python
60 IPython filters your input and converts it all into valid Python
62 source before executing it (things like magics or aliases are turned
61 source before executing it (things like magics or aliases are turned
63 into function calls, for example). With this option, you'll see the
62 into function calls, for example). With this option, you'll see the
64 native history instead of the user-entered version: '%%cd /' will be
63 native history instead of the user-entered version: '%%cd /' will be
65 seen as 'get_ipython().magic("%%cd /")' instead of '%%cd /'.
64 seen as 'get_ipython().magic("%%cd /")' instead of '%%cd /'.
66 """)
65 """)
67 @argument(
66 @argument(
68 '-f', dest='filename',
67 '-f', dest='filename',
69 help="""
68 help="""
70 FILENAME: instead of printing the output to the screen, redirect
69 FILENAME: instead of printing the output to the screen, redirect
71 it to the given file. The file is always overwritten, though *when
70 it to the given file. The file is always overwritten, though *when
72 it can*, IPython asks for confirmation first. In particular, running
71 it can*, IPython asks for confirmation first. In particular, running
73 the command 'history -f FILENAME' from the IPython Notebook
72 the command 'history -f FILENAME' from the IPython Notebook
74 interface will replace FILENAME even if it already exists *without*
73 interface will replace FILENAME even if it already exists *without*
75 confirmation.
74 confirmation.
76 """)
75 """)
77 @argument(
76 @argument(
78 '-g', dest='pattern', nargs='*', default=None,
77 '-g', dest='pattern', nargs='*', default=None,
79 help="""
78 help="""
80 treat the arg as a glob pattern to search for in (full) history.
79 treat the arg as a glob pattern to search for in (full) history.
81 This includes the saved history (almost all commands ever written).
80 This includes the saved history (almost all commands ever written).
82 The pattern may contain '?' to match one unknown character and '*'
81 The pattern may contain '?' to match one unknown character and '*'
83 to match any number of unknown characters. Use '%%hist -g' to show
82 to match any number of unknown characters. Use '%%hist -g' to show
84 full saved history (may be very long).
83 full saved history (may be very long).
85 """)
84 """)
86 @argument(
85 @argument(
87 '-l', dest='limit', type=int, nargs='?', default=_unspecified,
86 '-l', dest='limit', type=int, nargs='?', default=_unspecified,
88 help="""
87 help="""
89 get the last n lines from all sessions. Specify n as a single
88 get the last n lines from all sessions. Specify n as a single
90 arg, or the default is the last 10 lines.
89 arg, or the default is the last 10 lines.
91 """)
90 """)
92 @argument(
91 @argument(
93 '-u', dest='unique', action='store_true',
92 '-u', dest='unique', action='store_true',
94 help="""
93 help="""
95 when searching history using `-g`, show only unique history.
94 when searching history using `-g`, show only unique history.
96 """)
95 """)
97 @argument('range', nargs='*')
96 @argument('range', nargs='*')
98 @skip_doctest
97 @skip_doctest
99 @line_magic
98 @line_magic
100 def history(self, parameter_s = ''):
99 def history(self, parameter_s = ''):
101 """Print input history (_i<n> variables), with most recent last.
100 """Print input history (_i<n> variables), with most recent last.
102
101
103 By default, input history is printed without line numbers so it can be
102 By default, input history is printed without line numbers so it can be
104 directly pasted into an editor. Use -n to show them.
103 directly pasted into an editor. Use -n to show them.
105
104
106 By default, all input history from the current session is displayed.
105 By default, all input history from the current session is displayed.
107 Ranges of history can be indicated using the syntax:
106 Ranges of history can be indicated using the syntax:
108
107
109 ``4``
108 ``4``
110 Line 4, current session
109 Line 4, current session
111 ``4-6``
110 ``4-6``
112 Lines 4-6, current session
111 Lines 4-6, current session
113 ``243/1-5``
112 ``243/1-5``
114 Lines 1-5, session 243
113 Lines 1-5, session 243
115 ``~2/7``
114 ``~2/7``
116 Line 7, session 2 before current
115 Line 7, session 2 before current
117 ``~8/1-~6/5``
116 ``~8/1-~6/5``
118 From the first line of 8 sessions ago, to the fifth line of 6
117 From the first line of 8 sessions ago, to the fifth line of 6
119 sessions ago.
118 sessions ago.
120
119
121 Multiple ranges can be entered, separated by spaces
120 Multiple ranges can be entered, separated by spaces
122
121
123 The same syntax is used by %macro, %save, %edit, %rerun
122 The same syntax is used by %macro, %save, %edit, %rerun
124
123
125 Examples
124 Examples
126 --------
125 --------
127 ::
126 ::
128
127
129 In [6]: %history -n 4-6
128 In [6]: %history -n 4-6
130 4:a = 12
129 4:a = 12
131 5:print a**2
130 5:print a**2
132 6:%history -n 4-6
131 6:%history -n 4-6
133
132
134 """
133 """
135
134
136 args = parse_argstring(self.history, parameter_s)
135 args = parse_argstring(self.history, parameter_s)
137
136
138 # For brevity
137 # For brevity
139 history_manager = self.shell.history_manager
138 history_manager = self.shell.history_manager
140
139
141 def _format_lineno(session, line):
140 def _format_lineno(session, line):
142 """Helper function to format line numbers properly."""
141 """Helper function to format line numbers properly."""
143 if session in (0, history_manager.session_number):
142 if session in (0, history_manager.session_number):
144 return str(line)
143 return str(line)
145 return "%s/%s" % (session, line)
144 return "%s/%s" % (session, line)
146
145
147 # Check if output to specific file was requested.
146 # Check if output to specific file was requested.
148 outfname = args.filename
147 outfname = args.filename
149 if not outfname:
148 if not outfname:
150 outfile = sys.stdout # default
149 outfile = sys.stdout # default
151 # We don't want to close stdout at the end!
150 # We don't want to close stdout at the end!
152 close_at_end = False
151 close_at_end = False
153 else:
152 else:
154 if os.path.exists(outfname):
153 if os.path.exists(outfname):
155 try:
154 try:
156 ans = io.ask_yes_no("File %r exists. Overwrite?" % outfname)
155 ans = io.ask_yes_no("File %r exists. Overwrite?" % outfname)
157 except StdinNotImplementedError:
156 except StdinNotImplementedError:
158 ans = True
157 ans = True
159 if not ans:
158 if not ans:
160 print('Aborting.')
159 print('Aborting.')
161 return
160 return
162 print("Overwriting file.")
161 print("Overwriting file.")
163 outfile = io_open(outfname, 'w', encoding='utf-8')
162 outfile = io_open(outfname, 'w', encoding='utf-8')
164 close_at_end = True
163 close_at_end = True
165
164
166 print_nums = args.print_nums
165 print_nums = args.print_nums
167 get_output = args.get_output
166 get_output = args.get_output
168 pyprompts = args.pyprompts
167 pyprompts = args.pyprompts
169 raw = args.raw
168 raw = args.raw
170
169
171 pattern = None
170 pattern = None
172 limit = None if args.limit is _unspecified else args.limit
171 limit = None if args.limit is _unspecified else args.limit
173
172
174 if args.pattern is not None:
173 if args.pattern is not None:
175 if args.pattern:
174 if args.pattern:
176 pattern = "*" + " ".join(args.pattern) + "*"
175 pattern = "*" + " ".join(args.pattern) + "*"
177 else:
176 else:
178 pattern = "*"
177 pattern = "*"
179 hist = history_manager.search(pattern, raw=raw, output=get_output,
178 hist = history_manager.search(pattern, raw=raw, output=get_output,
180 n=limit, unique=args.unique)
179 n=limit, unique=args.unique)
181 print_nums = True
180 print_nums = True
182 elif args.limit is not _unspecified:
181 elif args.limit is not _unspecified:
183 n = 10 if limit is None else limit
182 n = 10 if limit is None else limit
184 hist = history_manager.get_tail(n, raw=raw, output=get_output)
183 hist = history_manager.get_tail(n, raw=raw, output=get_output)
185 else:
184 else:
186 if args.range: # Get history by ranges
185 if args.range: # Get history by ranges
187 hist = history_manager.get_range_by_str(" ".join(args.range),
186 hist = history_manager.get_range_by_str(" ".join(args.range),
188 raw, get_output)
187 raw, get_output)
189 else: # Just get history for the current session
188 else: # Just get history for the current session
190 hist = history_manager.get_range(raw=raw, output=get_output)
189 hist = history_manager.get_range(raw=raw, output=get_output)
191
190
192 # We could be displaying the entire history, so let's not try to pull
191 # We could be displaying the entire history, so let's not try to pull
193 # it into a list in memory. Anything that needs more space will just
192 # it into a list in memory. Anything that needs more space will just
194 # misalign.
193 # misalign.
195 width = 4
194 width = 4
196
195
197 for session, lineno, inline in hist:
196 for session, lineno, inline in hist:
198 # Print user history with tabs expanded to 4 spaces. The GUI
197 # Print user history with tabs expanded to 4 spaces. The GUI
199 # clients use hard tabs for easier usability in auto-indented code,
198 # clients use hard tabs for easier usability in auto-indented code,
200 # but we want to produce PEP-8 compliant history for safe pasting
199 # but we want to produce PEP-8 compliant history for safe pasting
201 # into an editor.
200 # into an editor.
202 if get_output:
201 if get_output:
203 inline, output = inline
202 inline, output = inline
204 inline = inline.expandtabs(4).rstrip()
203 inline = inline.expandtabs(4).rstrip()
205
204
206 multiline = "\n" in inline
205 multiline = "\n" in inline
207 line_sep = '\n' if multiline else ' '
206 line_sep = '\n' if multiline else ' '
208 if print_nums:
207 if print_nums:
209 print(u'%s:%s' % (_format_lineno(session, lineno).rjust(width),
208 print(u'%s:%s' % (_format_lineno(session, lineno).rjust(width),
210 line_sep), file=outfile, end=u'')
209 line_sep), file=outfile, end=u'')
211 if pyprompts:
210 if pyprompts:
212 print(u">>> ", end=u"", file=outfile)
211 print(u">>> ", end=u"", file=outfile)
213 if multiline:
212 if multiline:
214 inline = "\n... ".join(inline.splitlines()) + "\n..."
213 inline = "\n... ".join(inline.splitlines()) + "\n..."
215 print(inline, file=outfile)
214 print(inline, file=outfile)
216 if get_output and output:
215 if get_output and output:
217 print(cast_unicode_py2(output), file=outfile)
216 print(output, file=outfile)
218
217
219 if close_at_end:
218 if close_at_end:
220 outfile.close()
219 outfile.close()
221
220
222 @line_magic
221 @line_magic
223 def recall(self, arg):
222 def recall(self, arg):
224 r"""Repeat a command, or get command to input line for editing.
223 r"""Repeat a command, or get command to input line for editing.
225
224
226 %recall and %rep are equivalent.
225 %recall and %rep are equivalent.
227
226
228 - %recall (no arguments):
227 - %recall (no arguments):
229
228
230 Place a string version of last computation result (stored in the
229 Place a string version of last computation result (stored in the
231 special '_' variable) to the next input prompt. Allows you to create
230 special '_' variable) to the next input prompt. Allows you to create
232 elaborate command lines without using copy-paste::
231 elaborate command lines without using copy-paste::
233
232
234 In[1]: l = ["hei", "vaan"]
233 In[1]: l = ["hei", "vaan"]
235 In[2]: "".join(l)
234 In[2]: "".join(l)
236 Out[2]: heivaan
235 Out[2]: heivaan
237 In[3]: %recall
236 In[3]: %recall
238 In[4]: heivaan_ <== cursor blinking
237 In[4]: heivaan_ <== cursor blinking
239
238
240 %recall 45
239 %recall 45
241
240
242 Place history line 45 on the next input prompt. Use %hist to find
241 Place history line 45 on the next input prompt. Use %hist to find
243 out the number.
242 out the number.
244
243
245 %recall 1-4
244 %recall 1-4
246
245
247 Combine the specified lines into one cell, and place it on the next
246 Combine the specified lines into one cell, and place it on the next
248 input prompt. See %history for the slice syntax.
247 input prompt. See %history for the slice syntax.
249
248
250 %recall foo+bar
249 %recall foo+bar
251
250
252 If foo+bar can be evaluated in the user namespace, the result is
251 If foo+bar can be evaluated in the user namespace, the result is
253 placed at the next input prompt. Otherwise, the history is searched
252 placed at the next input prompt. Otherwise, the history is searched
254 for lines which contain that substring, and the most recent one is
253 for lines which contain that substring, and the most recent one is
255 placed at the next input prompt.
254 placed at the next input prompt.
256 """
255 """
257 if not arg: # Last output
256 if not arg: # Last output
258 self.shell.set_next_input(str(self.shell.user_ns["_"]))
257 self.shell.set_next_input(str(self.shell.user_ns["_"]))
259 return
258 return
260 # Get history range
259 # Get history range
261 histlines = self.shell.history_manager.get_range_by_str(arg)
260 histlines = self.shell.history_manager.get_range_by_str(arg)
262 cmd = "\n".join(x[2] for x in histlines)
261 cmd = "\n".join(x[2] for x in histlines)
263 if cmd:
262 if cmd:
264 self.shell.set_next_input(cmd.rstrip())
263 self.shell.set_next_input(cmd.rstrip())
265 return
264 return
266
265
267 try: # Variable in user namespace
266 try: # Variable in user namespace
268 cmd = str(eval(arg, self.shell.user_ns))
267 cmd = str(eval(arg, self.shell.user_ns))
269 except Exception: # Search for term in history
268 except Exception: # Search for term in history
270 histlines = self.shell.history_manager.search("*"+arg+"*")
269 histlines = self.shell.history_manager.search("*"+arg+"*")
271 for h in reversed([x[2] for x in histlines]):
270 for h in reversed([x[2] for x in histlines]):
272 if 'recall' in h or 'rep' in h:
271 if 'recall' in h or 'rep' in h:
273 continue
272 continue
274 self.shell.set_next_input(h.rstrip())
273 self.shell.set_next_input(h.rstrip())
275 return
274 return
276 else:
275 else:
277 self.shell.set_next_input(cmd.rstrip())
276 self.shell.set_next_input(cmd.rstrip())
278 print("Couldn't evaluate or find in history:", arg)
277 print("Couldn't evaluate or find in history:", arg)
279
278
280 @line_magic
279 @line_magic
281 def rerun(self, parameter_s=''):
280 def rerun(self, parameter_s=''):
282 """Re-run previous input
281 """Re-run previous input
283
282
284 By default, you can specify ranges of input history to be repeated
283 By default, you can specify ranges of input history to be repeated
285 (as with %history). With no arguments, it will repeat the last line.
284 (as with %history). With no arguments, it will repeat the last line.
286
285
287 Options:
286 Options:
288
287
289 -l <n> : Repeat the last n lines of input, not including the
288 -l <n> : Repeat the last n lines of input, not including the
290 current command.
289 current command.
291
290
292 -g foo : Repeat the most recent line which contains foo
291 -g foo : Repeat the most recent line which contains foo
293 """
292 """
294 opts, args = self.parse_options(parameter_s, 'l:g:', mode='string')
293 opts, args = self.parse_options(parameter_s, 'l:g:', mode='string')
295 if "l" in opts: # Last n lines
294 if "l" in opts: # Last n lines
296 n = int(opts['l'])
295 n = int(opts['l'])
297 hist = self.shell.history_manager.get_tail(n)
296 hist = self.shell.history_manager.get_tail(n)
298 elif "g" in opts: # Search
297 elif "g" in opts: # Search
299 p = "*"+opts['g']+"*"
298 p = "*"+opts['g']+"*"
300 hist = list(self.shell.history_manager.search(p))
299 hist = list(self.shell.history_manager.search(p))
301 for l in reversed(hist):
300 for l in reversed(hist):
302 if "rerun" not in l[2]:
301 if "rerun" not in l[2]:
303 hist = [l] # The last match which isn't a %rerun
302 hist = [l] # The last match which isn't a %rerun
304 break
303 break
305 else:
304 else:
306 hist = [] # No matches except %rerun
305 hist = [] # No matches except %rerun
307 elif args: # Specify history ranges
306 elif args: # Specify history ranges
308 hist = self.shell.history_manager.get_range_by_str(args)
307 hist = self.shell.history_manager.get_range_by_str(args)
309 else: # Last line
308 else: # Last line
310 hist = self.shell.history_manager.get_tail(1)
309 hist = self.shell.history_manager.get_tail(1)
311 hist = [x[2] for x in hist]
310 hist = [x[2] for x in hist]
312 if not hist:
311 if not hist:
313 print("No lines in history match specification")
312 print("No lines in history match specification")
314 return
313 return
315 histlines = "\n".join(hist)
314 histlines = "\n".join(hist)
316 print("=== Executing: ===")
315 print("=== Executing: ===")
317 print(histlines)
316 print(histlines)
318 print("=== Output: ===")
317 print("=== Output: ===")
319 self.shell.run_cell("\n".join(hist), store_history=False)
318 self.shell.run_cell("\n".join(hist), store_history=False)
@@ -1,1461 +1,1456 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 Verbose and colourful traceback formatting.
3 Verbose and colourful traceback formatting.
4
4
5 **ColorTB**
5 **ColorTB**
6
6
7 I've always found it a bit hard to visually parse tracebacks in Python. The
7 I've always found it a bit hard to visually parse tracebacks in Python. The
8 ColorTB class is a solution to that problem. It colors the different parts of a
8 ColorTB class is a solution to that problem. It colors the different parts of a
9 traceback in a manner similar to what you would expect from a syntax-highlighting
9 traceback in a manner similar to what you would expect from a syntax-highlighting
10 text editor.
10 text editor.
11
11
12 Installation instructions for ColorTB::
12 Installation instructions for ColorTB::
13
13
14 import sys,ultratb
14 import sys,ultratb
15 sys.excepthook = ultratb.ColorTB()
15 sys.excepthook = ultratb.ColorTB()
16
16
17 **VerboseTB**
17 **VerboseTB**
18
18
19 I've also included a port of Ka-Ping Yee's "cgitb.py" that produces all kinds
19 I've also included a port of Ka-Ping Yee's "cgitb.py" that produces all kinds
20 of useful info when a traceback occurs. Ping originally had it spit out HTML
20 of useful info when a traceback occurs. Ping originally had it spit out HTML
21 and intended it for CGI programmers, but why should they have all the fun? I
21 and intended it for CGI programmers, but why should they have all the fun? I
22 altered it to spit out colored text to the terminal. It's a bit overwhelming,
22 altered it to spit out colored text to the terminal. It's a bit overwhelming,
23 but kind of neat, and maybe useful for long-running programs that you believe
23 but kind of neat, and maybe useful for long-running programs that you believe
24 are bug-free. If a crash *does* occur in that type of program you want details.
24 are bug-free. If a crash *does* occur in that type of program you want details.
25 Give it a shot--you'll love it or you'll hate it.
25 Give it a shot--you'll love it or you'll hate it.
26
26
27 .. note::
27 .. note::
28
28
29 The Verbose mode prints the variables currently visible where the exception
29 The Verbose mode prints the variables currently visible where the exception
30 happened (shortening their strings if too long). This can potentially be
30 happened (shortening their strings if too long). This can potentially be
31 very slow, if you happen to have a huge data structure whose string
31 very slow, if you happen to have a huge data structure whose string
32 representation is complex to compute. Your computer may appear to freeze for
32 representation is complex to compute. Your computer may appear to freeze for
33 a while with cpu usage at 100%. If this occurs, you can cancel the traceback
33 a while with cpu usage at 100%. If this occurs, you can cancel the traceback
34 with Ctrl-C (maybe hitting it more than once).
34 with Ctrl-C (maybe hitting it more than once).
35
35
36 If you encounter this kind of situation often, you may want to use the
36 If you encounter this kind of situation often, you may want to use the
37 Verbose_novars mode instead of the regular Verbose, which avoids formatting
37 Verbose_novars mode instead of the regular Verbose, which avoids formatting
38 variables (but otherwise includes the information and context given by
38 variables (but otherwise includes the information and context given by
39 Verbose).
39 Verbose).
40
40
41 .. note::
41 .. note::
42
42
43 The verbose mode print all variables in the stack, which means it can
43 The verbose mode print all variables in the stack, which means it can
44 potentially leak sensitive information like access keys, or unencryted
44 potentially leak sensitive information like access keys, or unencryted
45 password.
45 password.
46
46
47 Installation instructions for VerboseTB::
47 Installation instructions for VerboseTB::
48
48
49 import sys,ultratb
49 import sys,ultratb
50 sys.excepthook = ultratb.VerboseTB()
50 sys.excepthook = ultratb.VerboseTB()
51
51
52 Note: Much of the code in this module was lifted verbatim from the standard
52 Note: Much of the code in this module was lifted verbatim from the standard
53 library module 'traceback.py' and Ka-Ping Yee's 'cgitb.py'.
53 library module 'traceback.py' and Ka-Ping Yee's 'cgitb.py'.
54
54
55 Color schemes
55 Color schemes
56 -------------
56 -------------
57
57
58 The colors are defined in the class TBTools through the use of the
58 The colors are defined in the class TBTools through the use of the
59 ColorSchemeTable class. Currently the following exist:
59 ColorSchemeTable class. Currently the following exist:
60
60
61 - NoColor: allows all of this module to be used in any terminal (the color
61 - NoColor: allows all of this module to be used in any terminal (the color
62 escapes are just dummy blank strings).
62 escapes are just dummy blank strings).
63
63
64 - Linux: is meant to look good in a terminal like the Linux console (black
64 - Linux: is meant to look good in a terminal like the Linux console (black
65 or very dark background).
65 or very dark background).
66
66
67 - LightBG: similar to Linux but swaps dark/light colors to be more readable
67 - LightBG: similar to Linux but swaps dark/light colors to be more readable
68 in light background terminals.
68 in light background terminals.
69
69
70 - Neutral: a neutral color scheme that should be readable on both light and
70 - Neutral: a neutral color scheme that should be readable on both light and
71 dark background
71 dark background
72
72
73 You can implement other color schemes easily, the syntax is fairly
73 You can implement other color schemes easily, the syntax is fairly
74 self-explanatory. Please send back new schemes you develop to the author for
74 self-explanatory. Please send back new schemes you develop to the author for
75 possible inclusion in future releases.
75 possible inclusion in future releases.
76
76
77 Inheritance diagram:
77 Inheritance diagram:
78
78
79 .. inheritance-diagram:: IPython.core.ultratb
79 .. inheritance-diagram:: IPython.core.ultratb
80 :parts: 3
80 :parts: 3
81 """
81 """
82
82
83 #*****************************************************************************
83 #*****************************************************************************
84 # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu>
84 # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu>
85 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
85 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
86 #
86 #
87 # Distributed under the terms of the BSD License. The full license is in
87 # Distributed under the terms of the BSD License. The full license is in
88 # the file COPYING, distributed as part of this software.
88 # the file COPYING, distributed as part of this software.
89 #*****************************************************************************
89 #*****************************************************************************
90
90
91
91
92 import dis
92 import dis
93 import inspect
93 import inspect
94 import keyword
94 import keyword
95 import linecache
95 import linecache
96 import os
96 import os
97 import pydoc
97 import pydoc
98 import re
98 import re
99 import sys
99 import sys
100 import time
100 import time
101 import tokenize
101 import tokenize
102 import traceback
102 import traceback
103 import types
103 import types
104
104
105 try: # Python 2
105 try: # Python 2
106 generate_tokens = tokenize.generate_tokens
106 generate_tokens = tokenize.generate_tokens
107 except AttributeError: # Python 3
107 except AttributeError: # Python 3
108 generate_tokens = tokenize.tokenize
108 generate_tokens = tokenize.tokenize
109
109
110 # For purposes of monkeypatching inspect to fix a bug in it.
110 # For purposes of monkeypatching inspect to fix a bug in it.
111 from inspect import getsourcefile, getfile, getmodule, \
111 from inspect import getsourcefile, getfile, getmodule, \
112 ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode
112 ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode
113
113
114 # IPython's own modules
114 # IPython's own modules
115 from IPython import get_ipython
115 from IPython import get_ipython
116 from IPython.core import debugger
116 from IPython.core import debugger
117 from IPython.core.display_trap import DisplayTrap
117 from IPython.core.display_trap import DisplayTrap
118 from IPython.core.excolors import exception_colors
118 from IPython.core.excolors import exception_colors
119 from IPython.utils import PyColorize
119 from IPython.utils import PyColorize
120 from IPython.utils import openpy
120 from IPython.utils import openpy
121 from IPython.utils import path as util_path
121 from IPython.utils import path as util_path
122 from IPython.utils import py3compat
122 from IPython.utils import py3compat
123 from IPython.utils.data import uniq_stable
123 from IPython.utils.data import uniq_stable
124 from IPython.utils.terminal import get_terminal_size
124 from IPython.utils.terminal import get_terminal_size
125 from logging import info, error
125 from logging import info, error
126
126
127 import IPython.utils.colorable as colorable
127 import IPython.utils.colorable as colorable
128
128
129 # Globals
129 # Globals
130 # amount of space to put line numbers before verbose tracebacks
130 # amount of space to put line numbers before verbose tracebacks
131 INDENT_SIZE = 8
131 INDENT_SIZE = 8
132
132
133 # Default color scheme. This is used, for example, by the traceback
133 # Default color scheme. This is used, for example, by the traceback
134 # formatter. When running in an actual IPython instance, the user's rc.colors
134 # formatter. When running in an actual IPython instance, the user's rc.colors
135 # value is used, but having a module global makes this functionality available
135 # value is used, but having a module global makes this functionality available
136 # to users of ultratb who are NOT running inside ipython.
136 # to users of ultratb who are NOT running inside ipython.
137 DEFAULT_SCHEME = 'NoColor'
137 DEFAULT_SCHEME = 'NoColor'
138
138
139 # ---------------------------------------------------------------------------
139 # ---------------------------------------------------------------------------
140 # Code begins
140 # Code begins
141
141
142 # Utility functions
142 # Utility functions
143 def inspect_error():
143 def inspect_error():
144 """Print a message about internal inspect errors.
144 """Print a message about internal inspect errors.
145
145
146 These are unfortunately quite common."""
146 These are unfortunately quite common."""
147
147
148 error('Internal Python error in the inspect module.\n'
148 error('Internal Python error in the inspect module.\n'
149 'Below is the traceback from this internal error.\n')
149 'Below is the traceback from this internal error.\n')
150
150
151
151
152 # This function is a monkeypatch we apply to the Python inspect module. We have
152 # This function is a monkeypatch we apply to the Python inspect module. We have
153 # now found when it's needed (see discussion on issue gh-1456), and we have a
153 # now found when it's needed (see discussion on issue gh-1456), and we have a
154 # test case (IPython.core.tests.test_ultratb.ChangedPyFileTest) that fails if
154 # test case (IPython.core.tests.test_ultratb.ChangedPyFileTest) that fails if
155 # the monkeypatch is not applied. TK, Aug 2012.
155 # the monkeypatch is not applied. TK, Aug 2012.
156 def findsource(object):
156 def findsource(object):
157 """Return the entire source file and starting line number for an object.
157 """Return the entire source file and starting line number for an object.
158
158
159 The argument may be a module, class, method, function, traceback, frame,
159 The argument may be a module, class, method, function, traceback, frame,
160 or code object. The source code is returned as a list of all the lines
160 or code object. The source code is returned as a list of all the lines
161 in the file and the line number indexes a line in that list. An IOError
161 in the file and the line number indexes a line in that list. An IOError
162 is raised if the source code cannot be retrieved.
162 is raised if the source code cannot be retrieved.
163
163
164 FIXED version with which we monkeypatch the stdlib to work around a bug."""
164 FIXED version with which we monkeypatch the stdlib to work around a bug."""
165
165
166 file = getsourcefile(object) or getfile(object)
166 file = getsourcefile(object) or getfile(object)
167 # If the object is a frame, then trying to get the globals dict from its
167 # If the object is a frame, then trying to get the globals dict from its
168 # module won't work. Instead, the frame object itself has the globals
168 # module won't work. Instead, the frame object itself has the globals
169 # dictionary.
169 # dictionary.
170 globals_dict = None
170 globals_dict = None
171 if inspect.isframe(object):
171 if inspect.isframe(object):
172 # XXX: can this ever be false?
172 # XXX: can this ever be false?
173 globals_dict = object.f_globals
173 globals_dict = object.f_globals
174 else:
174 else:
175 module = getmodule(object, file)
175 module = getmodule(object, file)
176 if module:
176 if module:
177 globals_dict = module.__dict__
177 globals_dict = module.__dict__
178 lines = linecache.getlines(file, globals_dict)
178 lines = linecache.getlines(file, globals_dict)
179 if not lines:
179 if not lines:
180 raise IOError('could not get source code')
180 raise IOError('could not get source code')
181
181
182 if ismodule(object):
182 if ismodule(object):
183 return lines, 0
183 return lines, 0
184
184
185 if isclass(object):
185 if isclass(object):
186 name = object.__name__
186 name = object.__name__
187 pat = re.compile(r'^(\s*)class\s*' + name + r'\b')
187 pat = re.compile(r'^(\s*)class\s*' + name + r'\b')
188 # make some effort to find the best matching class definition:
188 # make some effort to find the best matching class definition:
189 # use the one with the least indentation, which is the one
189 # use the one with the least indentation, which is the one
190 # that's most probably not inside a function definition.
190 # that's most probably not inside a function definition.
191 candidates = []
191 candidates = []
192 for i, line in enumerate(lines):
192 for i, line in enumerate(lines):
193 match = pat.match(line)
193 match = pat.match(line)
194 if match:
194 if match:
195 # if it's at toplevel, it's already the best one
195 # if it's at toplevel, it's already the best one
196 if line[0] == 'c':
196 if line[0] == 'c':
197 return lines, i
197 return lines, i
198 # else add whitespace to candidate list
198 # else add whitespace to candidate list
199 candidates.append((match.group(1), i))
199 candidates.append((match.group(1), i))
200 if candidates:
200 if candidates:
201 # this will sort by whitespace, and by line number,
201 # this will sort by whitespace, and by line number,
202 # less whitespace first
202 # less whitespace first
203 candidates.sort()
203 candidates.sort()
204 return lines, candidates[0][1]
204 return lines, candidates[0][1]
205 else:
205 else:
206 raise IOError('could not find class definition')
206 raise IOError('could not find class definition')
207
207
208 if ismethod(object):
208 if ismethod(object):
209 object = object.__func__
209 object = object.__func__
210 if isfunction(object):
210 if isfunction(object):
211 object = object.__code__
211 object = object.__code__
212 if istraceback(object):
212 if istraceback(object):
213 object = object.tb_frame
213 object = object.tb_frame
214 if isframe(object):
214 if isframe(object):
215 object = object.f_code
215 object = object.f_code
216 if iscode(object):
216 if iscode(object):
217 if not hasattr(object, 'co_firstlineno'):
217 if not hasattr(object, 'co_firstlineno'):
218 raise IOError('could not find function definition')
218 raise IOError('could not find function definition')
219 pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)')
219 pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)')
220 pmatch = pat.match
220 pmatch = pat.match
221 # fperez - fix: sometimes, co_firstlineno can give a number larger than
221 # fperez - fix: sometimes, co_firstlineno can give a number larger than
222 # the length of lines, which causes an error. Safeguard against that.
222 # the length of lines, which causes an error. Safeguard against that.
223 lnum = min(object.co_firstlineno, len(lines)) - 1
223 lnum = min(object.co_firstlineno, len(lines)) - 1
224 while lnum > 0:
224 while lnum > 0:
225 if pmatch(lines[lnum]):
225 if pmatch(lines[lnum]):
226 break
226 break
227 lnum -= 1
227 lnum -= 1
228
228
229 return lines, lnum
229 return lines, lnum
230 raise IOError('could not find code object')
230 raise IOError('could not find code object')
231
231
232
232
233 # This is a patched version of inspect.getargs that applies the (unmerged)
233 # This is a patched version of inspect.getargs that applies the (unmerged)
234 # patch for http://bugs.python.org/issue14611 by Stefano Taschini. This fixes
234 # patch for http://bugs.python.org/issue14611 by Stefano Taschini. This fixes
235 # https://github.com/ipython/ipython/issues/8205 and
235 # https://github.com/ipython/ipython/issues/8205 and
236 # https://github.com/ipython/ipython/issues/8293
236 # https://github.com/ipython/ipython/issues/8293
237 def getargs(co):
237 def getargs(co):
238 """Get information about the arguments accepted by a code object.
238 """Get information about the arguments accepted by a code object.
239
239
240 Three things are returned: (args, varargs, varkw), where 'args' is
240 Three things are returned: (args, varargs, varkw), where 'args' is
241 a list of argument names (possibly containing nested lists), and
241 a list of argument names (possibly containing nested lists), and
242 'varargs' and 'varkw' are the names of the * and ** arguments or None."""
242 'varargs' and 'varkw' are the names of the * and ** arguments or None."""
243 if not iscode(co):
243 if not iscode(co):
244 raise TypeError('{!r} is not a code object'.format(co))
244 raise TypeError('{!r} is not a code object'.format(co))
245
245
246 nargs = co.co_argcount
246 nargs = co.co_argcount
247 names = co.co_varnames
247 names = co.co_varnames
248 args = list(names[:nargs])
248 args = list(names[:nargs])
249 step = 0
249 step = 0
250
250
251 # The following acrobatics are for anonymous (tuple) arguments.
251 # The following acrobatics are for anonymous (tuple) arguments.
252 for i in range(nargs):
252 for i in range(nargs):
253 if args[i][:1] in ('', '.'):
253 if args[i][:1] in ('', '.'):
254 stack, remain, count = [], [], []
254 stack, remain, count = [], [], []
255 while step < len(co.co_code):
255 while step < len(co.co_code):
256 op = ord(co.co_code[step])
256 op = ord(co.co_code[step])
257 step = step + 1
257 step = step + 1
258 if op >= dis.HAVE_ARGUMENT:
258 if op >= dis.HAVE_ARGUMENT:
259 opname = dis.opname[op]
259 opname = dis.opname[op]
260 value = ord(co.co_code[step]) + ord(co.co_code[step+1])*256
260 value = ord(co.co_code[step]) + ord(co.co_code[step+1])*256
261 step = step + 2
261 step = step + 2
262 if opname in ('UNPACK_TUPLE', 'UNPACK_SEQUENCE'):
262 if opname in ('UNPACK_TUPLE', 'UNPACK_SEQUENCE'):
263 remain.append(value)
263 remain.append(value)
264 count.append(value)
264 count.append(value)
265 elif opname in ('STORE_FAST', 'STORE_DEREF'):
265 elif opname in ('STORE_FAST', 'STORE_DEREF'):
266 if op in dis.haslocal:
266 if op in dis.haslocal:
267 stack.append(co.co_varnames[value])
267 stack.append(co.co_varnames[value])
268 elif op in dis.hasfree:
268 elif op in dis.hasfree:
269 stack.append((co.co_cellvars + co.co_freevars)[value])
269 stack.append((co.co_cellvars + co.co_freevars)[value])
270 # Special case for sublists of length 1: def foo((bar))
270 # Special case for sublists of length 1: def foo((bar))
271 # doesn't generate the UNPACK_TUPLE bytecode, so if
271 # doesn't generate the UNPACK_TUPLE bytecode, so if
272 # `remain` is empty here, we have such a sublist.
272 # `remain` is empty here, we have such a sublist.
273 if not remain:
273 if not remain:
274 stack[0] = [stack[0]]
274 stack[0] = [stack[0]]
275 break
275 break
276 else:
276 else:
277 remain[-1] = remain[-1] - 1
277 remain[-1] = remain[-1] - 1
278 while remain[-1] == 0:
278 while remain[-1] == 0:
279 remain.pop()
279 remain.pop()
280 size = count.pop()
280 size = count.pop()
281 stack[-size:] = [stack[-size:]]
281 stack[-size:] = [stack[-size:]]
282 if not remain:
282 if not remain:
283 break
283 break
284 remain[-1] = remain[-1] - 1
284 remain[-1] = remain[-1] - 1
285 if not remain:
285 if not remain:
286 break
286 break
287 args[i] = stack[0]
287 args[i] = stack[0]
288
288
289 varargs = None
289 varargs = None
290 if co.co_flags & inspect.CO_VARARGS:
290 if co.co_flags & inspect.CO_VARARGS:
291 varargs = co.co_varnames[nargs]
291 varargs = co.co_varnames[nargs]
292 nargs = nargs + 1
292 nargs = nargs + 1
293 varkw = None
293 varkw = None
294 if co.co_flags & inspect.CO_VARKEYWORDS:
294 if co.co_flags & inspect.CO_VARKEYWORDS:
295 varkw = co.co_varnames[nargs]
295 varkw = co.co_varnames[nargs]
296 return inspect.Arguments(args, varargs, varkw)
296 return inspect.Arguments(args, varargs, varkw)
297
297
298
298
299 # Monkeypatch inspect to apply our bugfix.
299 # Monkeypatch inspect to apply our bugfix.
300 def with_patch_inspect(f):
300 def with_patch_inspect(f):
301 """
301 """
302 Deprecated since IPython 6.0
302 Deprecated since IPython 6.0
303 decorator for monkeypatching inspect.findsource
303 decorator for monkeypatching inspect.findsource
304 """
304 """
305
305
306 def wrapped(*args, **kwargs):
306 def wrapped(*args, **kwargs):
307 save_findsource = inspect.findsource
307 save_findsource = inspect.findsource
308 save_getargs = inspect.getargs
308 save_getargs = inspect.getargs
309 inspect.findsource = findsource
309 inspect.findsource = findsource
310 inspect.getargs = getargs
310 inspect.getargs = getargs
311 try:
311 try:
312 return f(*args, **kwargs)
312 return f(*args, **kwargs)
313 finally:
313 finally:
314 inspect.findsource = save_findsource
314 inspect.findsource = save_findsource
315 inspect.getargs = save_getargs
315 inspect.getargs = save_getargs
316
316
317 return wrapped
317 return wrapped
318
318
319
319
320 def fix_frame_records_filenames(records):
320 def fix_frame_records_filenames(records):
321 """Try to fix the filenames in each record from inspect.getinnerframes().
321 """Try to fix the filenames in each record from inspect.getinnerframes().
322
322
323 Particularly, modules loaded from within zip files have useless filenames
323 Particularly, modules loaded from within zip files have useless filenames
324 attached to their code object, and inspect.getinnerframes() just uses it.
324 attached to their code object, and inspect.getinnerframes() just uses it.
325 """
325 """
326 fixed_records = []
326 fixed_records = []
327 for frame, filename, line_no, func_name, lines, index in records:
327 for frame, filename, line_no, func_name, lines, index in records:
328 # Look inside the frame's globals dictionary for __file__,
328 # Look inside the frame's globals dictionary for __file__,
329 # which should be better. However, keep Cython filenames since
329 # which should be better. However, keep Cython filenames since
330 # we prefer the source filenames over the compiled .so file.
330 # we prefer the source filenames over the compiled .so file.
331 filename = py3compat.cast_unicode_py2(filename, "utf-8")
332 if not filename.endswith(('.pyx', '.pxd', '.pxi')):
331 if not filename.endswith(('.pyx', '.pxd', '.pxi')):
333 better_fn = frame.f_globals.get('__file__', None)
332 better_fn = frame.f_globals.get('__file__', None)
334 if isinstance(better_fn, str):
333 if isinstance(better_fn, str):
335 # Check the type just in case someone did something weird with
334 # Check the type just in case someone did something weird with
336 # __file__. It might also be None if the error occurred during
335 # __file__. It might also be None if the error occurred during
337 # import.
336 # import.
338 filename = better_fn
337 filename = better_fn
339 fixed_records.append((frame, filename, line_no, func_name, lines, index))
338 fixed_records.append((frame, filename, line_no, func_name, lines, index))
340 return fixed_records
339 return fixed_records
341
340
342
341
343 @with_patch_inspect
342 @with_patch_inspect
344 def _fixed_getinnerframes(etb, context=1, tb_offset=0):
343 def _fixed_getinnerframes(etb, context=1, tb_offset=0):
345 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
344 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
346
345
347 records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))
346 records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))
348 # If the error is at the console, don't build any context, since it would
347 # If the error is at the console, don't build any context, since it would
349 # otherwise produce 5 blank lines printed out (there is no file at the
348 # otherwise produce 5 blank lines printed out (there is no file at the
350 # console)
349 # console)
351 rec_check = records[tb_offset:]
350 rec_check = records[tb_offset:]
352 try:
351 try:
353 rname = rec_check[0][1]
352 rname = rec_check[0][1]
354 if rname == '<ipython console>' or rname.endswith('<string>'):
353 if rname == '<ipython console>' or rname.endswith('<string>'):
355 return rec_check
354 return rec_check
356 except IndexError:
355 except IndexError:
357 pass
356 pass
358
357
359 aux = traceback.extract_tb(etb)
358 aux = traceback.extract_tb(etb)
360 assert len(records) == len(aux)
359 assert len(records) == len(aux)
361 for i, (file, lnum, _, _) in enumerate(aux):
360 for i, (file, lnum, _, _) in enumerate(aux):
362 maybeStart = lnum - 1 - context // 2
361 maybeStart = lnum - 1 - context // 2
363 start = max(maybeStart, 0)
362 start = max(maybeStart, 0)
364 end = start + context
363 end = start + context
365 lines = linecache.getlines(file)[start:end]
364 lines = linecache.getlines(file)[start:end]
366 buf = list(records[i])
365 buf = list(records[i])
367 buf[LNUM_POS] = lnum
366 buf[LNUM_POS] = lnum
368 buf[INDEX_POS] = lnum - 1 - start
367 buf[INDEX_POS] = lnum - 1 - start
369 buf[LINES_POS] = lines
368 buf[LINES_POS] = lines
370 records[i] = tuple(buf)
369 records[i] = tuple(buf)
371 return records[tb_offset:]
370 return records[tb_offset:]
372
371
373 # Helper function -- largely belongs to VerboseTB, but we need the same
372 # Helper function -- largely belongs to VerboseTB, but we need the same
374 # functionality to produce a pseudo verbose TB for SyntaxErrors, so that they
373 # functionality to produce a pseudo verbose TB for SyntaxErrors, so that they
375 # can be recognized properly by ipython.el's py-traceback-line-re
374 # can be recognized properly by ipython.el's py-traceback-line-re
376 # (SyntaxErrors have to be treated specially because they have no traceback)
375 # (SyntaxErrors have to be treated specially because they have no traceback)
377
376
378
377
379 def _format_traceback_lines(lnum, index, lines, Colors, lvals=None, _line_format=(lambda x,_:x,None)):
378 def _format_traceback_lines(lnum, index, lines, Colors, lvals=None, _line_format=(lambda x,_:x,None)):
380 numbers_width = INDENT_SIZE - 1
379 numbers_width = INDENT_SIZE - 1
381 res = []
380 res = []
382 i = lnum - index
381 i = lnum - index
383
382
384 for line in lines:
383 for line in lines:
385 line = py3compat.cast_unicode(line)
386
387 new_line, err = _line_format(line, 'str')
384 new_line, err = _line_format(line, 'str')
388 if not err: line = new_line
385 if not err: line = new_line
389
386
390 if i == lnum:
387 if i == lnum:
391 # This is the line with the error
388 # This is the line with the error
392 pad = numbers_width - len(str(i))
389 pad = numbers_width - len(str(i))
393 num = '%s%s' % (debugger.make_arrow(pad), str(lnum))
390 num = '%s%s' % (debugger.make_arrow(pad), str(lnum))
394 line = '%s%s%s %s%s' % (Colors.linenoEm, num,
391 line = '%s%s%s %s%s' % (Colors.linenoEm, num,
395 Colors.line, line, Colors.Normal)
392 Colors.line, line, Colors.Normal)
396 else:
393 else:
397 num = '%*s' % (numbers_width, i)
394 num = '%*s' % (numbers_width, i)
398 line = '%s%s%s %s' % (Colors.lineno, num,
395 line = '%s%s%s %s' % (Colors.lineno, num,
399 Colors.Normal, line)
396 Colors.Normal, line)
400
397
401 res.append(line)
398 res.append(line)
402 if lvals and i == lnum:
399 if lvals and i == lnum:
403 res.append(lvals + '\n')
400 res.append(lvals + '\n')
404 i = i + 1
401 i = i + 1
405 return res
402 return res
406
403
407 def is_recursion_error(etype, value, records):
404 def is_recursion_error(etype, value, records):
408 try:
405 try:
409 # RecursionError is new in Python 3.5
406 # RecursionError is new in Python 3.5
410 recursion_error_type = RecursionError
407 recursion_error_type = RecursionError
411 except NameError:
408 except NameError:
412 recursion_error_type = RuntimeError
409 recursion_error_type = RuntimeError
413
410
414 # The default recursion limit is 1000, but some of that will be taken up
411 # The default recursion limit is 1000, but some of that will be taken up
415 # by stack frames in IPython itself. >500 frames probably indicates
412 # by stack frames in IPython itself. >500 frames probably indicates
416 # a recursion error.
413 # a recursion error.
417 return (etype is recursion_error_type) \
414 return (etype is recursion_error_type) \
418 and "recursion" in str(value).lower() \
415 and "recursion" in str(value).lower() \
419 and len(records) > 500
416 and len(records) > 500
420
417
421 def find_recursion(etype, value, records):
418 def find_recursion(etype, value, records):
422 """Identify the repeating stack frames from a RecursionError traceback
419 """Identify the repeating stack frames from a RecursionError traceback
423
420
424 'records' is a list as returned by VerboseTB.get_records()
421 'records' is a list as returned by VerboseTB.get_records()
425
422
426 Returns (last_unique, repeat_length)
423 Returns (last_unique, repeat_length)
427 """
424 """
428 # This involves a bit of guesswork - we want to show enough of the traceback
425 # This involves a bit of guesswork - we want to show enough of the traceback
429 # to indicate where the recursion is occurring. We guess that the innermost
426 # to indicate where the recursion is occurring. We guess that the innermost
430 # quarter of the traceback (250 frames by default) is repeats, and find the
427 # quarter of the traceback (250 frames by default) is repeats, and find the
431 # first frame (from in to out) that looks different.
428 # first frame (from in to out) that looks different.
432 if not is_recursion_error(etype, value, records):
429 if not is_recursion_error(etype, value, records):
433 return len(records), 0
430 return len(records), 0
434
431
435 # Select filename, lineno, func_name to track frames with
432 # Select filename, lineno, func_name to track frames with
436 records = [r[1:4] for r in records]
433 records = [r[1:4] for r in records]
437 inner_frames = records[-(len(records)//4):]
434 inner_frames = records[-(len(records)//4):]
438 frames_repeated = set(inner_frames)
435 frames_repeated = set(inner_frames)
439
436
440 last_seen_at = {}
437 last_seen_at = {}
441 longest_repeat = 0
438 longest_repeat = 0
442 i = len(records)
439 i = len(records)
443 for frame in reversed(records):
440 for frame in reversed(records):
444 i -= 1
441 i -= 1
445 if frame not in frames_repeated:
442 if frame not in frames_repeated:
446 last_unique = i
443 last_unique = i
447 break
444 break
448
445
449 if frame in last_seen_at:
446 if frame in last_seen_at:
450 distance = last_seen_at[frame] - i
447 distance = last_seen_at[frame] - i
451 longest_repeat = max(longest_repeat, distance)
448 longest_repeat = max(longest_repeat, distance)
452
449
453 last_seen_at[frame] = i
450 last_seen_at[frame] = i
454 else:
451 else:
455 last_unique = 0 # The whole traceback was recursion
452 last_unique = 0 # The whole traceback was recursion
456
453
457 return last_unique, longest_repeat
454 return last_unique, longest_repeat
458
455
459 #---------------------------------------------------------------------------
456 #---------------------------------------------------------------------------
460 # Module classes
457 # Module classes
461 class TBTools(colorable.Colorable):
458 class TBTools(colorable.Colorable):
462 """Basic tools used by all traceback printer classes."""
459 """Basic tools used by all traceback printer classes."""
463
460
464 # Number of frames to skip when reporting tracebacks
461 # Number of frames to skip when reporting tracebacks
465 tb_offset = 0
462 tb_offset = 0
466
463
467 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None, parent=None, config=None):
464 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None, parent=None, config=None):
468 # Whether to call the interactive pdb debugger after printing
465 # Whether to call the interactive pdb debugger after printing
469 # tracebacks or not
466 # tracebacks or not
470 super(TBTools, self).__init__(parent=parent, config=config)
467 super(TBTools, self).__init__(parent=parent, config=config)
471 self.call_pdb = call_pdb
468 self.call_pdb = call_pdb
472
469
473 # Output stream to write to. Note that we store the original value in
470 # Output stream to write to. Note that we store the original value in
474 # a private attribute and then make the public ostream a property, so
471 # a private attribute and then make the public ostream a property, so
475 # that we can delay accessing sys.stdout until runtime. The way
472 # that we can delay accessing sys.stdout until runtime. The way
476 # things are written now, the sys.stdout object is dynamically managed
473 # things are written now, the sys.stdout object is dynamically managed
477 # so a reference to it should NEVER be stored statically. This
474 # so a reference to it should NEVER be stored statically. This
478 # property approach confines this detail to a single location, and all
475 # property approach confines this detail to a single location, and all
479 # subclasses can simply access self.ostream for writing.
476 # subclasses can simply access self.ostream for writing.
480 self._ostream = ostream
477 self._ostream = ostream
481
478
482 # Create color table
479 # Create color table
483 self.color_scheme_table = exception_colors()
480 self.color_scheme_table = exception_colors()
484
481
485 self.set_colors(color_scheme)
482 self.set_colors(color_scheme)
486 self.old_scheme = color_scheme # save initial value for toggles
483 self.old_scheme = color_scheme # save initial value for toggles
487
484
488 if call_pdb:
485 if call_pdb:
489 self.pdb = debugger.Pdb()
486 self.pdb = debugger.Pdb()
490 else:
487 else:
491 self.pdb = None
488 self.pdb = None
492
489
493 def _get_ostream(self):
490 def _get_ostream(self):
494 """Output stream that exceptions are written to.
491 """Output stream that exceptions are written to.
495
492
496 Valid values are:
493 Valid values are:
497
494
498 - None: the default, which means that IPython will dynamically resolve
495 - None: the default, which means that IPython will dynamically resolve
499 to sys.stdout. This ensures compatibility with most tools, including
496 to sys.stdout. This ensures compatibility with most tools, including
500 Windows (where plain stdout doesn't recognize ANSI escapes).
497 Windows (where plain stdout doesn't recognize ANSI escapes).
501
498
502 - Any object with 'write' and 'flush' attributes.
499 - Any object with 'write' and 'flush' attributes.
503 """
500 """
504 return sys.stdout if self._ostream is None else self._ostream
501 return sys.stdout if self._ostream is None else self._ostream
505
502
506 def _set_ostream(self, val):
503 def _set_ostream(self, val):
507 assert val is None or (hasattr(val, 'write') and hasattr(val, 'flush'))
504 assert val is None or (hasattr(val, 'write') and hasattr(val, 'flush'))
508 self._ostream = val
505 self._ostream = val
509
506
510 ostream = property(_get_ostream, _set_ostream)
507 ostream = property(_get_ostream, _set_ostream)
511
508
512 def set_colors(self, *args, **kw):
509 def set_colors(self, *args, **kw):
513 """Shorthand access to the color table scheme selector method."""
510 """Shorthand access to the color table scheme selector method."""
514
511
515 # Set own color table
512 # Set own color table
516 self.color_scheme_table.set_active_scheme(*args, **kw)
513 self.color_scheme_table.set_active_scheme(*args, **kw)
517 # for convenience, set Colors to the active scheme
514 # for convenience, set Colors to the active scheme
518 self.Colors = self.color_scheme_table.active_colors
515 self.Colors = self.color_scheme_table.active_colors
519 # Also set colors of debugger
516 # Also set colors of debugger
520 if hasattr(self, 'pdb') and self.pdb is not None:
517 if hasattr(self, 'pdb') and self.pdb is not None:
521 self.pdb.set_colors(*args, **kw)
518 self.pdb.set_colors(*args, **kw)
522
519
523 def color_toggle(self):
520 def color_toggle(self):
524 """Toggle between the currently active color scheme and NoColor."""
521 """Toggle between the currently active color scheme and NoColor."""
525
522
526 if self.color_scheme_table.active_scheme_name == 'NoColor':
523 if self.color_scheme_table.active_scheme_name == 'NoColor':
527 self.color_scheme_table.set_active_scheme(self.old_scheme)
524 self.color_scheme_table.set_active_scheme(self.old_scheme)
528 self.Colors = self.color_scheme_table.active_colors
525 self.Colors = self.color_scheme_table.active_colors
529 else:
526 else:
530 self.old_scheme = self.color_scheme_table.active_scheme_name
527 self.old_scheme = self.color_scheme_table.active_scheme_name
531 self.color_scheme_table.set_active_scheme('NoColor')
528 self.color_scheme_table.set_active_scheme('NoColor')
532 self.Colors = self.color_scheme_table.active_colors
529 self.Colors = self.color_scheme_table.active_colors
533
530
534 def stb2text(self, stb):
531 def stb2text(self, stb):
535 """Convert a structured traceback (a list) to a string."""
532 """Convert a structured traceback (a list) to a string."""
536 return '\n'.join(stb)
533 return '\n'.join(stb)
537
534
538 def text(self, etype, value, tb, tb_offset=None, context=5):
535 def text(self, etype, value, tb, tb_offset=None, context=5):
539 """Return formatted traceback.
536 """Return formatted traceback.
540
537
541 Subclasses may override this if they add extra arguments.
538 Subclasses may override this if they add extra arguments.
542 """
539 """
543 tb_list = self.structured_traceback(etype, value, tb,
540 tb_list = self.structured_traceback(etype, value, tb,
544 tb_offset, context)
541 tb_offset, context)
545 return self.stb2text(tb_list)
542 return self.stb2text(tb_list)
546
543
547 def structured_traceback(self, etype, evalue, tb, tb_offset=None,
544 def structured_traceback(self, etype, evalue, tb, tb_offset=None,
548 context=5, mode=None):
545 context=5, mode=None):
549 """Return a list of traceback frames.
546 """Return a list of traceback frames.
550
547
551 Must be implemented by each class.
548 Must be implemented by each class.
552 """
549 """
553 raise NotImplementedError()
550 raise NotImplementedError()
554
551
555
552
556 #---------------------------------------------------------------------------
553 #---------------------------------------------------------------------------
557 class ListTB(TBTools):
554 class ListTB(TBTools):
558 """Print traceback information from a traceback list, with optional color.
555 """Print traceback information from a traceback list, with optional color.
559
556
560 Calling requires 3 arguments: (etype, evalue, elist)
557 Calling requires 3 arguments: (etype, evalue, elist)
561 as would be obtained by::
558 as would be obtained by::
562
559
563 etype, evalue, tb = sys.exc_info()
560 etype, evalue, tb = sys.exc_info()
564 if tb:
561 if tb:
565 elist = traceback.extract_tb(tb)
562 elist = traceback.extract_tb(tb)
566 else:
563 else:
567 elist = None
564 elist = None
568
565
569 It can thus be used by programs which need to process the traceback before
566 It can thus be used by programs which need to process the traceback before
570 printing (such as console replacements based on the code module from the
567 printing (such as console replacements based on the code module from the
571 standard library).
568 standard library).
572
569
573 Because they are meant to be called without a full traceback (only a
570 Because they are meant to be called without a full traceback (only a
574 list), instances of this class can't call the interactive pdb debugger."""
571 list), instances of this class can't call the interactive pdb debugger."""
575
572
576 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None, parent=None, config=None):
573 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None, parent=None, config=None):
577 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
574 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
578 ostream=ostream, parent=parent,config=config)
575 ostream=ostream, parent=parent,config=config)
579
576
580 def __call__(self, etype, value, elist):
577 def __call__(self, etype, value, elist):
581 self.ostream.flush()
578 self.ostream.flush()
582 self.ostream.write(self.text(etype, value, elist))
579 self.ostream.write(self.text(etype, value, elist))
583 self.ostream.write('\n')
580 self.ostream.write('\n')
584
581
585 def structured_traceback(self, etype, value, elist, tb_offset=None,
582 def structured_traceback(self, etype, value, elist, tb_offset=None,
586 context=5):
583 context=5):
587 """Return a color formatted string with the traceback info.
584 """Return a color formatted string with the traceback info.
588
585
589 Parameters
586 Parameters
590 ----------
587 ----------
591 etype : exception type
588 etype : exception type
592 Type of the exception raised.
589 Type of the exception raised.
593
590
594 value : object
591 value : object
595 Data stored in the exception
592 Data stored in the exception
596
593
597 elist : list
594 elist : list
598 List of frames, see class docstring for details.
595 List of frames, see class docstring for details.
599
596
600 tb_offset : int, optional
597 tb_offset : int, optional
601 Number of frames in the traceback to skip. If not given, the
598 Number of frames in the traceback to skip. If not given, the
602 instance value is used (set in constructor).
599 instance value is used (set in constructor).
603
600
604 context : int, optional
601 context : int, optional
605 Number of lines of context information to print.
602 Number of lines of context information to print.
606
603
607 Returns
604 Returns
608 -------
605 -------
609 String with formatted exception.
606 String with formatted exception.
610 """
607 """
611 tb_offset = self.tb_offset if tb_offset is None else tb_offset
608 tb_offset = self.tb_offset if tb_offset is None else tb_offset
612 Colors = self.Colors
609 Colors = self.Colors
613 out_list = []
610 out_list = []
614 if elist:
611 if elist:
615
612
616 if tb_offset and len(elist) > tb_offset:
613 if tb_offset and len(elist) > tb_offset:
617 elist = elist[tb_offset:]
614 elist = elist[tb_offset:]
618
615
619 out_list.append('Traceback %s(most recent call last)%s:' %
616 out_list.append('Traceback %s(most recent call last)%s:' %
620 (Colors.normalEm, Colors.Normal) + '\n')
617 (Colors.normalEm, Colors.Normal) + '\n')
621 out_list.extend(self._format_list(elist))
618 out_list.extend(self._format_list(elist))
622 # The exception info should be a single entry in the list.
619 # The exception info should be a single entry in the list.
623 lines = ''.join(self._format_exception_only(etype, value))
620 lines = ''.join(self._format_exception_only(etype, value))
624 out_list.append(lines)
621 out_list.append(lines)
625
622
626 # Note: this code originally read:
623 # Note: this code originally read:
627
624
628 ## for line in lines[:-1]:
625 ## for line in lines[:-1]:
629 ## out_list.append(" "+line)
626 ## out_list.append(" "+line)
630 ## out_list.append(lines[-1])
627 ## out_list.append(lines[-1])
631
628
632 # This means it was indenting everything but the last line by a little
629 # This means it was indenting everything but the last line by a little
633 # bit. I've disabled this for now, but if we see ugliness somewhere we
630 # bit. I've disabled this for now, but if we see ugliness somewhere we
634 # can restore it.
631 # can restore it.
635
632
636 return out_list
633 return out_list
637
634
638 def _format_list(self, extracted_list):
635 def _format_list(self, extracted_list):
639 """Format a list of traceback entry tuples for printing.
636 """Format a list of traceback entry tuples for printing.
640
637
641 Given a list of tuples as returned by extract_tb() or
638 Given a list of tuples as returned by extract_tb() or
642 extract_stack(), return a list of strings ready for printing.
639 extract_stack(), return a list of strings ready for printing.
643 Each string in the resulting list corresponds to the item with the
640 Each string in the resulting list corresponds to the item with the
644 same index in the argument list. Each string ends in a newline;
641 same index in the argument list. Each string ends in a newline;
645 the strings may contain internal newlines as well, for those items
642 the strings may contain internal newlines as well, for those items
646 whose source text line is not None.
643 whose source text line is not None.
647
644
648 Lifted almost verbatim from traceback.py
645 Lifted almost verbatim from traceback.py
649 """
646 """
650
647
651 Colors = self.Colors
648 Colors = self.Colors
652 list = []
649 list = []
653 for filename, lineno, name, line in extracted_list[:-1]:
650 for filename, lineno, name, line in extracted_list[:-1]:
654 item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \
651 item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \
655 (Colors.filename, py3compat.cast_unicode_py2(filename, "utf-8"), Colors.Normal,
652 (Colors.filename, filename, Colors.Normal,
656 Colors.lineno, lineno, Colors.Normal,
653 Colors.lineno, lineno, Colors.Normal,
657 Colors.name, py3compat.cast_unicode_py2(name, "utf-8"), Colors.Normal)
654 Colors.name, name, Colors.Normal)
658 if line:
655 if line:
659 item += ' %s\n' % line.strip()
656 item += ' %s\n' % line.strip()
660 list.append(item)
657 list.append(item)
661 # Emphasize the last entry
658 # Emphasize the last entry
662 filename, lineno, name, line = extracted_list[-1]
659 filename, lineno, name, line = extracted_list[-1]
663 item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \
660 item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \
664 (Colors.normalEm,
661 (Colors.normalEm,
665 Colors.filenameEm, py3compat.cast_unicode_py2(filename, "utf-8"), Colors.normalEm,
662 Colors.filenameEm, filename, Colors.normalEm,
666 Colors.linenoEm, lineno, Colors.normalEm,
663 Colors.linenoEm, lineno, Colors.normalEm,
667 Colors.nameEm, py3compat.cast_unicode_py2(name, "utf-8"), Colors.normalEm,
664 Colors.nameEm, name, Colors.normalEm,
668 Colors.Normal)
665 Colors.Normal)
669 if line:
666 if line:
670 item += '%s %s%s\n' % (Colors.line, line.strip(),
667 item += '%s %s%s\n' % (Colors.line, line.strip(),
671 Colors.Normal)
668 Colors.Normal)
672 list.append(item)
669 list.append(item)
673 return list
670 return list
674
671
675 def _format_exception_only(self, etype, value):
672 def _format_exception_only(self, etype, value):
676 """Format the exception part of a traceback.
673 """Format the exception part of a traceback.
677
674
678 The arguments are the exception type and value such as given by
675 The arguments are the exception type and value such as given by
679 sys.exc_info()[:2]. The return value is a list of strings, each ending
676 sys.exc_info()[:2]. The return value is a list of strings, each ending
680 in a newline. Normally, the list contains a single string; however,
677 in a newline. Normally, the list contains a single string; however,
681 for SyntaxError exceptions, it contains several lines that (when
678 for SyntaxError exceptions, it contains several lines that (when
682 printed) display detailed information about where the syntax error
679 printed) display detailed information about where the syntax error
683 occurred. The message indicating which exception occurred is the
680 occurred. The message indicating which exception occurred is the
684 always last string in the list.
681 always last string in the list.
685
682
686 Also lifted nearly verbatim from traceback.py
683 Also lifted nearly verbatim from traceback.py
687 """
684 """
688 have_filedata = False
685 have_filedata = False
689 Colors = self.Colors
686 Colors = self.Colors
690 list = []
687 list = []
691 stype = py3compat.cast_unicode(Colors.excName + etype.__name__ + Colors.Normal)
688 stype = Colors.excName + etype.__name__ + Colors.Normal
692 if value is None:
689 if value is None:
693 # Not sure if this can still happen in Python 2.6 and above
690 # Not sure if this can still happen in Python 2.6 and above
694 list.append(stype + '\n')
691 list.append(stype + '\n')
695 else:
692 else:
696 if issubclass(etype, SyntaxError):
693 if issubclass(etype, SyntaxError):
697 have_filedata = True
694 have_filedata = True
698 if not value.filename: value.filename = "<string>"
695 if not value.filename: value.filename = "<string>"
699 if value.lineno:
696 if value.lineno:
700 lineno = value.lineno
697 lineno = value.lineno
701 textline = linecache.getline(value.filename, value.lineno)
698 textline = linecache.getline(value.filename, value.lineno)
702 else:
699 else:
703 lineno = 'unknown'
700 lineno = 'unknown'
704 textline = ''
701 textline = ''
705 list.append('%s File %s"%s"%s, line %s%s%s\n' % \
702 list.append('%s File %s"%s"%s, line %s%s%s\n' % \
706 (Colors.normalEm,
703 (Colors.normalEm,
707 Colors.filenameEm, py3compat.cast_unicode(value.filename), Colors.normalEm,
704 Colors.filenameEm, value.filename, Colors.normalEm,
708 Colors.linenoEm, lineno, Colors.Normal ))
705 Colors.linenoEm, lineno, Colors.Normal ))
709 if textline == '':
706 if textline == '':
710 textline = py3compat.cast_unicode(value.text, "utf-8")
707 textline = value.text
711
708
712 if textline is not None:
709 if textline is not None:
713 i = 0
710 i = 0
714 while i < len(textline) and textline[i].isspace():
711 while i < len(textline) and textline[i].isspace():
715 i += 1
712 i += 1
716 list.append('%s %s%s\n' % (Colors.line,
713 list.append('%s %s%s\n' % (Colors.line,
717 textline.strip(),
714 textline.strip(),
718 Colors.Normal))
715 Colors.Normal))
719 if value.offset is not None:
716 if value.offset is not None:
720 s = ' '
717 s = ' '
721 for c in textline[i:value.offset - 1]:
718 for c in textline[i:value.offset - 1]:
722 if c.isspace():
719 if c.isspace():
723 s += c
720 s += c
724 else:
721 else:
725 s += ' '
722 s += ' '
726 list.append('%s%s^%s\n' % (Colors.caret, s,
723 list.append('%s%s^%s\n' % (Colors.caret, s,
727 Colors.Normal))
724 Colors.Normal))
728
725
729 try:
726 try:
730 s = value.msg
727 s = value.msg
731 except Exception:
728 except Exception:
732 s = self._some_str(value)
729 s = self._some_str(value)
733 if s:
730 if s:
734 list.append('%s%s:%s %s\n' % (stype, Colors.excName,
731 list.append('%s%s:%s %s\n' % (stype, Colors.excName,
735 Colors.Normal, s))
732 Colors.Normal, s))
736 else:
733 else:
737 list.append('%s\n' % stype)
734 list.append('%s\n' % stype)
738
735
739 # sync with user hooks
736 # sync with user hooks
740 if have_filedata:
737 if have_filedata:
741 ipinst = get_ipython()
738 ipinst = get_ipython()
742 if ipinst is not None:
739 if ipinst is not None:
743 ipinst.hooks.synchronize_with_editor(value.filename, value.lineno, 0)
740 ipinst.hooks.synchronize_with_editor(value.filename, value.lineno, 0)
744
741
745 return list
742 return list
746
743
747 def get_exception_only(self, etype, value):
744 def get_exception_only(self, etype, value):
748 """Only print the exception type and message, without a traceback.
745 """Only print the exception type and message, without a traceback.
749
746
750 Parameters
747 Parameters
751 ----------
748 ----------
752 etype : exception type
749 etype : exception type
753 value : exception value
750 value : exception value
754 """
751 """
755 return ListTB.structured_traceback(self, etype, value, [])
752 return ListTB.structured_traceback(self, etype, value, [])
756
753
757 def show_exception_only(self, etype, evalue):
754 def show_exception_only(self, etype, evalue):
758 """Only print the exception type and message, without a traceback.
755 """Only print the exception type and message, without a traceback.
759
756
760 Parameters
757 Parameters
761 ----------
758 ----------
762 etype : exception type
759 etype : exception type
763 value : exception value
760 value : exception value
764 """
761 """
765 # This method needs to use __call__ from *this* class, not the one from
762 # This method needs to use __call__ from *this* class, not the one from
766 # a subclass whose signature or behavior may be different
763 # a subclass whose signature or behavior may be different
767 ostream = self.ostream
764 ostream = self.ostream
768 ostream.flush()
765 ostream.flush()
769 ostream.write('\n'.join(self.get_exception_only(etype, evalue)))
766 ostream.write('\n'.join(self.get_exception_only(etype, evalue)))
770 ostream.flush()
767 ostream.flush()
771
768
772 def _some_str(self, value):
769 def _some_str(self, value):
773 # Lifted from traceback.py
770 # Lifted from traceback.py
774 try:
771 try:
775 return py3compat.cast_unicode(str(value))
772 return str(value)
776 except:
773 except:
777 return u'<unprintable %s object>' % type(value).__name__
774 return u'<unprintable %s object>' % type(value).__name__
778
775
779
776
780 #----------------------------------------------------------------------------
777 #----------------------------------------------------------------------------
781 class VerboseTB(TBTools):
778 class VerboseTB(TBTools):
782 """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead
779 """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead
783 of HTML. Requires inspect and pydoc. Crazy, man.
780 of HTML. Requires inspect and pydoc. Crazy, man.
784
781
785 Modified version which optionally strips the topmost entries from the
782 Modified version which optionally strips the topmost entries from the
786 traceback, to be used with alternate interpreters (because their own code
783 traceback, to be used with alternate interpreters (because their own code
787 would appear in the traceback)."""
784 would appear in the traceback)."""
788
785
789 def __init__(self, color_scheme='Linux', call_pdb=False, ostream=None,
786 def __init__(self, color_scheme='Linux', call_pdb=False, ostream=None,
790 tb_offset=0, long_header=False, include_vars=True,
787 tb_offset=0, long_header=False, include_vars=True,
791 check_cache=None, debugger_cls = None,
788 check_cache=None, debugger_cls = None,
792 parent=None, config=None):
789 parent=None, config=None):
793 """Specify traceback offset, headers and color scheme.
790 """Specify traceback offset, headers and color scheme.
794
791
795 Define how many frames to drop from the tracebacks. Calling it with
792 Define how many frames to drop from the tracebacks. Calling it with
796 tb_offset=1 allows use of this handler in interpreters which will have
793 tb_offset=1 allows use of this handler in interpreters which will have
797 their own code at the top of the traceback (VerboseTB will first
794 their own code at the top of the traceback (VerboseTB will first
798 remove that frame before printing the traceback info)."""
795 remove that frame before printing the traceback info)."""
799 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
796 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
800 ostream=ostream, parent=parent, config=config)
797 ostream=ostream, parent=parent, config=config)
801 self.tb_offset = tb_offset
798 self.tb_offset = tb_offset
802 self.long_header = long_header
799 self.long_header = long_header
803 self.include_vars = include_vars
800 self.include_vars = include_vars
804 # By default we use linecache.checkcache, but the user can provide a
801 # By default we use linecache.checkcache, but the user can provide a
805 # different check_cache implementation. This is used by the IPython
802 # different check_cache implementation. This is used by the IPython
806 # kernel to provide tracebacks for interactive code that is cached,
803 # kernel to provide tracebacks for interactive code that is cached,
807 # by a compiler instance that flushes the linecache but preserves its
804 # by a compiler instance that flushes the linecache but preserves its
808 # own code cache.
805 # own code cache.
809 if check_cache is None:
806 if check_cache is None:
810 check_cache = linecache.checkcache
807 check_cache = linecache.checkcache
811 self.check_cache = check_cache
808 self.check_cache = check_cache
812
809
813 self.debugger_cls = debugger_cls or debugger.Pdb
810 self.debugger_cls = debugger_cls or debugger.Pdb
814
811
815 def format_records(self, records, last_unique, recursion_repeat):
812 def format_records(self, records, last_unique, recursion_repeat):
816 """Format the stack frames of the traceback"""
813 """Format the stack frames of the traceback"""
817 frames = []
814 frames = []
818 for r in records[:last_unique+recursion_repeat+1]:
815 for r in records[:last_unique+recursion_repeat+1]:
819 #print '*** record:',file,lnum,func,lines,index # dbg
816 #print '*** record:',file,lnum,func,lines,index # dbg
820 frames.append(self.format_record(*r))
817 frames.append(self.format_record(*r))
821
818
822 if recursion_repeat:
819 if recursion_repeat:
823 frames.append('... last %d frames repeated, from the frame below ...\n' % recursion_repeat)
820 frames.append('... last %d frames repeated, from the frame below ...\n' % recursion_repeat)
824 frames.append(self.format_record(*records[last_unique+recursion_repeat+1]))
821 frames.append(self.format_record(*records[last_unique+recursion_repeat+1]))
825
822
826 return frames
823 return frames
827
824
828 def format_record(self, frame, file, lnum, func, lines, index):
825 def format_record(self, frame, file, lnum, func, lines, index):
829 """Format a single stack frame"""
826 """Format a single stack frame"""
830 Colors = self.Colors # just a shorthand + quicker name lookup
827 Colors = self.Colors # just a shorthand + quicker name lookup
831 ColorsNormal = Colors.Normal # used a lot
828 ColorsNormal = Colors.Normal # used a lot
832 col_scheme = self.color_scheme_table.active_scheme_name
829 col_scheme = self.color_scheme_table.active_scheme_name
833 indent = ' ' * INDENT_SIZE
830 indent = ' ' * INDENT_SIZE
834 em_normal = '%s\n%s%s' % (Colors.valEm, indent, ColorsNormal)
831 em_normal = '%s\n%s%s' % (Colors.valEm, indent, ColorsNormal)
835 undefined = '%sundefined%s' % (Colors.em, ColorsNormal)
832 undefined = '%sundefined%s' % (Colors.em, ColorsNormal)
836 tpl_link = '%s%%s%s' % (Colors.filenameEm, ColorsNormal)
833 tpl_link = '%s%%s%s' % (Colors.filenameEm, ColorsNormal)
837 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
834 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
838 ColorsNormal)
835 ColorsNormal)
839 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
836 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
840 (Colors.vName, Colors.valEm, ColorsNormal)
837 (Colors.vName, Colors.valEm, ColorsNormal)
841 tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal)
838 tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal)
842 tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal,
839 tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal,
843 Colors.vName, ColorsNormal)
840 Colors.vName, ColorsNormal)
844 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
841 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
845
842
846 tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal)
843 tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal)
847 tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm, Colors.line,
844 tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm, Colors.line,
848 ColorsNormal)
845 ColorsNormal)
849
846
850 abspath = os.path.abspath
847 abspath = os.path.abspath
851
848
852
849
853 if not file:
850 if not file:
854 file = '?'
851 file = '?'
855 elif file.startswith(str("<")) and file.endswith(str(">")):
852 elif file.startswith(str("<")) and file.endswith(str(">")):
856 # Not a real filename, no problem...
853 # Not a real filename, no problem...
857 pass
854 pass
858 elif not os.path.isabs(file):
855 elif not os.path.isabs(file):
859 # Try to make the filename absolute by trying all
856 # Try to make the filename absolute by trying all
860 # sys.path entries (which is also what linecache does)
857 # sys.path entries (which is also what linecache does)
861 for dirname in sys.path:
858 for dirname in sys.path:
862 try:
859 try:
863 fullname = os.path.join(dirname, file)
860 fullname = os.path.join(dirname, file)
864 if os.path.isfile(fullname):
861 if os.path.isfile(fullname):
865 file = os.path.abspath(fullname)
862 file = os.path.abspath(fullname)
866 break
863 break
867 except Exception:
864 except Exception:
868 # Just in case that sys.path contains very
865 # Just in case that sys.path contains very
869 # strange entries...
866 # strange entries...
870 pass
867 pass
871
868
872 file = py3compat.cast_unicode(file, util_path.fs_encoding)
873 link = tpl_link % util_path.compress_user(file)
869 link = tpl_link % util_path.compress_user(file)
874 args, varargs, varkw, locals = inspect.getargvalues(frame)
870 args, varargs, varkw, locals = inspect.getargvalues(frame)
875
871
876 if func == '?':
872 if func == '?':
877 call = ''
873 call = ''
878 else:
874 else:
879 # Decide whether to include variable details or not
875 # Decide whether to include variable details or not
880 var_repr = self.include_vars and eqrepr or nullrepr
876 var_repr = self.include_vars and eqrepr or nullrepr
881 try:
877 try:
882 call = tpl_call % (func, inspect.formatargvalues(args,
878 call = tpl_call % (func, inspect.formatargvalues(args,
883 varargs, varkw,
879 varargs, varkw,
884 locals, formatvalue=var_repr))
880 locals, formatvalue=var_repr))
885 except KeyError:
881 except KeyError:
886 # This happens in situations like errors inside generator
882 # This happens in situations like errors inside generator
887 # expressions, where local variables are listed in the
883 # expressions, where local variables are listed in the
888 # line, but can't be extracted from the frame. I'm not
884 # line, but can't be extracted from the frame. I'm not
889 # 100% sure this isn't actually a bug in inspect itself,
885 # 100% sure this isn't actually a bug in inspect itself,
890 # but since there's no info for us to compute with, the
886 # but since there's no info for us to compute with, the
891 # best we can do is report the failure and move on. Here
887 # best we can do is report the failure and move on. Here
892 # we must *not* call any traceback construction again,
888 # we must *not* call any traceback construction again,
893 # because that would mess up use of %debug later on. So we
889 # because that would mess up use of %debug later on. So we
894 # simply report the failure and move on. The only
890 # simply report the failure and move on. The only
895 # limitation will be that this frame won't have locals
891 # limitation will be that this frame won't have locals
896 # listed in the call signature. Quite subtle problem...
892 # listed in the call signature. Quite subtle problem...
897 # I can't think of a good way to validate this in a unit
893 # I can't think of a good way to validate this in a unit
898 # test, but running a script consisting of:
894 # test, but running a script consisting of:
899 # dict( (k,v.strip()) for (k,v) in range(10) )
895 # dict( (k,v.strip()) for (k,v) in range(10) )
900 # will illustrate the error, if this exception catch is
896 # will illustrate the error, if this exception catch is
901 # disabled.
897 # disabled.
902 call = tpl_call_fail % func
898 call = tpl_call_fail % func
903
899
904 # Don't attempt to tokenize binary files.
900 # Don't attempt to tokenize binary files.
905 if file.endswith(('.so', '.pyd', '.dll')):
901 if file.endswith(('.so', '.pyd', '.dll')):
906 return '%s %s\n' % (link, call)
902 return '%s %s\n' % (link, call)
907
903
908 elif file.endswith(('.pyc', '.pyo')):
904 elif file.endswith(('.pyc', '.pyo')):
909 # Look up the corresponding source file.
905 # Look up the corresponding source file.
910 try:
906 try:
911 file = openpy.source_from_cache(file)
907 file = openpy.source_from_cache(file)
912 except ValueError:
908 except ValueError:
913 # Failed to get the source file for some reason
909 # Failed to get the source file for some reason
914 # E.g. https://github.com/ipython/ipython/issues/9486
910 # E.g. https://github.com/ipython/ipython/issues/9486
915 return '%s %s\n' % (link, call)
911 return '%s %s\n' % (link, call)
916
912
917 def linereader(file=file, lnum=[lnum], getline=linecache.getline):
913 def linereader(file=file, lnum=[lnum], getline=linecache.getline):
918 line = getline(file, lnum[0])
914 line = getline(file, lnum[0])
919 lnum[0] += 1
915 lnum[0] += 1
920 return line
916 return line
921
917
922 # Build the list of names on this line of code where the exception
918 # Build the list of names on this line of code where the exception
923 # occurred.
919 # occurred.
924 try:
920 try:
925 names = []
921 names = []
926 name_cont = False
922 name_cont = False
927
923
928 for token_type, token, start, end, line in generate_tokens(linereader):
924 for token_type, token, start, end, line in generate_tokens(linereader):
929 # build composite names
925 # build composite names
930 if token_type == tokenize.NAME and token not in keyword.kwlist:
926 if token_type == tokenize.NAME and token not in keyword.kwlist:
931 if name_cont:
927 if name_cont:
932 # Continuation of a dotted name
928 # Continuation of a dotted name
933 try:
929 try:
934 names[-1].append(token)
930 names[-1].append(token)
935 except IndexError:
931 except IndexError:
936 names.append([token])
932 names.append([token])
937 name_cont = False
933 name_cont = False
938 else:
934 else:
939 # Regular new names. We append everything, the caller
935 # Regular new names. We append everything, the caller
940 # will be responsible for pruning the list later. It's
936 # will be responsible for pruning the list later. It's
941 # very tricky to try to prune as we go, b/c composite
937 # very tricky to try to prune as we go, b/c composite
942 # names can fool us. The pruning at the end is easy
938 # names can fool us. The pruning at the end is easy
943 # to do (or the caller can print a list with repeated
939 # to do (or the caller can print a list with repeated
944 # names if so desired.
940 # names if so desired.
945 names.append([token])
941 names.append([token])
946 elif token == '.':
942 elif token == '.':
947 name_cont = True
943 name_cont = True
948 elif token_type == tokenize.NEWLINE:
944 elif token_type == tokenize.NEWLINE:
949 break
945 break
950
946
951 except (IndexError, UnicodeDecodeError, SyntaxError):
947 except (IndexError, UnicodeDecodeError, SyntaxError):
952 # signals exit of tokenizer
948 # signals exit of tokenizer
953 # SyntaxError can occur if the file is not actually Python
949 # SyntaxError can occur if the file is not actually Python
954 # - see gh-6300
950 # - see gh-6300
955 pass
951 pass
956 except tokenize.TokenError as msg:
952 except tokenize.TokenError as msg:
957 _m = ("An unexpected error occurred while tokenizing input\n"
953 _m = ("An unexpected error occurred while tokenizing input\n"
958 "The following traceback may be corrupted or invalid\n"
954 "The following traceback may be corrupted or invalid\n"
959 "The error message is: %s\n" % msg)
955 "The error message is: %s\n" % msg)
960 error(_m)
956 error(_m)
961
957
962 # Join composite names (e.g. "dict.fromkeys")
958 # Join composite names (e.g. "dict.fromkeys")
963 names = ['.'.join(n) for n in names]
959 names = ['.'.join(n) for n in names]
964 # prune names list of duplicates, but keep the right order
960 # prune names list of duplicates, but keep the right order
965 unique_names = uniq_stable(names)
961 unique_names = uniq_stable(names)
966
962
967 # Start loop over vars
963 # Start loop over vars
968 lvals = []
964 lvals = []
969 if self.include_vars:
965 if self.include_vars:
970 for name_full in unique_names:
966 for name_full in unique_names:
971 name_base = name_full.split('.', 1)[0]
967 name_base = name_full.split('.', 1)[0]
972 if name_base in frame.f_code.co_varnames:
968 if name_base in frame.f_code.co_varnames:
973 if name_base in locals:
969 if name_base in locals:
974 try:
970 try:
975 value = repr(eval(name_full, locals))
971 value = repr(eval(name_full, locals))
976 except:
972 except:
977 value = undefined
973 value = undefined
978 else:
974 else:
979 value = undefined
975 value = undefined
980 name = tpl_local_var % name_full
976 name = tpl_local_var % name_full
981 else:
977 else:
982 if name_base in frame.f_globals:
978 if name_base in frame.f_globals:
983 try:
979 try:
984 value = repr(eval(name_full, frame.f_globals))
980 value = repr(eval(name_full, frame.f_globals))
985 except:
981 except:
986 value = undefined
982 value = undefined
987 else:
983 else:
988 value = undefined
984 value = undefined
989 name = tpl_global_var % name_full
985 name = tpl_global_var % name_full
990 lvals.append(tpl_name_val % (name, value))
986 lvals.append(tpl_name_val % (name, value))
991 if lvals:
987 if lvals:
992 lvals = '%s%s' % (indent, em_normal.join(lvals))
988 lvals = '%s%s' % (indent, em_normal.join(lvals))
993 else:
989 else:
994 lvals = ''
990 lvals = ''
995
991
996 level = '%s %s\n' % (link, call)
992 level = '%s %s\n' % (link, call)
997
993
998 if index is None:
994 if index is None:
999 return level
995 return level
1000 else:
996 else:
1001 _line_format = PyColorize.Parser(style=col_scheme, parent=self).format2
997 _line_format = PyColorize.Parser(style=col_scheme, parent=self).format2
1002 return '%s%s' % (level, ''.join(
998 return '%s%s' % (level, ''.join(
1003 _format_traceback_lines(lnum, index, lines, Colors, lvals,
999 _format_traceback_lines(lnum, index, lines, Colors, lvals,
1004 _line_format)))
1000 _line_format)))
1005
1001
1006 def prepare_chained_exception_message(self, cause):
1002 def prepare_chained_exception_message(self, cause):
1007 direct_cause = "\nThe above exception was the direct cause of the following exception:\n"
1003 direct_cause = "\nThe above exception was the direct cause of the following exception:\n"
1008 exception_during_handling = "\nDuring handling of the above exception, another exception occurred:\n"
1004 exception_during_handling = "\nDuring handling of the above exception, another exception occurred:\n"
1009
1005
1010 if cause:
1006 if cause:
1011 message = [[direct_cause]]
1007 message = [[direct_cause]]
1012 else:
1008 else:
1013 message = [[exception_during_handling]]
1009 message = [[exception_during_handling]]
1014 return message
1010 return message
1015
1011
1016 def prepare_header(self, etype, long_version=False):
1012 def prepare_header(self, etype, long_version=False):
1017 colors = self.Colors # just a shorthand + quicker name lookup
1013 colors = self.Colors # just a shorthand + quicker name lookup
1018 colorsnormal = colors.Normal # used a lot
1014 colorsnormal = colors.Normal # used a lot
1019 exc = '%s%s%s' % (colors.excName, etype, colorsnormal)
1015 exc = '%s%s%s' % (colors.excName, etype, colorsnormal)
1020 width = min(75, get_terminal_size()[0])
1016 width = min(75, get_terminal_size()[0])
1021 if long_version:
1017 if long_version:
1022 # Header with the exception type, python version, and date
1018 # Header with the exception type, python version, and date
1023 pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable
1019 pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable
1024 date = time.ctime(time.time())
1020 date = time.ctime(time.time())
1025
1021
1026 head = '%s%s%s\n%s%s%s\n%s' % (colors.topline, '-' * width, colorsnormal,
1022 head = '%s%s%s\n%s%s%s\n%s' % (colors.topline, '-' * width, colorsnormal,
1027 exc, ' ' * (width - len(str(etype)) - len(pyver)),
1023 exc, ' ' * (width - len(str(etype)) - len(pyver)),
1028 pyver, date.rjust(width) )
1024 pyver, date.rjust(width) )
1029 head += "\nA problem occurred executing Python code. Here is the sequence of function" \
1025 head += "\nA problem occurred executing Python code. Here is the sequence of function" \
1030 "\ncalls leading up to the error, with the most recent (innermost) call last."
1026 "\ncalls leading up to the error, with the most recent (innermost) call last."
1031 else:
1027 else:
1032 # Simplified header
1028 # Simplified header
1033 head = '%s%s' % (exc, 'Traceback (most recent call last)'. \
1029 head = '%s%s' % (exc, 'Traceback (most recent call last)'. \
1034 rjust(width - len(str(etype))) )
1030 rjust(width - len(str(etype))) )
1035
1031
1036 return head
1032 return head
1037
1033
1038 def format_exception(self, etype, evalue):
1034 def format_exception(self, etype, evalue):
1039 colors = self.Colors # just a shorthand + quicker name lookup
1035 colors = self.Colors # just a shorthand + quicker name lookup
1040 colorsnormal = colors.Normal # used a lot
1036 colorsnormal = colors.Normal # used a lot
1041 indent = ' ' * INDENT_SIZE
1037 indent = ' ' * INDENT_SIZE
1042 # Get (safely) a string form of the exception info
1038 # Get (safely) a string form of the exception info
1043 try:
1039 try:
1044 etype_str, evalue_str = map(str, (etype, evalue))
1040 etype_str, evalue_str = map(str, (etype, evalue))
1045 except:
1041 except:
1046 # User exception is improperly defined.
1042 # User exception is improperly defined.
1047 etype, evalue = str, sys.exc_info()[:2]
1043 etype, evalue = str, sys.exc_info()[:2]
1048 etype_str, evalue_str = map(str, (etype, evalue))
1044 etype_str, evalue_str = map(str, (etype, evalue))
1049 # ... and format it
1045 # ... and format it
1050 return ['%s%s%s: %s' % (colors.excName, etype_str,
1046 return ['%s%s%s: %s' % (colors.excName, etype_str, colorsnormal, evalue_str)]
1051 colorsnormal, py3compat.cast_unicode(evalue_str))]
1052
1047
1053 def format_exception_as_a_whole(self, etype, evalue, etb, number_of_lines_of_context, tb_offset):
1048 def format_exception_as_a_whole(self, etype, evalue, etb, number_of_lines_of_context, tb_offset):
1054 """Formats the header, traceback and exception message for a single exception.
1049 """Formats the header, traceback and exception message for a single exception.
1055
1050
1056 This may be called multiple times by Python 3 exception chaining
1051 This may be called multiple times by Python 3 exception chaining
1057 (PEP 3134).
1052 (PEP 3134).
1058 """
1053 """
1059 # some locals
1054 # some locals
1060 orig_etype = etype
1055 orig_etype = etype
1061 try:
1056 try:
1062 etype = etype.__name__
1057 etype = etype.__name__
1063 except AttributeError:
1058 except AttributeError:
1064 pass
1059 pass
1065
1060
1066 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1061 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1067 head = self.prepare_header(etype, self.long_header)
1062 head = self.prepare_header(etype, self.long_header)
1068 records = self.get_records(etb, number_of_lines_of_context, tb_offset)
1063 records = self.get_records(etb, number_of_lines_of_context, tb_offset)
1069
1064
1070 if records is None:
1065 if records is None:
1071 return ""
1066 return ""
1072
1067
1073 last_unique, recursion_repeat = find_recursion(orig_etype, evalue, records)
1068 last_unique, recursion_repeat = find_recursion(orig_etype, evalue, records)
1074
1069
1075 frames = self.format_records(records, last_unique, recursion_repeat)
1070 frames = self.format_records(records, last_unique, recursion_repeat)
1076
1071
1077 formatted_exception = self.format_exception(etype, evalue)
1072 formatted_exception = self.format_exception(etype, evalue)
1078 if records:
1073 if records:
1079 filepath, lnum = records[-1][1:3]
1074 filepath, lnum = records[-1][1:3]
1080 filepath = os.path.abspath(filepath)
1075 filepath = os.path.abspath(filepath)
1081 ipinst = get_ipython()
1076 ipinst = get_ipython()
1082 if ipinst is not None:
1077 if ipinst is not None:
1083 ipinst.hooks.synchronize_with_editor(filepath, lnum, 0)
1078 ipinst.hooks.synchronize_with_editor(filepath, lnum, 0)
1084
1079
1085 return [[head] + frames + [''.join(formatted_exception[0])]]
1080 return [[head] + frames + [''.join(formatted_exception[0])]]
1086
1081
1087 def get_records(self, etb, number_of_lines_of_context, tb_offset):
1082 def get_records(self, etb, number_of_lines_of_context, tb_offset):
1088 try:
1083 try:
1089 # Try the default getinnerframes and Alex's: Alex's fixes some
1084 # Try the default getinnerframes and Alex's: Alex's fixes some
1090 # problems, but it generates empty tracebacks for console errors
1085 # problems, but it generates empty tracebacks for console errors
1091 # (5 blanks lines) where none should be returned.
1086 # (5 blanks lines) where none should be returned.
1092 return _fixed_getinnerframes(etb, number_of_lines_of_context, tb_offset)
1087 return _fixed_getinnerframes(etb, number_of_lines_of_context, tb_offset)
1093 except UnicodeDecodeError:
1088 except UnicodeDecodeError:
1094 # This can occur if a file's encoding magic comment is wrong.
1089 # This can occur if a file's encoding magic comment is wrong.
1095 # I can't see a way to recover without duplicating a bunch of code
1090 # I can't see a way to recover without duplicating a bunch of code
1096 # from the stdlib traceback module. --TK
1091 # from the stdlib traceback module. --TK
1097 error('\nUnicodeDecodeError while processing traceback.\n')
1092 error('\nUnicodeDecodeError while processing traceback.\n')
1098 return None
1093 return None
1099 except:
1094 except:
1100 # FIXME: I've been getting many crash reports from python 2.3
1095 # FIXME: I've been getting many crash reports from python 2.3
1101 # users, traceable to inspect.py. If I can find a small test-case
1096 # users, traceable to inspect.py. If I can find a small test-case
1102 # to reproduce this, I should either write a better workaround or
1097 # to reproduce this, I should either write a better workaround or
1103 # file a bug report against inspect (if that's the real problem).
1098 # file a bug report against inspect (if that's the real problem).
1104 # So far, I haven't been able to find an isolated example to
1099 # So far, I haven't been able to find an isolated example to
1105 # reproduce the problem.
1100 # reproduce the problem.
1106 inspect_error()
1101 inspect_error()
1107 traceback.print_exc(file=self.ostream)
1102 traceback.print_exc(file=self.ostream)
1108 info('\nUnfortunately, your original traceback can not be constructed.\n')
1103 info('\nUnfortunately, your original traceback can not be constructed.\n')
1109 return None
1104 return None
1110
1105
1111 def get_parts_of_chained_exception(self, evalue):
1106 def get_parts_of_chained_exception(self, evalue):
1112 def get_chained_exception(exception_value):
1107 def get_chained_exception(exception_value):
1113 cause = getattr(exception_value, '__cause__', None)
1108 cause = getattr(exception_value, '__cause__', None)
1114 if cause:
1109 if cause:
1115 return cause
1110 return cause
1116 if getattr(exception_value, '__suppress_context__', False):
1111 if getattr(exception_value, '__suppress_context__', False):
1117 return None
1112 return None
1118 return getattr(exception_value, '__context__', None)
1113 return getattr(exception_value, '__context__', None)
1119
1114
1120 chained_evalue = get_chained_exception(evalue)
1115 chained_evalue = get_chained_exception(evalue)
1121
1116
1122 if chained_evalue:
1117 if chained_evalue:
1123 return chained_evalue.__class__, chained_evalue, chained_evalue.__traceback__
1118 return chained_evalue.__class__, chained_evalue, chained_evalue.__traceback__
1124
1119
1125 def structured_traceback(self, etype, evalue, etb, tb_offset=None,
1120 def structured_traceback(self, etype, evalue, etb, tb_offset=None,
1126 number_of_lines_of_context=5):
1121 number_of_lines_of_context=5):
1127 """Return a nice text document describing the traceback."""
1122 """Return a nice text document describing the traceback."""
1128
1123
1129 formatted_exception = self.format_exception_as_a_whole(etype, evalue, etb, number_of_lines_of_context,
1124 formatted_exception = self.format_exception_as_a_whole(etype, evalue, etb, number_of_lines_of_context,
1130 tb_offset)
1125 tb_offset)
1131
1126
1132 colors = self.Colors # just a shorthand + quicker name lookup
1127 colors = self.Colors # just a shorthand + quicker name lookup
1133 colorsnormal = colors.Normal # used a lot
1128 colorsnormal = colors.Normal # used a lot
1134 head = '%s%s%s' % (colors.topline, '-' * min(75, get_terminal_size()[0]), colorsnormal)
1129 head = '%s%s%s' % (colors.topline, '-' * min(75, get_terminal_size()[0]), colorsnormal)
1135 structured_traceback_parts = [head]
1130 structured_traceback_parts = [head]
1136 if py3compat.PY3:
1131 if py3compat.PY3:
1137 chained_exceptions_tb_offset = 0
1132 chained_exceptions_tb_offset = 0
1138 lines_of_context = 3
1133 lines_of_context = 3
1139 formatted_exceptions = formatted_exception
1134 formatted_exceptions = formatted_exception
1140 exception = self.get_parts_of_chained_exception(evalue)
1135 exception = self.get_parts_of_chained_exception(evalue)
1141 if exception:
1136 if exception:
1142 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
1137 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
1143 etype, evalue, etb = exception
1138 etype, evalue, etb = exception
1144 else:
1139 else:
1145 evalue = None
1140 evalue = None
1146 chained_exc_ids = set()
1141 chained_exc_ids = set()
1147 while evalue:
1142 while evalue:
1148 formatted_exceptions += self.format_exception_as_a_whole(etype, evalue, etb, lines_of_context,
1143 formatted_exceptions += self.format_exception_as_a_whole(etype, evalue, etb, lines_of_context,
1149 chained_exceptions_tb_offset)
1144 chained_exceptions_tb_offset)
1150 exception = self.get_parts_of_chained_exception(evalue)
1145 exception = self.get_parts_of_chained_exception(evalue)
1151
1146
1152 if exception and not id(exception[1]) in chained_exc_ids:
1147 if exception and not id(exception[1]) in chained_exc_ids:
1153 chained_exc_ids.add(id(exception[1])) # trace exception to avoid infinite 'cause' loop
1148 chained_exc_ids.add(id(exception[1])) # trace exception to avoid infinite 'cause' loop
1154 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
1149 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
1155 etype, evalue, etb = exception
1150 etype, evalue, etb = exception
1156 else:
1151 else:
1157 evalue = None
1152 evalue = None
1158
1153
1159 # we want to see exceptions in a reversed order:
1154 # we want to see exceptions in a reversed order:
1160 # the first exception should be on top
1155 # the first exception should be on top
1161 for formatted_exception in reversed(formatted_exceptions):
1156 for formatted_exception in reversed(formatted_exceptions):
1162 structured_traceback_parts += formatted_exception
1157 structured_traceback_parts += formatted_exception
1163 else:
1158 else:
1164 structured_traceback_parts += formatted_exception[0]
1159 structured_traceback_parts += formatted_exception[0]
1165
1160
1166 return structured_traceback_parts
1161 return structured_traceback_parts
1167
1162
1168 def debugger(self, force=False):
1163 def debugger(self, force=False):
1169 """Call up the pdb debugger if desired, always clean up the tb
1164 """Call up the pdb debugger if desired, always clean up the tb
1170 reference.
1165 reference.
1171
1166
1172 Keywords:
1167 Keywords:
1173
1168
1174 - force(False): by default, this routine checks the instance call_pdb
1169 - force(False): by default, this routine checks the instance call_pdb
1175 flag and does not actually invoke the debugger if the flag is false.
1170 flag and does not actually invoke the debugger if the flag is false.
1176 The 'force' option forces the debugger to activate even if the flag
1171 The 'force' option forces the debugger to activate even if the flag
1177 is false.
1172 is false.
1178
1173
1179 If the call_pdb flag is set, the pdb interactive debugger is
1174 If the call_pdb flag is set, the pdb interactive debugger is
1180 invoked. In all cases, the self.tb reference to the current traceback
1175 invoked. In all cases, the self.tb reference to the current traceback
1181 is deleted to prevent lingering references which hamper memory
1176 is deleted to prevent lingering references which hamper memory
1182 management.
1177 management.
1183
1178
1184 Note that each call to pdb() does an 'import readline', so if your app
1179 Note that each call to pdb() does an 'import readline', so if your app
1185 requires a special setup for the readline completers, you'll have to
1180 requires a special setup for the readline completers, you'll have to
1186 fix that by hand after invoking the exception handler."""
1181 fix that by hand after invoking the exception handler."""
1187
1182
1188 if force or self.call_pdb:
1183 if force or self.call_pdb:
1189 if self.pdb is None:
1184 if self.pdb is None:
1190 self.pdb = self.debugger_cls()
1185 self.pdb = self.debugger_cls()
1191 # the system displayhook may have changed, restore the original
1186 # the system displayhook may have changed, restore the original
1192 # for pdb
1187 # for pdb
1193 display_trap = DisplayTrap(hook=sys.__displayhook__)
1188 display_trap = DisplayTrap(hook=sys.__displayhook__)
1194 with display_trap:
1189 with display_trap:
1195 self.pdb.reset()
1190 self.pdb.reset()
1196 # Find the right frame so we don't pop up inside ipython itself
1191 # Find the right frame so we don't pop up inside ipython itself
1197 if hasattr(self, 'tb') and self.tb is not None:
1192 if hasattr(self, 'tb') and self.tb is not None:
1198 etb = self.tb
1193 etb = self.tb
1199 else:
1194 else:
1200 etb = self.tb = sys.last_traceback
1195 etb = self.tb = sys.last_traceback
1201 while self.tb is not None and self.tb.tb_next is not None:
1196 while self.tb is not None and self.tb.tb_next is not None:
1202 self.tb = self.tb.tb_next
1197 self.tb = self.tb.tb_next
1203 if etb and etb.tb_next:
1198 if etb and etb.tb_next:
1204 etb = etb.tb_next
1199 etb = etb.tb_next
1205 self.pdb.botframe = etb.tb_frame
1200 self.pdb.botframe = etb.tb_frame
1206 self.pdb.interaction(self.tb.tb_frame, self.tb)
1201 self.pdb.interaction(self.tb.tb_frame, self.tb)
1207
1202
1208 if hasattr(self, 'tb'):
1203 if hasattr(self, 'tb'):
1209 del self.tb
1204 del self.tb
1210
1205
1211 def handler(self, info=None):
1206 def handler(self, info=None):
1212 (etype, evalue, etb) = info or sys.exc_info()
1207 (etype, evalue, etb) = info or sys.exc_info()
1213 self.tb = etb
1208 self.tb = etb
1214 ostream = self.ostream
1209 ostream = self.ostream
1215 ostream.flush()
1210 ostream.flush()
1216 ostream.write(self.text(etype, evalue, etb))
1211 ostream.write(self.text(etype, evalue, etb))
1217 ostream.write('\n')
1212 ostream.write('\n')
1218 ostream.flush()
1213 ostream.flush()
1219
1214
1220 # Changed so an instance can just be called as VerboseTB_inst() and print
1215 # Changed so an instance can just be called as VerboseTB_inst() and print
1221 # out the right info on its own.
1216 # out the right info on its own.
1222 def __call__(self, etype=None, evalue=None, etb=None):
1217 def __call__(self, etype=None, evalue=None, etb=None):
1223 """This hook can replace sys.excepthook (for Python 2.1 or higher)."""
1218 """This hook can replace sys.excepthook (for Python 2.1 or higher)."""
1224 if etb is None:
1219 if etb is None:
1225 self.handler()
1220 self.handler()
1226 else:
1221 else:
1227 self.handler((etype, evalue, etb))
1222 self.handler((etype, evalue, etb))
1228 try:
1223 try:
1229 self.debugger()
1224 self.debugger()
1230 except KeyboardInterrupt:
1225 except KeyboardInterrupt:
1231 print("\nKeyboardInterrupt")
1226 print("\nKeyboardInterrupt")
1232
1227
1233
1228
1234 #----------------------------------------------------------------------------
1229 #----------------------------------------------------------------------------
1235 class FormattedTB(VerboseTB, ListTB):
1230 class FormattedTB(VerboseTB, ListTB):
1236 """Subclass ListTB but allow calling with a traceback.
1231 """Subclass ListTB but allow calling with a traceback.
1237
1232
1238 It can thus be used as a sys.excepthook for Python > 2.1.
1233 It can thus be used as a sys.excepthook for Python > 2.1.
1239
1234
1240 Also adds 'Context' and 'Verbose' modes, not available in ListTB.
1235 Also adds 'Context' and 'Verbose' modes, not available in ListTB.
1241
1236
1242 Allows a tb_offset to be specified. This is useful for situations where
1237 Allows a tb_offset to be specified. This is useful for situations where
1243 one needs to remove a number of topmost frames from the traceback (such as
1238 one needs to remove a number of topmost frames from the traceback (such as
1244 occurs with python programs that themselves execute other python code,
1239 occurs with python programs that themselves execute other python code,
1245 like Python shells). """
1240 like Python shells). """
1246
1241
1247 def __init__(self, mode='Plain', color_scheme='Linux', call_pdb=False,
1242 def __init__(self, mode='Plain', color_scheme='Linux', call_pdb=False,
1248 ostream=None,
1243 ostream=None,
1249 tb_offset=0, long_header=False, include_vars=False,
1244 tb_offset=0, long_header=False, include_vars=False,
1250 check_cache=None, debugger_cls=None,
1245 check_cache=None, debugger_cls=None,
1251 parent=None, config=None):
1246 parent=None, config=None):
1252
1247
1253 # NEVER change the order of this list. Put new modes at the end:
1248 # NEVER change the order of this list. Put new modes at the end:
1254 self.valid_modes = ['Plain', 'Context', 'Verbose']
1249 self.valid_modes = ['Plain', 'Context', 'Verbose']
1255 self.verbose_modes = self.valid_modes[1:3]
1250 self.verbose_modes = self.valid_modes[1:3]
1256
1251
1257 VerboseTB.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
1252 VerboseTB.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
1258 ostream=ostream, tb_offset=tb_offset,
1253 ostream=ostream, tb_offset=tb_offset,
1259 long_header=long_header, include_vars=include_vars,
1254 long_header=long_header, include_vars=include_vars,
1260 check_cache=check_cache, debugger_cls=debugger_cls,
1255 check_cache=check_cache, debugger_cls=debugger_cls,
1261 parent=parent, config=config)
1256 parent=parent, config=config)
1262
1257
1263 # Different types of tracebacks are joined with different separators to
1258 # Different types of tracebacks are joined with different separators to
1264 # form a single string. They are taken from this dict
1259 # form a single string. They are taken from this dict
1265 self._join_chars = dict(Plain='', Context='\n', Verbose='\n')
1260 self._join_chars = dict(Plain='', Context='\n', Verbose='\n')
1266 # set_mode also sets the tb_join_char attribute
1261 # set_mode also sets the tb_join_char attribute
1267 self.set_mode(mode)
1262 self.set_mode(mode)
1268
1263
1269 def _extract_tb(self, tb):
1264 def _extract_tb(self, tb):
1270 if tb:
1265 if tb:
1271 return traceback.extract_tb(tb)
1266 return traceback.extract_tb(tb)
1272 else:
1267 else:
1273 return None
1268 return None
1274
1269
1275 def structured_traceback(self, etype, value, tb, tb_offset=None, number_of_lines_of_context=5):
1270 def structured_traceback(self, etype, value, tb, tb_offset=None, number_of_lines_of_context=5):
1276 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1271 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1277 mode = self.mode
1272 mode = self.mode
1278 if mode in self.verbose_modes:
1273 if mode in self.verbose_modes:
1279 # Verbose modes need a full traceback
1274 # Verbose modes need a full traceback
1280 return VerboseTB.structured_traceback(
1275 return VerboseTB.structured_traceback(
1281 self, etype, value, tb, tb_offset, number_of_lines_of_context
1276 self, etype, value, tb, tb_offset, number_of_lines_of_context
1282 )
1277 )
1283 else:
1278 else:
1284 # We must check the source cache because otherwise we can print
1279 # We must check the source cache because otherwise we can print
1285 # out-of-date source code.
1280 # out-of-date source code.
1286 self.check_cache()
1281 self.check_cache()
1287 # Now we can extract and format the exception
1282 # Now we can extract and format the exception
1288 elist = self._extract_tb(tb)
1283 elist = self._extract_tb(tb)
1289 return ListTB.structured_traceback(
1284 return ListTB.structured_traceback(
1290 self, etype, value, elist, tb_offset, number_of_lines_of_context
1285 self, etype, value, elist, tb_offset, number_of_lines_of_context
1291 )
1286 )
1292
1287
1293 def stb2text(self, stb):
1288 def stb2text(self, stb):
1294 """Convert a structured traceback (a list) to a string."""
1289 """Convert a structured traceback (a list) to a string."""
1295 return self.tb_join_char.join(stb)
1290 return self.tb_join_char.join(stb)
1296
1291
1297
1292
1298 def set_mode(self, mode=None):
1293 def set_mode(self, mode=None):
1299 """Switch to the desired mode.
1294 """Switch to the desired mode.
1300
1295
1301 If mode is not specified, cycles through the available modes."""
1296 If mode is not specified, cycles through the available modes."""
1302
1297
1303 if not mode:
1298 if not mode:
1304 new_idx = (self.valid_modes.index(self.mode) + 1 ) % \
1299 new_idx = (self.valid_modes.index(self.mode) + 1 ) % \
1305 len(self.valid_modes)
1300 len(self.valid_modes)
1306 self.mode = self.valid_modes[new_idx]
1301 self.mode = self.valid_modes[new_idx]
1307 elif mode not in self.valid_modes:
1302 elif mode not in self.valid_modes:
1308 raise ValueError('Unrecognized mode in FormattedTB: <' + mode + '>\n'
1303 raise ValueError('Unrecognized mode in FormattedTB: <' + mode + '>\n'
1309 'Valid modes: ' + str(self.valid_modes))
1304 'Valid modes: ' + str(self.valid_modes))
1310 else:
1305 else:
1311 self.mode = mode
1306 self.mode = mode
1312 # include variable details only in 'Verbose' mode
1307 # include variable details only in 'Verbose' mode
1313 self.include_vars = (self.mode == self.valid_modes[2])
1308 self.include_vars = (self.mode == self.valid_modes[2])
1314 # Set the join character for generating text tracebacks
1309 # Set the join character for generating text tracebacks
1315 self.tb_join_char = self._join_chars[self.mode]
1310 self.tb_join_char = self._join_chars[self.mode]
1316
1311
1317 # some convenient shortcuts
1312 # some convenient shortcuts
1318 def plain(self):
1313 def plain(self):
1319 self.set_mode(self.valid_modes[0])
1314 self.set_mode(self.valid_modes[0])
1320
1315
1321 def context(self):
1316 def context(self):
1322 self.set_mode(self.valid_modes[1])
1317 self.set_mode(self.valid_modes[1])
1323
1318
1324 def verbose(self):
1319 def verbose(self):
1325 self.set_mode(self.valid_modes[2])
1320 self.set_mode(self.valid_modes[2])
1326
1321
1327
1322
1328 #----------------------------------------------------------------------------
1323 #----------------------------------------------------------------------------
1329 class AutoFormattedTB(FormattedTB):
1324 class AutoFormattedTB(FormattedTB):
1330 """A traceback printer which can be called on the fly.
1325 """A traceback printer which can be called on the fly.
1331
1326
1332 It will find out about exceptions by itself.
1327 It will find out about exceptions by itself.
1333
1328
1334 A brief example::
1329 A brief example::
1335
1330
1336 AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux')
1331 AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux')
1337 try:
1332 try:
1338 ...
1333 ...
1339 except:
1334 except:
1340 AutoTB() # or AutoTB(out=logfile) where logfile is an open file object
1335 AutoTB() # or AutoTB(out=logfile) where logfile is an open file object
1341 """
1336 """
1342
1337
1343 def __call__(self, etype=None, evalue=None, etb=None,
1338 def __call__(self, etype=None, evalue=None, etb=None,
1344 out=None, tb_offset=None):
1339 out=None, tb_offset=None):
1345 """Print out a formatted exception traceback.
1340 """Print out a formatted exception traceback.
1346
1341
1347 Optional arguments:
1342 Optional arguments:
1348 - out: an open file-like object to direct output to.
1343 - out: an open file-like object to direct output to.
1349
1344
1350 - tb_offset: the number of frames to skip over in the stack, on a
1345 - tb_offset: the number of frames to skip over in the stack, on a
1351 per-call basis (this overrides temporarily the instance's tb_offset
1346 per-call basis (this overrides temporarily the instance's tb_offset
1352 given at initialization time. """
1347 given at initialization time. """
1353
1348
1354 if out is None:
1349 if out is None:
1355 out = self.ostream
1350 out = self.ostream
1356 out.flush()
1351 out.flush()
1357 out.write(self.text(etype, evalue, etb, tb_offset))
1352 out.write(self.text(etype, evalue, etb, tb_offset))
1358 out.write('\n')
1353 out.write('\n')
1359 out.flush()
1354 out.flush()
1360 # FIXME: we should remove the auto pdb behavior from here and leave
1355 # FIXME: we should remove the auto pdb behavior from here and leave
1361 # that to the clients.
1356 # that to the clients.
1362 try:
1357 try:
1363 self.debugger()
1358 self.debugger()
1364 except KeyboardInterrupt:
1359 except KeyboardInterrupt:
1365 print("\nKeyboardInterrupt")
1360 print("\nKeyboardInterrupt")
1366
1361
1367 def structured_traceback(self, etype=None, value=None, tb=None,
1362 def structured_traceback(self, etype=None, value=None, tb=None,
1368 tb_offset=None, number_of_lines_of_context=5):
1363 tb_offset=None, number_of_lines_of_context=5):
1369 if etype is None:
1364 if etype is None:
1370 etype, value, tb = sys.exc_info()
1365 etype, value, tb = sys.exc_info()
1371 self.tb = tb
1366 self.tb = tb
1372 return FormattedTB.structured_traceback(
1367 return FormattedTB.structured_traceback(
1373 self, etype, value, tb, tb_offset, number_of_lines_of_context)
1368 self, etype, value, tb, tb_offset, number_of_lines_of_context)
1374
1369
1375
1370
1376 #---------------------------------------------------------------------------
1371 #---------------------------------------------------------------------------
1377
1372
1378 # A simple class to preserve Nathan's original functionality.
1373 # A simple class to preserve Nathan's original functionality.
1379 class ColorTB(FormattedTB):
1374 class ColorTB(FormattedTB):
1380 """Shorthand to initialize a FormattedTB in Linux colors mode."""
1375 """Shorthand to initialize a FormattedTB in Linux colors mode."""
1381
1376
1382 def __init__(self, color_scheme='Linux', call_pdb=0, **kwargs):
1377 def __init__(self, color_scheme='Linux', call_pdb=0, **kwargs):
1383 FormattedTB.__init__(self, color_scheme=color_scheme,
1378 FormattedTB.__init__(self, color_scheme=color_scheme,
1384 call_pdb=call_pdb, **kwargs)
1379 call_pdb=call_pdb, **kwargs)
1385
1380
1386
1381
1387 class SyntaxTB(ListTB):
1382 class SyntaxTB(ListTB):
1388 """Extension which holds some state: the last exception value"""
1383 """Extension which holds some state: the last exception value"""
1389
1384
1390 def __init__(self, color_scheme='NoColor', parent=None, config=None):
1385 def __init__(self, color_scheme='NoColor', parent=None, config=None):
1391 ListTB.__init__(self, color_scheme, parent=parent, config=config)
1386 ListTB.__init__(self, color_scheme, parent=parent, config=config)
1392 self.last_syntax_error = None
1387 self.last_syntax_error = None
1393
1388
1394 def __call__(self, etype, value, elist):
1389 def __call__(self, etype, value, elist):
1395 self.last_syntax_error = value
1390 self.last_syntax_error = value
1396
1391
1397 ListTB.__call__(self, etype, value, elist)
1392 ListTB.__call__(self, etype, value, elist)
1398
1393
1399 def structured_traceback(self, etype, value, elist, tb_offset=None,
1394 def structured_traceback(self, etype, value, elist, tb_offset=None,
1400 context=5):
1395 context=5):
1401 # If the source file has been edited, the line in the syntax error can
1396 # If the source file has been edited, the line in the syntax error can
1402 # be wrong (retrieved from an outdated cache). This replaces it with
1397 # be wrong (retrieved from an outdated cache). This replaces it with
1403 # the current value.
1398 # the current value.
1404 if isinstance(value, SyntaxError) \
1399 if isinstance(value, SyntaxError) \
1405 and isinstance(value.filename, str) \
1400 and isinstance(value.filename, str) \
1406 and isinstance(value.lineno, int):
1401 and isinstance(value.lineno, int):
1407 linecache.checkcache(value.filename)
1402 linecache.checkcache(value.filename)
1408 newtext = linecache.getline(value.filename, value.lineno)
1403 newtext = linecache.getline(value.filename, value.lineno)
1409 if newtext:
1404 if newtext:
1410 value.text = newtext
1405 value.text = newtext
1411 self.last_syntax_error = value
1406 self.last_syntax_error = value
1412 return super(SyntaxTB, self).structured_traceback(etype, value, elist,
1407 return super(SyntaxTB, self).structured_traceback(etype, value, elist,
1413 tb_offset=tb_offset, context=context)
1408 tb_offset=tb_offset, context=context)
1414
1409
1415 def clear_err_state(self):
1410 def clear_err_state(self):
1416 """Return the current error state and clear it"""
1411 """Return the current error state and clear it"""
1417 e = self.last_syntax_error
1412 e = self.last_syntax_error
1418 self.last_syntax_error = None
1413 self.last_syntax_error = None
1419 return e
1414 return e
1420
1415
1421 def stb2text(self, stb):
1416 def stb2text(self, stb):
1422 """Convert a structured traceback (a list) to a string."""
1417 """Convert a structured traceback (a list) to a string."""
1423 return ''.join(stb)
1418 return ''.join(stb)
1424
1419
1425
1420
1426 # some internal-use functions
1421 # some internal-use functions
1427 def text_repr(value):
1422 def text_repr(value):
1428 """Hopefully pretty robust repr equivalent."""
1423 """Hopefully pretty robust repr equivalent."""
1429 # this is pretty horrible but should always return *something*
1424 # this is pretty horrible but should always return *something*
1430 try:
1425 try:
1431 return pydoc.text.repr(value)
1426 return pydoc.text.repr(value)
1432 except KeyboardInterrupt:
1427 except KeyboardInterrupt:
1433 raise
1428 raise
1434 except:
1429 except:
1435 try:
1430 try:
1436 return repr(value)
1431 return repr(value)
1437 except KeyboardInterrupt:
1432 except KeyboardInterrupt:
1438 raise
1433 raise
1439 except:
1434 except:
1440 try:
1435 try:
1441 # all still in an except block so we catch
1436 # all still in an except block so we catch
1442 # getattr raising
1437 # getattr raising
1443 name = getattr(value, '__name__', None)
1438 name = getattr(value, '__name__', None)
1444 if name:
1439 if name:
1445 # ick, recursion
1440 # ick, recursion
1446 return text_repr(name)
1441 return text_repr(name)
1447 klass = getattr(value, '__class__', None)
1442 klass = getattr(value, '__class__', None)
1448 if klass:
1443 if klass:
1449 return '%s instance' % text_repr(klass)
1444 return '%s instance' % text_repr(klass)
1450 except KeyboardInterrupt:
1445 except KeyboardInterrupt:
1451 raise
1446 raise
1452 except:
1447 except:
1453 return 'UNRECOVERABLE REPR FAILURE'
1448 return 'UNRECOVERABLE REPR FAILURE'
1454
1449
1455
1450
1456 def eqrepr(value, repr=text_repr):
1451 def eqrepr(value, repr=text_repr):
1457 return '=%s' % repr(value)
1452 return '=%s' % repr(value)
1458
1453
1459
1454
1460 def nullrepr(value, repr=text_repr):
1455 def nullrepr(value, repr=text_repr):
1461 return ''
1456 return ''
@@ -1,201 +1,201 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Tools for handling LaTeX."""
2 """Tools for handling LaTeX."""
3
3
4 # Copyright (c) IPython Development Team.
4 # Copyright (c) IPython Development Team.
5 # Distributed under the terms of the Modified BSD License.
5 # Distributed under the terms of the Modified BSD License.
6
6
7 from io import BytesIO, open
7 from io import BytesIO, open
8 import os
8 import os
9 import tempfile
9 import tempfile
10 import shutil
10 import shutil
11 import subprocess
11 import subprocess
12 from base64 import encodebytes
12 from base64 import encodebytes
13
13
14 from IPython.utils.process import find_cmd, FindCmdError
14 from IPython.utils.process import find_cmd, FindCmdError
15 from traitlets.config import get_config
15 from traitlets.config import get_config
16 from traitlets.config.configurable import SingletonConfigurable
16 from traitlets.config.configurable import SingletonConfigurable
17 from traitlets import List, Bool, Unicode
17 from traitlets import List, Bool, Unicode
18 from IPython.utils.py3compat import cast_unicode, cast_unicode_py2 as u
18 from IPython.utils.py3compat import cast_unicode
19
19
20
20
21 class LaTeXTool(SingletonConfigurable):
21 class LaTeXTool(SingletonConfigurable):
22 """An object to store configuration of the LaTeX tool."""
22 """An object to store configuration of the LaTeX tool."""
23 def _config_default(self):
23 def _config_default(self):
24 return get_config()
24 return get_config()
25
25
26 backends = List(
26 backends = List(
27 Unicode(), ["matplotlib", "dvipng"],
27 Unicode(), ["matplotlib", "dvipng"],
28 help="Preferred backend to draw LaTeX math equations. "
28 help="Preferred backend to draw LaTeX math equations. "
29 "Backends in the list are checked one by one and the first "
29 "Backends in the list are checked one by one and the first "
30 "usable one is used. Note that `matplotlib` backend "
30 "usable one is used. Note that `matplotlib` backend "
31 "is usable only for inline style equations. To draw "
31 "is usable only for inline style equations. To draw "
32 "display style equations, `dvipng` backend must be specified. ",
32 "display style equations, `dvipng` backend must be specified. ",
33 # It is a List instead of Enum, to make configuration more
33 # It is a List instead of Enum, to make configuration more
34 # flexible. For example, to use matplotlib mainly but dvipng
34 # flexible. For example, to use matplotlib mainly but dvipng
35 # for display style, the default ["matplotlib", "dvipng"] can
35 # for display style, the default ["matplotlib", "dvipng"] can
36 # be used. To NOT use dvipng so that other repr such as
36 # be used. To NOT use dvipng so that other repr such as
37 # unicode pretty printing is used, you can use ["matplotlib"].
37 # unicode pretty printing is used, you can use ["matplotlib"].
38 ).tag(config=True)
38 ).tag(config=True)
39
39
40 use_breqn = Bool(
40 use_breqn = Bool(
41 True,
41 True,
42 help="Use breqn.sty to automatically break long equations. "
42 help="Use breqn.sty to automatically break long equations. "
43 "This configuration takes effect only for dvipng backend.",
43 "This configuration takes effect only for dvipng backend.",
44 ).tag(config=True)
44 ).tag(config=True)
45
45
46 packages = List(
46 packages = List(
47 ['amsmath', 'amsthm', 'amssymb', 'bm'],
47 ['amsmath', 'amsthm', 'amssymb', 'bm'],
48 help="A list of packages to use for dvipng backend. "
48 help="A list of packages to use for dvipng backend. "
49 "'breqn' will be automatically appended when use_breqn=True.",
49 "'breqn' will be automatically appended when use_breqn=True.",
50 ).tag(config=True)
50 ).tag(config=True)
51
51
52 preamble = Unicode(
52 preamble = Unicode(
53 help="Additional preamble to use when generating LaTeX source "
53 help="Additional preamble to use when generating LaTeX source "
54 "for dvipng backend.",
54 "for dvipng backend.",
55 ).tag(config=True)
55 ).tag(config=True)
56
56
57
57
58 def latex_to_png(s, encode=False, backend=None, wrap=False):
58 def latex_to_png(s, encode=False, backend=None, wrap=False):
59 """Render a LaTeX string to PNG.
59 """Render a LaTeX string to PNG.
60
60
61 Parameters
61 Parameters
62 ----------
62 ----------
63 s : str
63 s : str
64 The raw string containing valid inline LaTeX.
64 The raw string containing valid inline LaTeX.
65 encode : bool, optional
65 encode : bool, optional
66 Should the PNG data base64 encoded to make it JSON'able.
66 Should the PNG data base64 encoded to make it JSON'able.
67 backend : {matplotlib, dvipng}
67 backend : {matplotlib, dvipng}
68 Backend for producing PNG data.
68 Backend for producing PNG data.
69 wrap : bool
69 wrap : bool
70 If true, Automatically wrap `s` as a LaTeX equation.
70 If true, Automatically wrap `s` as a LaTeX equation.
71
71
72 None is returned when the backend cannot be used.
72 None is returned when the backend cannot be used.
73
73
74 """
74 """
75 s = cast_unicode(s)
75 s = cast_unicode(s)
76 allowed_backends = LaTeXTool.instance().backends
76 allowed_backends = LaTeXTool.instance().backends
77 if backend is None:
77 if backend is None:
78 backend = allowed_backends[0]
78 backend = allowed_backends[0]
79 if backend not in allowed_backends:
79 if backend not in allowed_backends:
80 return None
80 return None
81 if backend == 'matplotlib':
81 if backend == 'matplotlib':
82 f = latex_to_png_mpl
82 f = latex_to_png_mpl
83 elif backend == 'dvipng':
83 elif backend == 'dvipng':
84 f = latex_to_png_dvipng
84 f = latex_to_png_dvipng
85 else:
85 else:
86 raise ValueError('No such backend {0}'.format(backend))
86 raise ValueError('No such backend {0}'.format(backend))
87 bin_data = f(s, wrap)
87 bin_data = f(s, wrap)
88 if encode and bin_data:
88 if encode and bin_data:
89 bin_data = encodebytes(bin_data)
89 bin_data = encodebytes(bin_data)
90 return bin_data
90 return bin_data
91
91
92
92
93 def latex_to_png_mpl(s, wrap):
93 def latex_to_png_mpl(s, wrap):
94 try:
94 try:
95 from matplotlib import mathtext
95 from matplotlib import mathtext
96 from pyparsing import ParseFatalException
96 from pyparsing import ParseFatalException
97 except ImportError:
97 except ImportError:
98 return None
98 return None
99
99
100 # mpl mathtext doesn't support display math, force inline
100 # mpl mathtext doesn't support display math, force inline
101 s = s.replace('$$', '$')
101 s = s.replace('$$', '$')
102 if wrap:
102 if wrap:
103 s = u'${0}$'.format(s)
103 s = u'${0}$'.format(s)
104
104
105 try:
105 try:
106 mt = mathtext.MathTextParser('bitmap')
106 mt = mathtext.MathTextParser('bitmap')
107 f = BytesIO()
107 f = BytesIO()
108 mt.to_png(f, s, fontsize=12)
108 mt.to_png(f, s, fontsize=12)
109 return f.getvalue()
109 return f.getvalue()
110 except (ValueError, RuntimeError, ParseFatalException):
110 except (ValueError, RuntimeError, ParseFatalException):
111 return None
111 return None
112
112
113
113
114 def latex_to_png_dvipng(s, wrap):
114 def latex_to_png_dvipng(s, wrap):
115 try:
115 try:
116 find_cmd('latex')
116 find_cmd('latex')
117 find_cmd('dvipng')
117 find_cmd('dvipng')
118 except FindCmdError:
118 except FindCmdError:
119 return None
119 return None
120 try:
120 try:
121 workdir = tempfile.mkdtemp()
121 workdir = tempfile.mkdtemp()
122 tmpfile = os.path.join(workdir, "tmp.tex")
122 tmpfile = os.path.join(workdir, "tmp.tex")
123 dvifile = os.path.join(workdir, "tmp.dvi")
123 dvifile = os.path.join(workdir, "tmp.dvi")
124 outfile = os.path.join(workdir, "tmp.png")
124 outfile = os.path.join(workdir, "tmp.png")
125
125
126 with open(tmpfile, "w", encoding='utf8') as f:
126 with open(tmpfile, "w", encoding='utf8') as f:
127 f.writelines(genelatex(s, wrap))
127 f.writelines(genelatex(s, wrap))
128
128
129 with open(os.devnull, 'wb') as devnull:
129 with open(os.devnull, 'wb') as devnull:
130 subprocess.check_call(
130 subprocess.check_call(
131 ["latex", "-halt-on-error", "-interaction", "batchmode", tmpfile],
131 ["latex", "-halt-on-error", "-interaction", "batchmode", tmpfile],
132 cwd=workdir, stdout=devnull, stderr=devnull)
132 cwd=workdir, stdout=devnull, stderr=devnull)
133
133
134 subprocess.check_call(
134 subprocess.check_call(
135 ["dvipng", "-T", "tight", "-x", "1500", "-z", "9",
135 ["dvipng", "-T", "tight", "-x", "1500", "-z", "9",
136 "-bg", "transparent", "-o", outfile, dvifile], cwd=workdir,
136 "-bg", "transparent", "-o", outfile, dvifile], cwd=workdir,
137 stdout=devnull, stderr=devnull)
137 stdout=devnull, stderr=devnull)
138
138
139 with open(outfile, "rb") as f:
139 with open(outfile, "rb") as f:
140 return f.read()
140 return f.read()
141 except subprocess.CalledProcessError:
141 except subprocess.CalledProcessError:
142 return None
142 return None
143 finally:
143 finally:
144 shutil.rmtree(workdir)
144 shutil.rmtree(workdir)
145
145
146
146
147 def kpsewhich(filename):
147 def kpsewhich(filename):
148 """Invoke kpsewhich command with an argument `filename`."""
148 """Invoke kpsewhich command with an argument `filename`."""
149 try:
149 try:
150 find_cmd("kpsewhich")
150 find_cmd("kpsewhich")
151 proc = subprocess.Popen(
151 proc = subprocess.Popen(
152 ["kpsewhich", filename],
152 ["kpsewhich", filename],
153 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
153 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
154 (stdout, stderr) = proc.communicate()
154 (stdout, stderr) = proc.communicate()
155 return stdout.strip().decode('utf8', 'replace')
155 return stdout.strip().decode('utf8', 'replace')
156 except FindCmdError:
156 except FindCmdError:
157 pass
157 pass
158
158
159
159
160 def genelatex(body, wrap):
160 def genelatex(body, wrap):
161 """Generate LaTeX document for dvipng backend."""
161 """Generate LaTeX document for dvipng backend."""
162 lt = LaTeXTool.instance()
162 lt = LaTeXTool.instance()
163 breqn = wrap and lt.use_breqn and kpsewhich("breqn.sty")
163 breqn = wrap and lt.use_breqn and kpsewhich("breqn.sty")
164 yield u(r'\documentclass{article}')
164 yield r'\documentclass{article}'
165 packages = lt.packages
165 packages = lt.packages
166 if breqn:
166 if breqn:
167 packages = packages + ['breqn']
167 packages = packages + ['breqn']
168 for pack in packages:
168 for pack in packages:
169 yield u(r'\usepackage{{{0}}}'.format(pack))
169 yield r'\usepackage{{{0}}}'.format(pack)
170 yield u(r'\pagestyle{empty}')
170 yield r'\pagestyle{empty}'
171 if lt.preamble:
171 if lt.preamble:
172 yield lt.preamble
172 yield lt.preamble
173 yield u(r'\begin{document}')
173 yield r'\begin{document}'
174 if breqn:
174 if breqn:
175 yield u(r'\begin{dmath*}')
175 yield r'\begin{dmath*}'
176 yield body
176 yield body
177 yield u(r'\end{dmath*}')
177 yield r'\end{dmath*}'
178 elif wrap:
178 elif wrap:
179 yield u'$${0}$$'.format(body)
179 yield u'$${0}$$'.format(body)
180 else:
180 else:
181 yield body
181 yield body
182 yield u'\end{document}'
182 yield u'\end{document}'
183
183
184
184
185 _data_uri_template_png = u"""<img src="data:image/png;base64,%s" alt=%s />"""
185 _data_uri_template_png = u"""<img src="data:image/png;base64,%s" alt=%s />"""
186
186
187 def latex_to_html(s, alt='image'):
187 def latex_to_html(s, alt='image'):
188 """Render LaTeX to HTML with embedded PNG data using data URIs.
188 """Render LaTeX to HTML with embedded PNG data using data URIs.
189
189
190 Parameters
190 Parameters
191 ----------
191 ----------
192 s : str
192 s : str
193 The raw string containing valid inline LateX.
193 The raw string containing valid inline LateX.
194 alt : str
194 alt : str
195 The alt text to use for the HTML.
195 The alt text to use for the HTML.
196 """
196 """
197 base64_data = latex_to_png(s, encode=True).decode('ascii')
197 base64_data = latex_to_png(s, encode=True).decode('ascii')
198 if base64_data:
198 if base64_data:
199 return _data_uri_template_png % (base64_data, alt)
199 return _data_uri_template_png % (base64_data, alt)
200
200
201
201
@@ -1,530 +1,530 b''
1 """IPython terminal interface using prompt_toolkit"""
1 """IPython terminal interface using prompt_toolkit"""
2
2
3 import os
3 import os
4 import sys
4 import sys
5 import warnings
5 import warnings
6 from warnings import warn
6 from warnings import warn
7
7
8 from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC
8 from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC
9 from IPython.utils import io
9 from IPython.utils import io
10 from IPython.utils.py3compat import cast_unicode_py2, input
10 from IPython.utils.py3compat import input
11 from IPython.utils.terminal import toggle_set_term_title, set_term_title
11 from IPython.utils.terminal import toggle_set_term_title, set_term_title
12 from IPython.utils.process import abbrev_cwd
12 from IPython.utils.process import abbrev_cwd
13 from traitlets import (
13 from traitlets import (
14 Bool, Unicode, Dict, Integer, observe, Instance, Type, default, Enum, Union,
14 Bool, Unicode, Dict, Integer, observe, Instance, Type, default, Enum, Union,
15 Any,
15 Any,
16 )
16 )
17
17
18 from prompt_toolkit.document import Document
18 from prompt_toolkit.document import Document
19 from prompt_toolkit.enums import DEFAULT_BUFFER, EditingMode
19 from prompt_toolkit.enums import DEFAULT_BUFFER, EditingMode
20 from prompt_toolkit.filters import (HasFocus, Condition, IsDone)
20 from prompt_toolkit.filters import (HasFocus, Condition, IsDone)
21 from prompt_toolkit.history import InMemoryHistory
21 from prompt_toolkit.history import InMemoryHistory
22 from prompt_toolkit.shortcuts import create_prompt_application, create_eventloop, create_prompt_layout, create_output
22 from prompt_toolkit.shortcuts import create_prompt_application, create_eventloop, create_prompt_layout, create_output
23 from prompt_toolkit.interface import CommandLineInterface
23 from prompt_toolkit.interface import CommandLineInterface
24 from prompt_toolkit.key_binding.manager import KeyBindingManager
24 from prompt_toolkit.key_binding.manager import KeyBindingManager
25 from prompt_toolkit.layout.processors import ConditionalProcessor, HighlightMatchingBracketProcessor
25 from prompt_toolkit.layout.processors import ConditionalProcessor, HighlightMatchingBracketProcessor
26 from prompt_toolkit.styles import PygmentsStyle, DynamicStyle
26 from prompt_toolkit.styles import PygmentsStyle, DynamicStyle
27
27
28 from pygments.styles import get_style_by_name, get_all_styles
28 from pygments.styles import get_style_by_name, get_all_styles
29 from pygments.style import Style
29 from pygments.style import Style
30 from pygments.token import Token
30 from pygments.token import Token
31
31
32 from .debugger import TerminalPdb, Pdb
32 from .debugger import TerminalPdb, Pdb
33 from .magics import TerminalMagics
33 from .magics import TerminalMagics
34 from .pt_inputhooks import get_inputhook_name_and_func
34 from .pt_inputhooks import get_inputhook_name_and_func
35 from .prompts import Prompts, ClassicPrompts, RichPromptDisplayHook
35 from .prompts import Prompts, ClassicPrompts, RichPromptDisplayHook
36 from .ptutils import IPythonPTCompleter, IPythonPTLexer
36 from .ptutils import IPythonPTCompleter, IPythonPTLexer
37 from .shortcuts import register_ipython_shortcuts
37 from .shortcuts import register_ipython_shortcuts
38
38
39 DISPLAY_BANNER_DEPRECATED = object()
39 DISPLAY_BANNER_DEPRECATED = object()
40
40
41
41
42 class _NoStyle(Style): pass
42 class _NoStyle(Style): pass
43
43
44
44
45
45
46 _style_overrides_light_bg = {
46 _style_overrides_light_bg = {
47 Token.Prompt: '#0000ff',
47 Token.Prompt: '#0000ff',
48 Token.PromptNum: '#0000ee bold',
48 Token.PromptNum: '#0000ee bold',
49 Token.OutPrompt: '#cc0000',
49 Token.OutPrompt: '#cc0000',
50 Token.OutPromptNum: '#bb0000 bold',
50 Token.OutPromptNum: '#bb0000 bold',
51 }
51 }
52
52
53 _style_overrides_linux = {
53 _style_overrides_linux = {
54 Token.Prompt: '#00cc00',
54 Token.Prompt: '#00cc00',
55 Token.PromptNum: '#00bb00 bold',
55 Token.PromptNum: '#00bb00 bold',
56 Token.OutPrompt: '#cc0000',
56 Token.OutPrompt: '#cc0000',
57 Token.OutPromptNum: '#bb0000 bold',
57 Token.OutPromptNum: '#bb0000 bold',
58 }
58 }
59
59
60
60
61
61
62 def get_default_editor():
62 def get_default_editor():
63 try:
63 try:
64 return os.environ['EDITOR']
64 return os.environ['EDITOR']
65 except KeyError:
65 except KeyError:
66 pass
66 pass
67 except UnicodeError:
67 except UnicodeError:
68 warn("$EDITOR environment variable is not pure ASCII. Using platform "
68 warn("$EDITOR environment variable is not pure ASCII. Using platform "
69 "default editor.")
69 "default editor.")
70
70
71 if os.name == 'posix':
71 if os.name == 'posix':
72 return 'vi' # the only one guaranteed to be there!
72 return 'vi' # the only one guaranteed to be there!
73 else:
73 else:
74 return 'notepad' # same in Windows!
74 return 'notepad' # same in Windows!
75
75
76 # conservatively check for tty
76 # conservatively check for tty
77 # overridden streams can result in things like:
77 # overridden streams can result in things like:
78 # - sys.stdin = None
78 # - sys.stdin = None
79 # - no isatty method
79 # - no isatty method
80 for _name in ('stdin', 'stdout', 'stderr'):
80 for _name in ('stdin', 'stdout', 'stderr'):
81 _stream = getattr(sys, _name)
81 _stream = getattr(sys, _name)
82 if not _stream or not hasattr(_stream, 'isatty') or not _stream.isatty():
82 if not _stream or not hasattr(_stream, 'isatty') or not _stream.isatty():
83 _is_tty = False
83 _is_tty = False
84 break
84 break
85 else:
85 else:
86 _is_tty = True
86 _is_tty = True
87
87
88
88
89 _use_simple_prompt = ('IPY_TEST_SIMPLE_PROMPT' in os.environ) or (not _is_tty)
89 _use_simple_prompt = ('IPY_TEST_SIMPLE_PROMPT' in os.environ) or (not _is_tty)
90
90
91 class TerminalInteractiveShell(InteractiveShell):
91 class TerminalInteractiveShell(InteractiveShell):
92 space_for_menu = Integer(6, help='Number of line at the bottom of the screen '
92 space_for_menu = Integer(6, help='Number of line at the bottom of the screen '
93 'to reserve for the completion menu'
93 'to reserve for the completion menu'
94 ).tag(config=True)
94 ).tag(config=True)
95
95
96 def _space_for_menu_changed(self, old, new):
96 def _space_for_menu_changed(self, old, new):
97 self._update_layout()
97 self._update_layout()
98
98
99 pt_cli = None
99 pt_cli = None
100 debugger_history = None
100 debugger_history = None
101 _pt_app = None
101 _pt_app = None
102
102
103 simple_prompt = Bool(_use_simple_prompt,
103 simple_prompt = Bool(_use_simple_prompt,
104 help="""Use `raw_input` for the REPL, without completion, multiline input, and prompt colors.
104 help="""Use `raw_input` for the REPL, without completion, multiline input, and prompt colors.
105
105
106 Useful when controlling IPython as a subprocess, and piping STDIN/OUT/ERR. Known usage are:
106 Useful when controlling IPython as a subprocess, and piping STDIN/OUT/ERR. Known usage are:
107 IPython own testing machinery, and emacs inferior-shell integration through elpy.
107 IPython own testing machinery, and emacs inferior-shell integration through elpy.
108
108
109 This mode default to `True` if the `IPY_TEST_SIMPLE_PROMPT`
109 This mode default to `True` if the `IPY_TEST_SIMPLE_PROMPT`
110 environment variable is set, or the current terminal is not a tty."""
110 environment variable is set, or the current terminal is not a tty."""
111 ).tag(config=True)
111 ).tag(config=True)
112
112
113 @property
113 @property
114 def debugger_cls(self):
114 def debugger_cls(self):
115 return Pdb if self.simple_prompt else TerminalPdb
115 return Pdb if self.simple_prompt else TerminalPdb
116
116
117 confirm_exit = Bool(True,
117 confirm_exit = Bool(True,
118 help="""
118 help="""
119 Set to confirm when you try to exit IPython with an EOF (Control-D
119 Set to confirm when you try to exit IPython with an EOF (Control-D
120 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
120 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
121 you can force a direct exit without any confirmation.""",
121 you can force a direct exit without any confirmation.""",
122 ).tag(config=True)
122 ).tag(config=True)
123
123
124 editing_mode = Unicode('emacs',
124 editing_mode = Unicode('emacs',
125 help="Shortcut style to use at the prompt. 'vi' or 'emacs'.",
125 help="Shortcut style to use at the prompt. 'vi' or 'emacs'.",
126 ).tag(config=True)
126 ).tag(config=True)
127
127
128 mouse_support = Bool(False,
128 mouse_support = Bool(False,
129 help="Enable mouse support in the prompt"
129 help="Enable mouse support in the prompt"
130 ).tag(config=True)
130 ).tag(config=True)
131
131
132 highlighting_style = Union([Unicode('legacy'), Type(klass=Style)],
132 highlighting_style = Union([Unicode('legacy'), Type(klass=Style)],
133 help="""The name or class of a Pygments style to use for syntax
133 help="""The name or class of a Pygments style to use for syntax
134 highlighting: \n %s""" % ', '.join(get_all_styles())
134 highlighting: \n %s""" % ', '.join(get_all_styles())
135 ).tag(config=True)
135 ).tag(config=True)
136
136
137
137
138 @observe('highlighting_style')
138 @observe('highlighting_style')
139 @observe('colors')
139 @observe('colors')
140 def _highlighting_style_changed(self, change):
140 def _highlighting_style_changed(self, change):
141 self.refresh_style()
141 self.refresh_style()
142
142
143 def refresh_style(self):
143 def refresh_style(self):
144 self._style = self._make_style_from_name_or_cls(self.highlighting_style)
144 self._style = self._make_style_from_name_or_cls(self.highlighting_style)
145
145
146
146
147 highlighting_style_overrides = Dict(
147 highlighting_style_overrides = Dict(
148 help="Override highlighting format for specific tokens"
148 help="Override highlighting format for specific tokens"
149 ).tag(config=True)
149 ).tag(config=True)
150
150
151 true_color = Bool(False,
151 true_color = Bool(False,
152 help=("Use 24bit colors instead of 256 colors in prompt highlighting. "
152 help=("Use 24bit colors instead of 256 colors in prompt highlighting. "
153 "If your terminal supports true color, the following command "
153 "If your terminal supports true color, the following command "
154 "should print 'TRUECOLOR' in orange: "
154 "should print 'TRUECOLOR' in orange: "
155 "printf \"\\x1b[38;2;255;100;0mTRUECOLOR\\x1b[0m\\n\"")
155 "printf \"\\x1b[38;2;255;100;0mTRUECOLOR\\x1b[0m\\n\"")
156 ).tag(config=True)
156 ).tag(config=True)
157
157
158 editor = Unicode(get_default_editor(),
158 editor = Unicode(get_default_editor(),
159 help="Set the editor used by IPython (default to $EDITOR/vi/notepad)."
159 help="Set the editor used by IPython (default to $EDITOR/vi/notepad)."
160 ).tag(config=True)
160 ).tag(config=True)
161
161
162 prompts_class = Type(Prompts, help='Class used to generate Prompt token for prompt_toolkit').tag(config=True)
162 prompts_class = Type(Prompts, help='Class used to generate Prompt token for prompt_toolkit').tag(config=True)
163
163
164 prompts = Instance(Prompts)
164 prompts = Instance(Prompts)
165
165
166 @default('prompts')
166 @default('prompts')
167 def _prompts_default(self):
167 def _prompts_default(self):
168 return self.prompts_class(self)
168 return self.prompts_class(self)
169
169
170 @observe('prompts')
170 @observe('prompts')
171 def _(self, change):
171 def _(self, change):
172 self._update_layout()
172 self._update_layout()
173
173
174 @default('displayhook_class')
174 @default('displayhook_class')
175 def _displayhook_class_default(self):
175 def _displayhook_class_default(self):
176 return RichPromptDisplayHook
176 return RichPromptDisplayHook
177
177
178 term_title = Bool(True,
178 term_title = Bool(True,
179 help="Automatically set the terminal title"
179 help="Automatically set the terminal title"
180 ).tag(config=True)
180 ).tag(config=True)
181
181
182 term_title_format = Unicode("IPython: {cwd}",
182 term_title_format = Unicode("IPython: {cwd}",
183 help="Customize the terminal title format. This is a python format string. " +
183 help="Customize the terminal title format. This is a python format string. " +
184 "Available substitutions are: {cwd}."
184 "Available substitutions are: {cwd}."
185 ).tag(config=True)
185 ).tag(config=True)
186
186
187 display_completions = Enum(('column', 'multicolumn','readlinelike'),
187 display_completions = Enum(('column', 'multicolumn','readlinelike'),
188 help= ( "Options for displaying tab completions, 'column', 'multicolumn', and "
188 help= ( "Options for displaying tab completions, 'column', 'multicolumn', and "
189 "'readlinelike'. These options are for `prompt_toolkit`, see "
189 "'readlinelike'. These options are for `prompt_toolkit`, see "
190 "`prompt_toolkit` documentation for more information."
190 "`prompt_toolkit` documentation for more information."
191 ),
191 ),
192 default_value='multicolumn').tag(config=True)
192 default_value='multicolumn').tag(config=True)
193
193
194 highlight_matching_brackets = Bool(True,
194 highlight_matching_brackets = Bool(True,
195 help="Highlight matching brackets.",
195 help="Highlight matching brackets.",
196 ).tag(config=True)
196 ).tag(config=True)
197
197
198 extra_open_editor_shortcuts = Bool(False,
198 extra_open_editor_shortcuts = Bool(False,
199 help="Enable vi (v) or Emacs (C-X C-E) shortcuts to open an external editor. "
199 help="Enable vi (v) or Emacs (C-X C-E) shortcuts to open an external editor. "
200 "This is in addition to the F2 binding, which is always enabled."
200 "This is in addition to the F2 binding, which is always enabled."
201 ).tag(config=True)
201 ).tag(config=True)
202
202
203 handle_return = Any(None,
203 handle_return = Any(None,
204 help="Provide an alternative handler to be called when the user presses "
204 help="Provide an alternative handler to be called when the user presses "
205 "Return. This is an advanced option intended for debugging, which "
205 "Return. This is an advanced option intended for debugging, which "
206 "may be changed or removed in later releases."
206 "may be changed or removed in later releases."
207 ).tag(config=True)
207 ).tag(config=True)
208
208
209 @observe('term_title')
209 @observe('term_title')
210 def init_term_title(self, change=None):
210 def init_term_title(self, change=None):
211 # Enable or disable the terminal title.
211 # Enable or disable the terminal title.
212 if self.term_title:
212 if self.term_title:
213 toggle_set_term_title(True)
213 toggle_set_term_title(True)
214 set_term_title(self.term_title_format.format(cwd=abbrev_cwd()))
214 set_term_title(self.term_title_format.format(cwd=abbrev_cwd()))
215 else:
215 else:
216 toggle_set_term_title(False)
216 toggle_set_term_title(False)
217
217
218 def init_display_formatter(self):
218 def init_display_formatter(self):
219 super(TerminalInteractiveShell, self).init_display_formatter()
219 super(TerminalInteractiveShell, self).init_display_formatter()
220 # terminal only supports plain text
220 # terminal only supports plain text
221 self.display_formatter.active_types = ['text/plain']
221 self.display_formatter.active_types = ['text/plain']
222 # disable `_ipython_display_`
222 # disable `_ipython_display_`
223 self.display_formatter.ipython_display_formatter.enabled = False
223 self.display_formatter.ipython_display_formatter.enabled = False
224
224
225 def init_prompt_toolkit_cli(self):
225 def init_prompt_toolkit_cli(self):
226 if self.simple_prompt:
226 if self.simple_prompt:
227 # Fall back to plain non-interactive output for tests.
227 # Fall back to plain non-interactive output for tests.
228 # This is very limited, and only accepts a single line.
228 # This is very limited, and only accepts a single line.
229 def prompt():
229 def prompt():
230 return cast_unicode_py2(input('In [%d]: ' % self.execution_count))
230 return input('In [%d]: ' % self.execution_count)
231 self.prompt_for_code = prompt
231 self.prompt_for_code = prompt
232 return
232 return
233
233
234 # Set up keyboard shortcuts
234 # Set up keyboard shortcuts
235 kbmanager = KeyBindingManager.for_prompt(
235 kbmanager = KeyBindingManager.for_prompt(
236 enable_open_in_editor=self.extra_open_editor_shortcuts,
236 enable_open_in_editor=self.extra_open_editor_shortcuts,
237 )
237 )
238 register_ipython_shortcuts(kbmanager.registry, self)
238 register_ipython_shortcuts(kbmanager.registry, self)
239
239
240 # Pre-populate history from IPython's history database
240 # Pre-populate history from IPython's history database
241 history = InMemoryHistory()
241 history = InMemoryHistory()
242 last_cell = u""
242 last_cell = u""
243 for __, ___, cell in self.history_manager.get_tail(self.history_load_length,
243 for __, ___, cell in self.history_manager.get_tail(self.history_load_length,
244 include_latest=True):
244 include_latest=True):
245 # Ignore blank lines and consecutive duplicates
245 # Ignore blank lines and consecutive duplicates
246 cell = cell.rstrip()
246 cell = cell.rstrip()
247 if cell and (cell != last_cell):
247 if cell and (cell != last_cell):
248 history.append(cell)
248 history.append(cell)
249 last_cell = cell
249 last_cell = cell
250
250
251 self._style = self._make_style_from_name_or_cls(self.highlighting_style)
251 self._style = self._make_style_from_name_or_cls(self.highlighting_style)
252 self.style = DynamicStyle(lambda: self._style)
252 self.style = DynamicStyle(lambda: self._style)
253
253
254 editing_mode = getattr(EditingMode, self.editing_mode.upper())
254 editing_mode = getattr(EditingMode, self.editing_mode.upper())
255
255
256 def patch_stdout(**kwargs):
256 def patch_stdout(**kwargs):
257 return self.pt_cli.patch_stdout_context(**kwargs)
257 return self.pt_cli.patch_stdout_context(**kwargs)
258
258
259 self._pt_app = create_prompt_application(
259 self._pt_app = create_prompt_application(
260 editing_mode=editing_mode,
260 editing_mode=editing_mode,
261 key_bindings_registry=kbmanager.registry,
261 key_bindings_registry=kbmanager.registry,
262 history=history,
262 history=history,
263 completer=IPythonPTCompleter(shell=self,
263 completer=IPythonPTCompleter(shell=self,
264 patch_stdout=patch_stdout),
264 patch_stdout=patch_stdout),
265 enable_history_search=True,
265 enable_history_search=True,
266 style=self.style,
266 style=self.style,
267 mouse_support=self.mouse_support,
267 mouse_support=self.mouse_support,
268 **self._layout_options()
268 **self._layout_options()
269 )
269 )
270 self._eventloop = create_eventloop(self.inputhook)
270 self._eventloop = create_eventloop(self.inputhook)
271 self.pt_cli = CommandLineInterface(
271 self.pt_cli = CommandLineInterface(
272 self._pt_app, eventloop=self._eventloop,
272 self._pt_app, eventloop=self._eventloop,
273 output=create_output(true_color=self.true_color))
273 output=create_output(true_color=self.true_color))
274
274
275 def _make_style_from_name_or_cls(self, name_or_cls):
275 def _make_style_from_name_or_cls(self, name_or_cls):
276 """
276 """
277 Small wrapper that make an IPython compatible style from a style name
277 Small wrapper that make an IPython compatible style from a style name
278
278
279 We need that to add style for prompt ... etc.
279 We need that to add style for prompt ... etc.
280 """
280 """
281 style_overrides = {}
281 style_overrides = {}
282 if name_or_cls == 'legacy':
282 if name_or_cls == 'legacy':
283 legacy = self.colors.lower()
283 legacy = self.colors.lower()
284 if legacy == 'linux':
284 if legacy == 'linux':
285 style_cls = get_style_by_name('monokai')
285 style_cls = get_style_by_name('monokai')
286 style_overrides = _style_overrides_linux
286 style_overrides = _style_overrides_linux
287 elif legacy == 'lightbg':
287 elif legacy == 'lightbg':
288 style_overrides = _style_overrides_light_bg
288 style_overrides = _style_overrides_light_bg
289 style_cls = get_style_by_name('pastie')
289 style_cls = get_style_by_name('pastie')
290 elif legacy == 'neutral':
290 elif legacy == 'neutral':
291 # The default theme needs to be visible on both a dark background
291 # The default theme needs to be visible on both a dark background
292 # and a light background, because we can't tell what the terminal
292 # and a light background, because we can't tell what the terminal
293 # looks like. These tweaks to the default theme help with that.
293 # looks like. These tweaks to the default theme help with that.
294 style_cls = get_style_by_name('default')
294 style_cls = get_style_by_name('default')
295 style_overrides.update({
295 style_overrides.update({
296 Token.Number: '#007700',
296 Token.Number: '#007700',
297 Token.Operator: 'noinherit',
297 Token.Operator: 'noinherit',
298 Token.String: '#BB6622',
298 Token.String: '#BB6622',
299 Token.Name.Function: '#2080D0',
299 Token.Name.Function: '#2080D0',
300 Token.Name.Class: 'bold #2080D0',
300 Token.Name.Class: 'bold #2080D0',
301 Token.Name.Namespace: 'bold #2080D0',
301 Token.Name.Namespace: 'bold #2080D0',
302 Token.Prompt: '#009900',
302 Token.Prompt: '#009900',
303 Token.PromptNum: '#00ff00 bold',
303 Token.PromptNum: '#00ff00 bold',
304 Token.OutPrompt: '#990000',
304 Token.OutPrompt: '#990000',
305 Token.OutPromptNum: '#ff0000 bold',
305 Token.OutPromptNum: '#ff0000 bold',
306 })
306 })
307
307
308 # Hack: Due to limited color support on the Windows console
308 # Hack: Due to limited color support on the Windows console
309 # the prompt colors will be wrong without this
309 # the prompt colors will be wrong without this
310 if os.name == 'nt':
310 if os.name == 'nt':
311 style_overrides.update({
311 style_overrides.update({
312 Token.Prompt: '#ansidarkgreen',
312 Token.Prompt: '#ansidarkgreen',
313 Token.PromptNum: '#ansigreen bold',
313 Token.PromptNum: '#ansigreen bold',
314 Token.OutPrompt: '#ansidarkred',
314 Token.OutPrompt: '#ansidarkred',
315 Token.OutPromptNum: '#ansired bold',
315 Token.OutPromptNum: '#ansired bold',
316 })
316 })
317 elif legacy =='nocolor':
317 elif legacy =='nocolor':
318 style_cls=_NoStyle
318 style_cls=_NoStyle
319 style_overrides = {}
319 style_overrides = {}
320 else :
320 else :
321 raise ValueError('Got unknown colors: ', legacy)
321 raise ValueError('Got unknown colors: ', legacy)
322 else :
322 else :
323 if isinstance(name_or_cls, str):
323 if isinstance(name_or_cls, str):
324 style_cls = get_style_by_name(name_or_cls)
324 style_cls = get_style_by_name(name_or_cls)
325 else:
325 else:
326 style_cls = name_or_cls
326 style_cls = name_or_cls
327 style_overrides = {
327 style_overrides = {
328 Token.Prompt: '#009900',
328 Token.Prompt: '#009900',
329 Token.PromptNum: '#00ff00 bold',
329 Token.PromptNum: '#00ff00 bold',
330 Token.OutPrompt: '#990000',
330 Token.OutPrompt: '#990000',
331 Token.OutPromptNum: '#ff0000 bold',
331 Token.OutPromptNum: '#ff0000 bold',
332 }
332 }
333 style_overrides.update(self.highlighting_style_overrides)
333 style_overrides.update(self.highlighting_style_overrides)
334 style = PygmentsStyle.from_defaults(pygments_style_cls=style_cls,
334 style = PygmentsStyle.from_defaults(pygments_style_cls=style_cls,
335 style_dict=style_overrides)
335 style_dict=style_overrides)
336
336
337 return style
337 return style
338
338
339 def _layout_options(self):
339 def _layout_options(self):
340 """
340 """
341 Return the current layout option for the current Terminal InteractiveShell
341 Return the current layout option for the current Terminal InteractiveShell
342 """
342 """
343 return {
343 return {
344 'lexer':IPythonPTLexer(),
344 'lexer':IPythonPTLexer(),
345 'reserve_space_for_menu':self.space_for_menu,
345 'reserve_space_for_menu':self.space_for_menu,
346 'get_prompt_tokens':self.prompts.in_prompt_tokens,
346 'get_prompt_tokens':self.prompts.in_prompt_tokens,
347 'get_continuation_tokens':self.prompts.continuation_prompt_tokens,
347 'get_continuation_tokens':self.prompts.continuation_prompt_tokens,
348 'multiline':True,
348 'multiline':True,
349 'display_completions_in_columns': (self.display_completions == 'multicolumn'),
349 'display_completions_in_columns': (self.display_completions == 'multicolumn'),
350
350
351 # Highlight matching brackets, but only when this setting is
351 # Highlight matching brackets, but only when this setting is
352 # enabled, and only when the DEFAULT_BUFFER has the focus.
352 # enabled, and only when the DEFAULT_BUFFER has the focus.
353 'extra_input_processors': [ConditionalProcessor(
353 'extra_input_processors': [ConditionalProcessor(
354 processor=HighlightMatchingBracketProcessor(chars='[](){}'),
354 processor=HighlightMatchingBracketProcessor(chars='[](){}'),
355 filter=HasFocus(DEFAULT_BUFFER) & ~IsDone() &
355 filter=HasFocus(DEFAULT_BUFFER) & ~IsDone() &
356 Condition(lambda cli: self.highlight_matching_brackets))],
356 Condition(lambda cli: self.highlight_matching_brackets))],
357 }
357 }
358
358
359 def _update_layout(self):
359 def _update_layout(self):
360 """
360 """
361 Ask for a re computation of the application layout, if for example ,
361 Ask for a re computation of the application layout, if for example ,
362 some configuration options have changed.
362 some configuration options have changed.
363 """
363 """
364 if self._pt_app:
364 if self._pt_app:
365 self._pt_app.layout = create_prompt_layout(**self._layout_options())
365 self._pt_app.layout = create_prompt_layout(**self._layout_options())
366
366
367 def prompt_for_code(self):
367 def prompt_for_code(self):
368 document = self.pt_cli.run(
368 document = self.pt_cli.run(
369 pre_run=self.pre_prompt, reset_current_buffer=True)
369 pre_run=self.pre_prompt, reset_current_buffer=True)
370 return document.text
370 return document.text
371
371
372 def enable_win_unicode_console(self):
372 def enable_win_unicode_console(self):
373 if sys.version_info >= (3, 6):
373 if sys.version_info >= (3, 6):
374 # Since PEP 528, Python uses the unicode APIs for the Windows
374 # Since PEP 528, Python uses the unicode APIs for the Windows
375 # console by default, so WUC shouldn't be needed.
375 # console by default, so WUC shouldn't be needed.
376 return
376 return
377
377
378 import win_unicode_console
378 import win_unicode_console
379 win_unicode_console.enable()
379 win_unicode_console.enable()
380
380
381 def init_io(self):
381 def init_io(self):
382 if sys.platform not in {'win32', 'cli'}:
382 if sys.platform not in {'win32', 'cli'}:
383 return
383 return
384
384
385 self.enable_win_unicode_console()
385 self.enable_win_unicode_console()
386
386
387 import colorama
387 import colorama
388 colorama.init()
388 colorama.init()
389
389
390 # For some reason we make these wrappers around stdout/stderr.
390 # For some reason we make these wrappers around stdout/stderr.
391 # For now, we need to reset them so all output gets coloured.
391 # For now, we need to reset them so all output gets coloured.
392 # https://github.com/ipython/ipython/issues/8669
392 # https://github.com/ipython/ipython/issues/8669
393 # io.std* are deprecated, but don't show our own deprecation warnings
393 # io.std* are deprecated, but don't show our own deprecation warnings
394 # during initialization of the deprecated API.
394 # during initialization of the deprecated API.
395 with warnings.catch_warnings():
395 with warnings.catch_warnings():
396 warnings.simplefilter('ignore', DeprecationWarning)
396 warnings.simplefilter('ignore', DeprecationWarning)
397 io.stdout = io.IOStream(sys.stdout)
397 io.stdout = io.IOStream(sys.stdout)
398 io.stderr = io.IOStream(sys.stderr)
398 io.stderr = io.IOStream(sys.stderr)
399
399
400 def init_magics(self):
400 def init_magics(self):
401 super(TerminalInteractiveShell, self).init_magics()
401 super(TerminalInteractiveShell, self).init_magics()
402 self.register_magics(TerminalMagics)
402 self.register_magics(TerminalMagics)
403
403
404 def init_alias(self):
404 def init_alias(self):
405 # The parent class defines aliases that can be safely used with any
405 # The parent class defines aliases that can be safely used with any
406 # frontend.
406 # frontend.
407 super(TerminalInteractiveShell, self).init_alias()
407 super(TerminalInteractiveShell, self).init_alias()
408
408
409 # Now define aliases that only make sense on the terminal, because they
409 # Now define aliases that only make sense on the terminal, because they
410 # need direct access to the console in a way that we can't emulate in
410 # need direct access to the console in a way that we can't emulate in
411 # GUI or web frontend
411 # GUI or web frontend
412 if os.name == 'posix':
412 if os.name == 'posix':
413 for cmd in ['clear', 'more', 'less', 'man']:
413 for cmd in ['clear', 'more', 'less', 'man']:
414 self.alias_manager.soft_define_alias(cmd, cmd)
414 self.alias_manager.soft_define_alias(cmd, cmd)
415
415
416
416
417 def __init__(self, *args, **kwargs):
417 def __init__(self, *args, **kwargs):
418 super(TerminalInteractiveShell, self).__init__(*args, **kwargs)
418 super(TerminalInteractiveShell, self).__init__(*args, **kwargs)
419 self.init_prompt_toolkit_cli()
419 self.init_prompt_toolkit_cli()
420 self.init_term_title()
420 self.init_term_title()
421 self.keep_running = True
421 self.keep_running = True
422
422
423 self.debugger_history = InMemoryHistory()
423 self.debugger_history = InMemoryHistory()
424
424
425 def ask_exit(self):
425 def ask_exit(self):
426 self.keep_running = False
426 self.keep_running = False
427
427
428 rl_next_input = None
428 rl_next_input = None
429
429
430 def pre_prompt(self):
430 def pre_prompt(self):
431 if self.rl_next_input:
431 if self.rl_next_input:
432 # We can't set the buffer here, because it will be reset just after
432 # We can't set the buffer here, because it will be reset just after
433 # this. Adding a callable to pre_run_callables does what we need
433 # this. Adding a callable to pre_run_callables does what we need
434 # after the buffer is reset.
434 # after the buffer is reset.
435 s = cast_unicode_py2(self.rl_next_input)
435 s = self.rl_next_input
436 def set_doc():
436 def set_doc():
437 self.pt_cli.application.buffer.document = Document(s)
437 self.pt_cli.application.buffer.document = Document(s)
438 if hasattr(self.pt_cli, 'pre_run_callables'):
438 if hasattr(self.pt_cli, 'pre_run_callables'):
439 self.pt_cli.pre_run_callables.append(set_doc)
439 self.pt_cli.pre_run_callables.append(set_doc)
440 else:
440 else:
441 # Older version of prompt_toolkit; it's OK to set the document
441 # Older version of prompt_toolkit; it's OK to set the document
442 # directly here.
442 # directly here.
443 set_doc()
443 set_doc()
444 self.rl_next_input = None
444 self.rl_next_input = None
445
445
446 def interact(self, display_banner=DISPLAY_BANNER_DEPRECATED):
446 def interact(self, display_banner=DISPLAY_BANNER_DEPRECATED):
447
447
448 if display_banner is not DISPLAY_BANNER_DEPRECATED:
448 if display_banner is not DISPLAY_BANNER_DEPRECATED:
449 warn('interact `display_banner` argument is deprecated since IPython 5.0. Call `show_banner()` if needed.', DeprecationWarning, stacklevel=2)
449 warn('interact `display_banner` argument is deprecated since IPython 5.0. Call `show_banner()` if needed.', DeprecationWarning, stacklevel=2)
450
450
451 self.keep_running = True
451 self.keep_running = True
452 while self.keep_running:
452 while self.keep_running:
453 print(self.separate_in, end='')
453 print(self.separate_in, end='')
454
454
455 try:
455 try:
456 code = self.prompt_for_code()
456 code = self.prompt_for_code()
457 except EOFError:
457 except EOFError:
458 if (not self.confirm_exit) \
458 if (not self.confirm_exit) \
459 or self.ask_yes_no('Do you really want to exit ([y]/n)?','y','n'):
459 or self.ask_yes_no('Do you really want to exit ([y]/n)?','y','n'):
460 self.ask_exit()
460 self.ask_exit()
461
461
462 else:
462 else:
463 if code:
463 if code:
464 self.run_cell(code, store_history=True)
464 self.run_cell(code, store_history=True)
465
465
466 def mainloop(self, display_banner=DISPLAY_BANNER_DEPRECATED):
466 def mainloop(self, display_banner=DISPLAY_BANNER_DEPRECATED):
467 # An extra layer of protection in case someone mashing Ctrl-C breaks
467 # An extra layer of protection in case someone mashing Ctrl-C breaks
468 # out of our internal code.
468 # out of our internal code.
469 if display_banner is not DISPLAY_BANNER_DEPRECATED:
469 if display_banner is not DISPLAY_BANNER_DEPRECATED:
470 warn('mainloop `display_banner` argument is deprecated since IPython 5.0. Call `show_banner()` if needed.', DeprecationWarning, stacklevel=2)
470 warn('mainloop `display_banner` argument is deprecated since IPython 5.0. Call `show_banner()` if needed.', DeprecationWarning, stacklevel=2)
471 while True:
471 while True:
472 try:
472 try:
473 self.interact()
473 self.interact()
474 break
474 break
475 except KeyboardInterrupt as e:
475 except KeyboardInterrupt as e:
476 print("\n%s escaped interact()\n" % type(e).__name__)
476 print("\n%s escaped interact()\n" % type(e).__name__)
477 finally:
477 finally:
478 # An interrupt during the eventloop will mess up the
478 # An interrupt during the eventloop will mess up the
479 # internal state of the prompt_toolkit library.
479 # internal state of the prompt_toolkit library.
480 # Stopping the eventloop fixes this, see
480 # Stopping the eventloop fixes this, see
481 # https://github.com/ipython/ipython/pull/9867
481 # https://github.com/ipython/ipython/pull/9867
482 if hasattr(self, '_eventloop'):
482 if hasattr(self, '_eventloop'):
483 self._eventloop.stop()
483 self._eventloop.stop()
484
484
485 _inputhook = None
485 _inputhook = None
486 def inputhook(self, context):
486 def inputhook(self, context):
487 if self._inputhook is not None:
487 if self._inputhook is not None:
488 self._inputhook(context)
488 self._inputhook(context)
489
489
490 active_eventloop = None
490 active_eventloop = None
491 def enable_gui(self, gui=None):
491 def enable_gui(self, gui=None):
492 if gui:
492 if gui:
493 self.active_eventloop, self._inputhook =\
493 self.active_eventloop, self._inputhook =\
494 get_inputhook_name_and_func(gui)
494 get_inputhook_name_and_func(gui)
495 else:
495 else:
496 self.active_eventloop = self._inputhook = None
496 self.active_eventloop = self._inputhook = None
497
497
498 # Run !system commands directly, not through pipes, so terminal programs
498 # Run !system commands directly, not through pipes, so terminal programs
499 # work correctly.
499 # work correctly.
500 system = InteractiveShell.system_raw
500 system = InteractiveShell.system_raw
501
501
502 def auto_rewrite_input(self, cmd):
502 def auto_rewrite_input(self, cmd):
503 """Overridden from the parent class to use fancy rewriting prompt"""
503 """Overridden from the parent class to use fancy rewriting prompt"""
504 if not self.show_rewritten_input:
504 if not self.show_rewritten_input:
505 return
505 return
506
506
507 tokens = self.prompts.rewrite_prompt_tokens()
507 tokens = self.prompts.rewrite_prompt_tokens()
508 if self.pt_cli:
508 if self.pt_cli:
509 self.pt_cli.print_tokens(tokens)
509 self.pt_cli.print_tokens(tokens)
510 print(cmd)
510 print(cmd)
511 else:
511 else:
512 prompt = ''.join(s for t, s in tokens)
512 prompt = ''.join(s for t, s in tokens)
513 print(prompt, cmd, sep='')
513 print(prompt, cmd, sep='')
514
514
515 _prompts_before = None
515 _prompts_before = None
516 def switch_doctest_mode(self, mode):
516 def switch_doctest_mode(self, mode):
517 """Switch prompts to classic for %doctest_mode"""
517 """Switch prompts to classic for %doctest_mode"""
518 if mode:
518 if mode:
519 self._prompts_before = self.prompts
519 self._prompts_before = self.prompts
520 self.prompts = ClassicPrompts(self)
520 self.prompts = ClassicPrompts(self)
521 elif self._prompts_before:
521 elif self._prompts_before:
522 self.prompts = self._prompts_before
522 self.prompts = self._prompts_before
523 self._prompts_before = None
523 self._prompts_before = None
524 self._update_layout()
524 self._update_layout()
525
525
526
526
527 InteractiveShellABC.register(TerminalInteractiveShell)
527 InteractiveShellABC.register(TerminalInteractiveShell)
528
528
529 if __name__ == '__main__':
529 if __name__ == '__main__':
530 TerminalInteractiveShell.instance().interact()
530 TerminalInteractiveShell.instance().interact()
@@ -1,127 +1,125 b''
1 """Token-related utilities"""
1 """Token-related utilities"""
2
2
3 # Copyright (c) IPython Development Team.
3 # Copyright (c) IPython Development Team.
4 # Distributed under the terms of the Modified BSD License.
4 # Distributed under the terms of the Modified BSD License.
5
5
6
7 from collections import namedtuple
6 from collections import namedtuple
8 from io import StringIO
7 from io import StringIO
9 from keyword import iskeyword
8 from keyword import iskeyword
10
9
11 from . import tokenize2
10 from . import tokenize2
12 from .py3compat import cast_unicode_py2
11
13
12
14 Token = namedtuple('Token', ['token', 'text', 'start', 'end', 'line'])
13 Token = namedtuple('Token', ['token', 'text', 'start', 'end', 'line'])
15
14
16 def generate_tokens(readline):
15 def generate_tokens(readline):
17 """wrap generate_tokens to catch EOF errors"""
16 """wrap generate_tokens to catch EOF errors"""
18 try:
17 try:
19 for token in tokenize2.generate_tokens(readline):
18 for token in tokenize2.generate_tokens(readline):
20 yield token
19 yield token
21 except tokenize2.TokenError:
20 except tokenize2.TokenError:
22 # catch EOF error
21 # catch EOF error
23 return
22 return
24
23
25 def line_at_cursor(cell, cursor_pos=0):
24 def line_at_cursor(cell, cursor_pos=0):
26 """Return the line in a cell at a given cursor position
25 """Return the line in a cell at a given cursor position
27
26
28 Used for calling line-based APIs that don't support multi-line input, yet.
27 Used for calling line-based APIs that don't support multi-line input, yet.
29
28
30 Parameters
29 Parameters
31 ----------
30 ----------
32
31
33 cell: str
32 cell: str
34 multiline block of text
33 multiline block of text
35 cursor_pos: integer
34 cursor_pos: integer
36 the cursor position
35 the cursor position
37
36
38 Returns
37 Returns
39 -------
38 -------
40
39
41 (line, offset): (string, integer)
40 (line, offset): (string, integer)
42 The line with the current cursor, and the character offset of the start of the line.
41 The line with the current cursor, and the character offset of the start of the line.
43 """
42 """
44 offset = 0
43 offset = 0
45 lines = cell.splitlines(True)
44 lines = cell.splitlines(True)
46 for line in lines:
45 for line in lines:
47 next_offset = offset + len(line)
46 next_offset = offset + len(line)
48 if next_offset >= cursor_pos:
47 if next_offset >= cursor_pos:
49 break
48 break
50 offset = next_offset
49 offset = next_offset
51 else:
50 else:
52 line = ""
51 line = ""
53 return (line, offset)
52 return (line, offset)
54
53
55 def token_at_cursor(cell, cursor_pos=0):
54 def token_at_cursor(cell, cursor_pos=0):
56 """Get the token at a given cursor
55 """Get the token at a given cursor
57
56
58 Used for introspection.
57 Used for introspection.
59
58
60 Function calls are prioritized, so the token for the callable will be returned
59 Function calls are prioritized, so the token for the callable will be returned
61 if the cursor is anywhere inside the call.
60 if the cursor is anywhere inside the call.
62
61
63 Parameters
62 Parameters
64 ----------
63 ----------
65
64
66 cell : unicode
65 cell : unicode
67 A block of Python code
66 A block of Python code
68 cursor_pos : int
67 cursor_pos : int
69 The location of the cursor in the block where the token should be found
68 The location of the cursor in the block where the token should be found
70 """
69 """
71 cell = cast_unicode_py2(cell)
72 names = []
70 names = []
73 tokens = []
71 tokens = []
74 call_names = []
72 call_names = []
75
73
76 offsets = {1: 0} # lines start at 1
74 offsets = {1: 0} # lines start at 1
77 for tup in generate_tokens(StringIO(cell).readline):
75 for tup in generate_tokens(StringIO(cell).readline):
78
76
79 tok = Token(*tup)
77 tok = Token(*tup)
80
78
81 # token, text, start, end, line = tup
79 # token, text, start, end, line = tup
82 start_line, start_col = tok.start
80 start_line, start_col = tok.start
83 end_line, end_col = tok.end
81 end_line, end_col = tok.end
84 if end_line + 1 not in offsets:
82 if end_line + 1 not in offsets:
85 # keep track of offsets for each line
83 # keep track of offsets for each line
86 lines = tok.line.splitlines(True)
84 lines = tok.line.splitlines(True)
87 for lineno, line in enumerate(lines, start_line + 1):
85 for lineno, line in enumerate(lines, start_line + 1):
88 if lineno not in offsets:
86 if lineno not in offsets:
89 offsets[lineno] = offsets[lineno-1] + len(line)
87 offsets[lineno] = offsets[lineno-1] + len(line)
90
88
91 offset = offsets[start_line]
89 offset = offsets[start_line]
92 # allow '|foo' to find 'foo' at the beginning of a line
90 # allow '|foo' to find 'foo' at the beginning of a line
93 boundary = cursor_pos + 1 if start_col == 0 else cursor_pos
91 boundary = cursor_pos + 1 if start_col == 0 else cursor_pos
94 if offset + start_col >= boundary:
92 if offset + start_col >= boundary:
95 # current token starts after the cursor,
93 # current token starts after the cursor,
96 # don't consume it
94 # don't consume it
97 break
95 break
98
96
99 if tok.token == tokenize2.NAME and not iskeyword(tok.text):
97 if tok.token == tokenize2.NAME and not iskeyword(tok.text):
100 if names and tokens and tokens[-1].token == tokenize2.OP and tokens[-1].text == '.':
98 if names and tokens and tokens[-1].token == tokenize2.OP and tokens[-1].text == '.':
101 names[-1] = "%s.%s" % (names[-1], tok.text)
99 names[-1] = "%s.%s" % (names[-1], tok.text)
102 else:
100 else:
103 names.append(tok.text)
101 names.append(tok.text)
104 elif tok.token == tokenize2.OP:
102 elif tok.token == tokenize2.OP:
105 if tok.text == '=' and names:
103 if tok.text == '=' and names:
106 # don't inspect the lhs of an assignment
104 # don't inspect the lhs of an assignment
107 names.pop(-1)
105 names.pop(-1)
108 if tok.text == '(' and names:
106 if tok.text == '(' and names:
109 # if we are inside a function call, inspect the function
107 # if we are inside a function call, inspect the function
110 call_names.append(names[-1])
108 call_names.append(names[-1])
111 elif tok.text == ')' and call_names:
109 elif tok.text == ')' and call_names:
112 call_names.pop(-1)
110 call_names.pop(-1)
113
111
114 tokens.append(tok)
112 tokens.append(tok)
115
113
116 if offsets[end_line] + end_col > cursor_pos:
114 if offsets[end_line] + end_col > cursor_pos:
117 # we found the cursor, stop reading
115 # we found the cursor, stop reading
118 break
116 break
119
117
120 if call_names:
118 if call_names:
121 return call_names[-1]
119 return call_names[-1]
122 elif names:
120 elif names:
123 return names[-1]
121 return names[-1]
124 else:
122 else:
125 return ''
123 return ''
126
124
127
125
General Comments 0
You need to be logged in to leave comments. Login now