##// END OF EJS Templates
fix some deprecations...
Min RK -
Show More

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

@@ -1,295 +1,295 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Displayhook for IPython.
3 3
4 4 This defines a callable class that IPython uses for `sys.displayhook`.
5 5 """
6 6
7 7 # Copyright (c) IPython Development Team.
8 8 # Distributed under the terms of the Modified BSD License.
9 9
10 10 from __future__ import print_function
11 11
12 12 import sys
13 13 import io as _io
14 14 import tokenize
15 15
16 16 from traitlets.config.configurable import Configurable
17 17 from IPython.utils.py3compat import builtin_mod, cast_unicode_py2
18 18 from traitlets import Instance, Float
19 19 from warnings import warn
20 20
21 21 # TODO: Move the various attributes (cache_size, [others now moved]). Some
22 22 # of these are also attributes of InteractiveShell. They should be on ONE object
23 23 # only and the other objects should ask that one object for their values.
24 24
25 25 class DisplayHook(Configurable):
26 26 """The custom IPython displayhook to replace sys.displayhook.
27 27
28 28 This class does many things, but the basic idea is that it is a callable
29 29 that gets called anytime user code returns a value.
30 30 """
31 31
32 32 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC',
33 33 allow_none=True)
34 34 exec_result = Instance('IPython.core.interactiveshell.ExecutionResult',
35 35 allow_none=True)
36 36 cull_fraction = Float(0.2)
37 37
38 38 def __init__(self, shell=None, cache_size=1000, **kwargs):
39 39 super(DisplayHook, self).__init__(shell=shell, **kwargs)
40 40 cache_size_min = 3
41 41 if cache_size <= 0:
42 42 self.do_full_cache = 0
43 43 cache_size = 0
44 44 elif cache_size < cache_size_min:
45 45 self.do_full_cache = 0
46 46 cache_size = 0
47 47 warn('caching was disabled (min value for cache size is %s).' %
48 48 cache_size_min,level=3)
49 49 else:
50 50 self.do_full_cache = 1
51 51
52 52 self.cache_size = cache_size
53 53
54 54 # we need a reference to the user-level namespace
55 55 self.shell = shell
56 56
57 57 self._,self.__,self.___ = '','',''
58 58
59 59 # these are deliberately global:
60 60 to_user_ns = {'_':self._,'__':self.__,'___':self.___}
61 61 self.shell.user_ns.update(to_user_ns)
62 62
63 63 @property
64 64 def prompt_count(self):
65 65 return self.shell.execution_count
66 66
67 67 #-------------------------------------------------------------------------
68 68 # Methods used in __call__. Override these methods to modify the behavior
69 69 # of the displayhook.
70 70 #-------------------------------------------------------------------------
71 71
72 72 def check_for_underscore(self):
73 73 """Check if the user has set the '_' variable by hand."""
74 74 # If something injected a '_' variable in __builtin__, delete
75 75 # ipython's automatic one so we don't clobber that. gettext() in
76 76 # particular uses _, so we need to stay away from it.
77 77 if '_' in builtin_mod.__dict__:
78 78 try:
79 79 del self.shell.user_ns['_']
80 80 except KeyError:
81 81 pass
82 82
83 83 def quiet(self):
84 84 """Should we silence the display hook because of ';'?"""
85 85 # do not print output if input ends in ';'
86 86
87 87 try:
88 88 cell = cast_unicode_py2(self.shell.history_manager.input_hist_parsed[-1])
89 89 except IndexError:
90 90 # some uses of ipshellembed may fail here
91 91 return False
92 92
93 93 sio = _io.StringIO(cell)
94 94 tokens = list(tokenize.generate_tokens(sio.readline))
95 95
96 96 for token in reversed(tokens):
97 97 if token[0] in (tokenize.ENDMARKER, tokenize.NL, tokenize.NEWLINE, tokenize.COMMENT):
98 98 continue
99 99 if (token[0] == tokenize.OP) and (token[1] == ';'):
100 100 return True
101 101 else:
102 102 return False
103 103
104 104 def start_displayhook(self):
105 105 """Start the displayhook, initializing resources."""
106 106 pass
107 107
108 108 def write_output_prompt(self):
109 109 """Write the output prompt.
110 110
111 111 The default implementation simply writes the prompt to
112 ``io.stdout``.
112 ``sys.stdout``.
113 113 """
114 114 # Use write, not print which adds an extra space.
115 115 sys.stdout.write(self.shell.separate_out)
116 116 outprompt = 'Out[{}]: '.format(self.shell.execution_count)
117 117 if self.do_full_cache:
118 118 sys.stdout.write(outprompt)
119 119
120 120 def compute_format_data(self, result):
121 121 """Compute format data of the object to be displayed.
122 122
123 123 The format data is a generalization of the :func:`repr` of an object.
124 124 In the default implementation the format data is a :class:`dict` of
125 125 key value pair where the keys are valid MIME types and the values
126 126 are JSON'able data structure containing the raw data for that MIME
127 127 type. It is up to frontends to determine pick a MIME to to use and
128 128 display that data in an appropriate manner.
129 129
130 130 This method only computes the format data for the object and should
131 131 NOT actually print or write that to a stream.
132 132
133 133 Parameters
134 134 ----------
135 135 result : object
136 136 The Python object passed to the display hook, whose format will be
137 137 computed.
138 138
139 139 Returns
140 140 -------
141 141 (format_dict, md_dict) : dict
142 142 format_dict is a :class:`dict` whose keys are valid MIME types and values are
143 143 JSON'able raw data for that MIME type. It is recommended that
144 144 all return values of this should always include the "text/plain"
145 145 MIME type representation of the object.
146 146 md_dict is a :class:`dict` with the same MIME type keys
147 147 of metadata associated with each output.
148 148
149 149 """
150 150 return self.shell.display_formatter.format(result)
151 151
152 152 # This can be set to True by the write_output_prompt method in a subclass
153 153 prompt_end_newline = False
154 154
155 155 def write_format_data(self, format_dict, md_dict=None):
156 156 """Write the format data dict to the frontend.
157 157
158 158 This default version of this method simply writes the plain text
159 representation of the object to ``io.stdout``. Subclasses should
159 representation of the object to ``sys.stdout``. Subclasses should
160 160 override this method to send the entire `format_dict` to the
161 161 frontends.
162 162
163 163 Parameters
164 164 ----------
165 165 format_dict : dict
166 166 The format dict for the object passed to `sys.displayhook`.
167 167 md_dict : dict (optional)
168 168 The metadata dict to be associated with the display data.
169 169 """
170 170 if 'text/plain' not in format_dict:
171 171 # nothing to do
172 172 return
173 173 # We want to print because we want to always make sure we have a
174 174 # newline, even if all the prompt separators are ''. This is the
175 175 # standard IPython behavior.
176 176 result_repr = format_dict['text/plain']
177 177 if '\n' in result_repr:
178 178 # So that multi-line strings line up with the left column of
179 179 # the screen, instead of having the output prompt mess up
180 180 # their first line.
181 181 # We use the prompt template instead of the expanded prompt
182 182 # because the expansion may add ANSI escapes that will interfere
183 183 # with our ability to determine whether or not we should add
184 184 # a newline.
185 185 if not self.prompt_end_newline:
186 186 # But avoid extraneous empty lines.
187 187 result_repr = '\n' + result_repr
188 188
189 189 print(result_repr)
190 190
191 191 def update_user_ns(self, result):
192 192 """Update user_ns with various things like _, __, _1, etc."""
193 193
194 194 # Avoid recursive reference when displaying _oh/Out
195 195 if result is not self.shell.user_ns['_oh']:
196 196 if len(self.shell.user_ns['_oh']) >= self.cache_size and self.do_full_cache:
197 197 self.cull_cache()
198 198 # Don't overwrite '_' and friends if '_' is in __builtin__ (otherwise
199 199 # we cause buggy behavior for things like gettext).
200 200
201 201 if '_' not in builtin_mod.__dict__:
202 202 self.___ = self.__
203 203 self.__ = self._
204 204 self._ = result
205 205 self.shell.push({'_':self._,
206 206 '__':self.__,
207 207 '___':self.___}, interactive=False)
208 208
209 209 # hackish access to top-level namespace to create _1,_2... dynamically
210 210 to_main = {}
211 211 if self.do_full_cache:
212 212 new_result = '_'+repr(self.prompt_count)
213 213 to_main[new_result] = result
214 214 self.shell.push(to_main, interactive=False)
215 215 self.shell.user_ns['_oh'][self.prompt_count] = result
216 216
217 217 def fill_exec_result(self, result):
218 218 if self.exec_result is not None:
219 219 self.exec_result.result = result
220 220
221 221 def log_output(self, format_dict):
222 222 """Log the output."""
223 223 if 'text/plain' not in format_dict:
224 224 # nothing to do
225 225 return
226 226 if self.shell.logger.log_output:
227 227 self.shell.logger.log_write(format_dict['text/plain'], 'output')
228 228 self.shell.history_manager.output_hist_reprs[self.prompt_count] = \
229 229 format_dict['text/plain']
230 230
231 231 def finish_displayhook(self):
232 232 """Finish up all displayhook activities."""
233 233 sys.stdout.write(self.shell.separate_out2)
234 234 sys.stdout.flush()
235 235
236 236 def __call__(self, result=None):
237 237 """Printing with history cache management.
238 238
239 239 This is invoked everytime the interpreter needs to print, and is
240 240 activated by setting the variable sys.displayhook to it.
241 241 """
242 242 self.check_for_underscore()
243 243 if result is not None and not self.quiet():
244 244 self.start_displayhook()
245 245 self.write_output_prompt()
246 246 format_dict, md_dict = self.compute_format_data(result)
247 247 self.update_user_ns(result)
248 248 self.fill_exec_result(result)
249 249 if format_dict:
250 250 self.write_format_data(format_dict, md_dict)
251 251 self.log_output(format_dict)
252 252 self.finish_displayhook()
253 253
254 254 def cull_cache(self):
255 255 """Output cache is full, cull the oldest entries"""
256 256 oh = self.shell.user_ns.get('_oh', {})
257 257 sz = len(oh)
258 258 cull_count = max(int(sz * self.cull_fraction), 2)
259 259 warn('Output cache limit (currently {sz} entries) hit.\n'
260 260 'Flushing oldest {cull_count} entries.'.format(sz=sz, cull_count=cull_count))
261 261
262 262 for i, n in enumerate(sorted(oh)):
263 263 if i >= cull_count:
264 264 break
265 265 self.shell.user_ns.pop('_%i' % n, None)
266 266 oh.pop(n, None)
267 267
268 268
269 269 def flush(self):
270 270 if not self.do_full_cache:
271 271 raise ValueError("You shouldn't have reached the cache flush "
272 272 "if full caching is not enabled!")
273 273 # delete auto-generated vars from global namespace
274 274
275 275 for n in range(1,self.prompt_count + 1):
276 276 key = '_'+repr(n)
277 277 try:
278 278 del self.shell.user_ns[key]
279 279 except: pass
280 280 # In some embedded circumstances, the user_ns doesn't have the
281 281 # '_oh' key set up.
282 282 oh = self.shell.user_ns.get('_oh', None)
283 283 if oh is not None:
284 284 oh.clear()
285 285
286 286 # Release our own references to objects:
287 287 self._, self.__, self.___ = '', '', ''
288 288
289 289 if '_' not in builtin_mod.__dict__:
290 290 self.shell.user_ns.update({'_':None,'__':None, '___':None})
291 291 import gc
292 292 # TODO: Is this really needed?
293 293 # IronPython blocks here forever
294 294 if sys.platform != "cli":
295 295 gc.collect()
@@ -1,117 +1,117 b''
1 1 """An interface for publishing rich data to frontends.
2 2
3 3 There are two components of the display system:
4 4
5 5 * Display formatters, which take a Python object and compute the
6 6 representation of the object in various formats (text, HTML, SVG, etc.).
7 7 * The display publisher that is used to send the representation data to the
8 8 various frontends.
9 9
10 10 This module defines the logic display publishing. The display publisher uses
11 11 the ``display_data`` message type that is defined in the IPython messaging
12 12 spec.
13 13 """
14 14
15 15 # Copyright (c) IPython Development Team.
16 16 # Distributed under the terms of the Modified BSD License.
17 17
18 18 from __future__ import print_function
19 19
20 20 import sys
21 21
22 22 from traitlets.config.configurable import Configurable
23 23 from traitlets import List
24 24
25 25 # This used to be defined here - it is imported for backwards compatibility
26 26 from .display import publish_display_data
27 27
28 28 #-----------------------------------------------------------------------------
29 29 # Main payload class
30 30 #-----------------------------------------------------------------------------
31 31
32 32 class DisplayPublisher(Configurable):
33 33 """A traited class that publishes display data to frontends.
34 34
35 35 Instances of this class are created by the main IPython object and should
36 36 be accessed there.
37 37 """
38 38
39 39 def _validate_data(self, data, metadata=None):
40 40 """Validate the display data.
41 41
42 42 Parameters
43 43 ----------
44 44 data : dict
45 45 The formata data dictionary.
46 46 metadata : dict
47 47 Any metadata for the data.
48 48 """
49 49
50 50 if not isinstance(data, dict):
51 51 raise TypeError('data must be a dict, got: %r' % data)
52 52 if metadata is not None:
53 53 if not isinstance(metadata, dict):
54 54 raise TypeError('metadata must be a dict, got: %r' % data)
55 55
56 56 def publish(self, data, metadata=None, source=None):
57 57 """Publish data and metadata to all frontends.
58 58
59 59 See the ``display_data`` message in the messaging documentation for
60 60 more details about this message type.
61 61
62 62 The following MIME types are currently implemented:
63 63
64 64 * text/plain
65 65 * text/html
66 66 * text/markdown
67 67 * text/latex
68 68 * application/json
69 69 * application/javascript
70 70 * image/png
71 71 * image/jpeg
72 72 * image/svg+xml
73 73
74 74 Parameters
75 75 ----------
76 76 data : dict
77 77 A dictionary having keys that are valid MIME types (like
78 78 'text/plain' or 'image/svg+xml') and values that are the data for
79 79 that MIME type. The data itself must be a JSON'able data
80 80 structure. Minimally all data should have the 'text/plain' data,
81 81 which can be displayed by all frontends. If more than the plain
82 82 text is given, it is up to the frontend to decide which
83 83 representation to use.
84 84 metadata : dict
85 85 A dictionary for metadata related to the data. This can contain
86 86 arbitrary key, value pairs that frontends can use to interpret
87 87 the data. Metadata specific to each mime-type can be specified
88 88 in the metadata dict with the same mime-type keys as
89 89 the data itself.
90 90 source : str, deprecated
91 91 Unused.
92 92 """
93 93
94 # The default is to simply write the plain text data using io.stdout.
94 # The default is to simply write the plain text data using sys.stdout.
95 95 if 'text/plain' in data:
96 96 print(data['text/plain'])
97 97
98 98 def clear_output(self, wait=False):
99 99 """Clear the output of the cell receiving output."""
100 100 print('\033[2K\r', end='')
101 101 sys.stdout.flush()
102 102 print('\033[2K\r', end='')
103 103 sys.stderr.flush()
104 104
105 105
106 106 class CapturingDisplayPublisher(DisplayPublisher):
107 107 """A DisplayPublisher that stores"""
108 108 outputs = List()
109 109
110 110 def publish(self, data, metadata=None, source=None):
111 111 self.outputs.append((data, metadata))
112 112
113 113 def clear_output(self, wait=False):
114 114 super(CapturingDisplayPublisher, self).clear_output(wait)
115 115
116 116 # empty the list, *do not* reassign a new list
117 117 del self.outputs[:]
@@ -1,945 +1,947 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Display formatters.
3 3
4 4 Inheritance diagram:
5 5
6 6 .. inheritance-diagram:: IPython.core.formatters
7 7 :parts: 3
8 8 """
9 9
10 10 # Copyright (c) IPython Development Team.
11 11 # Distributed under the terms of the Modified BSD License.
12 12
13 13 import abc
14 14 import json
15 15 import sys
16 16 import traceback
17 17 import warnings
18 18
19 19 from decorator import decorator
20 20
21 21 from traitlets.config.configurable import Configurable
22 22 from IPython.core.getipython import get_ipython
23 23 from IPython.utils.sentinel import Sentinel
24 24 from IPython.utils.dir2 import get_real_method
25 25 from IPython.lib import pretty
26 26 from traitlets import (
27 27 Bool, Dict, Integer, Unicode, CUnicode, ObjectName, List,
28 28 ForwardDeclaredInstance,
29 29 default, observe,
30 30 )
31 31 from IPython.utils.py3compat import (
32 32 with_metaclass, string_types, unicode_type,
33 33 )
34 34
35 35
36 36 class DisplayFormatter(Configurable):
37 37
38 38 active_types = List(Unicode(),
39 39 help="""List of currently active mime-types to display.
40 40 You can use this to set a white-list for formats to display.
41 41
42 42 Most users will not need to change this value.
43 43 """).tag(config=True)
44 44
45 45 @default('active_types')
46 46 def _active_types_default(self):
47 47 return self.format_types
48 48
49 49 @observe('active_types')
50 50 def _active_types_changed(self, change):
51 51 for key, formatter in self.formatters.items():
52 52 if key in change['new']:
53 53 formatter.enabled = True
54 54 else:
55 55 formatter.enabled = False
56 56
57 57 ipython_display_formatter = ForwardDeclaredInstance('FormatterABC')
58 58 @default('ipython_display_formatter')
59 59 def _default_formatter(self):
60 60 return IPythonDisplayFormatter(parent=self)
61 61
62 62 # A dict of formatter whose keys are format types (MIME types) and whose
63 63 # values are subclasses of BaseFormatter.
64 64 formatters = Dict()
65 65 @default('formatters')
66 66 def _formatters_default(self):
67 67 """Activate the default formatters."""
68 68 formatter_classes = [
69 69 PlainTextFormatter,
70 70 HTMLFormatter,
71 71 MarkdownFormatter,
72 72 SVGFormatter,
73 73 PNGFormatter,
74 74 PDFFormatter,
75 75 JPEGFormatter,
76 76 LatexFormatter,
77 77 JSONFormatter,
78 78 JavascriptFormatter
79 79 ]
80 80 d = {}
81 81 for cls in formatter_classes:
82 82 f = cls(parent=self)
83 83 d[f.format_type] = f
84 84 return d
85 85
86 86 def format(self, obj, include=None, exclude=None):
87 87 """Return a format data dict for an object.
88 88
89 89 By default all format types will be computed.
90 90
91 91 The following MIME types are currently implemented:
92 92
93 93 * text/plain
94 94 * text/html
95 95 * text/markdown
96 96 * text/latex
97 97 * application/json
98 98 * application/javascript
99 99 * application/pdf
100 100 * image/png
101 101 * image/jpeg
102 102 * image/svg+xml
103 103
104 104 Parameters
105 105 ----------
106 106 obj : object
107 107 The Python object whose format data will be computed.
108 108 include : list or tuple, optional
109 109 A list of format type strings (MIME types) to include in the
110 110 format data dict. If this is set *only* the format types included
111 111 in this list will be computed.
112 112 exclude : list or tuple, optional
113 113 A list of format type string (MIME types) to exclude in the format
114 114 data dict. If this is set all format types will be computed,
115 115 except for those included in this argument.
116 116
117 117 Returns
118 118 -------
119 119 (format_dict, metadata_dict) : tuple of two dicts
120 120
121 121 format_dict is a dictionary of key/value pairs, one of each format that was
122 122 generated for the object. The keys are the format types, which
123 123 will usually be MIME type strings and the values and JSON'able
124 124 data structure containing the raw data for the representation in
125 125 that format.
126 126
127 127 metadata_dict is a dictionary of metadata about each mime-type output.
128 128 Its keys will be a strict subset of the keys in format_dict.
129 129 """
130 130 format_dict = {}
131 131 md_dict = {}
132 132
133 133 if self.ipython_display_formatter(obj):
134 134 # object handled itself, don't proceed
135 135 return {}, {}
136 136
137 137 for format_type, formatter in self.formatters.items():
138 138 if include and format_type not in include:
139 139 continue
140 140 if exclude and format_type in exclude:
141 141 continue
142 142
143 143 md = None
144 144 try:
145 145 data = formatter(obj)
146 146 except:
147 147 # FIXME: log the exception
148 148 raise
149 149
150 150 # formatters can return raw data or (data, metadata)
151 151 if isinstance(data, tuple) and len(data) == 2:
152 152 data, md = data
153 153
154 154 if data is not None:
155 155 format_dict[format_type] = data
156 156 if md is not None:
157 157 md_dict[format_type] = md
158 158
159 159 return format_dict, md_dict
160 160
161 161 @property
162 162 def format_types(self):
163 163 """Return the format types (MIME types) of the active formatters."""
164 164 return list(self.formatters.keys())
165 165
166 166
167 167 #-----------------------------------------------------------------------------
168 168 # Formatters for specific format types (text, html, svg, etc.)
169 169 #-----------------------------------------------------------------------------
170 170
171 171
172 172 def _safe_repr(obj):
173 173 """Try to return a repr of an object
174 174
175 175 always returns a string, at least.
176 176 """
177 177 try:
178 178 return repr(obj)
179 179 except Exception as e:
180 180 return "un-repr-able object (%r)" % e
181 181
182 182
183 183 class FormatterWarning(UserWarning):
184 184 """Warning class for errors in formatters"""
185 185
186 186 @decorator
187 187 def catch_format_error(method, self, *args, **kwargs):
188 188 """show traceback on failed format call"""
189 189 try:
190 190 r = method(self, *args, **kwargs)
191 191 except NotImplementedError:
192 192 # don't warn on NotImplementedErrors
193 193 return None
194 194 except Exception:
195 195 exc_info = sys.exc_info()
196 196 ip = get_ipython()
197 197 if ip is not None:
198 198 ip.showtraceback(exc_info)
199 199 else:
200 200 traceback.print_exception(*exc_info)
201 201 return None
202 202 return self._check_return(r, args[0])
203 203
204 204
205 205 class FormatterABC(with_metaclass(abc.ABCMeta, object)):
206 206 """ Abstract base class for Formatters.
207 207
208 208 A formatter is a callable class that is responsible for computing the
209 209 raw format data for a particular format type (MIME type). For example,
210 210 an HTML formatter would have a format type of `text/html` and would return
211 211 the HTML representation of the object when called.
212 212 """
213 213
214 214 # The format type of the data returned, usually a MIME type.
215 215 format_type = 'text/plain'
216 216
217 217 # Is the formatter enabled...
218 218 enabled = True
219 219
220 220 @abc.abstractmethod
221 221 def __call__(self, obj):
222 222 """Return a JSON'able representation of the object.
223 223
224 224 If the object cannot be formatted by this formatter,
225 225 warn and return None.
226 226 """
227 227 return repr(obj)
228 228
229 229
230 230 def _mod_name_key(typ):
231 231 """Return a (__module__, __name__) tuple for a type.
232 232
233 233 Used as key in Formatter.deferred_printers.
234 234 """
235 235 module = getattr(typ, '__module__', None)
236 236 name = getattr(typ, '__name__', None)
237 237 return (module, name)
238 238
239 239
240 240 def _get_type(obj):
241 241 """Return the type of an instance (old and new-style)"""
242 242 return getattr(obj, '__class__', None) or type(obj)
243 243
244 244
245 245 _raise_key_error = Sentinel('_raise_key_error', __name__,
246 246 """
247 247 Special value to raise a KeyError
248 248
249 249 Raise KeyError in `BaseFormatter.pop` if passed as the default value to `pop`
250 250 """)
251 251
252 252
253 253 class BaseFormatter(Configurable):
254 254 """A base formatter class that is configurable.
255 255
256 256 This formatter should usually be used as the base class of all formatters.
257 257 It is a traited :class:`Configurable` class and includes an extensible
258 258 API for users to determine how their objects are formatted. The following
259 259 logic is used to find a function to format an given object.
260 260
261 261 1. The object is introspected to see if it has a method with the name
262 262 :attr:`print_method`. If is does, that object is passed to that method
263 263 for formatting.
264 264 2. If no print method is found, three internal dictionaries are consulted
265 265 to find print method: :attr:`singleton_printers`, :attr:`type_printers`
266 266 and :attr:`deferred_printers`.
267 267
268 268 Users should use these dictionaries to register functions that will be
269 269 used to compute the format data for their objects (if those objects don't
270 270 have the special print methods). The easiest way of using these
271 271 dictionaries is through the :meth:`for_type` and :meth:`for_type_by_name`
272 272 methods.
273 273
274 274 If no function/callable is found to compute the format data, ``None`` is
275 275 returned and this format type is not used.
276 276 """
277 277
278 278 format_type = Unicode('text/plain')
279 279 _return_type = string_types
280 280
281 281 enabled = Bool(True).tag(config=True)
282 282
283 283 print_method = ObjectName('__repr__')
284 284
285 285 # The singleton printers.
286 286 # Maps the IDs of the builtin singleton objects to the format functions.
287 287 singleton_printers = Dict().tag(config=True)
288 288
289 289 # The type-specific printers.
290 290 # Map type objects to the format functions.
291 291 type_printers = Dict().tag(config=True)
292 292
293 293 # The deferred-import type-specific printers.
294 294 # Map (modulename, classname) pairs to the format functions.
295 295 deferred_printers = Dict().tag(config=True)
296 296
297 297 @catch_format_error
298 298 def __call__(self, obj):
299 299 """Compute the format for an object."""
300 300 if self.enabled:
301 301 # lookup registered printer
302 302 try:
303 303 printer = self.lookup(obj)
304 304 except KeyError:
305 305 pass
306 306 else:
307 307 return printer(obj)
308 308 # Finally look for special method names
309 309 method = get_real_method(obj, self.print_method)
310 310 if method is not None:
311 311 return method()
312 312 return None
313 313 else:
314 314 return None
315 315
316 316 def __contains__(self, typ):
317 317 """map in to lookup_by_type"""
318 318 try:
319 319 self.lookup_by_type(typ)
320 320 except KeyError:
321 321 return False
322 322 else:
323 323 return True
324 324
325 325 def _check_return(self, r, obj):
326 326 """Check that a return value is appropriate
327 327
328 328 Return the value if so, None otherwise, warning if invalid.
329 329 """
330 330 if r is None or isinstance(r, self._return_type) or \
331 331 (isinstance(r, tuple) and r and isinstance(r[0], self._return_type)):
332 332 return r
333 333 else:
334 334 warnings.warn(
335 335 "%s formatter returned invalid type %s (expected %s) for object: %s" % \
336 336 (self.format_type, type(r), self._return_type, _safe_repr(obj)),
337 337 FormatterWarning
338 338 )
339 339
340 340 def lookup(self, obj):
341 341 """Look up the formatter for a given instance.
342 342
343 343 Parameters
344 344 ----------
345 345 obj : object instance
346 346
347 347 Returns
348 348 -------
349 349 f : callable
350 350 The registered formatting callable for the type.
351 351
352 352 Raises
353 353 ------
354 354 KeyError if the type has not been registered.
355 355 """
356 356 # look for singleton first
357 357 obj_id = id(obj)
358 358 if obj_id in self.singleton_printers:
359 359 return self.singleton_printers[obj_id]
360 360 # then lookup by type
361 361 return self.lookup_by_type(_get_type(obj))
362 362
363 363 def lookup_by_type(self, typ):
364 364 """Look up the registered formatter for a type.
365 365
366 366 Parameters
367 367 ----------
368 368 typ : type or '__module__.__name__' string for a type
369 369
370 370 Returns
371 371 -------
372 372 f : callable
373 373 The registered formatting callable for the type.
374 374
375 375 Raises
376 376 ------
377 377 KeyError if the type has not been registered.
378 378 """
379 379 if isinstance(typ, string_types):
380 380 typ_key = tuple(typ.rsplit('.',1))
381 381 if typ_key not in self.deferred_printers:
382 382 # We may have it cached in the type map. We will have to
383 383 # iterate over all of the types to check.
384 384 for cls in self.type_printers:
385 385 if _mod_name_key(cls) == typ_key:
386 386 return self.type_printers[cls]
387 387 else:
388 388 return self.deferred_printers[typ_key]
389 389 else:
390 390 for cls in pretty._get_mro(typ):
391 391 if cls in self.type_printers or self._in_deferred_types(cls):
392 392 return self.type_printers[cls]
393 393
394 394 # If we have reached here, the lookup failed.
395 395 raise KeyError("No registered printer for {0!r}".format(typ))
396 396
397 397 def for_type(self, typ, func=None):
398 398 """Add a format function for a given type.
399 399
400 400 Parameters
401 401 -----------
402 402 typ : type or '__module__.__name__' string for a type
403 403 The class of the object that will be formatted using `func`.
404 404 func : callable
405 405 A callable for computing the format data.
406 406 `func` will be called with the object to be formatted,
407 407 and will return the raw data in this formatter's format.
408 408 Subclasses may use a different call signature for the
409 409 `func` argument.
410 410
411 411 If `func` is None or not specified, there will be no change,
412 412 only returning the current value.
413 413
414 414 Returns
415 415 -------
416 416 oldfunc : callable
417 417 The currently registered callable.
418 418 If you are registering a new formatter,
419 419 this will be the previous value (to enable restoring later).
420 420 """
421 421 # if string given, interpret as 'pkg.module.class_name'
422 422 if isinstance(typ, string_types):
423 423 type_module, type_name = typ.rsplit('.', 1)
424 424 return self.for_type_by_name(type_module, type_name, func)
425 425
426 426 try:
427 427 oldfunc = self.lookup_by_type(typ)
428 428 except KeyError:
429 429 oldfunc = None
430 430
431 431 if func is not None:
432 432 self.type_printers[typ] = func
433 433
434 434 return oldfunc
435 435
436 436 def for_type_by_name(self, type_module, type_name, func=None):
437 437 """Add a format function for a type specified by the full dotted
438 438 module and name of the type, rather than the type of the object.
439 439
440 440 Parameters
441 441 ----------
442 442 type_module : str
443 443 The full dotted name of the module the type is defined in, like
444 444 ``numpy``.
445 445 type_name : str
446 446 The name of the type (the class name), like ``dtype``
447 447 func : callable
448 448 A callable for computing the format data.
449 449 `func` will be called with the object to be formatted,
450 450 and will return the raw data in this formatter's format.
451 451 Subclasses may use a different call signature for the
452 452 `func` argument.
453 453
454 454 If `func` is None or unspecified, there will be no change,
455 455 only returning the current value.
456 456
457 457 Returns
458 458 -------
459 459 oldfunc : callable
460 460 The currently registered callable.
461 461 If you are registering a new formatter,
462 462 this will be the previous value (to enable restoring later).
463 463 """
464 464 key = (type_module, type_name)
465 465
466 466 try:
467 467 oldfunc = self.lookup_by_type("%s.%s" % key)
468 468 except KeyError:
469 469 oldfunc = None
470 470
471 471 if func is not None:
472 472 self.deferred_printers[key] = func
473 473 return oldfunc
474 474
475 475 def pop(self, typ, default=_raise_key_error):
476 476 """Pop a formatter for the given type.
477 477
478 478 Parameters
479 479 ----------
480 480 typ : type or '__module__.__name__' string for a type
481 481 default : object
482 482 value to be returned if no formatter is registered for typ.
483 483
484 484 Returns
485 485 -------
486 486 obj : object
487 487 The last registered object for the type.
488 488
489 489 Raises
490 490 ------
491 491 KeyError if the type is not registered and default is not specified.
492 492 """
493 493
494 494 if isinstance(typ, string_types):
495 495 typ_key = tuple(typ.rsplit('.',1))
496 496 if typ_key not in self.deferred_printers:
497 497 # We may have it cached in the type map. We will have to
498 498 # iterate over all of the types to check.
499 499 for cls in self.type_printers:
500 500 if _mod_name_key(cls) == typ_key:
501 501 old = self.type_printers.pop(cls)
502 502 break
503 503 else:
504 504 old = default
505 505 else:
506 506 old = self.deferred_printers.pop(typ_key)
507 507 else:
508 508 if typ in self.type_printers:
509 509 old = self.type_printers.pop(typ)
510 510 else:
511 511 old = self.deferred_printers.pop(_mod_name_key(typ), default)
512 512 if old is _raise_key_error:
513 513 raise KeyError("No registered value for {0!r}".format(typ))
514 514 return old
515 515
516 516 def _in_deferred_types(self, cls):
517 517 """
518 518 Check if the given class is specified in the deferred type registry.
519 519
520 520 Successful matches will be moved to the regular type registry for future use.
521 521 """
522 522 mod = getattr(cls, '__module__', None)
523 523 name = getattr(cls, '__name__', None)
524 524 key = (mod, name)
525 525 if key in self.deferred_printers:
526 526 # Move the printer over to the regular registry.
527 527 printer = self.deferred_printers.pop(key)
528 528 self.type_printers[cls] = printer
529 529 return True
530 530 return False
531 531
532 532
533 533 class PlainTextFormatter(BaseFormatter):
534 534 """The default pretty-printer.
535 535
536 536 This uses :mod:`IPython.lib.pretty` to compute the format data of
537 537 the object. If the object cannot be pretty printed, :func:`repr` is used.
538 538 See the documentation of :mod:`IPython.lib.pretty` for details on
539 539 how to write pretty printers. Here is a simple example::
540 540
541 541 def dtype_pprinter(obj, p, cycle):
542 542 if cycle:
543 543 return p.text('dtype(...)')
544 544 if hasattr(obj, 'fields'):
545 545 if obj.fields is None:
546 546 p.text(repr(obj))
547 547 else:
548 548 p.begin_group(7, 'dtype([')
549 549 for i, field in enumerate(obj.descr):
550 550 if i > 0:
551 551 p.text(',')
552 552 p.breakable()
553 553 p.pretty(field)
554 554 p.end_group(7, '])')
555 555 """
556 556
557 557 # The format type of data returned.
558 558 format_type = Unicode('text/plain')
559 559
560 560 # This subclass ignores this attribute as it always need to return
561 561 # something.
562 562 enabled = Bool(True).tag(config=False)
563 563
564 564 max_seq_length = Integer(pretty.MAX_SEQ_LENGTH,
565 565 help="""Truncate large collections (lists, dicts, tuples, sets) to this size.
566 566
567 567 Set to 0 to disable truncation.
568 568 """
569 569 ).tag(config=True)
570 570
571 571 # Look for a _repr_pretty_ methods to use for pretty printing.
572 572 print_method = ObjectName('_repr_pretty_')
573 573
574 574 # Whether to pretty-print or not.
575 575 pprint = Bool(True).tag(config=True)
576 576
577 577 # Whether to be verbose or not.
578 578 verbose = Bool(False).tag(config=True)
579 579
580 580 # The maximum width.
581 581 max_width = Integer(79).tag(config=True)
582 582
583 583 # The newline character.
584 584 newline = Unicode('\n').tag(config=True)
585 585
586 586 # format-string for pprinting floats
587 587 float_format = Unicode('%r')
588 588 # setter for float precision, either int or direct format-string
589 589 float_precision = CUnicode('').tag(config=True)
590 590
591 def _float_precision_changed(self, name, old, new):
591 @observe('float_precision')
592 def _float_precision_changed(self, change):
592 593 """float_precision changed, set float_format accordingly.
593 594
594 595 float_precision can be set by int or str.
595 596 This will set float_format, after interpreting input.
596 597 If numpy has been imported, numpy print precision will also be set.
597 598
598 599 integer `n` sets format to '%.nf', otherwise, format set directly.
599 600
600 601 An empty string returns to defaults (repr for float, 8 for numpy).
601 602
602 603 This parameter can be set via the '%precision' magic.
603 604 """
604 605
606 new = change['new']
605 607 if '%' in new:
606 608 # got explicit format string
607 609 fmt = new
608 610 try:
609 611 fmt%3.14159
610 612 except Exception:
611 613 raise ValueError("Precision must be int or format string, not %r"%new)
612 614 elif new:
613 615 # otherwise, should be an int
614 616 try:
615 617 i = int(new)
616 618 assert i >= 0
617 619 except ValueError:
618 620 raise ValueError("Precision must be int or format string, not %r"%new)
619 621 except AssertionError:
620 622 raise ValueError("int precision must be non-negative, not %r"%i)
621 623
622 624 fmt = '%%.%if'%i
623 625 if 'numpy' in sys.modules:
624 626 # set numpy precision if it has been imported
625 627 import numpy
626 628 numpy.set_printoptions(precision=i)
627 629 else:
628 630 # default back to repr
629 631 fmt = '%r'
630 632 if 'numpy' in sys.modules:
631 633 import numpy
632 634 # numpy default is 8
633 635 numpy.set_printoptions(precision=8)
634 636 self.float_format = fmt
635 637
636 638 # Use the default pretty printers from IPython.lib.pretty.
637 639 @default('singleton_printers')
638 640 def _singleton_printers_default(self):
639 641 return pretty._singleton_pprinters.copy()
640 642
641 643 @default('type_printers')
642 644 def _type_printers_default(self):
643 645 d = pretty._type_pprinters.copy()
644 646 d[float] = lambda obj,p,cycle: p.text(self.float_format%obj)
645 647 return d
646 648
647 649 @default('deferred_printers')
648 650 def _deferred_printers_default(self):
649 651 return pretty._deferred_type_pprinters.copy()
650 652
651 653 #### FormatterABC interface ####
652 654
653 655 @catch_format_error
654 656 def __call__(self, obj):
655 657 """Compute the pretty representation of the object."""
656 658 if not self.pprint:
657 659 return repr(obj)
658 660 else:
659 661 # handle str and unicode on Python 2
660 662 # io.StringIO only accepts unicode,
661 663 # cStringIO doesn't handle unicode on py2,
662 664 # StringIO allows str, unicode but only ascii str
663 665 stream = pretty.CUnicodeIO()
664 666 printer = pretty.RepresentationPrinter(stream, self.verbose,
665 667 self.max_width, self.newline,
666 668 max_seq_length=self.max_seq_length,
667 669 singleton_pprinters=self.singleton_printers,
668 670 type_pprinters=self.type_printers,
669 671 deferred_pprinters=self.deferred_printers)
670 672 printer.pretty(obj)
671 673 printer.flush()
672 674 return stream.getvalue()
673 675
674 676
675 677 class HTMLFormatter(BaseFormatter):
676 678 """An HTML formatter.
677 679
678 680 To define the callables that compute the HTML representation of your
679 681 objects, define a :meth:`_repr_html_` method or use the :meth:`for_type`
680 682 or :meth:`for_type_by_name` methods to register functions that handle
681 683 this.
682 684
683 685 The return value of this formatter should be a valid HTML snippet that
684 686 could be injected into an existing DOM. It should *not* include the
685 687 ```<html>`` or ```<body>`` tags.
686 688 """
687 689 format_type = Unicode('text/html')
688 690
689 691 print_method = ObjectName('_repr_html_')
690 692
691 693
692 694 class MarkdownFormatter(BaseFormatter):
693 695 """A Markdown formatter.
694 696
695 697 To define the callables that compute the Markdown representation of your
696 698 objects, define a :meth:`_repr_markdown_` method or use the :meth:`for_type`
697 699 or :meth:`for_type_by_name` methods to register functions that handle
698 700 this.
699 701
700 702 The return value of this formatter should be a valid Markdown.
701 703 """
702 704 format_type = Unicode('text/markdown')
703 705
704 706 print_method = ObjectName('_repr_markdown_')
705 707
706 708 class SVGFormatter(BaseFormatter):
707 709 """An SVG formatter.
708 710
709 711 To define the callables that compute the SVG representation of your
710 712 objects, define a :meth:`_repr_svg_` method or use the :meth:`for_type`
711 713 or :meth:`for_type_by_name` methods to register functions that handle
712 714 this.
713 715
714 716 The return value of this formatter should be valid SVG enclosed in
715 717 ```<svg>``` tags, that could be injected into an existing DOM. It should
716 718 *not* include the ```<html>`` or ```<body>`` tags.
717 719 """
718 720 format_type = Unicode('image/svg+xml')
719 721
720 722 print_method = ObjectName('_repr_svg_')
721 723
722 724
723 725 class PNGFormatter(BaseFormatter):
724 726 """A PNG formatter.
725 727
726 728 To define the callables that compute the PNG representation of your
727 729 objects, define a :meth:`_repr_png_` method or use the :meth:`for_type`
728 730 or :meth:`for_type_by_name` methods to register functions that handle
729 731 this.
730 732
731 733 The return value of this formatter should be raw PNG data, *not*
732 734 base64 encoded.
733 735 """
734 736 format_type = Unicode('image/png')
735 737
736 738 print_method = ObjectName('_repr_png_')
737 739
738 740 _return_type = (bytes, unicode_type)
739 741
740 742
741 743 class JPEGFormatter(BaseFormatter):
742 744 """A JPEG formatter.
743 745
744 746 To define the callables that compute the JPEG representation of your
745 747 objects, define a :meth:`_repr_jpeg_` method or use the :meth:`for_type`
746 748 or :meth:`for_type_by_name` methods to register functions that handle
747 749 this.
748 750
749 751 The return value of this formatter should be raw JPEG data, *not*
750 752 base64 encoded.
751 753 """
752 754 format_type = Unicode('image/jpeg')
753 755
754 756 print_method = ObjectName('_repr_jpeg_')
755 757
756 758 _return_type = (bytes, unicode_type)
757 759
758 760
759 761 class LatexFormatter(BaseFormatter):
760 762 """A LaTeX formatter.
761 763
762 764 To define the callables that compute the LaTeX representation of your
763 765 objects, define a :meth:`_repr_latex_` method or use the :meth:`for_type`
764 766 or :meth:`for_type_by_name` methods to register functions that handle
765 767 this.
766 768
767 769 The return value of this formatter should be a valid LaTeX equation,
768 770 enclosed in either ```$```, ```$$``` or another LaTeX equation
769 771 environment.
770 772 """
771 773 format_type = Unicode('text/latex')
772 774
773 775 print_method = ObjectName('_repr_latex_')
774 776
775 777
776 778 class JSONFormatter(BaseFormatter):
777 779 """A JSON string formatter.
778 780
779 781 To define the callables that compute the JSONable representation of
780 782 your objects, define a :meth:`_repr_json_` method or use the :meth:`for_type`
781 783 or :meth:`for_type_by_name` methods to register functions that handle
782 784 this.
783 785
784 786 The return value of this formatter should be a JSONable list or dict.
785 787 JSON scalars (None, number, string) are not allowed, only dict or list containers.
786 788 """
787 789 format_type = Unicode('application/json')
788 790 _return_type = (list, dict)
789 791
790 792 print_method = ObjectName('_repr_json_')
791 793
792 794 def _check_return(self, r, obj):
793 795 """Check that a return value is appropriate
794 796
795 797 Return the value if so, None otherwise, warning if invalid.
796 798 """
797 799 if r is None:
798 800 return
799 801 md = None
800 802 if isinstance(r, tuple):
801 803 # unpack data, metadata tuple for type checking on first element
802 804 r, md = r
803 805
804 806 # handle deprecated JSON-as-string form from IPython < 3
805 807 if isinstance(r, string_types):
806 808 warnings.warn("JSON expects JSONable list/dict containers, not JSON strings",
807 809 FormatterWarning)
808 810 r = json.loads(r)
809 811
810 812 if md is not None:
811 813 # put the tuple back together
812 814 r = (r, md)
813 815 return super(JSONFormatter, self)._check_return(r, obj)
814 816
815 817
816 818 class JavascriptFormatter(BaseFormatter):
817 819 """A Javascript formatter.
818 820
819 821 To define the callables that compute the Javascript representation of
820 822 your objects, define a :meth:`_repr_javascript_` method or use the
821 823 :meth:`for_type` or :meth:`for_type_by_name` methods to register functions
822 824 that handle this.
823 825
824 826 The return value of this formatter should be valid Javascript code and
825 827 should *not* be enclosed in ```<script>``` tags.
826 828 """
827 829 format_type = Unicode('application/javascript')
828 830
829 831 print_method = ObjectName('_repr_javascript_')
830 832
831 833
832 834 class PDFFormatter(BaseFormatter):
833 835 """A PDF formatter.
834 836
835 837 To define the callables that compute the PDF representation of your
836 838 objects, define a :meth:`_repr_pdf_` method or use the :meth:`for_type`
837 839 or :meth:`for_type_by_name` methods to register functions that handle
838 840 this.
839 841
840 842 The return value of this formatter should be raw PDF data, *not*
841 843 base64 encoded.
842 844 """
843 845 format_type = Unicode('application/pdf')
844 846
845 847 print_method = ObjectName('_repr_pdf_')
846 848
847 849 _return_type = (bytes, unicode_type)
848 850
849 851 class IPythonDisplayFormatter(BaseFormatter):
850 852 """A Formatter for objects that know how to display themselves.
851 853
852 854 To define the callables that compute the representation of your
853 855 objects, define a :meth:`_ipython_display_` method or use the :meth:`for_type`
854 856 or :meth:`for_type_by_name` methods to register functions that handle
855 857 this. Unlike mime-type displays, this method should not return anything,
856 858 instead calling any appropriate display methods itself.
857 859
858 860 This display formatter has highest priority.
859 861 If it fires, no other display formatter will be called.
860 862 """
861 863 print_method = ObjectName('_ipython_display_')
862 864 _return_type = (type(None), bool)
863 865
864 866
865 867 @catch_format_error
866 868 def __call__(self, obj):
867 869 """Compute the format for an object."""
868 870 if self.enabled:
869 871 # lookup registered printer
870 872 try:
871 873 printer = self.lookup(obj)
872 874 except KeyError:
873 875 pass
874 876 else:
875 877 printer(obj)
876 878 return True
877 879 # Finally look for special method names
878 880 method = get_real_method(obj, self.print_method)
879 881 if method is not None:
880 882 method()
881 883 return True
882 884
883 885
884 886 FormatterABC.register(BaseFormatter)
885 887 FormatterABC.register(PlainTextFormatter)
886 888 FormatterABC.register(HTMLFormatter)
887 889 FormatterABC.register(MarkdownFormatter)
888 890 FormatterABC.register(SVGFormatter)
889 891 FormatterABC.register(PNGFormatter)
890 892 FormatterABC.register(PDFFormatter)
891 893 FormatterABC.register(JPEGFormatter)
892 894 FormatterABC.register(LatexFormatter)
893 895 FormatterABC.register(JSONFormatter)
894 896 FormatterABC.register(JavascriptFormatter)
895 897 FormatterABC.register(IPythonDisplayFormatter)
896 898
897 899
898 900 def format_display_data(obj, include=None, exclude=None):
899 901 """Return a format data dict for an object.
900 902
901 903 By default all format types will be computed.
902 904
903 905 The following MIME types are currently implemented:
904 906
905 907 * text/plain
906 908 * text/html
907 909 * text/markdown
908 910 * text/latex
909 911 * application/json
910 912 * application/javascript
911 913 * application/pdf
912 914 * image/png
913 915 * image/jpeg
914 916 * image/svg+xml
915 917
916 918 Parameters
917 919 ----------
918 920 obj : object
919 921 The Python object whose format data will be computed.
920 922
921 923 Returns
922 924 -------
923 925 format_dict : dict
924 926 A dictionary of key/value pairs, one or each format that was
925 927 generated for the object. The keys are the format types, which
926 928 will usually be MIME type strings and the values and JSON'able
927 929 data structure containing the raw data for the representation in
928 930 that format.
929 931 include : list or tuple, optional
930 932 A list of format type strings (MIME types) to include in the
931 933 format data dict. If this is set *only* the format types included
932 934 in this list will be computed.
933 935 exclude : list or tuple, optional
934 936 A list of format type string (MIME types) to exclue in the format
935 937 data dict. If this is set all format types will be computed,
936 938 except for those included in this argument.
937 939 """
938 940 from IPython.core.interactiveshell import InteractiveShell
939 941
940 942 return InteractiveShell.instance().display_formatter.format(
941 943 obj,
942 944 include,
943 945 exclude
944 946 )
945 947
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
@@ -1,411 +1,411 b''
1 1 # encoding: utf-8
2 2 """
3 3 A mixin for :class:`~IPython.core.application.Application` classes that
4 4 launch InteractiveShell instances, load extensions, etc.
5 5 """
6 6
7 7 # Copyright (c) IPython Development Team.
8 8 # Distributed under the terms of the Modified BSD License.
9 9
10 10 from __future__ import absolute_import
11 11 from __future__ import print_function
12 12
13 13 import glob
14 14 import os
15 15 import sys
16 16
17 17 from traitlets.config.application import boolean_flag
18 18 from traitlets.config.configurable import Configurable
19 19 from traitlets.config.loader import Config
20 20 from IPython.core import pylabtools
21 21 from IPython.utils import py3compat
22 22 from IPython.utils.contexts import preserve_keys
23 23 from IPython.utils.path import filefind
24 24 from traitlets import (
25 25 Unicode, Instance, List, Bool, CaselessStrEnum, observe,
26 26 )
27 from IPython.lib.inputhook import guis
27 from IPython.terminal import pt_inputhooks
28 28
29 29 #-----------------------------------------------------------------------------
30 30 # Aliases and Flags
31 31 #-----------------------------------------------------------------------------
32 32
33 gui_keys = tuple(sorted([ key for key in guis if key is not None ]))
33 gui_keys = tuple(sorted(pt_inputhooks.backends) + sorted(pt_inputhooks.aliases))
34 34
35 35 backend_keys = sorted(pylabtools.backends.keys())
36 36 backend_keys.insert(0, 'auto')
37 37
38 38 shell_flags = {}
39 39
40 40 addflag = lambda *args: shell_flags.update(boolean_flag(*args))
41 41 addflag('autoindent', 'InteractiveShell.autoindent',
42 42 'Turn on autoindenting.', 'Turn off autoindenting.'
43 43 )
44 44 addflag('automagic', 'InteractiveShell.automagic',
45 45 """Turn on the auto calling of magic commands. Type %%magic at the
46 46 IPython prompt for more information.""",
47 47 'Turn off the auto calling of magic commands.'
48 48 )
49 49 addflag('pdb', 'InteractiveShell.pdb',
50 50 "Enable auto calling the pdb debugger after every exception.",
51 51 "Disable auto calling the pdb debugger after every exception."
52 52 )
53 53 addflag('pprint', 'PlainTextFormatter.pprint',
54 54 "Enable auto pretty printing of results.",
55 55 "Disable auto pretty printing of results."
56 56 )
57 57 addflag('color-info', 'InteractiveShell.color_info',
58 58 """IPython can display information about objects via a set of functions,
59 59 and optionally can use colors for this, syntax highlighting
60 60 source code and various other elements. This is on by default, but can cause
61 61 problems with some pagers. If you see such problems, you can disable the
62 62 colours.""",
63 63 "Disable using colors for info related things."
64 64 )
65 65 nosep_config = Config()
66 66 nosep_config.InteractiveShell.separate_in = ''
67 67 nosep_config.InteractiveShell.separate_out = ''
68 68 nosep_config.InteractiveShell.separate_out2 = ''
69 69
70 70 shell_flags['nosep']=(nosep_config, "Eliminate all spacing between prompts.")
71 71 shell_flags['pylab'] = (
72 72 {'InteractiveShellApp' : {'pylab' : 'auto'}},
73 73 """Pre-load matplotlib and numpy for interactive use with
74 74 the default matplotlib backend."""
75 75 )
76 76 shell_flags['matplotlib'] = (
77 77 {'InteractiveShellApp' : {'matplotlib' : 'auto'}},
78 78 """Configure matplotlib for interactive use with
79 79 the default matplotlib backend."""
80 80 )
81 81
82 82 # it's possible we don't want short aliases for *all* of these:
83 83 shell_aliases = dict(
84 84 autocall='InteractiveShell.autocall',
85 85 colors='InteractiveShell.colors',
86 86 logfile='InteractiveShell.logfile',
87 87 logappend='InteractiveShell.logappend',
88 88 c='InteractiveShellApp.code_to_run',
89 89 m='InteractiveShellApp.module_to_run',
90 90 ext='InteractiveShellApp.extra_extension',
91 91 gui='InteractiveShellApp.gui',
92 92 pylab='InteractiveShellApp.pylab',
93 93 matplotlib='InteractiveShellApp.matplotlib',
94 94 )
95 95 shell_aliases['cache-size'] = 'InteractiveShell.cache_size'
96 96
97 97 #-----------------------------------------------------------------------------
98 98 # Main classes and functions
99 99 #-----------------------------------------------------------------------------
100 100
101 101 class InteractiveShellApp(Configurable):
102 102 """A Mixin for applications that start InteractiveShell instances.
103 103
104 104 Provides configurables for loading extensions and executing files
105 105 as part of configuring a Shell environment.
106 106
107 107 The following methods should be called by the :meth:`initialize` method
108 108 of the subclass:
109 109
110 110 - :meth:`init_path`
111 111 - :meth:`init_shell` (to be implemented by the subclass)
112 112 - :meth:`init_gui_pylab`
113 113 - :meth:`init_extensions`
114 114 - :meth:`init_code`
115 115 """
116 116 extensions = List(Unicode(),
117 117 help="A list of dotted module names of IPython extensions to load."
118 118 ).tag(config=True)
119 119 extra_extension = Unicode('',
120 120 help="dotted module name of an IPython extension to load."
121 121 ).tag(config=True)
122 122
123 123 reraise_ipython_extension_failures = Bool(False,
124 124 help="Reraise exceptions encountered loading IPython extensions?",
125 125 ).tag(config=True)
126 126
127 127 # Extensions that are always loaded (not configurable)
128 128 default_extensions = List(Unicode(), [u'storemagic']).tag(config=False)
129 129
130 130 hide_initial_ns = Bool(True,
131 131 help="""Should variables loaded at startup (by startup files, exec_lines, etc.)
132 132 be hidden from tools like %who?"""
133 133 ).tag(config=True)
134 134
135 135 exec_files = List(Unicode(),
136 136 help="""List of files to run at IPython startup."""
137 137 ).tag(config=True)
138 138 exec_PYTHONSTARTUP = Bool(True,
139 139 help="""Run the file referenced by the PYTHONSTARTUP environment
140 140 variable at IPython startup."""
141 141 ).tag(config=True)
142 142 file_to_run = Unicode('',
143 143 help="""A file to be run""").tag(config=True)
144 144
145 145 exec_lines = List(Unicode(),
146 146 help="""lines of code to run at IPython startup."""
147 147 ).tag(config=True)
148 148 code_to_run = Unicode('',
149 149 help="Execute the given command string."
150 150 ).tag(config=True)
151 151 module_to_run = Unicode('',
152 152 help="Run the module as a script."
153 153 ).tag(config=True)
154 154 gui = CaselessStrEnum(gui_keys, allow_none=True,
155 155 help="Enable GUI event loop integration with any of {0}.".format(gui_keys)
156 156 ).tag(config=True)
157 157 matplotlib = CaselessStrEnum(backend_keys, allow_none=True,
158 158 help="""Configure matplotlib for interactive use with
159 159 the default matplotlib backend."""
160 160 ).tag(config=True)
161 161 pylab = CaselessStrEnum(backend_keys, allow_none=True,
162 162 help="""Pre-load matplotlib and numpy for interactive use,
163 163 selecting a particular matplotlib backend and loop integration.
164 164 """
165 165 ).tag(config=True)
166 166 pylab_import_all = Bool(True,
167 167 help="""If true, IPython will populate the user namespace with numpy, pylab, etc.
168 168 and an ``import *`` is done from numpy and pylab, when using pylab mode.
169 169
170 170 When False, pylab mode should not import any names into the user namespace.
171 171 """
172 172 ).tag(config=True)
173 173 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC',
174 174 allow_none=True)
175 175 # whether interact-loop should start
176 176 interact = Bool(True)
177 177
178 178 user_ns = Instance(dict, args=None, allow_none=True)
179 179 @observe('user_ns')
180 180 def _user_ns_changed(self, change):
181 181 if self.shell is not None:
182 182 self.shell.user_ns = change['new']
183 183 self.shell.init_user_ns()
184 184
185 185 def init_path(self):
186 186 """Add current working directory, '', to sys.path"""
187 187 if sys.path[0] != '':
188 188 sys.path.insert(0, '')
189 189
190 190 def init_shell(self):
191 191 raise NotImplementedError("Override in subclasses")
192 192
193 193 def init_gui_pylab(self):
194 194 """Enable GUI event loop integration, taking pylab into account."""
195 195 enable = False
196 196 shell = self.shell
197 197 if self.pylab:
198 198 enable = lambda key: shell.enable_pylab(key, import_all=self.pylab_import_all)
199 199 key = self.pylab
200 200 elif self.matplotlib:
201 201 enable = shell.enable_matplotlib
202 202 key = self.matplotlib
203 203 elif self.gui:
204 204 enable = shell.enable_gui
205 205 key = self.gui
206 206
207 207 if not enable:
208 208 return
209 209
210 210 try:
211 211 r = enable(key)
212 212 except ImportError:
213 213 self.log.warning("Eventloop or matplotlib integration failed. Is matplotlib installed?")
214 214 self.shell.showtraceback()
215 215 return
216 216 except Exception:
217 217 self.log.warning("GUI event loop or pylab initialization failed")
218 218 self.shell.showtraceback()
219 219 return
220 220
221 221 if isinstance(r, tuple):
222 222 gui, backend = r[:2]
223 223 self.log.info("Enabling GUI event loop integration, "
224 224 "eventloop=%s, matplotlib=%s", gui, backend)
225 225 if key == "auto":
226 226 print("Using matplotlib backend: %s" % backend)
227 227 else:
228 228 gui = r
229 229 self.log.info("Enabling GUI event loop integration, "
230 230 "eventloop=%s", gui)
231 231
232 232 def init_extensions(self):
233 233 """Load all IPython extensions in IPythonApp.extensions.
234 234
235 235 This uses the :meth:`ExtensionManager.load_extensions` to load all
236 236 the extensions listed in ``self.extensions``.
237 237 """
238 238 try:
239 239 self.log.debug("Loading IPython extensions...")
240 240 extensions = self.default_extensions + self.extensions
241 241 if self.extra_extension:
242 242 extensions.append(self.extra_extension)
243 243 for ext in extensions:
244 244 try:
245 245 self.log.info("Loading IPython extension: %s" % ext)
246 246 self.shell.extension_manager.load_extension(ext)
247 247 except:
248 248 if self.reraise_ipython_extension_failures:
249 249 raise
250 250 msg = ("Error in loading extension: {ext}\n"
251 251 "Check your config files in {location}".format(
252 252 ext=ext,
253 253 location=self.profile_dir.location
254 254 ))
255 255 self.log.warning(msg, exc_info=True)
256 256 except:
257 257 if self.reraise_ipython_extension_failures:
258 258 raise
259 259 self.log.warning("Unknown error in loading extensions:", exc_info=True)
260 260
261 261 def init_code(self):
262 262 """run the pre-flight code, specified via exec_lines"""
263 263 self._run_startup_files()
264 264 self._run_exec_lines()
265 265 self._run_exec_files()
266 266
267 267 # Hide variables defined here from %who etc.
268 268 if self.hide_initial_ns:
269 269 self.shell.user_ns_hidden.update(self.shell.user_ns)
270 270
271 271 # command-line execution (ipython -i script.py, ipython -m module)
272 272 # should *not* be excluded from %whos
273 273 self._run_cmd_line_code()
274 274 self._run_module()
275 275
276 276 # flush output, so itwon't be attached to the first cell
277 277 sys.stdout.flush()
278 278 sys.stderr.flush()
279 279
280 280 def _run_exec_lines(self):
281 281 """Run lines of code in IPythonApp.exec_lines in the user's namespace."""
282 282 if not self.exec_lines:
283 283 return
284 284 try:
285 285 self.log.debug("Running code from IPythonApp.exec_lines...")
286 286 for line in self.exec_lines:
287 287 try:
288 288 self.log.info("Running code in user namespace: %s" %
289 289 line)
290 290 self.shell.run_cell(line, store_history=False)
291 291 except:
292 292 self.log.warning("Error in executing line in user "
293 293 "namespace: %s" % line)
294 294 self.shell.showtraceback()
295 295 except:
296 296 self.log.warning("Unknown error in handling IPythonApp.exec_lines:")
297 297 self.shell.showtraceback()
298 298
299 299 def _exec_file(self, fname, shell_futures=False):
300 300 try:
301 301 full_filename = filefind(fname, [u'.', self.ipython_dir])
302 302 except IOError:
303 303 self.log.warning("File not found: %r"%fname)
304 304 return
305 305 # Make sure that the running script gets a proper sys.argv as if it
306 306 # were run from a system shell.
307 307 save_argv = sys.argv
308 308 sys.argv = [full_filename] + self.extra_args[1:]
309 309 # protect sys.argv from potential unicode strings on Python 2:
310 310 if not py3compat.PY3:
311 311 sys.argv = [ py3compat.cast_bytes(a) for a in sys.argv ]
312 312 try:
313 313 if os.path.isfile(full_filename):
314 314 self.log.info("Running file in user namespace: %s" %
315 315 full_filename)
316 316 # Ensure that __file__ is always defined to match Python
317 317 # behavior.
318 318 with preserve_keys(self.shell.user_ns, '__file__'):
319 319 self.shell.user_ns['__file__'] = fname
320 320 if full_filename.endswith('.ipy'):
321 321 self.shell.safe_execfile_ipy(full_filename,
322 322 shell_futures=shell_futures)
323 323 else:
324 324 # default to python, even without extension
325 325 self.shell.safe_execfile(full_filename,
326 326 self.shell.user_ns,
327 327 shell_futures=shell_futures,
328 328 raise_exceptions=True)
329 329 finally:
330 330 sys.argv = save_argv
331 331
332 332 def _run_startup_files(self):
333 333 """Run files from profile startup directory"""
334 334 startup_dir = self.profile_dir.startup_dir
335 335 startup_files = []
336 336
337 337 if self.exec_PYTHONSTARTUP and os.environ.get('PYTHONSTARTUP', False) and \
338 338 not (self.file_to_run or self.code_to_run or self.module_to_run):
339 339 python_startup = os.environ['PYTHONSTARTUP']
340 340 self.log.debug("Running PYTHONSTARTUP file %s...", python_startup)
341 341 try:
342 342 self._exec_file(python_startup)
343 343 except:
344 344 self.log.warning("Unknown error in handling PYTHONSTARTUP file %s:", python_startup)
345 345 self.shell.showtraceback()
346 346
347 347 startup_files += glob.glob(os.path.join(startup_dir, '*.py'))
348 348 startup_files += glob.glob(os.path.join(startup_dir, '*.ipy'))
349 349 if not startup_files:
350 350 return
351 351
352 352 self.log.debug("Running startup files from %s...", startup_dir)
353 353 try:
354 354 for fname in sorted(startup_files):
355 355 self._exec_file(fname)
356 356 except:
357 357 self.log.warning("Unknown error in handling startup files:")
358 358 self.shell.showtraceback()
359 359
360 360 def _run_exec_files(self):
361 361 """Run files from IPythonApp.exec_files"""
362 362 if not self.exec_files:
363 363 return
364 364
365 365 self.log.debug("Running files in IPythonApp.exec_files...")
366 366 try:
367 367 for fname in self.exec_files:
368 368 self._exec_file(fname)
369 369 except:
370 370 self.log.warning("Unknown error in handling IPythonApp.exec_files:")
371 371 self.shell.showtraceback()
372 372
373 373 def _run_cmd_line_code(self):
374 374 """Run code or file specified at the command-line"""
375 375 if self.code_to_run:
376 376 line = self.code_to_run
377 377 try:
378 378 self.log.info("Running code given at command line (c=): %s" %
379 379 line)
380 380 self.shell.run_cell(line, store_history=False)
381 381 except:
382 382 self.log.warning("Error in executing line in user namespace: %s" %
383 383 line)
384 384 self.shell.showtraceback()
385 385 if not self.interact:
386 386 self.exit(1)
387 387
388 388 # Like Python itself, ignore the second if the first of these is present
389 389 elif self.file_to_run:
390 390 fname = self.file_to_run
391 391 if os.path.isdir(fname):
392 392 fname = os.path.join(fname, "__main__.py")
393 393 try:
394 394 self._exec_file(fname, shell_futures=True)
395 395 except:
396 396 self.shell.showtraceback(tb_offset=4)
397 397 if not self.interact:
398 398 self.exit(1)
399 399
400 400 def _run_module(self):
401 401 """Run module specified at the command-line."""
402 402 if self.module_to_run:
403 403 # Make sure that the module gets a proper sys.argv as if it were
404 404 # run using `python -m`.
405 405 save_argv = sys.argv
406 406 sys.argv = [sys.executable] + self.extra_args
407 407 try:
408 408 self.shell.safe_run_module(self.module_to_run,
409 409 self.shell.user_ns)
410 410 finally:
411 411 sys.argv = save_argv
@@ -1,233 +1,226 b''
1 1 """Tests for debugging machinery.
2 2 """
3 3 from __future__ import print_function
4 #-----------------------------------------------------------------------------
5 # Copyright (c) 2012, The IPython Development Team.
6 #
7 # Distributed under the terms of the Modified BSD License.
8 #
9 # The full license is in the file COPYING.txt, distributed with this software.
10 #-----------------------------------------------------------------------------
11 4
12 #-----------------------------------------------------------------------------
13 # Imports
14 #-----------------------------------------------------------------------------
5 # Copyright (c) IPython Development Team.
6 # Distributed under the terms of the Modified BSD License.
15 7
16 8 import sys
9 import warnings
17 10
18 # third-party
19 11 import nose.tools as nt
20 12
21 # Our own
22 13 from IPython.core import debugger
23 14
24 15 #-----------------------------------------------------------------------------
25 16 # Helper classes, from CPython's Pdb test suite
26 17 #-----------------------------------------------------------------------------
27 18
28 19 class _FakeInput(object):
29 20 """
30 21 A fake input stream for pdb's interactive debugger. Whenever a
31 22 line is read, print it (to simulate the user typing it), and then
32 23 return it. The set of lines to return is specified in the
33 24 constructor; they should not have trailing newlines.
34 25 """
35 26 def __init__(self, lines):
36 27 self.lines = iter(lines)
37 28
38 29 def readline(self):
39 30 line = next(self.lines)
40 31 print(line)
41 32 return line+'\n'
42 33
43 34 class PdbTestInput(object):
44 35 """Context manager that makes testing Pdb in doctests easier."""
45 36
46 37 def __init__(self, input):
47 38 self.input = input
48 39
49 40 def __enter__(self):
50 41 self.real_stdin = sys.stdin
51 42 sys.stdin = _FakeInput(self.input)
52 43
53 44 def __exit__(self, *exc):
54 45 sys.stdin = self.real_stdin
55 46
56 47 #-----------------------------------------------------------------------------
57 48 # Tests
58 49 #-----------------------------------------------------------------------------
59 50
60 51 def test_longer_repr():
61 52 try:
62 53 from reprlib import repr as trepr # Py 3
63 54 except ImportError:
64 55 from repr import repr as trepr # Py 2
65 56
66 57 a = '1234567890'* 7
67 58 ar = "'1234567890123456789012345678901234567890123456789012345678901234567890'"
68 59 a_trunc = "'123456789012...8901234567890'"
69 60 nt.assert_equal(trepr(a), a_trunc)
70 61 # The creation of our tracer modifies the repr module's repr function
71 62 # in-place, since that global is used directly by the stdlib's pdb module.
72 debugger.Tracer()
63 with warnings.catch_warnings():
64 warnings.simplefilter('ignore', DeprecationWarning)
65 debugger.Tracer()
73 66 nt.assert_equal(trepr(a), ar)
74 67
75 68 def test_ipdb_magics():
76 69 '''Test calling some IPython magics from ipdb.
77 70
78 71 First, set up some test functions and classes which we can inspect.
79 72
80 73 >>> class ExampleClass(object):
81 74 ... """Docstring for ExampleClass."""
82 75 ... def __init__(self):
83 76 ... """Docstring for ExampleClass.__init__"""
84 77 ... pass
85 78 ... def __str__(self):
86 79 ... return "ExampleClass()"
87 80
88 81 >>> def example_function(x, y, z="hello"):
89 82 ... """Docstring for example_function."""
90 83 ... pass
91 84
92 85 >>> old_trace = sys.gettrace()
93 86
94 87 Create a function which triggers ipdb.
95 88
96 89 >>> def trigger_ipdb():
97 90 ... a = ExampleClass()
98 91 ... debugger.Pdb().set_trace()
99 92
100 93 >>> with PdbTestInput([
101 94 ... 'pdef example_function',
102 95 ... 'pdoc ExampleClass',
103 96 ... 'up',
104 97 ... 'down',
105 98 ... 'list',
106 99 ... 'pinfo a',
107 100 ... 'll',
108 101 ... 'continue',
109 102 ... ]):
110 103 ... trigger_ipdb()
111 104 --Return--
112 105 None
113 106 > <doctest ...>(3)trigger_ipdb()
114 107 1 def trigger_ipdb():
115 108 2 a = ExampleClass()
116 109 ----> 3 debugger.Pdb().set_trace()
117 110 <BLANKLINE>
118 111 ipdb> pdef example_function
119 112 example_function(x, y, z='hello')
120 113 ipdb> pdoc ExampleClass
121 114 Class docstring:
122 115 Docstring for ExampleClass.
123 116 Init docstring:
124 117 Docstring for ExampleClass.__init__
125 118 ipdb> up
126 119 > <doctest ...>(11)<module>()
127 120 7 'pinfo a',
128 121 8 'll',
129 122 9 'continue',
130 123 10 ]):
131 124 ---> 11 trigger_ipdb()
132 125 <BLANKLINE>
133 126 ipdb> down
134 127 None
135 128 > <doctest ...>(3)trigger_ipdb()
136 129 1 def trigger_ipdb():
137 130 2 a = ExampleClass()
138 131 ----> 3 debugger.Pdb().set_trace()
139 132 <BLANKLINE>
140 133 ipdb> list
141 134 1 def trigger_ipdb():
142 135 2 a = ExampleClass()
143 136 ----> 3 debugger.Pdb().set_trace()
144 137 <BLANKLINE>
145 138 ipdb> pinfo a
146 139 Type: ExampleClass
147 140 String form: ExampleClass()
148 141 Namespace: Local...
149 142 Docstring: Docstring for ExampleClass.
150 143 Init docstring: Docstring for ExampleClass.__init__
151 144 ipdb> ll
152 145 1 def trigger_ipdb():
153 146 2 a = ExampleClass()
154 147 ----> 3 debugger.Pdb().set_trace()
155 148 <BLANKLINE>
156 149 ipdb> continue
157 150
158 151 Restore previous trace function, e.g. for coverage.py
159 152
160 153 >>> sys.settrace(old_trace)
161 154 '''
162 155
163 156 def test_ipdb_magics2():
164 157 '''Test ipdb with a very short function.
165 158
166 159 >>> old_trace = sys.gettrace()
167 160
168 161 >>> def bar():
169 162 ... pass
170 163
171 164 Run ipdb.
172 165
173 166 >>> with PdbTestInput([
174 167 ... 'continue',
175 168 ... ]):
176 169 ... debugger.Pdb().runcall(bar)
177 170 > <doctest ...>(2)bar()
178 171 1 def bar():
179 172 ----> 2 pass
180 173 <BLANKLINE>
181 174 ipdb> continue
182 175
183 176 Restore previous trace function, e.g. for coverage.py
184 177
185 178 >>> sys.settrace(old_trace)
186 179 '''
187 180
188 181 def can_quit():
189 182 '''Test that quit work in ipydb
190 183
191 184 >>> old_trace = sys.gettrace()
192 185
193 186 >>> def bar():
194 187 ... pass
195 188
196 189 >>> with PdbTestInput([
197 190 ... 'quit',
198 191 ... ]):
199 192 ... debugger.Pdb().runcall(bar)
200 193 > <doctest ...>(2)bar()
201 194 1 def bar():
202 195 ----> 2 pass
203 196 <BLANKLINE>
204 197 ipdb> quit
205 198
206 199 Restore previous trace function, e.g. for coverage.py
207 200
208 201 >>> sys.settrace(old_trace)
209 202 '''
210 203
211 204
212 205 def can_exit():
213 206 '''Test that quit work in ipydb
214 207
215 208 >>> old_trace = sys.gettrace()
216 209
217 210 >>> def bar():
218 211 ... pass
219 212
220 213 >>> with PdbTestInput([
221 214 ... 'exit',
222 215 ... ]):
223 216 ... debugger.Pdb().runcall(bar)
224 217 > <doctest ...>(2)bar()
225 218 1 def bar():
226 219 ----> 2 pass
227 220 <BLANKLINE>
228 221 ipdb> exit
229 222
230 223 Restore previous trace function, e.g. for coverage.py
231 224
232 225 >>> sys.settrace(old_trace)
233 226 '''
@@ -1,1494 +1,1494 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 Verbose and colourful traceback formatting.
4 4
5 5 **ColorTB**
6 6
7 7 I've always found it a bit hard to visually parse tracebacks in Python. The
8 8 ColorTB class is a solution to that problem. It colors the different parts of a
9 9 traceback in a manner similar to what you would expect from a syntax-highlighting
10 10 text editor.
11 11
12 12 Installation instructions for ColorTB::
13 13
14 14 import sys,ultratb
15 15 sys.excepthook = ultratb.ColorTB()
16 16
17 17 **VerboseTB**
18 18
19 19 I've also included a port of Ka-Ping Yee's "cgitb.py" that produces all kinds
20 20 of useful info when a traceback occurs. Ping originally had it spit out HTML
21 21 and intended it for CGI programmers, but why should they have all the fun? I
22 22 altered it to spit out colored text to the terminal. It's a bit overwhelming,
23 23 but kind of neat, and maybe useful for long-running programs that you believe
24 24 are bug-free. If a crash *does* occur in that type of program you want details.
25 25 Give it a shot--you'll love it or you'll hate it.
26 26
27 27 .. note::
28 28
29 29 The Verbose mode prints the variables currently visible where the exception
30 30 happened (shortening their strings if too long). This can potentially be
31 31 very slow, if you happen to have a huge data structure whose string
32 32 representation is complex to compute. Your computer may appear to freeze for
33 33 a while with cpu usage at 100%. If this occurs, you can cancel the traceback
34 34 with Ctrl-C (maybe hitting it more than once).
35 35
36 36 If you encounter this kind of situation often, you may want to use the
37 37 Verbose_novars mode instead of the regular Verbose, which avoids formatting
38 38 variables (but otherwise includes the information and context given by
39 39 Verbose).
40 40
41 41 .. note::
42 42
43 43 The verbose mode print all variables in the stack, which means it can
44 44 potentially leak sensitive information like access keys, or unencryted
45 45 password.
46 46
47 47 Installation instructions for VerboseTB::
48 48
49 49 import sys,ultratb
50 50 sys.excepthook = ultratb.VerboseTB()
51 51
52 52 Note: Much of the code in this module was lifted verbatim from the standard
53 53 library module 'traceback.py' and Ka-Ping Yee's 'cgitb.py'.
54 54
55 55 Color schemes
56 56 -------------
57 57
58 58 The colors are defined in the class TBTools through the use of the
59 59 ColorSchemeTable class. Currently the following exist:
60 60
61 61 - NoColor: allows all of this module to be used in any terminal (the color
62 62 escapes are just dummy blank strings).
63 63
64 64 - Linux: is meant to look good in a terminal like the Linux console (black
65 65 or very dark background).
66 66
67 67 - LightBG: similar to Linux but swaps dark/light colors to be more readable
68 68 in light background terminals.
69 69
70 70 - Neutral: a neutral color scheme that should be readable on both light and
71 71 dark background
72 72
73 73 You can implement other color schemes easily, the syntax is fairly
74 74 self-explanatory. Please send back new schemes you develop to the author for
75 75 possible inclusion in future releases.
76 76
77 77 Inheritance diagram:
78 78
79 79 .. inheritance-diagram:: IPython.core.ultratb
80 80 :parts: 3
81 81 """
82 82
83 83 #*****************************************************************************
84 84 # Copyright (C) 2001 Nathaniel Gray <n8gray@caltech.edu>
85 85 # Copyright (C) 2001-2004 Fernando Perez <fperez@colorado.edu>
86 86 #
87 87 # Distributed under the terms of the BSD License. The full license is in
88 88 # the file COPYING, distributed as part of this software.
89 89 #*****************************************************************************
90 90
91 91 from __future__ import absolute_import
92 92 from __future__ import unicode_literals
93 93 from __future__ import print_function
94 94
95 95 import dis
96 96 import inspect
97 97 import keyword
98 98 import linecache
99 99 import os
100 100 import pydoc
101 101 import re
102 102 import sys
103 103 import time
104 104 import tokenize
105 105 import traceback
106 106 import types
107 107
108 108 try: # Python 2
109 109 generate_tokens = tokenize.generate_tokens
110 110 except AttributeError: # Python 3
111 111 generate_tokens = tokenize.tokenize
112 112
113 113 # For purposes of monkeypatching inspect to fix a bug in it.
114 114 from inspect import getsourcefile, getfile, getmodule, \
115 115 ismodule, isclass, ismethod, isfunction, istraceback, isframe, iscode
116 116
117 117 # IPython's own modules
118 118 from IPython import get_ipython
119 119 from IPython.core import debugger
120 120 from IPython.core.display_trap import DisplayTrap
121 121 from IPython.core.excolors import exception_colors
122 122 from IPython.utils import PyColorize
123 123 from IPython.utils import openpy
124 124 from IPython.utils import path as util_path
125 125 from IPython.utils import py3compat
126 126 from IPython.utils import ulinecache
127 127 from IPython.utils.data import uniq_stable
128 128 from IPython.utils.terminal import get_terminal_size
129 129 from logging import info, error
130 130
131 131 import IPython.utils.colorable as colorable
132 132
133 133 # Globals
134 134 # amount of space to put line numbers before verbose tracebacks
135 135 INDENT_SIZE = 8
136 136
137 137 # Default color scheme. This is used, for example, by the traceback
138 138 # formatter. When running in an actual IPython instance, the user's rc.colors
139 139 # value is used, but having a module global makes this functionality available
140 140 # to users of ultratb who are NOT running inside ipython.
141 141 DEFAULT_SCHEME = 'NoColor'
142 142
143 143 # ---------------------------------------------------------------------------
144 144 # Code begins
145 145
146 146 # Utility functions
147 147 def inspect_error():
148 148 """Print a message about internal inspect errors.
149 149
150 150 These are unfortunately quite common."""
151 151
152 152 error('Internal Python error in the inspect module.\n'
153 153 'Below is the traceback from this internal error.\n')
154 154
155 155
156 156 # This function is a monkeypatch we apply to the Python inspect module. We have
157 157 # now found when it's needed (see discussion on issue gh-1456), and we have a
158 158 # test case (IPython.core.tests.test_ultratb.ChangedPyFileTest) that fails if
159 159 # the monkeypatch is not applied. TK, Aug 2012.
160 160 def findsource(object):
161 161 """Return the entire source file and starting line number for an object.
162 162
163 163 The argument may be a module, class, method, function, traceback, frame,
164 164 or code object. The source code is returned as a list of all the lines
165 165 in the file and the line number indexes a line in that list. An IOError
166 166 is raised if the source code cannot be retrieved.
167 167
168 168 FIXED version with which we monkeypatch the stdlib to work around a bug."""
169 169
170 170 file = getsourcefile(object) or getfile(object)
171 171 # If the object is a frame, then trying to get the globals dict from its
172 172 # module won't work. Instead, the frame object itself has the globals
173 173 # dictionary.
174 174 globals_dict = None
175 175 if inspect.isframe(object):
176 176 # XXX: can this ever be false?
177 177 globals_dict = object.f_globals
178 178 else:
179 179 module = getmodule(object, file)
180 180 if module:
181 181 globals_dict = module.__dict__
182 182 lines = linecache.getlines(file, globals_dict)
183 183 if not lines:
184 184 raise IOError('could not get source code')
185 185
186 186 if ismodule(object):
187 187 return lines, 0
188 188
189 189 if isclass(object):
190 190 name = object.__name__
191 191 pat = re.compile(r'^(\s*)class\s*' + name + r'\b')
192 192 # make some effort to find the best matching class definition:
193 193 # use the one with the least indentation, which is the one
194 194 # that's most probably not inside a function definition.
195 195 candidates = []
196 196 for i in range(len(lines)):
197 197 match = pat.match(lines[i])
198 198 if match:
199 199 # if it's at toplevel, it's already the best one
200 200 if lines[i][0] == 'c':
201 201 return lines, i
202 202 # else add whitespace to candidate list
203 203 candidates.append((match.group(1), i))
204 204 if candidates:
205 205 # this will sort by whitespace, and by line number,
206 206 # less whitespace first
207 207 candidates.sort()
208 208 return lines, candidates[0][1]
209 209 else:
210 210 raise IOError('could not find class definition')
211 211
212 212 if ismethod(object):
213 213 object = object.__func__
214 214 if isfunction(object):
215 215 object = object.__code__
216 216 if istraceback(object):
217 217 object = object.tb_frame
218 218 if isframe(object):
219 219 object = object.f_code
220 220 if iscode(object):
221 221 if not hasattr(object, 'co_firstlineno'):
222 222 raise IOError('could not find function definition')
223 223 pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)')
224 224 pmatch = pat.match
225 225 # fperez - fix: sometimes, co_firstlineno can give a number larger than
226 226 # the length of lines, which causes an error. Safeguard against that.
227 227 lnum = min(object.co_firstlineno, len(lines)) - 1
228 228 while lnum > 0:
229 229 if pmatch(lines[lnum]):
230 230 break
231 231 lnum -= 1
232 232
233 233 return lines, lnum
234 234 raise IOError('could not find code object')
235 235
236 236
237 237 # This is a patched version of inspect.getargs that applies the (unmerged)
238 238 # patch for http://bugs.python.org/issue14611 by Stefano Taschini. This fixes
239 239 # https://github.com/ipython/ipython/issues/8205 and
240 240 # https://github.com/ipython/ipython/issues/8293
241 241 def getargs(co):
242 242 """Get information about the arguments accepted by a code object.
243 243
244 244 Three things are returned: (args, varargs, varkw), where 'args' is
245 245 a list of argument names (possibly containing nested lists), and
246 246 'varargs' and 'varkw' are the names of the * and ** arguments or None."""
247 247 if not iscode(co):
248 248 raise TypeError('{!r} is not a code object'.format(co))
249 249
250 250 nargs = co.co_argcount
251 251 names = co.co_varnames
252 252 args = list(names[:nargs])
253 253 step = 0
254 254
255 255 # The following acrobatics are for anonymous (tuple) arguments.
256 256 for i in range(nargs):
257 257 if args[i][:1] in ('', '.'):
258 258 stack, remain, count = [], [], []
259 259 while step < len(co.co_code):
260 260 op = ord(co.co_code[step])
261 261 step = step + 1
262 262 if op >= dis.HAVE_ARGUMENT:
263 263 opname = dis.opname[op]
264 264 value = ord(co.co_code[step]) + ord(co.co_code[step+1])*256
265 265 step = step + 2
266 266 if opname in ('UNPACK_TUPLE', 'UNPACK_SEQUENCE'):
267 267 remain.append(value)
268 268 count.append(value)
269 269 elif opname in ('STORE_FAST', 'STORE_DEREF'):
270 270 if op in dis.haslocal:
271 271 stack.append(co.co_varnames[value])
272 272 elif op in dis.hasfree:
273 273 stack.append((co.co_cellvars + co.co_freevars)[value])
274 274 # Special case for sublists of length 1: def foo((bar))
275 275 # doesn't generate the UNPACK_TUPLE bytecode, so if
276 276 # `remain` is empty here, we have such a sublist.
277 277 if not remain:
278 278 stack[0] = [stack[0]]
279 279 break
280 280 else:
281 281 remain[-1] = remain[-1] - 1
282 282 while remain[-1] == 0:
283 283 remain.pop()
284 284 size = count.pop()
285 285 stack[-size:] = [stack[-size:]]
286 286 if not remain:
287 287 break
288 288 remain[-1] = remain[-1] - 1
289 289 if not remain:
290 290 break
291 291 args[i] = stack[0]
292 292
293 293 varargs = None
294 294 if co.co_flags & inspect.CO_VARARGS:
295 295 varargs = co.co_varnames[nargs]
296 296 nargs = nargs + 1
297 297 varkw = None
298 298 if co.co_flags & inspect.CO_VARKEYWORDS:
299 299 varkw = co.co_varnames[nargs]
300 300 return inspect.Arguments(args, varargs, varkw)
301 301
302 302
303 303 # Monkeypatch inspect to apply our bugfix.
304 304 def with_patch_inspect(f):
305 305 """decorator for monkeypatching inspect.findsource"""
306 306
307 307 def wrapped(*args, **kwargs):
308 308 save_findsource = inspect.findsource
309 309 save_getargs = inspect.getargs
310 310 inspect.findsource = findsource
311 311 inspect.getargs = getargs
312 312 try:
313 313 return f(*args, **kwargs)
314 314 finally:
315 315 inspect.findsource = save_findsource
316 316 inspect.getargs = save_getargs
317 317
318 318 return wrapped
319 319
320 320
321 321 if py3compat.PY3:
322 322 fixed_getargvalues = inspect.getargvalues
323 323 else:
324 324 # Fixes for https://github.com/ipython/ipython/issues/8293
325 325 # and https://github.com/ipython/ipython/issues/8205.
326 326 # The relevant bug is caused by failure to correctly handle anonymous tuple
327 327 # unpacking, which only exists in Python 2.
328 328 fixed_getargvalues = with_patch_inspect(inspect.getargvalues)
329 329
330 330
331 331 def fix_frame_records_filenames(records):
332 332 """Try to fix the filenames in each record from inspect.getinnerframes().
333 333
334 334 Particularly, modules loaded from within zip files have useless filenames
335 335 attached to their code object, and inspect.getinnerframes() just uses it.
336 336 """
337 337 fixed_records = []
338 338 for frame, filename, line_no, func_name, lines, index in records:
339 339 # Look inside the frame's globals dictionary for __file__,
340 340 # which should be better. However, keep Cython filenames since
341 341 # we prefer the source filenames over the compiled .so file.
342 342 filename = py3compat.cast_unicode_py2(filename, "utf-8")
343 343 if not filename.endswith(('.pyx', '.pxd', '.pxi')):
344 344 better_fn = frame.f_globals.get('__file__', None)
345 345 if isinstance(better_fn, str):
346 346 # Check the type just in case someone did something weird with
347 347 # __file__. It might also be None if the error occurred during
348 348 # import.
349 349 filename = better_fn
350 350 fixed_records.append((frame, filename, line_no, func_name, lines, index))
351 351 return fixed_records
352 352
353 353
354 354 @with_patch_inspect
355 355 def _fixed_getinnerframes(etb, context=1, tb_offset=0):
356 356 LNUM_POS, LINES_POS, INDEX_POS = 2, 4, 5
357 357
358 358 records = fix_frame_records_filenames(inspect.getinnerframes(etb, context))
359 359 # If the error is at the console, don't build any context, since it would
360 360 # otherwise produce 5 blank lines printed out (there is no file at the
361 361 # console)
362 362 rec_check = records[tb_offset:]
363 363 try:
364 364 rname = rec_check[0][1]
365 365 if rname == '<ipython console>' or rname.endswith('<string>'):
366 366 return rec_check
367 367 except IndexError:
368 368 pass
369 369
370 370 aux = traceback.extract_tb(etb)
371 371 assert len(records) == len(aux)
372 372 for i, (file, lnum, _, _) in zip(range(len(records)), aux):
373 373 maybeStart = lnum - 1 - context // 2
374 374 start = max(maybeStart, 0)
375 375 end = start + context
376 376 lines = ulinecache.getlines(file)[start:end]
377 377 buf = list(records[i])
378 378 buf[LNUM_POS] = lnum
379 379 buf[INDEX_POS] = lnum - 1 - start
380 380 buf[LINES_POS] = lines
381 381 records[i] = tuple(buf)
382 382 return records[tb_offset:]
383 383
384 384 # Helper function -- largely belongs to VerboseTB, but we need the same
385 385 # functionality to produce a pseudo verbose TB for SyntaxErrors, so that they
386 386 # can be recognized properly by ipython.el's py-traceback-line-re
387 387 # (SyntaxErrors have to be treated specially because they have no traceback)
388 388
389 389 _parser = PyColorize.Parser()
390 390
391 391
392 392 def _format_traceback_lines(lnum, index, lines, Colors, lvals=None, scheme=None):
393 393 numbers_width = INDENT_SIZE - 1
394 394 res = []
395 395 i = lnum - index
396 396
397 397 # This lets us get fully syntax-highlighted tracebacks.
398 398 if scheme is None:
399 399 ipinst = get_ipython()
400 400 if ipinst is not None:
401 401 scheme = ipinst.colors
402 402 else:
403 403 scheme = DEFAULT_SCHEME
404 404
405 405 _line_format = _parser.format2
406 406
407 407 for line in lines:
408 408 line = py3compat.cast_unicode(line)
409 409
410 410 new_line, err = _line_format(line, 'str', scheme)
411 411 if not err: line = new_line
412 412
413 413 if i == lnum:
414 414 # This is the line with the error
415 415 pad = numbers_width - len(str(i))
416 416 num = '%s%s' % (debugger.make_arrow(pad), str(lnum))
417 417 line = '%s%s%s %s%s' % (Colors.linenoEm, num,
418 418 Colors.line, line, Colors.Normal)
419 419 else:
420 420 num = '%*s' % (numbers_width, i)
421 421 line = '%s%s%s %s' % (Colors.lineno, num,
422 422 Colors.Normal, line)
423 423
424 424 res.append(line)
425 425 if lvals and i == lnum:
426 426 res.append(lvals + '\n')
427 427 i = i + 1
428 428 return res
429 429
430 430 def is_recursion_error(etype, value, records):
431 431 try:
432 432 # RecursionError is new in Python 3.5
433 433 recursion_error_type = RecursionError
434 434 except NameError:
435 435 recursion_error_type = RuntimeError
436 436
437 437 # The default recursion limit is 1000, but some of that will be taken up
438 438 # by stack frames in IPython itself. >500 frames probably indicates
439 439 # a recursion error.
440 440 return (etype is recursion_error_type) \
441 441 and "recursion" in str(value).lower() \
442 442 and len(records) > 500
443 443
444 444 def find_recursion(etype, value, records):
445 445 """Identify the repeating stack frames from a RecursionError traceback
446 446
447 447 'records' is a list as returned by VerboseTB.get_records()
448 448
449 449 Returns (last_unique, repeat_length)
450 450 """
451 451 # This involves a bit of guesswork - we want to show enough of the traceback
452 452 # to indicate where the recursion is occurring. We guess that the innermost
453 453 # quarter of the traceback (250 frames by default) is repeats, and find the
454 454 # first frame (from in to out) that looks different.
455 455 if not is_recursion_error(etype, value, records):
456 456 return len(records), 0
457 457
458 458 # Select filename, lineno, func_name to track frames with
459 459 records = [r[1:4] for r in records]
460 460 inner_frames = records[-(len(records)//4):]
461 461 frames_repeated = set(inner_frames)
462 462
463 463 last_seen_at = {}
464 464 longest_repeat = 0
465 465 i = len(records)
466 466 for frame in reversed(records):
467 467 i -= 1
468 468 if frame not in frames_repeated:
469 469 last_unique = i
470 470 break
471 471
472 472 if frame in last_seen_at:
473 473 distance = last_seen_at[frame] - i
474 474 longest_repeat = max(longest_repeat, distance)
475 475
476 476 last_seen_at[frame] = i
477 477 else:
478 478 last_unique = 0 # The whole traceback was recursion
479 479
480 480 return last_unique, longest_repeat
481 481
482 482 #---------------------------------------------------------------------------
483 483 # Module classes
484 484 class TBTools(colorable.Colorable):
485 485 """Basic tools used by all traceback printer classes."""
486 486
487 487 # Number of frames to skip when reporting tracebacks
488 488 tb_offset = 0
489 489
490 490 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None, parent=None, config=None):
491 491 # Whether to call the interactive pdb debugger after printing
492 492 # tracebacks or not
493 493 super(TBTools, self).__init__(parent=parent, config=config)
494 494 self.call_pdb = call_pdb
495 495
496 496 # Output stream to write to. Note that we store the original value in
497 497 # a private attribute and then make the public ostream a property, so
498 # that we can delay accessing io.stdout until runtime. The way
499 # things are written now, the io.stdout object is dynamically managed
498 # that we can delay accessing sys.stdout until runtime. The way
499 # things are written now, the sys.stdout object is dynamically managed
500 500 # so a reference to it should NEVER be stored statically. This
501 501 # property approach confines this detail to a single location, and all
502 502 # subclasses can simply access self.ostream for writing.
503 503 self._ostream = ostream
504 504
505 505 # Create color table
506 506 self.color_scheme_table = exception_colors()
507 507
508 508 self.set_colors(color_scheme)
509 509 self.old_scheme = color_scheme # save initial value for toggles
510 510
511 511 if call_pdb:
512 self.pdb = debugger.Pdb(self.color_scheme_table.active_scheme_name)
512 self.pdb = debugger.Pdb()
513 513 else:
514 514 self.pdb = None
515 515
516 516 def _get_ostream(self):
517 517 """Output stream that exceptions are written to.
518 518
519 519 Valid values are:
520 520
521 521 - None: the default, which means that IPython will dynamically resolve
522 to io.stdout. This ensures compatibility with most tools, including
522 to sys.stdout. This ensures compatibility with most tools, including
523 523 Windows (where plain stdout doesn't recognize ANSI escapes).
524 524
525 525 - Any object with 'write' and 'flush' attributes.
526 526 """
527 527 return sys.stdout if self._ostream is None else self._ostream
528 528
529 529 def _set_ostream(self, val):
530 530 assert val is None or (hasattr(val, 'write') and hasattr(val, 'flush'))
531 531 self._ostream = val
532 532
533 533 ostream = property(_get_ostream, _set_ostream)
534 534
535 535 def set_colors(self, *args, **kw):
536 536 """Shorthand access to the color table scheme selector method."""
537 537
538 538 # Set own color table
539 539 self.color_scheme_table.set_active_scheme(*args, **kw)
540 540 # for convenience, set Colors to the active scheme
541 541 self.Colors = self.color_scheme_table.active_colors
542 542 # Also set colors of debugger
543 543 if hasattr(self, 'pdb') and self.pdb is not None:
544 544 self.pdb.set_colors(*args, **kw)
545 545
546 546 def color_toggle(self):
547 547 """Toggle between the currently active color scheme and NoColor."""
548 548
549 549 if self.color_scheme_table.active_scheme_name == 'NoColor':
550 550 self.color_scheme_table.set_active_scheme(self.old_scheme)
551 551 self.Colors = self.color_scheme_table.active_colors
552 552 else:
553 553 self.old_scheme = self.color_scheme_table.active_scheme_name
554 554 self.color_scheme_table.set_active_scheme('NoColor')
555 555 self.Colors = self.color_scheme_table.active_colors
556 556
557 557 def stb2text(self, stb):
558 558 """Convert a structured traceback (a list) to a string."""
559 559 return '\n'.join(stb)
560 560
561 561 def text(self, etype, value, tb, tb_offset=None, context=5):
562 562 """Return formatted traceback.
563 563
564 564 Subclasses may override this if they add extra arguments.
565 565 """
566 566 tb_list = self.structured_traceback(etype, value, tb,
567 567 tb_offset, context)
568 568 return self.stb2text(tb_list)
569 569
570 570 def structured_traceback(self, etype, evalue, tb, tb_offset=None,
571 571 context=5, mode=None):
572 572 """Return a list of traceback frames.
573 573
574 574 Must be implemented by each class.
575 575 """
576 576 raise NotImplementedError()
577 577
578 578
579 579 #---------------------------------------------------------------------------
580 580 class ListTB(TBTools):
581 581 """Print traceback information from a traceback list, with optional color.
582 582
583 583 Calling requires 3 arguments: (etype, evalue, elist)
584 584 as would be obtained by::
585 585
586 586 etype, evalue, tb = sys.exc_info()
587 587 if tb:
588 588 elist = traceback.extract_tb(tb)
589 589 else:
590 590 elist = None
591 591
592 592 It can thus be used by programs which need to process the traceback before
593 593 printing (such as console replacements based on the code module from the
594 594 standard library).
595 595
596 596 Because they are meant to be called without a full traceback (only a
597 597 list), instances of this class can't call the interactive pdb debugger."""
598 598
599 599 def __init__(self, color_scheme='NoColor', call_pdb=False, ostream=None, parent=None):
600 600 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
601 601 ostream=ostream, parent=parent)
602 602
603 603 def __call__(self, etype, value, elist):
604 604 self.ostream.flush()
605 605 self.ostream.write(self.text(etype, value, elist))
606 606 self.ostream.write('\n')
607 607
608 608 def structured_traceback(self, etype, value, elist, tb_offset=None,
609 609 context=5):
610 610 """Return a color formatted string with the traceback info.
611 611
612 612 Parameters
613 613 ----------
614 614 etype : exception type
615 615 Type of the exception raised.
616 616
617 617 value : object
618 618 Data stored in the exception
619 619
620 620 elist : list
621 621 List of frames, see class docstring for details.
622 622
623 623 tb_offset : int, optional
624 624 Number of frames in the traceback to skip. If not given, the
625 625 instance value is used (set in constructor).
626 626
627 627 context : int, optional
628 628 Number of lines of context information to print.
629 629
630 630 Returns
631 631 -------
632 632 String with formatted exception.
633 633 """
634 634 tb_offset = self.tb_offset if tb_offset is None else tb_offset
635 635 Colors = self.Colors
636 636 out_list = []
637 637 if elist:
638 638
639 639 if tb_offset and len(elist) > tb_offset:
640 640 elist = elist[tb_offset:]
641 641
642 642 out_list.append('Traceback %s(most recent call last)%s:' %
643 643 (Colors.normalEm, Colors.Normal) + '\n')
644 644 out_list.extend(self._format_list(elist))
645 645 # The exception info should be a single entry in the list.
646 646 lines = ''.join(self._format_exception_only(etype, value))
647 647 out_list.append(lines)
648 648
649 649 # Note: this code originally read:
650 650
651 651 ## for line in lines[:-1]:
652 652 ## out_list.append(" "+line)
653 653 ## out_list.append(lines[-1])
654 654
655 655 # This means it was indenting everything but the last line by a little
656 656 # bit. I've disabled this for now, but if we see ugliness somewhere we
657 657 # can restore it.
658 658
659 659 return out_list
660 660
661 661 def _format_list(self, extracted_list):
662 662 """Format a list of traceback entry tuples for printing.
663 663
664 664 Given a list of tuples as returned by extract_tb() or
665 665 extract_stack(), return a list of strings ready for printing.
666 666 Each string in the resulting list corresponds to the item with the
667 667 same index in the argument list. Each string ends in a newline;
668 668 the strings may contain internal newlines as well, for those items
669 669 whose source text line is not None.
670 670
671 671 Lifted almost verbatim from traceback.py
672 672 """
673 673
674 674 Colors = self.Colors
675 675 list = []
676 676 for filename, lineno, name, line in extracted_list[:-1]:
677 677 item = ' File %s"%s"%s, line %s%d%s, in %s%s%s\n' % \
678 678 (Colors.filename, py3compat.cast_unicode_py2(filename, "utf-8"), Colors.Normal,
679 679 Colors.lineno, lineno, Colors.Normal,
680 680 Colors.name, py3compat.cast_unicode_py2(name, "utf-8"), Colors.Normal)
681 681 if line:
682 682 item += ' %s\n' % line.strip()
683 683 list.append(item)
684 684 # Emphasize the last entry
685 685 filename, lineno, name, line = extracted_list[-1]
686 686 item = '%s File %s"%s"%s, line %s%d%s, in %s%s%s%s\n' % \
687 687 (Colors.normalEm,
688 688 Colors.filenameEm, py3compat.cast_unicode_py2(filename, "utf-8"), Colors.normalEm,
689 689 Colors.linenoEm, lineno, Colors.normalEm,
690 690 Colors.nameEm, py3compat.cast_unicode_py2(name, "utf-8"), Colors.normalEm,
691 691 Colors.Normal)
692 692 if line:
693 693 item += '%s %s%s\n' % (Colors.line, line.strip(),
694 694 Colors.Normal)
695 695 list.append(item)
696 696 return list
697 697
698 698 def _format_exception_only(self, etype, value):
699 699 """Format the exception part of a traceback.
700 700
701 701 The arguments are the exception type and value such as given by
702 702 sys.exc_info()[:2]. The return value is a list of strings, each ending
703 703 in a newline. Normally, the list contains a single string; however,
704 704 for SyntaxError exceptions, it contains several lines that (when
705 705 printed) display detailed information about where the syntax error
706 706 occurred. The message indicating which exception occurred is the
707 707 always last string in the list.
708 708
709 709 Also lifted nearly verbatim from traceback.py
710 710 """
711 711 have_filedata = False
712 712 Colors = self.Colors
713 713 list = []
714 714 stype = py3compat.cast_unicode(Colors.excName + etype.__name__ + Colors.Normal)
715 715 if value is None:
716 716 # Not sure if this can still happen in Python 2.6 and above
717 717 list.append(stype + '\n')
718 718 else:
719 719 if issubclass(etype, SyntaxError):
720 720 have_filedata = True
721 721 if not value.filename: value.filename = "<string>"
722 722 if value.lineno:
723 723 lineno = value.lineno
724 724 textline = ulinecache.getline(value.filename, value.lineno)
725 725 else:
726 726 lineno = 'unknown'
727 727 textline = ''
728 728 list.append('%s File %s"%s"%s, line %s%s%s\n' % \
729 729 (Colors.normalEm,
730 730 Colors.filenameEm, py3compat.cast_unicode(value.filename), Colors.normalEm,
731 731 Colors.linenoEm, lineno, Colors.Normal ))
732 732 if textline == '':
733 733 textline = py3compat.cast_unicode(value.text, "utf-8")
734 734
735 735 if textline is not None:
736 736 i = 0
737 737 while i < len(textline) and textline[i].isspace():
738 738 i += 1
739 739 list.append('%s %s%s\n' % (Colors.line,
740 740 textline.strip(),
741 741 Colors.Normal))
742 742 if value.offset is not None:
743 743 s = ' '
744 744 for c in textline[i:value.offset - 1]:
745 745 if c.isspace():
746 746 s += c
747 747 else:
748 748 s += ' '
749 749 list.append('%s%s^%s\n' % (Colors.caret, s,
750 750 Colors.Normal))
751 751
752 752 try:
753 753 s = value.msg
754 754 except Exception:
755 755 s = self._some_str(value)
756 756 if s:
757 757 list.append('%s%s:%s %s\n' % (stype, Colors.excName,
758 758 Colors.Normal, s))
759 759 else:
760 760 list.append('%s\n' % stype)
761 761
762 762 # sync with user hooks
763 763 if have_filedata:
764 764 ipinst = get_ipython()
765 765 if ipinst is not None:
766 766 ipinst.hooks.synchronize_with_editor(value.filename, value.lineno, 0)
767 767
768 768 return list
769 769
770 770 def get_exception_only(self, etype, value):
771 771 """Only print the exception type and message, without a traceback.
772 772
773 773 Parameters
774 774 ----------
775 775 etype : exception type
776 776 value : exception value
777 777 """
778 778 return ListTB.structured_traceback(self, etype, value, [])
779 779
780 780 def show_exception_only(self, etype, evalue):
781 781 """Only print the exception type and message, without a traceback.
782 782
783 783 Parameters
784 784 ----------
785 785 etype : exception type
786 786 value : exception value
787 787 """
788 788 # This method needs to use __call__ from *this* class, not the one from
789 789 # a subclass whose signature or behavior may be different
790 790 ostream = self.ostream
791 791 ostream.flush()
792 792 ostream.write('\n'.join(self.get_exception_only(etype, evalue)))
793 793 ostream.flush()
794 794
795 795 def _some_str(self, value):
796 796 # Lifted from traceback.py
797 797 try:
798 798 return py3compat.cast_unicode(str(value))
799 799 except:
800 800 return u'<unprintable %s object>' % type(value).__name__
801 801
802 802
803 803 #----------------------------------------------------------------------------
804 804 class VerboseTB(TBTools):
805 805 """A port of Ka-Ping Yee's cgitb.py module that outputs color text instead
806 806 of HTML. Requires inspect and pydoc. Crazy, man.
807 807
808 808 Modified version which optionally strips the topmost entries from the
809 809 traceback, to be used with alternate interpreters (because their own code
810 810 would appear in the traceback)."""
811 811
812 812 def __init__(self, color_scheme='Linux', call_pdb=False, ostream=None,
813 813 tb_offset=0, long_header=False, include_vars=True,
814 814 check_cache=None, debugger_cls = None):
815 815 """Specify traceback offset, headers and color scheme.
816 816
817 817 Define how many frames to drop from the tracebacks. Calling it with
818 818 tb_offset=1 allows use of this handler in interpreters which will have
819 819 their own code at the top of the traceback (VerboseTB will first
820 820 remove that frame before printing the traceback info)."""
821 821 TBTools.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
822 822 ostream=ostream)
823 823 self.tb_offset = tb_offset
824 824 self.long_header = long_header
825 825 self.include_vars = include_vars
826 826 # By default we use linecache.checkcache, but the user can provide a
827 827 # different check_cache implementation. This is used by the IPython
828 828 # kernel to provide tracebacks for interactive code that is cached,
829 829 # by a compiler instance that flushes the linecache but preserves its
830 830 # own code cache.
831 831 if check_cache is None:
832 832 check_cache = linecache.checkcache
833 833 self.check_cache = check_cache
834 834
835 835 self.debugger_cls = debugger_cls or debugger.Pdb
836 836
837 837 def format_records(self, records, last_unique, recursion_repeat):
838 838 """Format the stack frames of the traceback"""
839 839 frames = []
840 840 for r in records[:last_unique+recursion_repeat+1]:
841 841 #print '*** record:',file,lnum,func,lines,index # dbg
842 842 frames.append(self.format_record(*r))
843 843
844 844 if recursion_repeat:
845 845 frames.append('... last %d frames repeated, from the frame below ...\n' % recursion_repeat)
846 846 frames.append(self.format_record(*records[last_unique+recursion_repeat+1]))
847 847
848 848 return frames
849 849
850 850 def format_record(self, frame, file, lnum, func, lines, index):
851 851 """Format a single stack frame"""
852 852 Colors = self.Colors # just a shorthand + quicker name lookup
853 853 ColorsNormal = Colors.Normal # used a lot
854 854 col_scheme = self.color_scheme_table.active_scheme_name
855 855 indent = ' ' * INDENT_SIZE
856 856 em_normal = '%s\n%s%s' % (Colors.valEm, indent, ColorsNormal)
857 857 undefined = '%sundefined%s' % (Colors.em, ColorsNormal)
858 858 tpl_link = '%s%%s%s' % (Colors.filenameEm, ColorsNormal)
859 859 tpl_call = 'in %s%%s%s%%s%s' % (Colors.vName, Colors.valEm,
860 860 ColorsNormal)
861 861 tpl_call_fail = 'in %s%%s%s(***failed resolving arguments***)%s' % \
862 862 (Colors.vName, Colors.valEm, ColorsNormal)
863 863 tpl_local_var = '%s%%s%s' % (Colors.vName, ColorsNormal)
864 864 tpl_global_var = '%sglobal%s %s%%s%s' % (Colors.em, ColorsNormal,
865 865 Colors.vName, ColorsNormal)
866 866 tpl_name_val = '%%s %s= %%s%s' % (Colors.valEm, ColorsNormal)
867 867
868 868 tpl_line = '%s%%s%s %%s' % (Colors.lineno, ColorsNormal)
869 869 tpl_line_em = '%s%%s%s %%s%s' % (Colors.linenoEm, Colors.line,
870 870 ColorsNormal)
871 871
872 872 abspath = os.path.abspath
873 873
874 874
875 875 if not file:
876 876 file = '?'
877 877 elif file.startswith(str("<")) and file.endswith(str(">")):
878 878 # Not a real filename, no problem...
879 879 pass
880 880 elif not os.path.isabs(file):
881 881 # Try to make the filename absolute by trying all
882 882 # sys.path entries (which is also what linecache does)
883 883 for dirname in sys.path:
884 884 try:
885 885 fullname = os.path.join(dirname, file)
886 886 if os.path.isfile(fullname):
887 887 file = os.path.abspath(fullname)
888 888 break
889 889 except Exception:
890 890 # Just in case that sys.path contains very
891 891 # strange entries...
892 892 pass
893 893
894 894 file = py3compat.cast_unicode(file, util_path.fs_encoding)
895 895 link = tpl_link % file
896 896 args, varargs, varkw, locals = fixed_getargvalues(frame)
897 897
898 898 if func == '?':
899 899 call = ''
900 900 else:
901 901 # Decide whether to include variable details or not
902 902 var_repr = self.include_vars and eqrepr or nullrepr
903 903 try:
904 904 call = tpl_call % (func, inspect.formatargvalues(args,
905 905 varargs, varkw,
906 906 locals, formatvalue=var_repr))
907 907 except KeyError:
908 908 # This happens in situations like errors inside generator
909 909 # expressions, where local variables are listed in the
910 910 # line, but can't be extracted from the frame. I'm not
911 911 # 100% sure this isn't actually a bug in inspect itself,
912 912 # but since there's no info for us to compute with, the
913 913 # best we can do is report the failure and move on. Here
914 914 # we must *not* call any traceback construction again,
915 915 # because that would mess up use of %debug later on. So we
916 916 # simply report the failure and move on. The only
917 917 # limitation will be that this frame won't have locals
918 918 # listed in the call signature. Quite subtle problem...
919 919 # I can't think of a good way to validate this in a unit
920 920 # test, but running a script consisting of:
921 921 # dict( (k,v.strip()) for (k,v) in range(10) )
922 922 # will illustrate the error, if this exception catch is
923 923 # disabled.
924 924 call = tpl_call_fail % func
925 925
926 926 # Don't attempt to tokenize binary files.
927 927 if file.endswith(('.so', '.pyd', '.dll')):
928 928 return '%s %s\n' % (link, call)
929 929
930 930 elif file.endswith(('.pyc', '.pyo')):
931 931 # Look up the corresponding source file.
932 932 try:
933 933 file = openpy.source_from_cache(file)
934 934 except ValueError:
935 935 # Failed to get the source file for some reason
936 936 # E.g. https://github.com/ipython/ipython/issues/9486
937 937 return '%s %s\n' % (link, call)
938 938
939 939 def linereader(file=file, lnum=[lnum], getline=ulinecache.getline):
940 940 line = getline(file, lnum[0])
941 941 lnum[0] += 1
942 942 return line
943 943
944 944 # Build the list of names on this line of code where the exception
945 945 # occurred.
946 946 try:
947 947 names = []
948 948 name_cont = False
949 949
950 950 for token_type, token, start, end, line in generate_tokens(linereader):
951 951 # build composite names
952 952 if token_type == tokenize.NAME and token not in keyword.kwlist:
953 953 if name_cont:
954 954 # Continuation of a dotted name
955 955 try:
956 956 names[-1].append(token)
957 957 except IndexError:
958 958 names.append([token])
959 959 name_cont = False
960 960 else:
961 961 # Regular new names. We append everything, the caller
962 962 # will be responsible for pruning the list later. It's
963 963 # very tricky to try to prune as we go, b/c composite
964 964 # names can fool us. The pruning at the end is easy
965 965 # to do (or the caller can print a list with repeated
966 966 # names if so desired.
967 967 names.append([token])
968 968 elif token == '.':
969 969 name_cont = True
970 970 elif token_type == tokenize.NEWLINE:
971 971 break
972 972
973 973 except (IndexError, UnicodeDecodeError, SyntaxError):
974 974 # signals exit of tokenizer
975 975 # SyntaxError can occur if the file is not actually Python
976 976 # - see gh-6300
977 977 pass
978 978 except tokenize.TokenError as msg:
979 979 _m = ("An unexpected error occurred while tokenizing input\n"
980 980 "The following traceback may be corrupted or invalid\n"
981 981 "The error message is: %s\n" % msg)
982 982 error(_m)
983 983
984 984 # Join composite names (e.g. "dict.fromkeys")
985 985 names = ['.'.join(n) for n in names]
986 986 # prune names list of duplicates, but keep the right order
987 987 unique_names = uniq_stable(names)
988 988
989 989 # Start loop over vars
990 990 lvals = []
991 991 if self.include_vars:
992 992 for name_full in unique_names:
993 993 name_base = name_full.split('.', 1)[0]
994 994 if name_base in frame.f_code.co_varnames:
995 995 if name_base in locals:
996 996 try:
997 997 value = repr(eval(name_full, locals))
998 998 except:
999 999 value = undefined
1000 1000 else:
1001 1001 value = undefined
1002 1002 name = tpl_local_var % name_full
1003 1003 else:
1004 1004 if name_base in frame.f_globals:
1005 1005 try:
1006 1006 value = repr(eval(name_full, frame.f_globals))
1007 1007 except:
1008 1008 value = undefined
1009 1009 else:
1010 1010 value = undefined
1011 1011 name = tpl_global_var % name_full
1012 1012 lvals.append(tpl_name_val % (name, value))
1013 1013 if lvals:
1014 1014 lvals = '%s%s' % (indent, em_normal.join(lvals))
1015 1015 else:
1016 1016 lvals = ''
1017 1017
1018 1018 level = '%s %s\n' % (link, call)
1019 1019
1020 1020 if index is None:
1021 1021 return level
1022 1022 else:
1023 1023 return '%s%s' % (level, ''.join(
1024 1024 _format_traceback_lines(lnum, index, lines, Colors, lvals,
1025 1025 col_scheme)))
1026 1026
1027 1027 def prepare_chained_exception_message(self, cause):
1028 1028 direct_cause = "\nThe above exception was the direct cause of the following exception:\n"
1029 1029 exception_during_handling = "\nDuring handling of the above exception, another exception occurred:\n"
1030 1030
1031 1031 if cause:
1032 1032 message = [[direct_cause]]
1033 1033 else:
1034 1034 message = [[exception_during_handling]]
1035 1035 return message
1036 1036
1037 1037 def prepare_header(self, etype, long_version=False):
1038 1038 colors = self.Colors # just a shorthand + quicker name lookup
1039 1039 colorsnormal = colors.Normal # used a lot
1040 1040 exc = '%s%s%s' % (colors.excName, etype, colorsnormal)
1041 1041 width = min(75, get_terminal_size()[0])
1042 1042 if long_version:
1043 1043 # Header with the exception type, python version, and date
1044 1044 pyver = 'Python ' + sys.version.split()[0] + ': ' + sys.executable
1045 1045 date = time.ctime(time.time())
1046 1046
1047 1047 head = '%s%s%s\n%s%s%s\n%s' % (colors.topline, '-' * width, colorsnormal,
1048 1048 exc, ' ' * (width - len(str(etype)) - len(pyver)),
1049 1049 pyver, date.rjust(width) )
1050 1050 head += "\nA problem occurred executing Python code. Here is the sequence of function" \
1051 1051 "\ncalls leading up to the error, with the most recent (innermost) call last."
1052 1052 else:
1053 1053 # Simplified header
1054 1054 head = '%s%s' % (exc, 'Traceback (most recent call last)'. \
1055 1055 rjust(width - len(str(etype))) )
1056 1056
1057 1057 return head
1058 1058
1059 1059 def format_exception(self, etype, evalue):
1060 1060 colors = self.Colors # just a shorthand + quicker name lookup
1061 1061 colorsnormal = colors.Normal # used a lot
1062 1062 indent = ' ' * INDENT_SIZE
1063 1063 # Get (safely) a string form of the exception info
1064 1064 try:
1065 1065 etype_str, evalue_str = map(str, (etype, evalue))
1066 1066 except:
1067 1067 # User exception is improperly defined.
1068 1068 etype, evalue = str, sys.exc_info()[:2]
1069 1069 etype_str, evalue_str = map(str, (etype, evalue))
1070 1070 # ... and format it
1071 1071 exception = ['%s%s%s: %s' % (colors.excName, etype_str,
1072 1072 colorsnormal, py3compat.cast_unicode(evalue_str))]
1073 1073
1074 1074 if (not py3compat.PY3) and type(evalue) is types.InstanceType:
1075 1075 try:
1076 1076 names = [w for w in dir(evalue) if isinstance(w, py3compat.string_types)]
1077 1077 except:
1078 1078 # Every now and then, an object with funny internals blows up
1079 1079 # when dir() is called on it. We do the best we can to report
1080 1080 # the problem and continue
1081 1081 _m = '%sException reporting error (object with broken dir())%s:'
1082 1082 exception.append(_m % (colors.excName, colorsnormal))
1083 1083 etype_str, evalue_str = map(str, sys.exc_info()[:2])
1084 1084 exception.append('%s%s%s: %s' % (colors.excName, etype_str,
1085 1085 colorsnormal, py3compat.cast_unicode(evalue_str)))
1086 1086 names = []
1087 1087 for name in names:
1088 1088 value = text_repr(getattr(evalue, name))
1089 1089 exception.append('\n%s%s = %s' % (indent, name, value))
1090 1090
1091 1091 return exception
1092 1092
1093 1093 def format_exception_as_a_whole(self, etype, evalue, etb, number_of_lines_of_context, tb_offset):
1094 1094 """Formats the header, traceback and exception message for a single exception.
1095 1095
1096 1096 This may be called multiple times by Python 3 exception chaining
1097 1097 (PEP 3134).
1098 1098 """
1099 1099 # some locals
1100 1100 orig_etype = etype
1101 1101 try:
1102 1102 etype = etype.__name__
1103 1103 except AttributeError:
1104 1104 pass
1105 1105
1106 1106 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1107 1107 head = self.prepare_header(etype, self.long_header)
1108 1108 records = self.get_records(etb, number_of_lines_of_context, tb_offset)
1109 1109
1110 1110 if records is None:
1111 1111 return ""
1112 1112
1113 1113 last_unique, recursion_repeat = find_recursion(orig_etype, evalue, records)
1114 1114
1115 1115 frames = self.format_records(records, last_unique, recursion_repeat)
1116 1116
1117 1117 formatted_exception = self.format_exception(etype, evalue)
1118 1118 if records:
1119 1119 filepath, lnum = records[-1][1:3]
1120 1120 filepath = os.path.abspath(filepath)
1121 1121 ipinst = get_ipython()
1122 1122 if ipinst is not None:
1123 1123 ipinst.hooks.synchronize_with_editor(filepath, lnum, 0)
1124 1124
1125 1125 return [[head] + frames + [''.join(formatted_exception[0])]]
1126 1126
1127 1127 def get_records(self, etb, number_of_lines_of_context, tb_offset):
1128 1128 try:
1129 1129 # Try the default getinnerframes and Alex's: Alex's fixes some
1130 1130 # problems, but it generates empty tracebacks for console errors
1131 1131 # (5 blanks lines) where none should be returned.
1132 1132 return _fixed_getinnerframes(etb, number_of_lines_of_context, tb_offset)
1133 1133 except:
1134 1134 # FIXME: I've been getting many crash reports from python 2.3
1135 1135 # users, traceable to inspect.py. If I can find a small test-case
1136 1136 # to reproduce this, I should either write a better workaround or
1137 1137 # file a bug report against inspect (if that's the real problem).
1138 1138 # So far, I haven't been able to find an isolated example to
1139 1139 # reproduce the problem.
1140 1140 inspect_error()
1141 1141 traceback.print_exc(file=self.ostream)
1142 1142 info('\nUnfortunately, your original traceback can not be constructed.\n')
1143 1143 return None
1144 1144
1145 1145 def get_parts_of_chained_exception(self, evalue):
1146 1146 def get_chained_exception(exception_value):
1147 1147 cause = getattr(exception_value, '__cause__', None)
1148 1148 if cause:
1149 1149 return cause
1150 1150 if getattr(exception_value, '__suppress_context__', False):
1151 1151 return None
1152 1152 return getattr(exception_value, '__context__', None)
1153 1153
1154 1154 chained_evalue = get_chained_exception(evalue)
1155 1155
1156 1156 if chained_evalue:
1157 1157 return chained_evalue.__class__, chained_evalue, chained_evalue.__traceback__
1158 1158
1159 1159 def structured_traceback(self, etype, evalue, etb, tb_offset=None,
1160 1160 number_of_lines_of_context=5):
1161 1161 """Return a nice text document describing the traceback."""
1162 1162
1163 1163 formatted_exception = self.format_exception_as_a_whole(etype, evalue, etb, number_of_lines_of_context,
1164 1164 tb_offset)
1165 1165
1166 1166 colors = self.Colors # just a shorthand + quicker name lookup
1167 1167 colorsnormal = colors.Normal # used a lot
1168 1168 head = '%s%s%s' % (colors.topline, '-' * min(75, get_terminal_size()[0]), colorsnormal)
1169 1169 structured_traceback_parts = [head]
1170 1170 if py3compat.PY3:
1171 1171 chained_exceptions_tb_offset = 0
1172 1172 lines_of_context = 3
1173 1173 formatted_exceptions = formatted_exception
1174 1174 exception = self.get_parts_of_chained_exception(evalue)
1175 1175 if exception:
1176 1176 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
1177 1177 etype, evalue, etb = exception
1178 1178 else:
1179 1179 evalue = None
1180 1180 chained_exc_ids = set()
1181 1181 while evalue:
1182 1182 formatted_exceptions += self.format_exception_as_a_whole(etype, evalue, etb, lines_of_context,
1183 1183 chained_exceptions_tb_offset)
1184 1184 exception = self.get_parts_of_chained_exception(evalue)
1185 1185
1186 1186 if exception and not id(exception[1]) in chained_exc_ids:
1187 1187 chained_exc_ids.add(id(exception[1])) # trace exception to avoid infinite 'cause' loop
1188 1188 formatted_exceptions += self.prepare_chained_exception_message(evalue.__cause__)
1189 1189 etype, evalue, etb = exception
1190 1190 else:
1191 1191 evalue = None
1192 1192
1193 1193 # we want to see exceptions in a reversed order:
1194 1194 # the first exception should be on top
1195 1195 for formatted_exception in reversed(formatted_exceptions):
1196 1196 structured_traceback_parts += formatted_exception
1197 1197 else:
1198 1198 structured_traceback_parts += formatted_exception[0]
1199 1199
1200 1200 return structured_traceback_parts
1201 1201
1202 1202 def debugger(self, force=False):
1203 1203 """Call up the pdb debugger if desired, always clean up the tb
1204 1204 reference.
1205 1205
1206 1206 Keywords:
1207 1207
1208 1208 - force(False): by default, this routine checks the instance call_pdb
1209 1209 flag and does not actually invoke the debugger if the flag is false.
1210 1210 The 'force' option forces the debugger to activate even if the flag
1211 1211 is false.
1212 1212
1213 1213 If the call_pdb flag is set, the pdb interactive debugger is
1214 1214 invoked. In all cases, the self.tb reference to the current traceback
1215 1215 is deleted to prevent lingering references which hamper memory
1216 1216 management.
1217 1217
1218 1218 Note that each call to pdb() does an 'import readline', so if your app
1219 1219 requires a special setup for the readline completers, you'll have to
1220 1220 fix that by hand after invoking the exception handler."""
1221 1221
1222 1222 if force or self.call_pdb:
1223 1223 if self.pdb is None:
1224 1224 self.pdb = self.debugger_cls(
1225 1225 self.color_scheme_table.active_scheme_name)
1226 1226 # the system displayhook may have changed, restore the original
1227 1227 # for pdb
1228 1228 display_trap = DisplayTrap(hook=sys.__displayhook__)
1229 1229 with display_trap:
1230 1230 self.pdb.reset()
1231 1231 # Find the right frame so we don't pop up inside ipython itself
1232 1232 if hasattr(self, 'tb') and self.tb is not None:
1233 1233 etb = self.tb
1234 1234 else:
1235 1235 etb = self.tb = sys.last_traceback
1236 1236 while self.tb is not None and self.tb.tb_next is not None:
1237 1237 self.tb = self.tb.tb_next
1238 1238 if etb and etb.tb_next:
1239 1239 etb = etb.tb_next
1240 1240 self.pdb.botframe = etb.tb_frame
1241 1241 self.pdb.interaction(self.tb.tb_frame, self.tb)
1242 1242
1243 1243 if hasattr(self, 'tb'):
1244 1244 del self.tb
1245 1245
1246 1246 def handler(self, info=None):
1247 1247 (etype, evalue, etb) = info or sys.exc_info()
1248 1248 self.tb = etb
1249 1249 ostream = self.ostream
1250 1250 ostream.flush()
1251 1251 ostream.write(self.text(etype, evalue, etb))
1252 1252 ostream.write('\n')
1253 1253 ostream.flush()
1254 1254
1255 1255 # Changed so an instance can just be called as VerboseTB_inst() and print
1256 1256 # out the right info on its own.
1257 1257 def __call__(self, etype=None, evalue=None, etb=None):
1258 1258 """This hook can replace sys.excepthook (for Python 2.1 or higher)."""
1259 1259 if etb is None:
1260 1260 self.handler()
1261 1261 else:
1262 1262 self.handler((etype, evalue, etb))
1263 1263 try:
1264 1264 self.debugger()
1265 1265 except KeyboardInterrupt:
1266 1266 print("\nKeyboardInterrupt")
1267 1267
1268 1268
1269 1269 #----------------------------------------------------------------------------
1270 1270 class FormattedTB(VerboseTB, ListTB):
1271 1271 """Subclass ListTB but allow calling with a traceback.
1272 1272
1273 1273 It can thus be used as a sys.excepthook for Python > 2.1.
1274 1274
1275 1275 Also adds 'Context' and 'Verbose' modes, not available in ListTB.
1276 1276
1277 1277 Allows a tb_offset to be specified. This is useful for situations where
1278 1278 one needs to remove a number of topmost frames from the traceback (such as
1279 1279 occurs with python programs that themselves execute other python code,
1280 1280 like Python shells). """
1281 1281
1282 1282 def __init__(self, mode='Plain', color_scheme='Linux', call_pdb=False,
1283 1283 ostream=None,
1284 1284 tb_offset=0, long_header=False, include_vars=False,
1285 1285 check_cache=None, debugger_cls=None):
1286 1286
1287 1287 # NEVER change the order of this list. Put new modes at the end:
1288 1288 self.valid_modes = ['Plain', 'Context', 'Verbose']
1289 1289 self.verbose_modes = self.valid_modes[1:3]
1290 1290
1291 1291 VerboseTB.__init__(self, color_scheme=color_scheme, call_pdb=call_pdb,
1292 1292 ostream=ostream, tb_offset=tb_offset,
1293 1293 long_header=long_header, include_vars=include_vars,
1294 1294 check_cache=check_cache, debugger_cls=debugger_cls)
1295 1295
1296 1296 # Different types of tracebacks are joined with different separators to
1297 1297 # form a single string. They are taken from this dict
1298 1298 self._join_chars = dict(Plain='', Context='\n', Verbose='\n')
1299 1299 # set_mode also sets the tb_join_char attribute
1300 1300 self.set_mode(mode)
1301 1301
1302 1302 def _extract_tb(self, tb):
1303 1303 if tb:
1304 1304 return traceback.extract_tb(tb)
1305 1305 else:
1306 1306 return None
1307 1307
1308 1308 def structured_traceback(self, etype, value, tb, tb_offset=None, number_of_lines_of_context=5):
1309 1309 tb_offset = self.tb_offset if tb_offset is None else tb_offset
1310 1310 mode = self.mode
1311 1311 if mode in self.verbose_modes:
1312 1312 # Verbose modes need a full traceback
1313 1313 return VerboseTB.structured_traceback(
1314 1314 self, etype, value, tb, tb_offset, number_of_lines_of_context
1315 1315 )
1316 1316 else:
1317 1317 # We must check the source cache because otherwise we can print
1318 1318 # out-of-date source code.
1319 1319 self.check_cache()
1320 1320 # Now we can extract and format the exception
1321 1321 elist = self._extract_tb(tb)
1322 1322 return ListTB.structured_traceback(
1323 1323 self, etype, value, elist, tb_offset, number_of_lines_of_context
1324 1324 )
1325 1325
1326 1326 def stb2text(self, stb):
1327 1327 """Convert a structured traceback (a list) to a string."""
1328 1328 return self.tb_join_char.join(stb)
1329 1329
1330 1330
1331 1331 def set_mode(self, mode=None):
1332 1332 """Switch to the desired mode.
1333 1333
1334 1334 If mode is not specified, cycles through the available modes."""
1335 1335
1336 1336 if not mode:
1337 1337 new_idx = (self.valid_modes.index(self.mode) + 1 ) % \
1338 1338 len(self.valid_modes)
1339 1339 self.mode = self.valid_modes[new_idx]
1340 1340 elif mode not in self.valid_modes:
1341 1341 raise ValueError('Unrecognized mode in FormattedTB: <' + mode + '>\n'
1342 1342 'Valid modes: ' + str(self.valid_modes))
1343 1343 else:
1344 1344 self.mode = mode
1345 1345 # include variable details only in 'Verbose' mode
1346 1346 self.include_vars = (self.mode == self.valid_modes[2])
1347 1347 # Set the join character for generating text tracebacks
1348 1348 self.tb_join_char = self._join_chars[self.mode]
1349 1349
1350 1350 # some convenient shortcuts
1351 1351 def plain(self):
1352 1352 self.set_mode(self.valid_modes[0])
1353 1353
1354 1354 def context(self):
1355 1355 self.set_mode(self.valid_modes[1])
1356 1356
1357 1357 def verbose(self):
1358 1358 self.set_mode(self.valid_modes[2])
1359 1359
1360 1360
1361 1361 #----------------------------------------------------------------------------
1362 1362 class AutoFormattedTB(FormattedTB):
1363 1363 """A traceback printer which can be called on the fly.
1364 1364
1365 1365 It will find out about exceptions by itself.
1366 1366
1367 1367 A brief example::
1368 1368
1369 1369 AutoTB = AutoFormattedTB(mode = 'Verbose',color_scheme='Linux')
1370 1370 try:
1371 1371 ...
1372 1372 except:
1373 1373 AutoTB() # or AutoTB(out=logfile) where logfile is an open file object
1374 1374 """
1375 1375
1376 1376 def __call__(self, etype=None, evalue=None, etb=None,
1377 1377 out=None, tb_offset=None):
1378 1378 """Print out a formatted exception traceback.
1379 1379
1380 1380 Optional arguments:
1381 1381 - out: an open file-like object to direct output to.
1382 1382
1383 1383 - tb_offset: the number of frames to skip over in the stack, on a
1384 1384 per-call basis (this overrides temporarily the instance's tb_offset
1385 1385 given at initialization time. """
1386 1386
1387 1387 if out is None:
1388 1388 out = self.ostream
1389 1389 out.flush()
1390 1390 out.write(self.text(etype, evalue, etb, tb_offset))
1391 1391 out.write('\n')
1392 1392 out.flush()
1393 1393 # FIXME: we should remove the auto pdb behavior from here and leave
1394 1394 # that to the clients.
1395 1395 try:
1396 1396 self.debugger()
1397 1397 except KeyboardInterrupt:
1398 1398 print("\nKeyboardInterrupt")
1399 1399
1400 1400 def structured_traceback(self, etype=None, value=None, tb=None,
1401 1401 tb_offset=None, number_of_lines_of_context=5):
1402 1402 if etype is None:
1403 1403 etype, value, tb = sys.exc_info()
1404 1404 self.tb = tb
1405 1405 return FormattedTB.structured_traceback(
1406 1406 self, etype, value, tb, tb_offset, number_of_lines_of_context)
1407 1407
1408 1408
1409 1409 #---------------------------------------------------------------------------
1410 1410
1411 1411 # A simple class to preserve Nathan's original functionality.
1412 1412 class ColorTB(FormattedTB):
1413 1413 """Shorthand to initialize a FormattedTB in Linux colors mode."""
1414 1414
1415 1415 def __init__(self, color_scheme='Linux', call_pdb=0, **kwargs):
1416 1416 FormattedTB.__init__(self, color_scheme=color_scheme,
1417 1417 call_pdb=call_pdb, **kwargs)
1418 1418
1419 1419
1420 1420 class SyntaxTB(ListTB):
1421 1421 """Extension which holds some state: the last exception value"""
1422 1422
1423 1423 def __init__(self, color_scheme='NoColor'):
1424 1424 ListTB.__init__(self, color_scheme)
1425 1425 self.last_syntax_error = None
1426 1426
1427 1427 def __call__(self, etype, value, elist):
1428 1428 self.last_syntax_error = value
1429 1429
1430 1430 ListTB.__call__(self, etype, value, elist)
1431 1431
1432 1432 def structured_traceback(self, etype, value, elist, tb_offset=None,
1433 1433 context=5):
1434 1434 # If the source file has been edited, the line in the syntax error can
1435 1435 # be wrong (retrieved from an outdated cache). This replaces it with
1436 1436 # the current value.
1437 1437 if isinstance(value, SyntaxError) \
1438 1438 and isinstance(value.filename, py3compat.string_types) \
1439 1439 and isinstance(value.lineno, int):
1440 1440 linecache.checkcache(value.filename)
1441 1441 newtext = ulinecache.getline(value.filename, value.lineno)
1442 1442 if newtext:
1443 1443 value.text = newtext
1444 1444 self.last_syntax_error = value
1445 1445 return super(SyntaxTB, self).structured_traceback(etype, value, elist,
1446 1446 tb_offset=tb_offset, context=context)
1447 1447
1448 1448 def clear_err_state(self):
1449 1449 """Return the current error state and clear it"""
1450 1450 e = self.last_syntax_error
1451 1451 self.last_syntax_error = None
1452 1452 return e
1453 1453
1454 1454 def stb2text(self, stb):
1455 1455 """Convert a structured traceback (a list) to a string."""
1456 1456 return ''.join(stb)
1457 1457
1458 1458
1459 1459 # some internal-use functions
1460 1460 def text_repr(value):
1461 1461 """Hopefully pretty robust repr equivalent."""
1462 1462 # this is pretty horrible but should always return *something*
1463 1463 try:
1464 1464 return pydoc.text.repr(value)
1465 1465 except KeyboardInterrupt:
1466 1466 raise
1467 1467 except:
1468 1468 try:
1469 1469 return repr(value)
1470 1470 except KeyboardInterrupt:
1471 1471 raise
1472 1472 except:
1473 1473 try:
1474 1474 # all still in an except block so we catch
1475 1475 # getattr raising
1476 1476 name = getattr(value, '__name__', None)
1477 1477 if name:
1478 1478 # ick, recursion
1479 1479 return text_repr(name)
1480 1480 klass = getattr(value, '__class__', None)
1481 1481 if klass:
1482 1482 return '%s instance' % text_repr(klass)
1483 1483 except KeyboardInterrupt:
1484 1484 raise
1485 1485 except:
1486 1486 return 'UNRECOVERABLE REPR FAILURE'
1487 1487
1488 1488
1489 1489 def eqrepr(value, repr=text_repr):
1490 1490 return '=%s' % repr(value)
1491 1491
1492 1492
1493 1493 def nullrepr(value, repr=text_repr):
1494 1494 return ''
@@ -1,583 +1,583 b''
1 1 """Module for interactive demos using IPython.
2 2
3 3 This module implements a few classes for running Python scripts interactively
4 4 in IPython for demonstrations. With very simple markup (a few tags in
5 5 comments), you can control points where the script stops executing and returns
6 6 control to IPython.
7 7
8 8
9 9 Provided classes
10 10 ----------------
11 11
12 12 The classes are (see their docstrings for further details):
13 13
14 14 - Demo: pure python demos
15 15
16 16 - IPythonDemo: demos with input to be processed by IPython as if it had been
17 17 typed interactively (so magics work, as well as any other special syntax you
18 18 may have added via input prefilters).
19 19
20 20 - LineDemo: single-line version of the Demo class. These demos are executed
21 21 one line at a time, and require no markup.
22 22
23 23 - IPythonLineDemo: IPython version of the LineDemo class (the demo is
24 24 executed a line at a time, but processed via IPython).
25 25
26 26 - ClearMixin: mixin to make Demo classes with less visual clutter. It
27 27 declares an empty marquee and a pre_cmd that clears the screen before each
28 28 block (see Subclassing below).
29 29
30 30 - ClearDemo, ClearIPDemo: mixin-enabled versions of the Demo and IPythonDemo
31 31 classes.
32 32
33 33 Inheritance diagram:
34 34
35 35 .. inheritance-diagram:: IPython.lib.demo
36 36 :parts: 3
37 37
38 38 Subclassing
39 39 -----------
40 40
41 41 The classes here all include a few methods meant to make customization by
42 42 subclassing more convenient. Their docstrings below have some more details:
43 43
44 44 - marquee(): generates a marquee to provide visible on-screen markers at each
45 45 block start and end.
46 46
47 47 - pre_cmd(): run right before the execution of each block.
48 48
49 49 - post_cmd(): run right after the execution of each block. If the block
50 50 raises an exception, this is NOT called.
51 51
52 52
53 53 Operation
54 54 ---------
55 55
56 56 The file is run in its own empty namespace (though you can pass it a string of
57 57 arguments as if in a command line environment, and it will see those as
58 58 sys.argv). But at each stop, the global IPython namespace is updated with the
59 59 current internal demo namespace, so you can work interactively with the data
60 60 accumulated so far.
61 61
62 62 By default, each block of code is printed (with syntax highlighting) before
63 63 executing it and you have to confirm execution. This is intended to show the
64 64 code to an audience first so you can discuss it, and only proceed with
65 65 execution once you agree. There are a few tags which allow you to modify this
66 66 behavior.
67 67
68 68 The supported tags are:
69 69
70 70 # <demo> stop
71 71
72 72 Defines block boundaries, the points where IPython stops execution of the
73 73 file and returns to the interactive prompt.
74 74
75 75 You can optionally mark the stop tag with extra dashes before and after the
76 76 word 'stop', to help visually distinguish the blocks in a text editor:
77 77
78 78 # <demo> --- stop ---
79 79
80 80
81 81 # <demo> silent
82 82
83 83 Make a block execute silently (and hence automatically). Typically used in
84 84 cases where you have some boilerplate or initialization code which you need
85 85 executed but do not want to be seen in the demo.
86 86
87 87 # <demo> auto
88 88
89 89 Make a block execute automatically, but still being printed. Useful for
90 90 simple code which does not warrant discussion, since it avoids the extra
91 91 manual confirmation.
92 92
93 93 # <demo> auto_all
94 94
95 95 This tag can _only_ be in the first block, and if given it overrides the
96 96 individual auto tags to make the whole demo fully automatic (no block asks
97 97 for confirmation). It can also be given at creation time (or the attribute
98 98 set later) to override what's in the file.
99 99
100 100 While _any_ python file can be run as a Demo instance, if there are no stop
101 101 tags the whole file will run in a single block (no different that calling
102 102 first %pycat and then %run). The minimal markup to make this useful is to
103 103 place a set of stop tags; the other tags are only there to let you fine-tune
104 104 the execution.
105 105
106 106 This is probably best explained with the simple example file below. You can
107 107 copy this into a file named ex_demo.py, and try running it via::
108 108
109 109 from IPython.demo import Demo
110 110 d = Demo('ex_demo.py')
111 111 d()
112 112
113 113 Each time you call the demo object, it runs the next block. The demo object
114 114 has a few useful methods for navigation, like again(), edit(), jump(), seek()
115 115 and back(). It can be reset for a new run via reset() or reloaded from disk
116 116 (in case you've edited the source) via reload(). See their docstrings below.
117 117
118 118 Note: To make this simpler to explore, a file called "demo-exercizer.py" has
119 119 been added to the "docs/examples/core" directory. Just cd to this directory in
120 120 an IPython session, and type::
121 121
122 122 %run demo-exercizer.py
123 123
124 124 and then follow the directions.
125 125
126 126 Example
127 127 -------
128 128
129 129 The following is a very simple example of a valid demo file.
130 130
131 131 ::
132 132
133 133 #################### EXAMPLE DEMO <ex_demo.py> ###############################
134 134 '''A simple interactive demo to illustrate the use of IPython's Demo class.'''
135 135
136 136 print 'Hello, welcome to an interactive IPython demo.'
137 137
138 138 # The mark below defines a block boundary, which is a point where IPython will
139 139 # stop execution and return to the interactive prompt. The dashes are actually
140 140 # optional and used only as a visual aid to clearly separate blocks while
141 141 # editing the demo code.
142 142 # <demo> stop
143 143
144 144 x = 1
145 145 y = 2
146 146
147 147 # <demo> stop
148 148
149 149 # the mark below makes this block as silent
150 150 # <demo> silent
151 151
152 152 print 'This is a silent block, which gets executed but not printed.'
153 153
154 154 # <demo> stop
155 155 # <demo> auto
156 156 print 'This is an automatic block.'
157 157 print 'It is executed without asking for confirmation, but printed.'
158 158 z = x+y
159 159
160 160 print 'z=',x
161 161
162 162 # <demo> stop
163 163 # This is just another normal block.
164 164 print 'z is now:', z
165 165
166 166 print 'bye!'
167 167 ################### END EXAMPLE DEMO <ex_demo.py> ############################
168 168 """
169 169
170 170 from __future__ import unicode_literals
171 171
172 172 #*****************************************************************************
173 173 # Copyright (C) 2005-2006 Fernando Perez. <Fernando.Perez@colorado.edu>
174 174 #
175 175 # Distributed under the terms of the BSD License. The full license is in
176 176 # the file COPYING, distributed as part of this software.
177 177 #
178 178 #*****************************************************************************
179 179 from __future__ import print_function
180 180
181 181 import os
182 182 import re
183 183 import shlex
184 184 import sys
185 185
186 186 from IPython.utils import io
187 187 from IPython.utils.text import marquee
188 188 from IPython.utils import openpy
189 189 from IPython.utils import py3compat
190 190 __all__ = ['Demo','IPythonDemo','LineDemo','IPythonLineDemo','DemoError']
191 191
192 192 class DemoError(Exception): pass
193 193
194 194 def re_mark(mark):
195 195 return re.compile(r'^\s*#\s+<demo>\s+%s\s*$' % mark,re.MULTILINE)
196 196
197 197 class Demo(object):
198 198
199 199 re_stop = re_mark('-*\s?stop\s?-*')
200 200 re_silent = re_mark('silent')
201 201 re_auto = re_mark('auto')
202 202 re_auto_all = re_mark('auto_all')
203 203
204 204 def __init__(self,src,title='',arg_str='',auto_all=None):
205 205 """Make a new demo object. To run the demo, simply call the object.
206 206
207 207 See the module docstring for full details and an example (you can use
208 208 IPython.Demo? in IPython to see it).
209 209
210 210 Inputs:
211 211
212 212 - src is either a file, or file-like object, or a
213 213 string that can be resolved to a filename.
214 214
215 215 Optional inputs:
216 216
217 217 - title: a string to use as the demo name. Of most use when the demo
218 218 you are making comes from an object that has no filename, or if you
219 219 want an alternate denotation distinct from the filename.
220 220
221 221 - arg_str(''): a string of arguments, internally converted to a list
222 222 just like sys.argv, so the demo script can see a similar
223 223 environment.
224 224
225 225 - auto_all(None): global flag to run all blocks automatically without
226 226 confirmation. This attribute overrides the block-level tags and
227 227 applies to the whole demo. It is an attribute of the object, and
228 228 can be changed at runtime simply by reassigning it to a boolean
229 229 value.
230 230 """
231 231 if hasattr(src, "read"):
232 232 # It seems to be a file or a file-like object
233 233 self.fname = "from a file-like object"
234 234 if title == '':
235 235 self.title = "from a file-like object"
236 236 else:
237 237 self.title = title
238 238 else:
239 239 # Assume it's a string or something that can be converted to one
240 240 self.fname = src
241 241 if title == '':
242 242 (filepath, filename) = os.path.split(src)
243 243 self.title = filename
244 244 else:
245 245 self.title = title
246 246 self.sys_argv = [src] + shlex.split(arg_str)
247 247 self.auto_all = auto_all
248 248 self.src = src
249 249
250 250 # get a few things from ipython. While it's a bit ugly design-wise,
251 251 # it ensures that things like color scheme and the like are always in
252 252 # sync with the ipython mode being used. This class is only meant to
253 253 # be used inside ipython anyways, so it's OK.
254 254 ip = get_ipython() # this is in builtins whenever IPython is running
255 255 self.ip_ns = ip.user_ns
256 256 self.ip_colorize = ip.pycolorize
257 257 self.ip_showtb = ip.showtraceback
258 258 self.ip_run_cell = ip.run_cell
259 259 self.shell = ip
260 260
261 261 # load user data and initialize data structures
262 262 self.reload()
263 263
264 264 def fload(self):
265 265 """Load file object."""
266 266 # read data and parse into blocks
267 267 if hasattr(self, 'fobj') and self.fobj is not None:
268 268 self.fobj.close()
269 269 if hasattr(self.src, "read"):
270 270 # It seems to be a file or a file-like object
271 271 self.fobj = self.src
272 272 else:
273 273 # Assume it's a string or something that can be converted to one
274 274 self.fobj = openpy.open(self.fname)
275 275
276 276 def reload(self):
277 277 """Reload source from disk and initialize state."""
278 278 self.fload()
279 279
280 280 self.src = "".join(openpy.strip_encoding_cookie(self.fobj))
281 281 src_b = [b.strip() for b in self.re_stop.split(self.src) if b]
282 282 self._silent = [bool(self.re_silent.findall(b)) for b in src_b]
283 283 self._auto = [bool(self.re_auto.findall(b)) for b in src_b]
284 284
285 285 # if auto_all is not given (def. None), we read it from the file
286 286 if self.auto_all is None:
287 287 self.auto_all = bool(self.re_auto_all.findall(src_b[0]))
288 288 else:
289 289 self.auto_all = bool(self.auto_all)
290 290
291 291 # Clean the sources from all markup so it doesn't get displayed when
292 292 # running the demo
293 293 src_blocks = []
294 294 auto_strip = lambda s: self.re_auto.sub('',s)
295 295 for i,b in enumerate(src_b):
296 296 if self._auto[i]:
297 297 src_blocks.append(auto_strip(b))
298 298 else:
299 299 src_blocks.append(b)
300 300 # remove the auto_all marker
301 301 src_blocks[0] = self.re_auto_all.sub('',src_blocks[0])
302 302
303 303 self.nblocks = len(src_blocks)
304 304 self.src_blocks = src_blocks
305 305
306 306 # also build syntax-highlighted source
307 307 self.src_blocks_colored = list(map(self.ip_colorize,self.src_blocks))
308 308
309 309 # ensure clean namespace and seek offset
310 310 self.reset()
311 311
312 312 def reset(self):
313 313 """Reset the namespace and seek pointer to restart the demo"""
314 314 self.user_ns = {}
315 315 self.finished = False
316 316 self.block_index = 0
317 317
318 318 def _validate_index(self,index):
319 319 if index<0 or index>=self.nblocks:
320 320 raise ValueError('invalid block index %s' % index)
321 321
322 322 def _get_index(self,index):
323 323 """Get the current block index, validating and checking status.
324 324
325 325 Returns None if the demo is finished"""
326 326
327 327 if index is None:
328 328 if self.finished:
329 329 print('Demo finished. Use <demo_name>.reset() if you want to rerun it.')
330 330 return None
331 331 index = self.block_index
332 332 else:
333 333 self._validate_index(index)
334 334 return index
335 335
336 336 def seek(self,index):
337 337 """Move the current seek pointer to the given block.
338 338
339 339 You can use negative indices to seek from the end, with identical
340 340 semantics to those of Python lists."""
341 341 if index<0:
342 342 index = self.nblocks + index
343 343 self._validate_index(index)
344 344 self.block_index = index
345 345 self.finished = False
346 346
347 347 def back(self,num=1):
348 348 """Move the seek pointer back num blocks (default is 1)."""
349 349 self.seek(self.block_index-num)
350 350
351 351 def jump(self,num=1):
352 352 """Jump a given number of blocks relative to the current one.
353 353
354 354 The offset can be positive or negative, defaults to 1."""
355 355 self.seek(self.block_index+num)
356 356
357 357 def again(self):
358 358 """Move the seek pointer back one block and re-execute."""
359 359 self.back(1)
360 360 self()
361 361
362 362 def edit(self,index=None):
363 363 """Edit a block.
364 364
365 365 If no number is given, use the last block executed.
366 366
367 367 This edits the in-memory copy of the demo, it does NOT modify the
368 368 original source file. If you want to do that, simply open the file in
369 369 an editor and use reload() when you make changes to the file. This
370 370 method is meant to let you change a block during a demonstration for
371 371 explanatory purposes, without damaging your original script."""
372 372
373 373 index = self._get_index(index)
374 374 if index is None:
375 375 return
376 376 # decrease the index by one (unless we're at the very beginning), so
377 377 # that the default demo.edit() call opens up the sblock we've last run
378 378 if index>0:
379 379 index -= 1
380 380
381 381 filename = self.shell.mktempfile(self.src_blocks[index])
382 382 self.shell.hooks.editor(filename,1)
383 383 with open(filename, 'r') as f:
384 384 new_block = f.read()
385 385 # update the source and colored block
386 386 self.src_blocks[index] = new_block
387 387 self.src_blocks_colored[index] = self.ip_colorize(new_block)
388 388 self.block_index = index
389 389 # call to run with the newly edited index
390 390 self()
391 391
392 392 def show(self,index=None):
393 393 """Show a single block on screen"""
394 394
395 395 index = self._get_index(index)
396 396 if index is None:
397 397 return
398 398
399 399 print(self.marquee('<%s> block # %s (%s remaining)' %
400 400 (self.title,index,self.nblocks-index-1)))
401 401 print(self.src_blocks_colored[index])
402 402 sys.stdout.flush()
403 403
404 404 def show_all(self):
405 405 """Show entire demo on screen, block by block"""
406 406
407 407 fname = self.title
408 408 title = self.title
409 409 nblocks = self.nblocks
410 410 silent = self._silent
411 411 marquee = self.marquee
412 412 for index,block in enumerate(self.src_blocks_colored):
413 413 if silent[index]:
414 414 print(marquee('<%s> SILENT block # %s (%s remaining)' %
415 415 (title,index,nblocks-index-1)))
416 416 else:
417 417 print(marquee('<%s> block # %s (%s remaining)' %
418 418 (title,index,nblocks-index-1)))
419 419 print(block, end=' ')
420 420 sys.stdout.flush()
421 421
422 422 def run_cell(self,source):
423 423 """Execute a string with one or more lines of code"""
424 424
425 425 exec(source, self.user_ns)
426 426
427 427 def __call__(self,index=None):
428 428 """run a block of the demo.
429 429
430 430 If index is given, it should be an integer >=1 and <= nblocks. This
431 431 means that the calling convention is one off from typical Python
432 432 lists. The reason for the inconsistency is that the demo always
433 433 prints 'Block n/N, and N is the total, so it would be very odd to use
434 434 zero-indexing here."""
435 435
436 436 index = self._get_index(index)
437 437 if index is None:
438 438 return
439 439 try:
440 440 marquee = self.marquee
441 441 next_block = self.src_blocks[index]
442 442 self.block_index += 1
443 443 if self._silent[index]:
444 444 print(marquee('Executing silent block # %s (%s remaining)' %
445 445 (index,self.nblocks-index-1)))
446 446 else:
447 447 self.pre_cmd()
448 448 self.show(index)
449 449 if self.auto_all or self._auto[index]:
450 450 print(marquee('output:'))
451 451 else:
452 452 print(marquee('Press <q> to quit, <Enter> to execute...'), end=' ')
453 453 ans = py3compat.input().strip()
454 454 if ans:
455 455 print(marquee('Block NOT executed'))
456 456 return
457 457 try:
458 458 save_argv = sys.argv
459 459 sys.argv = self.sys_argv
460 460 self.run_cell(next_block)
461 461 self.post_cmd()
462 462 finally:
463 463 sys.argv = save_argv
464 464
465 465 except:
466 466 self.ip_showtb(filename=self.fname)
467 467 else:
468 468 self.ip_ns.update(self.user_ns)
469 469
470 470 if self.block_index == self.nblocks:
471 471 mq1 = self.marquee('END OF DEMO')
472 472 if mq1:
473 # avoid spurious print >>io.stdout,s if empty marquees are used
473 # avoid spurious print if empty marquees are used
474 474 print()
475 475 print(mq1)
476 476 print(self.marquee('Use <demo_name>.reset() if you want to rerun it.'))
477 477 self.finished = True
478 478
479 479 # These methods are meant to be overridden by subclasses who may wish to
480 480 # customize the behavior of of their demos.
481 481 def marquee(self,txt='',width=78,mark='*'):
482 482 """Return the input string centered in a 'marquee'."""
483 483 return marquee(txt,width,mark)
484 484
485 485 def pre_cmd(self):
486 486 """Method called before executing each block."""
487 487 pass
488 488
489 489 def post_cmd(self):
490 490 """Method called after executing each block."""
491 491 pass
492 492
493 493
494 494 class IPythonDemo(Demo):
495 495 """Class for interactive demos with IPython's input processing applied.
496 496
497 497 This subclasses Demo, but instead of executing each block by the Python
498 498 interpreter (via exec), it actually calls IPython on it, so that any input
499 499 filters which may be in place are applied to the input block.
500 500
501 501 If you have an interactive environment which exposes special input
502 502 processing, you can use this class instead to write demo scripts which
503 503 operate exactly as if you had typed them interactively. The default Demo
504 504 class requires the input to be valid, pure Python code.
505 505 """
506 506
507 507 def run_cell(self,source):
508 508 """Execute a string with one or more lines of code"""
509 509
510 510 self.shell.run_cell(source)
511 511
512 512 class LineDemo(Demo):
513 513 """Demo where each line is executed as a separate block.
514 514
515 515 The input script should be valid Python code.
516 516
517 517 This class doesn't require any markup at all, and it's meant for simple
518 518 scripts (with no nesting or any kind of indentation) which consist of
519 519 multiple lines of input to be executed, one at a time, as if they had been
520 520 typed in the interactive prompt.
521 521
522 522 Note: the input can not have *any* indentation, which means that only
523 523 single-lines of input are accepted, not even function definitions are
524 524 valid."""
525 525
526 526 def reload(self):
527 527 """Reload source from disk and initialize state."""
528 528 # read data and parse into blocks
529 529 self.fload()
530 530 lines = self.fobj.readlines()
531 531 src_b = [l for l in lines if l.strip()]
532 532 nblocks = len(src_b)
533 533 self.src = ''.join(lines)
534 534 self._silent = [False]*nblocks
535 535 self._auto = [True]*nblocks
536 536 self.auto_all = True
537 537 self.nblocks = nblocks
538 538 self.src_blocks = src_b
539 539
540 540 # also build syntax-highlighted source
541 541 self.src_blocks_colored = map(self.ip_colorize,self.src_blocks)
542 542
543 543 # ensure clean namespace and seek offset
544 544 self.reset()
545 545
546 546
547 547 class IPythonLineDemo(IPythonDemo,LineDemo):
548 548 """Variant of the LineDemo class whose input is processed by IPython."""
549 549 pass
550 550
551 551
552 552 class ClearMixin(object):
553 553 """Use this mixin to make Demo classes with less visual clutter.
554 554
555 555 Demos using this mixin will clear the screen before every block and use
556 556 blank marquees.
557 557
558 558 Note that in order for the methods defined here to actually override those
559 559 of the classes it's mixed with, it must go /first/ in the inheritance
560 560 tree. For example:
561 561
562 562 class ClearIPDemo(ClearMixin,IPythonDemo): pass
563 563
564 564 will provide an IPythonDemo class with the mixin's features.
565 565 """
566 566
567 567 def marquee(self,txt='',width=78,mark='*'):
568 568 """Blank marquee that returns '' no matter what the input."""
569 569 return ''
570 570
571 571 def pre_cmd(self):
572 572 """Method called before executing each block.
573 573
574 574 This one simply clears the screen."""
575 575 from IPython.utils.terminal import term_clear
576 576 term_clear()
577 577
578 578 class ClearDemo(ClearMixin,Demo):
579 579 pass
580 580
581 581
582 582 class ClearIPDemo(ClearMixin,IPythonDemo):
583 583 pass
@@ -1,139 +1,139 b''
1 1 # encoding: utf-8
2 2 """Tests for IPython.utils.path.py"""
3 3
4 4 # Copyright (c) IPython Development Team.
5 5 # Distributed under the terms of the Modified BSD License.
6 6
7 7 try:
8 8 from unittest.mock import patch
9 9 except ImportError:
10 10 from mock import patch
11 11
12 12 import nose.tools as nt
13 13
14 14 from IPython.lib import latextools
15 15 from IPython.testing.decorators import onlyif_cmds_exist, skipif_not_matplotlib
16 16 from IPython.utils.process import FindCmdError
17 17
18 18
19 19 def test_latex_to_png_dvipng_fails_when_no_cmd():
20 20 """
21 21 `latex_to_png_dvipng` should return None when there is no required command
22 22 """
23 23 for command in ['latex', 'dvipng']:
24 24 yield (check_latex_to_png_dvipng_fails_when_no_cmd, command)
25 25
26 26
27 27 def check_latex_to_png_dvipng_fails_when_no_cmd(command):
28 28 def mock_find_cmd(arg):
29 29 if arg == command:
30 30 raise FindCmdError
31 31
32 32 with patch.object(latextools, "find_cmd", mock_find_cmd):
33 nt.assert_equals(latextools.latex_to_png_dvipng("whatever", True),
33 nt.assert_equal(latextools.latex_to_png_dvipng("whatever", True),
34 34 None)
35 35
36 36
37 37 @onlyif_cmds_exist('latex', 'dvipng')
38 38 def test_latex_to_png_dvipng_runs():
39 39 """
40 40 Test that latex_to_png_dvipng just runs without error.
41 41 """
42 42 def mock_kpsewhich(filename):
43 nt.assert_equals(filename, "breqn.sty")
43 nt.assert_equal(filename, "breqn.sty")
44 44 return None
45 45
46 46 for (s, wrap) in [(u"$$x^2$$", False), (u"x^2", True)]:
47 47 yield (latextools.latex_to_png_dvipng, s, wrap)
48 48
49 49 with patch.object(latextools, "kpsewhich", mock_kpsewhich):
50 50 yield (latextools.latex_to_png_dvipng, s, wrap)
51 51
52 52 @skipif_not_matplotlib
53 53 def test_latex_to_png_mpl_runs():
54 54 """
55 55 Test that latex_to_png_mpl just runs without error.
56 56 """
57 57 def mock_kpsewhich(filename):
58 nt.assert_equals(filename, "breqn.sty")
58 nt.assert_equal(filename, "breqn.sty")
59 59 return None
60 60
61 61 for (s, wrap) in [("$x^2$", False), ("x^2", True)]:
62 62 yield (latextools.latex_to_png_mpl, s, wrap)
63 63
64 64 with patch.object(latextools, "kpsewhich", mock_kpsewhich):
65 65 yield (latextools.latex_to_png_mpl, s, wrap)
66 66
67 67 @skipif_not_matplotlib
68 68 def test_latex_to_html():
69 69 img = latextools.latex_to_html("$x^2$")
70 70 nt.assert_in("data:image/png;base64,iVBOR", img)
71 71
72 72
73 73 def test_genelatex_no_wrap():
74 74 """
75 75 Test genelatex with wrap=False.
76 76 """
77 77 def mock_kpsewhich(filename):
78 78 assert False, ("kpsewhich should not be called "
79 79 "(called with {0})".format(filename))
80 80
81 81 with patch.object(latextools, "kpsewhich", mock_kpsewhich):
82 nt.assert_equals(
82 nt.assert_equal(
83 83 '\n'.join(latextools.genelatex("body text", False)),
84 84 r'''\documentclass{article}
85 85 \usepackage{amsmath}
86 86 \usepackage{amsthm}
87 87 \usepackage{amssymb}
88 88 \usepackage{bm}
89 89 \pagestyle{empty}
90 90 \begin{document}
91 91 body text
92 92 \end{document}''')
93 93
94 94
95 95 def test_genelatex_wrap_with_breqn():
96 96 """
97 97 Test genelatex with wrap=True for the case breqn.sty is installed.
98 98 """
99 99 def mock_kpsewhich(filename):
100 nt.assert_equals(filename, "breqn.sty")
100 nt.assert_equal(filename, "breqn.sty")
101 101 return "path/to/breqn.sty"
102 102
103 103 with patch.object(latextools, "kpsewhich", mock_kpsewhich):
104 nt.assert_equals(
104 nt.assert_equal(
105 105 '\n'.join(latextools.genelatex("x^2", True)),
106 106 r'''\documentclass{article}
107 107 \usepackage{amsmath}
108 108 \usepackage{amsthm}
109 109 \usepackage{amssymb}
110 110 \usepackage{bm}
111 111 \usepackage{breqn}
112 112 \pagestyle{empty}
113 113 \begin{document}
114 114 \begin{dmath*}
115 115 x^2
116 116 \end{dmath*}
117 117 \end{document}''')
118 118
119 119
120 120 def test_genelatex_wrap_without_breqn():
121 121 """
122 122 Test genelatex with wrap=True for the case breqn.sty is not installed.
123 123 """
124 124 def mock_kpsewhich(filename):
125 nt.assert_equals(filename, "breqn.sty")
125 nt.assert_equal(filename, "breqn.sty")
126 126 return None
127 127
128 128 with patch.object(latextools, "kpsewhich", mock_kpsewhich):
129 nt.assert_equals(
129 nt.assert_equal(
130 130 '\n'.join(latextools.genelatex("x^2", True)),
131 131 r'''\documentclass{article}
132 132 \usepackage{amsmath}
133 133 \usepackage{amsthm}
134 134 \usepackage{amssymb}
135 135 \usepackage{bm}
136 136 \pagestyle{empty}
137 137 \begin{document}
138 138 $$x^2$$
139 139 \end{document}''')
@@ -1,1185 +1,1184 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 Sphinx directive to support embedded IPython code.
4 4
5 5 This directive allows pasting of entire interactive IPython sessions, prompts
6 6 and all, and their code will actually get re-executed at doc build time, with
7 7 all prompts renumbered sequentially. It also allows you to input code as a pure
8 8 python input by giving the argument python to the directive. The output looks
9 9 like an interactive ipython section.
10 10
11 11 To enable this directive, simply list it in your Sphinx ``conf.py`` file
12 12 (making sure the directory where you placed it is visible to sphinx, as is
13 13 needed for all Sphinx directives). For example, to enable syntax highlighting
14 14 and the IPython directive::
15 15
16 16 extensions = ['IPython.sphinxext.ipython_console_highlighting',
17 17 'IPython.sphinxext.ipython_directive']
18 18
19 19 The IPython directive outputs code-blocks with the language 'ipython'. So
20 20 if you do not have the syntax highlighting extension enabled as well, then
21 21 all rendered code-blocks will be uncolored. By default this directive assumes
22 22 that your prompts are unchanged IPython ones, but this can be customized.
23 23 The configurable options that can be placed in conf.py are:
24 24
25 25 ipython_savefig_dir:
26 26 The directory in which to save the figures. This is relative to the
27 27 Sphinx source directory. The default is `html_static_path`.
28 28 ipython_rgxin:
29 29 The compiled regular expression to denote the start of IPython input
30 30 lines. The default is re.compile('In \[(\d+)\]:\s?(.*)\s*'). You
31 31 shouldn't need to change this.
32 32 ipython_rgxout:
33 33 The compiled regular expression to denote the start of IPython output
34 34 lines. The default is re.compile('Out\[(\d+)\]:\s?(.*)\s*'). You
35 35 shouldn't need to change this.
36 36 ipython_promptin:
37 37 The string to represent the IPython input prompt in the generated ReST.
38 38 The default is 'In [%d]:'. This expects that the line numbers are used
39 39 in the prompt.
40 40 ipython_promptout:
41 41 The string to represent the IPython prompt in the generated ReST. The
42 42 default is 'Out [%d]:'. This expects that the line numbers are used
43 43 in the prompt.
44 44 ipython_mplbackend:
45 45 The string which specifies if the embedded Sphinx shell should import
46 46 Matplotlib and set the backend. The value specifies a backend that is
47 47 passed to `matplotlib.use()` before any lines in `ipython_execlines` are
48 48 executed. If not specified in conf.py, then the default value of 'agg' is
49 49 used. To use the IPython directive without matplotlib as a dependency, set
50 50 the value to `None`. It may end up that matplotlib is still imported
51 51 if the user specifies so in `ipython_execlines` or makes use of the
52 52 @savefig pseudo decorator.
53 53 ipython_execlines:
54 54 A list of strings to be exec'd in the embedded Sphinx shell. Typical
55 55 usage is to make certain packages always available. Set this to an empty
56 56 list if you wish to have no imports always available. If specified in
57 57 conf.py as `None`, then it has the effect of making no imports available.
58 58 If omitted from conf.py altogether, then the default value of
59 59 ['import numpy as np', 'import matplotlib.pyplot as plt'] is used.
60 60 ipython_holdcount
61 61 When the @suppress pseudo-decorator is used, the execution count can be
62 62 incremented or not. The default behavior is to hold the execution count,
63 63 corresponding to a value of `True`. Set this to `False` to increment
64 64 the execution count after each suppressed command.
65 65
66 66 As an example, to use the IPython directive when `matplotlib` is not available,
67 67 one sets the backend to `None`::
68 68
69 69 ipython_mplbackend = None
70 70
71 71 An example usage of the directive is:
72 72
73 73 .. code-block:: rst
74 74
75 75 .. ipython::
76 76
77 77 In [1]: x = 1
78 78
79 79 In [2]: y = x**2
80 80
81 81 In [3]: print(y)
82 82
83 83 See http://matplotlib.org/sampledoc/ipython_directive.html for additional
84 84 documentation.
85 85
86 86 Pseudo-Decorators
87 87 =================
88 88
89 89 Note: Only one decorator is supported per input. If more than one decorator
90 90 is specified, then only the last one is used.
91 91
92 92 In addition to the Pseudo-Decorators/options described at the above link,
93 93 several enhancements have been made. The directive will emit a message to the
94 94 console at build-time if code-execution resulted in an exception or warning.
95 95 You can suppress these on a per-block basis by specifying the :okexcept:
96 96 or :okwarning: options:
97 97
98 98 .. code-block:: rst
99 99
100 100 .. ipython::
101 101 :okexcept:
102 102 :okwarning:
103 103
104 104 In [1]: 1/0
105 105 In [2]: # raise warning.
106 106
107 107 ToDo
108 108 ----
109 109
110 110 - Turn the ad-hoc test() function into a real test suite.
111 111 - Break up ipython-specific functionality from matplotlib stuff into better
112 112 separated code.
113 113
114 114 Authors
115 115 -------
116 116
117 117 - John D Hunter: orignal author.
118 118 - Fernando Perez: refactoring, documentation, cleanups, port to 0.11.
119 119 - VΓ‘clavΕ milauer <eudoxos-AT-arcig.cz>: Prompt generalizations.
120 120 - Skipper Seabold, refactoring, cleanups, pure python addition
121 121 """
122 122 from __future__ import print_function
123 123
124 124 #-----------------------------------------------------------------------------
125 125 # Imports
126 126 #-----------------------------------------------------------------------------
127 127
128 128 # Stdlib
129 129 import atexit
130 130 import os
131 131 import re
132 132 import sys
133 133 import tempfile
134 134 import ast
135 135 import warnings
136 136 import shutil
137 137
138 138
139 139 # Third-party
140 140 from docutils.parsers.rst import directives
141 141 from sphinx.util.compat import Directive
142 142
143 143 # Our own
144 144 from traitlets.config import Config
145 145 from IPython import InteractiveShell
146 146 from IPython.core.profiledir import ProfileDir
147 147 from IPython.utils import io
148 148 from IPython.utils.py3compat import PY3
149 149
150 150 if PY3:
151 151 from io import StringIO
152 152 else:
153 153 from StringIO import StringIO
154 154
155 155 #-----------------------------------------------------------------------------
156 156 # Globals
157 157 #-----------------------------------------------------------------------------
158 158 # for tokenizing blocks
159 159 COMMENT, INPUT, OUTPUT = range(3)
160 160
161 161 #-----------------------------------------------------------------------------
162 162 # Functions and class declarations
163 163 #-----------------------------------------------------------------------------
164 164
165 165 def block_parser(part, rgxin, rgxout, fmtin, fmtout):
166 166 """
167 167 part is a string of ipython text, comprised of at most one
168 168 input, one output, comments, and blank lines. The block parser
169 169 parses the text into a list of::
170 170
171 171 blocks = [ (TOKEN0, data0), (TOKEN1, data1), ...]
172 172
173 173 where TOKEN is one of [COMMENT | INPUT | OUTPUT ] and
174 174 data is, depending on the type of token::
175 175
176 176 COMMENT : the comment string
177 177
178 178 INPUT: the (DECORATOR, INPUT_LINE, REST) where
179 179 DECORATOR: the input decorator (or None)
180 180 INPUT_LINE: the input as string (possibly multi-line)
181 181 REST : any stdout generated by the input line (not OUTPUT)
182 182
183 183 OUTPUT: the output string, possibly multi-line
184 184
185 185 """
186 186 block = []
187 187 lines = part.split('\n')
188 188 N = len(lines)
189 189 i = 0
190 190 decorator = None
191 191 while 1:
192 192
193 193 if i==N:
194 194 # nothing left to parse -- the last line
195 195 break
196 196
197 197 line = lines[i]
198 198 i += 1
199 199 line_stripped = line.strip()
200 200 if line_stripped.startswith('#'):
201 201 block.append((COMMENT, line))
202 202 continue
203 203
204 204 if line_stripped.startswith('@'):
205 205 # Here is where we assume there is, at most, one decorator.
206 206 # Might need to rethink this.
207 207 decorator = line_stripped
208 208 continue
209 209
210 210 # does this look like an input line?
211 211 matchin = rgxin.match(line)
212 212 if matchin:
213 213 lineno, inputline = int(matchin.group(1)), matchin.group(2)
214 214
215 215 # the ....: continuation string
216 216 continuation = ' %s:'%''.join(['.']*(len(str(lineno))+2))
217 217 Nc = len(continuation)
218 218 # input lines can continue on for more than one line, if
219 219 # we have a '\' line continuation char or a function call
220 220 # echo line 'print'. The input line can only be
221 221 # terminated by the end of the block or an output line, so
222 222 # we parse out the rest of the input line if it is
223 223 # multiline as well as any echo text
224 224
225 225 rest = []
226 226 while i<N:
227 227
228 228 # look ahead; if the next line is blank, or a comment, or
229 229 # an output line, we're done
230 230
231 231 nextline = lines[i]
232 232 matchout = rgxout.match(nextline)
233 233 #print "nextline=%s, continuation=%s, starts=%s"%(nextline, continuation, nextline.startswith(continuation))
234 234 if matchout or nextline.startswith('#'):
235 235 break
236 236 elif nextline.startswith(continuation):
237 237 # The default ipython_rgx* treat the space following the colon as optional.
238 238 # However, If the space is there we must consume it or code
239 239 # employing the cython_magic extension will fail to execute.
240 240 #
241 241 # This works with the default ipython_rgx* patterns,
242 242 # If you modify them, YMMV.
243 243 nextline = nextline[Nc:]
244 244 if nextline and nextline[0] == ' ':
245 245 nextline = nextline[1:]
246 246
247 247 inputline += '\n' + nextline
248 248 else:
249 249 rest.append(nextline)
250 250 i+= 1
251 251
252 252 block.append((INPUT, (decorator, inputline, '\n'.join(rest))))
253 253 continue
254 254
255 255 # if it looks like an output line grab all the text to the end
256 256 # of the block
257 257 matchout = rgxout.match(line)
258 258 if matchout:
259 259 lineno, output = int(matchout.group(1)), matchout.group(2)
260 260 if i<N-1:
261 261 output = '\n'.join([output] + lines[i:])
262 262
263 263 block.append((OUTPUT, output))
264 264 break
265 265
266 266 return block
267 267
268 268
269 269 class EmbeddedSphinxShell(object):
270 270 """An embedded IPython instance to run inside Sphinx"""
271 271
272 272 def __init__(self, exec_lines=None):
273 273
274 274 self.cout = StringIO()
275 275
276 276 if exec_lines is None:
277 277 exec_lines = []
278 278
279 279 # Create config object for IPython
280 280 config = Config()
281 281 config.HistoryManager.hist_file = ':memory:'
282 282 config.InteractiveShell.autocall = False
283 283 config.InteractiveShell.autoindent = False
284 284 config.InteractiveShell.colors = 'NoColor'
285 285
286 286 # create a profile so instance history isn't saved
287 287 tmp_profile_dir = tempfile.mkdtemp(prefix='profile_')
288 288 profname = 'auto_profile_sphinx_build'
289 289 pdir = os.path.join(tmp_profile_dir,profname)
290 290 profile = ProfileDir.create_profile_dir(pdir)
291 291
292 292 # Create and initialize global ipython, but don't start its mainloop.
293 293 # This will persist across different EmbededSphinxShell instances.
294 294 IP = InteractiveShell.instance(config=config, profile_dir=profile)
295 295 atexit.register(self.cleanup)
296 296
297 # io.stdout redirect must be done after instantiating InteractiveShell
298 io.stdout = self.cout
299 io.stderr = self.cout
297 sys.stdout = self.cout
298 sys.stderr = self.cout
300 299
301 300 # For debugging, so we can see normal output, use this:
302 301 #from IPython.utils.io import Tee
303 #io.stdout = Tee(self.cout, channel='stdout') # dbg
304 #io.stderr = Tee(self.cout, channel='stderr') # dbg
302 #sys.stdout = Tee(self.cout, channel='stdout') # dbg
303 #sys.stderr = Tee(self.cout, channel='stderr') # dbg
305 304
306 305 # Store a few parts of IPython we'll need.
307 306 self.IP = IP
308 307 self.user_ns = self.IP.user_ns
309 308 self.user_global_ns = self.IP.user_global_ns
310 309
311 310 self.input = ''
312 311 self.output = ''
313 312 self.tmp_profile_dir = tmp_profile_dir
314 313
315 314 self.is_verbatim = False
316 315 self.is_doctest = False
317 316 self.is_suppress = False
318 317
319 318 # Optionally, provide more detailed information to shell.
320 319 # this is assigned by the SetUp method of IPythonDirective
321 320 # to point at itself.
322 321 #
323 322 # So, you can access handy things at self.directive.state
324 323 self.directive = None
325 324
326 325 # on the first call to the savefig decorator, we'll import
327 326 # pyplot as plt so we can make a call to the plt.gcf().savefig
328 327 self._pyplot_imported = False
329 328
330 329 # Prepopulate the namespace.
331 330 for line in exec_lines:
332 331 self.process_input_line(line, store_history=False)
333 332
334 333 def cleanup(self):
335 334 shutil.rmtree(self.tmp_profile_dir, ignore_errors=True)
336 335
337 336 def clear_cout(self):
338 337 self.cout.seek(0)
339 338 self.cout.truncate(0)
340 339
341 340 def process_input_line(self, line, store_history=True):
342 341 """process the input, capturing stdout"""
343 342
344 343 stdout = sys.stdout
345 344 splitter = self.IP.input_splitter
346 345 try:
347 346 sys.stdout = self.cout
348 347 splitter.push(line)
349 348 more = splitter.push_accepts_more()
350 349 if not more:
351 350 source_raw = splitter.raw_reset()
352 351 self.IP.run_cell(source_raw, store_history=store_history)
353 352 finally:
354 353 sys.stdout = stdout
355 354
356 355 def process_image(self, decorator):
357 356 """
358 357 # build out an image directive like
359 358 # .. image:: somefile.png
360 359 # :width 4in
361 360 #
362 361 # from an input like
363 362 # savefig somefile.png width=4in
364 363 """
365 364 savefig_dir = self.savefig_dir
366 365 source_dir = self.source_dir
367 366 saveargs = decorator.split(' ')
368 367 filename = saveargs[1]
369 368 # insert relative path to image file in source
370 369 outfile = os.path.relpath(os.path.join(savefig_dir,filename),
371 370 source_dir)
372 371
373 372 imagerows = ['.. image:: %s'%outfile]
374 373
375 374 for kwarg in saveargs[2:]:
376 375 arg, val = kwarg.split('=')
377 376 arg = arg.strip()
378 377 val = val.strip()
379 378 imagerows.append(' :%s: %s'%(arg, val))
380 379
381 380 image_file = os.path.basename(outfile) # only return file name
382 381 image_directive = '\n'.join(imagerows)
383 382 return image_file, image_directive
384 383
385 384 # Callbacks for each type of token
386 385 def process_input(self, data, input_prompt, lineno):
387 386 """
388 387 Process data block for INPUT token.
389 388
390 389 """
391 390 decorator, input, rest = data
392 391 image_file = None
393 392 image_directive = None
394 393
395 394 is_verbatim = decorator=='@verbatim' or self.is_verbatim
396 395 is_doctest = (decorator is not None and \
397 396 decorator.startswith('@doctest')) or self.is_doctest
398 397 is_suppress = decorator=='@suppress' or self.is_suppress
399 398 is_okexcept = decorator=='@okexcept' or self.is_okexcept
400 399 is_okwarning = decorator=='@okwarning' or self.is_okwarning
401 400 is_savefig = decorator is not None and \
402 401 decorator.startswith('@savefig')
403 402
404 403 input_lines = input.split('\n')
405 404 if len(input_lines) > 1:
406 405 if input_lines[-1] != "":
407 406 input_lines.append('') # make sure there's a blank line
408 407 # so splitter buffer gets reset
409 408
410 409 continuation = ' %s:'%''.join(['.']*(len(str(lineno))+2))
411 410
412 411 if is_savefig:
413 412 image_file, image_directive = self.process_image(decorator)
414 413
415 414 ret = []
416 415 is_semicolon = False
417 416
418 417 # Hold the execution count, if requested to do so.
419 418 if is_suppress and self.hold_count:
420 419 store_history = False
421 420 else:
422 421 store_history = True
423 422
424 423 # Note: catch_warnings is not thread safe
425 424 with warnings.catch_warnings(record=True) as ws:
426 425 for i, line in enumerate(input_lines):
427 426 if line.endswith(';'):
428 427 is_semicolon = True
429 428
430 429 if i == 0:
431 430 # process the first input line
432 431 if is_verbatim:
433 432 self.process_input_line('')
434 433 self.IP.execution_count += 1 # increment it anyway
435 434 else:
436 435 # only submit the line in non-verbatim mode
437 436 self.process_input_line(line, store_history=store_history)
438 437 formatted_line = '%s %s'%(input_prompt, line)
439 438 else:
440 439 # process a continuation line
441 440 if not is_verbatim:
442 441 self.process_input_line(line, store_history=store_history)
443 442
444 443 formatted_line = '%s %s'%(continuation, line)
445 444
446 445 if not is_suppress:
447 446 ret.append(formatted_line)
448 447
449 448 if not is_suppress and len(rest.strip()) and is_verbatim:
450 449 # The "rest" is the standard output of the input. This needs to be
451 450 # added when in verbatim mode. If there is no "rest", then we don't
452 451 # add it, as the new line will be added by the processed output.
453 452 ret.append(rest)
454 453
455 454 # Fetch the processed output. (This is not the submitted output.)
456 455 self.cout.seek(0)
457 456 processed_output = self.cout.read()
458 457 if not is_suppress and not is_semicolon:
459 458 #
460 459 # In IPythonDirective.run, the elements of `ret` are eventually
461 460 # combined such that '' entries correspond to newlines. So if
462 461 # `processed_output` is equal to '', then the adding it to `ret`
463 462 # ensures that there is a blank line between consecutive inputs
464 463 # that have no outputs, as in:
465 464 #
466 465 # In [1]: x = 4
467 466 #
468 467 # In [2]: x = 5
469 468 #
470 469 # When there is processed output, it has a '\n' at the tail end. So
471 470 # adding the output to `ret` will provide the necessary spacing
472 471 # between consecutive input/output blocks, as in:
473 472 #
474 473 # In [1]: x
475 474 # Out[1]: 5
476 475 #
477 476 # In [2]: x
478 477 # Out[2]: 5
479 478 #
480 479 # When there is stdout from the input, it also has a '\n' at the
481 480 # tail end, and so this ensures proper spacing as well. E.g.:
482 481 #
483 482 # In [1]: print x
484 483 # 5
485 484 #
486 485 # In [2]: x = 5
487 486 #
488 487 # When in verbatim mode, `processed_output` is empty (because
489 488 # nothing was passed to IP. Sometimes the submitted code block has
490 489 # an Out[] portion and sometimes it does not. When it does not, we
491 490 # need to ensure proper spacing, so we have to add '' to `ret`.
492 491 # However, if there is an Out[] in the submitted code, then we do
493 492 # not want to add a newline as `process_output` has stuff to add.
494 493 # The difficulty is that `process_input` doesn't know if
495 494 # `process_output` will be called---so it doesn't know if there is
496 495 # Out[] in the code block. The requires that we include a hack in
497 496 # `process_block`. See the comments there.
498 497 #
499 498 ret.append(processed_output)
500 499 elif is_semicolon:
501 500 # Make sure there is a newline after the semicolon.
502 501 ret.append('')
503 502
504 503 # context information
505 504 filename = "Unknown"
506 505 lineno = 0
507 506 if self.directive.state:
508 507 filename = self.directive.state.document.current_source
509 508 lineno = self.directive.state.document.current_line
510 509
511 510 # output any exceptions raised during execution to stdout
512 511 # unless :okexcept: has been specified.
513 512 if not is_okexcept and "Traceback" in processed_output:
514 513 s = "\nException in %s at block ending on line %s\n" % (filename, lineno)
515 514 s += "Specify :okexcept: as an option in the ipython:: block to suppress this message\n"
516 515 sys.stdout.write('\n\n>>>' + ('-' * 73))
517 516 sys.stdout.write(s)
518 517 sys.stdout.write(processed_output)
519 518 sys.stdout.write('<<<' + ('-' * 73) + '\n\n')
520 519
521 520 # output any warning raised during execution to stdout
522 521 # unless :okwarning: has been specified.
523 522 if not is_okwarning:
524 523 for w in ws:
525 524 s = "\nWarning in %s at block ending on line %s\n" % (filename, lineno)
526 525 s += "Specify :okwarning: as an option in the ipython:: block to suppress this message\n"
527 526 sys.stdout.write('\n\n>>>' + ('-' * 73))
528 527 sys.stdout.write(s)
529 528 sys.stdout.write(('-' * 76) + '\n')
530 529 s=warnings.formatwarning(w.message, w.category,
531 530 w.filename, w.lineno, w.line)
532 531 sys.stdout.write(s)
533 532 sys.stdout.write('<<<' + ('-' * 73) + '\n')
534 533
535 534 self.cout.truncate(0)
536 535
537 536 return (ret, input_lines, processed_output,
538 537 is_doctest, decorator, image_file, image_directive)
539 538
540 539
541 540 def process_output(self, data, output_prompt, input_lines, output,
542 541 is_doctest, decorator, image_file):
543 542 """
544 543 Process data block for OUTPUT token.
545 544
546 545 """
547 546 # Recall: `data` is the submitted output, and `output` is the processed
548 547 # output from `input_lines`.
549 548
550 549 TAB = ' ' * 4
551 550
552 551 if is_doctest and output is not None:
553 552
554 553 found = output # This is the processed output
555 554 found = found.strip()
556 555 submitted = data.strip()
557 556
558 557 if self.directive is None:
559 558 source = 'Unavailable'
560 559 content = 'Unavailable'
561 560 else:
562 561 source = self.directive.state.document.current_source
563 562 content = self.directive.content
564 563 # Add tabs and join into a single string.
565 564 content = '\n'.join([TAB + line for line in content])
566 565
567 566 # Make sure the output contains the output prompt.
568 567 ind = found.find(output_prompt)
569 568 if ind < 0:
570 569 e = ('output does not contain output prompt\n\n'
571 570 'Document source: {0}\n\n'
572 571 'Raw content: \n{1}\n\n'
573 572 'Input line(s):\n{TAB}{2}\n\n'
574 573 'Output line(s):\n{TAB}{3}\n\n')
575 574 e = e.format(source, content, '\n'.join(input_lines),
576 575 repr(found), TAB=TAB)
577 576 raise RuntimeError(e)
578 577 found = found[len(output_prompt):].strip()
579 578
580 579 # Handle the actual doctest comparison.
581 580 if decorator.strip() == '@doctest':
582 581 # Standard doctest
583 582 if found != submitted:
584 583 e = ('doctest failure\n\n'
585 584 'Document source: {0}\n\n'
586 585 'Raw content: \n{1}\n\n'
587 586 'On input line(s):\n{TAB}{2}\n\n'
588 587 'we found output:\n{TAB}{3}\n\n'
589 588 'instead of the expected:\n{TAB}{4}\n\n')
590 589 e = e.format(source, content, '\n'.join(input_lines),
591 590 repr(found), repr(submitted), TAB=TAB)
592 591 raise RuntimeError(e)
593 592 else:
594 593 self.custom_doctest(decorator, input_lines, found, submitted)
595 594
596 595 # When in verbatim mode, this holds additional submitted output
597 596 # to be written in the final Sphinx output.
598 597 # https://github.com/ipython/ipython/issues/5776
599 598 out_data = []
600 599
601 600 is_verbatim = decorator=='@verbatim' or self.is_verbatim
602 601 if is_verbatim and data.strip():
603 602 # Note that `ret` in `process_block` has '' as its last element if
604 603 # the code block was in verbatim mode. So if there is no submitted
605 604 # output, then we will have proper spacing only if we do not add
606 605 # an additional '' to `out_data`. This is why we condition on
607 606 # `and data.strip()`.
608 607
609 608 # The submitted output has no output prompt. If we want the
610 609 # prompt and the code to appear, we need to join them now
611 610 # instead of adding them separately---as this would create an
612 611 # undesired newline. How we do this ultimately depends on the
613 612 # format of the output regex. I'll do what works for the default
614 613 # prompt for now, and we might have to adjust if it doesn't work
615 614 # in other cases. Finally, the submitted output does not have
616 615 # a trailing newline, so we must add it manually.
617 616 out_data.append("{0} {1}\n".format(output_prompt, data))
618 617
619 618 return out_data
620 619
621 620 def process_comment(self, data):
622 621 """Process data fPblock for COMMENT token."""
623 622 if not self.is_suppress:
624 623 return [data]
625 624
626 625 def save_image(self, image_file):
627 626 """
628 627 Saves the image file to disk.
629 628 """
630 629 self.ensure_pyplot()
631 630 command = 'plt.gcf().savefig("%s")'%image_file
632 631 #print 'SAVEFIG', command # dbg
633 632 self.process_input_line('bookmark ipy_thisdir', store_history=False)
634 633 self.process_input_line('cd -b ipy_savedir', store_history=False)
635 634 self.process_input_line(command, store_history=False)
636 635 self.process_input_line('cd -b ipy_thisdir', store_history=False)
637 636 self.process_input_line('bookmark -d ipy_thisdir', store_history=False)
638 637 self.clear_cout()
639 638
640 639 def process_block(self, block):
641 640 """
642 641 process block from the block_parser and return a list of processed lines
643 642 """
644 643 ret = []
645 644 output = None
646 645 input_lines = None
647 646 lineno = self.IP.execution_count
648 647
649 648 input_prompt = self.promptin % lineno
650 649 output_prompt = self.promptout % lineno
651 650 image_file = None
652 651 image_directive = None
653 652
654 653 found_input = False
655 654 for token, data in block:
656 655 if token == COMMENT:
657 656 out_data = self.process_comment(data)
658 657 elif token == INPUT:
659 658 found_input = True
660 659 (out_data, input_lines, output, is_doctest,
661 660 decorator, image_file, image_directive) = \
662 661 self.process_input(data, input_prompt, lineno)
663 662 elif token == OUTPUT:
664 663 if not found_input:
665 664
666 665 TAB = ' ' * 4
667 666 linenumber = 0
668 667 source = 'Unavailable'
669 668 content = 'Unavailable'
670 669 if self.directive:
671 670 linenumber = self.directive.state.document.current_line
672 671 source = self.directive.state.document.current_source
673 672 content = self.directive.content
674 673 # Add tabs and join into a single string.
675 674 content = '\n'.join([TAB + line for line in content])
676 675
677 676 e = ('\n\nInvalid block: Block contains an output prompt '
678 677 'without an input prompt.\n\n'
679 678 'Document source: {0}\n\n'
680 679 'Content begins at line {1}: \n\n{2}\n\n'
681 680 'Problematic block within content: \n\n{TAB}{3}\n\n')
682 681 e = e.format(source, linenumber, content, block, TAB=TAB)
683 682
684 683 # Write, rather than include in exception, since Sphinx
685 684 # will truncate tracebacks.
686 685 sys.stdout.write(e)
687 686 raise RuntimeError('An invalid block was detected.')
688 687
689 688 out_data = \
690 689 self.process_output(data, output_prompt, input_lines,
691 690 output, is_doctest, decorator,
692 691 image_file)
693 692 if out_data:
694 693 # Then there was user submitted output in verbatim mode.
695 694 # We need to remove the last element of `ret` that was
696 695 # added in `process_input`, as it is '' and would introduce
697 696 # an undesirable newline.
698 697 assert(ret[-1] == '')
699 698 del ret[-1]
700 699
701 700 if out_data:
702 701 ret.extend(out_data)
703 702
704 703 # save the image files
705 704 if image_file is not None:
706 705 self.save_image(image_file)
707 706
708 707 return ret, image_directive
709 708
710 709 def ensure_pyplot(self):
711 710 """
712 711 Ensures that pyplot has been imported into the embedded IPython shell.
713 712
714 713 Also, makes sure to set the backend appropriately if not set already.
715 714
716 715 """
717 716 # We are here if the @figure pseudo decorator was used. Thus, it's
718 717 # possible that we could be here even if python_mplbackend were set to
719 718 # `None`. That's also strange and perhaps worthy of raising an
720 719 # exception, but for now, we just set the backend to 'agg'.
721 720
722 721 if not self._pyplot_imported:
723 722 if 'matplotlib.backends' not in sys.modules:
724 723 # Then ipython_matplotlib was set to None but there was a
725 724 # call to the @figure decorator (and ipython_execlines did
726 725 # not set a backend).
727 726 #raise Exception("No backend was set, but @figure was used!")
728 727 import matplotlib
729 728 matplotlib.use('agg')
730 729
731 730 # Always import pyplot into embedded shell.
732 731 self.process_input_line('import matplotlib.pyplot as plt',
733 732 store_history=False)
734 733 self._pyplot_imported = True
735 734
736 735 def process_pure_python(self, content):
737 736 """
738 737 content is a list of strings. it is unedited directive content
739 738
740 739 This runs it line by line in the InteractiveShell, prepends
741 740 prompts as needed capturing stderr and stdout, then returns
742 741 the content as a list as if it were ipython code
743 742 """
744 743 output = []
745 744 savefig = False # keep up with this to clear figure
746 745 multiline = False # to handle line continuation
747 746 multiline_start = None
748 747 fmtin = self.promptin
749 748
750 749 ct = 0
751 750
752 751 for lineno, line in enumerate(content):
753 752
754 753 line_stripped = line.strip()
755 754 if not len(line):
756 755 output.append(line)
757 756 continue
758 757
759 758 # handle decorators
760 759 if line_stripped.startswith('@'):
761 760 output.extend([line])
762 761 if 'savefig' in line:
763 762 savefig = True # and need to clear figure
764 763 continue
765 764
766 765 # handle comments
767 766 if line_stripped.startswith('#'):
768 767 output.extend([line])
769 768 continue
770 769
771 770 # deal with lines checking for multiline
772 771 continuation = u' %s:'% ''.join(['.']*(len(str(ct))+2))
773 772 if not multiline:
774 773 modified = u"%s %s" % (fmtin % ct, line_stripped)
775 774 output.append(modified)
776 775 ct += 1
777 776 try:
778 777 ast.parse(line_stripped)
779 778 output.append(u'')
780 779 except Exception: # on a multiline
781 780 multiline = True
782 781 multiline_start = lineno
783 782 else: # still on a multiline
784 783 modified = u'%s %s' % (continuation, line)
785 784 output.append(modified)
786 785
787 786 # if the next line is indented, it should be part of multiline
788 787 if len(content) > lineno + 1:
789 788 nextline = content[lineno + 1]
790 789 if len(nextline) - len(nextline.lstrip()) > 3:
791 790 continue
792 791 try:
793 792 mod = ast.parse(
794 793 '\n'.join(content[multiline_start:lineno+1]))
795 794 if isinstance(mod.body[0], ast.FunctionDef):
796 795 # check to see if we have the whole function
797 796 for element in mod.body[0].body:
798 797 if isinstance(element, ast.Return):
799 798 multiline = False
800 799 else:
801 800 output.append(u'')
802 801 multiline = False
803 802 except Exception:
804 803 pass
805 804
806 805 if savefig: # clear figure if plotted
807 806 self.ensure_pyplot()
808 807 self.process_input_line('plt.clf()', store_history=False)
809 808 self.clear_cout()
810 809 savefig = False
811 810
812 811 return output
813 812
814 813 def custom_doctest(self, decorator, input_lines, found, submitted):
815 814 """
816 815 Perform a specialized doctest.
817 816
818 817 """
819 818 from .custom_doctests import doctests
820 819
821 820 args = decorator.split()
822 821 doctest_type = args[1]
823 822 if doctest_type in doctests:
824 823 doctests[doctest_type](self, args, input_lines, found, submitted)
825 824 else:
826 825 e = "Invalid option to @doctest: {0}".format(doctest_type)
827 826 raise Exception(e)
828 827
829 828
830 829 class IPythonDirective(Directive):
831 830
832 831 has_content = True
833 832 required_arguments = 0
834 833 optional_arguments = 4 # python, suppress, verbatim, doctest
835 834 final_argumuent_whitespace = True
836 835 option_spec = { 'python': directives.unchanged,
837 836 'suppress' : directives.flag,
838 837 'verbatim' : directives.flag,
839 838 'doctest' : directives.flag,
840 839 'okexcept': directives.flag,
841 840 'okwarning': directives.flag
842 841 }
843 842
844 843 shell = None
845 844
846 845 seen_docs = set()
847 846
848 847 def get_config_options(self):
849 848 # contains sphinx configuration variables
850 849 config = self.state.document.settings.env.config
851 850
852 851 # get config variables to set figure output directory
853 852 outdir = self.state.document.settings.env.app.outdir
854 853 savefig_dir = config.ipython_savefig_dir
855 854 source_dir = os.path.dirname(self.state.document.current_source)
856 855 if savefig_dir is None:
857 856 savefig_dir = config.html_static_path or '_static'
858 857 if isinstance(savefig_dir, list):
859 858 savefig_dir = os.path.join(*savefig_dir)
860 859 savefig_dir = os.path.join(outdir, savefig_dir)
861 860
862 861 # get regex and prompt stuff
863 862 rgxin = config.ipython_rgxin
864 863 rgxout = config.ipython_rgxout
865 864 promptin = config.ipython_promptin
866 865 promptout = config.ipython_promptout
867 866 mplbackend = config.ipython_mplbackend
868 867 exec_lines = config.ipython_execlines
869 868 hold_count = config.ipython_holdcount
870 869
871 870 return (savefig_dir, source_dir, rgxin, rgxout,
872 871 promptin, promptout, mplbackend, exec_lines, hold_count)
873 872
874 873 def setup(self):
875 874 # Get configuration values.
876 875 (savefig_dir, source_dir, rgxin, rgxout, promptin, promptout,
877 876 mplbackend, exec_lines, hold_count) = self.get_config_options()
878 877
879 878 if self.shell is None:
880 879 # We will be here many times. However, when the
881 880 # EmbeddedSphinxShell is created, its interactive shell member
882 881 # is the same for each instance.
883 882
884 883 if mplbackend and 'matplotlib.backends' not in sys.modules:
885 884 import matplotlib
886 885 matplotlib.use(mplbackend)
887 886
888 887 # Must be called after (potentially) importing matplotlib and
889 888 # setting its backend since exec_lines might import pylab.
890 889 self.shell = EmbeddedSphinxShell(exec_lines)
891 890
892 891 # Store IPython directive to enable better error messages
893 892 self.shell.directive = self
894 893
895 894 # reset the execution count if we haven't processed this doc
896 895 #NOTE: this may be borked if there are multiple seen_doc tmp files
897 896 #check time stamp?
898 897 if not self.state.document.current_source in self.seen_docs:
899 898 self.shell.IP.history_manager.reset()
900 899 self.shell.IP.execution_count = 1
901 900 self.seen_docs.add(self.state.document.current_source)
902 901
903 902 # and attach to shell so we don't have to pass them around
904 903 self.shell.rgxin = rgxin
905 904 self.shell.rgxout = rgxout
906 905 self.shell.promptin = promptin
907 906 self.shell.promptout = promptout
908 907 self.shell.savefig_dir = savefig_dir
909 908 self.shell.source_dir = source_dir
910 909 self.shell.hold_count = hold_count
911 910
912 911 # setup bookmark for saving figures directory
913 912 self.shell.process_input_line('bookmark ipy_savedir %s'%savefig_dir,
914 913 store_history=False)
915 914 self.shell.clear_cout()
916 915
917 916 return rgxin, rgxout, promptin, promptout
918 917
919 918 def teardown(self):
920 919 # delete last bookmark
921 920 self.shell.process_input_line('bookmark -d ipy_savedir',
922 921 store_history=False)
923 922 self.shell.clear_cout()
924 923
925 924 def run(self):
926 925 debug = False
927 926
928 927 #TODO, any reason block_parser can't be a method of embeddable shell
929 928 # then we wouldn't have to carry these around
930 929 rgxin, rgxout, promptin, promptout = self.setup()
931 930
932 931 options = self.options
933 932 self.shell.is_suppress = 'suppress' in options
934 933 self.shell.is_doctest = 'doctest' in options
935 934 self.shell.is_verbatim = 'verbatim' in options
936 935 self.shell.is_okexcept = 'okexcept' in options
937 936 self.shell.is_okwarning = 'okwarning' in options
938 937
939 938 # handle pure python code
940 939 if 'python' in self.arguments:
941 940 content = self.content
942 941 self.content = self.shell.process_pure_python(content)
943 942
944 943 # parts consists of all text within the ipython-block.
945 944 # Each part is an input/output block.
946 945 parts = '\n'.join(self.content).split('\n\n')
947 946
948 947 lines = ['.. code-block:: ipython', '']
949 948 figures = []
950 949
951 950 for part in parts:
952 951 block = block_parser(part, rgxin, rgxout, promptin, promptout)
953 952 if len(block):
954 953 rows, figure = self.shell.process_block(block)
955 954 for row in rows:
956 955 lines.extend([' {0}'.format(line)
957 956 for line in row.split('\n')])
958 957
959 958 if figure is not None:
960 959 figures.append(figure)
961 960
962 961 for figure in figures:
963 962 lines.append('')
964 963 lines.extend(figure.split('\n'))
965 964 lines.append('')
966 965
967 966 if len(lines) > 2:
968 967 if debug:
969 968 print('\n'.join(lines))
970 969 else:
971 970 # This has to do with input, not output. But if we comment
972 971 # these lines out, then no IPython code will appear in the
973 972 # final output.
974 973 self.state_machine.insert_input(
975 974 lines, self.state_machine.input_lines.source(0))
976 975
977 976 # cleanup
978 977 self.teardown()
979 978
980 979 return []
981 980
982 981 # Enable as a proper Sphinx directive
983 982 def setup(app):
984 983 setup.app = app
985 984
986 985 app.add_directive('ipython', IPythonDirective)
987 986 app.add_config_value('ipython_savefig_dir', None, 'env')
988 987 app.add_config_value('ipython_rgxin',
989 988 re.compile('In \[(\d+)\]:\s?(.*)\s*'), 'env')
990 989 app.add_config_value('ipython_rgxout',
991 990 re.compile('Out\[(\d+)\]:\s?(.*)\s*'), 'env')
992 991 app.add_config_value('ipython_promptin', 'In [%d]:', 'env')
993 992 app.add_config_value('ipython_promptout', 'Out[%d]:', 'env')
994 993
995 994 # We could just let matplotlib pick whatever is specified as the default
996 995 # backend in the matplotlibrc file, but this would cause issues if the
997 996 # backend didn't work in headless environments. For this reason, 'agg'
998 997 # is a good default backend choice.
999 998 app.add_config_value('ipython_mplbackend', 'agg', 'env')
1000 999
1001 1000 # If the user sets this config value to `None`, then EmbeddedSphinxShell's
1002 1001 # __init__ method will treat it as [].
1003 1002 execlines = ['import numpy as np', 'import matplotlib.pyplot as plt']
1004 1003 app.add_config_value('ipython_execlines', execlines, 'env')
1005 1004
1006 1005 app.add_config_value('ipython_holdcount', True, 'env')
1007 1006
1008 1007 metadata = {'parallel_read_safe': True, 'parallel_write_safe': True}
1009 1008 return metadata
1010 1009
1011 1010 # Simple smoke test, needs to be converted to a proper automatic test.
1012 1011 def test():
1013 1012
1014 1013 examples = [
1015 1014 r"""
1016 1015 In [9]: pwd
1017 1016 Out[9]: '/home/jdhunter/py4science/book'
1018 1017
1019 1018 In [10]: cd bookdata/
1020 1019 /home/jdhunter/py4science/book/bookdata
1021 1020
1022 1021 In [2]: from pylab import *
1023 1022
1024 1023 In [2]: ion()
1025 1024
1026 1025 In [3]: im = imread('stinkbug.png')
1027 1026
1028 1027 @savefig mystinkbug.png width=4in
1029 1028 In [4]: imshow(im)
1030 1029 Out[4]: <matplotlib.image.AxesImage object at 0x39ea850>
1031 1030
1032 1031 """,
1033 1032 r"""
1034 1033
1035 1034 In [1]: x = 'hello world'
1036 1035
1037 1036 # string methods can be
1038 1037 # used to alter the string
1039 1038 @doctest
1040 1039 In [2]: x.upper()
1041 1040 Out[2]: 'HELLO WORLD'
1042 1041
1043 1042 @verbatim
1044 1043 In [3]: x.st<TAB>
1045 1044 x.startswith x.strip
1046 1045 """,
1047 1046 r"""
1048 1047
1049 1048 In [130]: url = 'http://ichart.finance.yahoo.com/table.csv?s=CROX\
1050 1049 .....: &d=9&e=22&f=2009&g=d&a=1&br=8&c=2006&ignore=.csv'
1051 1050
1052 1051 In [131]: print url.split('&')
1053 1052 ['http://ichart.finance.yahoo.com/table.csv?s=CROX', 'd=9', 'e=22', 'f=2009', 'g=d', 'a=1', 'b=8', 'c=2006', 'ignore=.csv']
1054 1053
1055 1054 In [60]: import urllib
1056 1055
1057 1056 """,
1058 1057 r"""\
1059 1058
1060 1059 In [133]: import numpy.random
1061 1060
1062 1061 @suppress
1063 1062 In [134]: numpy.random.seed(2358)
1064 1063
1065 1064 @doctest
1066 1065 In [135]: numpy.random.rand(10,2)
1067 1066 Out[135]:
1068 1067 array([[ 0.64524308, 0.59943846],
1069 1068 [ 0.47102322, 0.8715456 ],
1070 1069 [ 0.29370834, 0.74776844],
1071 1070 [ 0.99539577, 0.1313423 ],
1072 1071 [ 0.16250302, 0.21103583],
1073 1072 [ 0.81626524, 0.1312433 ],
1074 1073 [ 0.67338089, 0.72302393],
1075 1074 [ 0.7566368 , 0.07033696],
1076 1075 [ 0.22591016, 0.77731835],
1077 1076 [ 0.0072729 , 0.34273127]])
1078 1077
1079 1078 """,
1080 1079
1081 1080 r"""
1082 1081 In [106]: print x
1083 1082 jdh
1084 1083
1085 1084 In [109]: for i in range(10):
1086 1085 .....: print i
1087 1086 .....:
1088 1087 .....:
1089 1088 0
1090 1089 1
1091 1090 2
1092 1091 3
1093 1092 4
1094 1093 5
1095 1094 6
1096 1095 7
1097 1096 8
1098 1097 9
1099 1098 """,
1100 1099
1101 1100 r"""
1102 1101
1103 1102 In [144]: from pylab import *
1104 1103
1105 1104 In [145]: ion()
1106 1105
1107 1106 # use a semicolon to suppress the output
1108 1107 @savefig test_hist.png width=4in
1109 1108 In [151]: hist(np.random.randn(10000), 100);
1110 1109
1111 1110
1112 1111 @savefig test_plot.png width=4in
1113 1112 In [151]: plot(np.random.randn(10000), 'o');
1114 1113 """,
1115 1114
1116 1115 r"""
1117 1116 # use a semicolon to suppress the output
1118 1117 In [151]: plt.clf()
1119 1118
1120 1119 @savefig plot_simple.png width=4in
1121 1120 In [151]: plot([1,2,3])
1122 1121
1123 1122 @savefig hist_simple.png width=4in
1124 1123 In [151]: hist(np.random.randn(10000), 100);
1125 1124
1126 1125 """,
1127 1126 r"""
1128 1127 # update the current fig
1129 1128 In [151]: ylabel('number')
1130 1129
1131 1130 In [152]: title('normal distribution')
1132 1131
1133 1132
1134 1133 @savefig hist_with_text.png
1135 1134 In [153]: grid(True)
1136 1135
1137 1136 @doctest float
1138 1137 In [154]: 0.1 + 0.2
1139 1138 Out[154]: 0.3
1140 1139
1141 1140 @doctest float
1142 1141 In [155]: np.arange(16).reshape(4,4)
1143 1142 Out[155]:
1144 1143 array([[ 0, 1, 2, 3],
1145 1144 [ 4, 5, 6, 7],
1146 1145 [ 8, 9, 10, 11],
1147 1146 [12, 13, 14, 15]])
1148 1147
1149 1148 In [1]: x = np.arange(16, dtype=float).reshape(4,4)
1150 1149
1151 1150 In [2]: x[0,0] = np.inf
1152 1151
1153 1152 In [3]: x[0,1] = np.nan
1154 1153
1155 1154 @doctest float
1156 1155 In [4]: x
1157 1156 Out[4]:
1158 1157 array([[ inf, nan, 2., 3.],
1159 1158 [ 4., 5., 6., 7.],
1160 1159 [ 8., 9., 10., 11.],
1161 1160 [ 12., 13., 14., 15.]])
1162 1161
1163 1162
1164 1163 """,
1165 1164 ]
1166 1165 # skip local-file depending first example:
1167 1166 examples = examples[1:]
1168 1167
1169 1168 #ipython_directive.DEBUG = True # dbg
1170 1169 #options = dict(suppress=True) # dbg
1171 1170 options = dict()
1172 1171 for example in examples:
1173 1172 content = example.split('\n')
1174 1173 IPythonDirective('debug', arguments=None, options=options,
1175 1174 content=content, lineno=0,
1176 1175 content_offset=None, block_text=None,
1177 1176 state=None, state_machine=None,
1178 1177 )
1179 1178
1180 1179 # Run test suite as a script
1181 1180 if __name__=='__main__':
1182 1181 if not os.path.isdir('_static'):
1183 1182 os.mkdir('_static')
1184 1183 test()
1185 1184 print('All OK? Check figures in _static/')
@@ -1,479 +1,484 b''
1 1 """IPython terminal interface using prompt_toolkit"""
2 2 from __future__ import print_function
3 3
4 4 import os
5 5 import sys
6 import warnings
6 7 from warnings import warn
7 8
8 9 from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC
10 from IPython.utils import io
9 11 from IPython.utils.py3compat import PY3, cast_unicode_py2, input
10 12 from IPython.utils.terminal import toggle_set_term_title, set_term_title
11 13 from IPython.utils.process import abbrev_cwd
12 14 from traitlets import Bool, Unicode, Dict, Integer, observe, Instance, Type, default, Enum
13 15
14 16 from prompt_toolkit.enums import DEFAULT_BUFFER, EditingMode
15 17 from prompt_toolkit.filters import (HasFocus, Condition, IsDone)
16 18 from prompt_toolkit.history import InMemoryHistory
17 19 from prompt_toolkit.shortcuts import create_prompt_application, create_eventloop, create_prompt_layout, create_output
18 20 from prompt_toolkit.interface import CommandLineInterface
19 21 from prompt_toolkit.key_binding.manager import KeyBindingManager
20 22 from prompt_toolkit.layout.processors import ConditionalProcessor, HighlightMatchingBracketProcessor
21 23 from prompt_toolkit.styles import PygmentsStyle, DynamicStyle
22 24
23 25 from pygments.styles import get_style_by_name, get_all_styles
24 26 from pygments.token import Token
25 27
26 28 from .debugger import TerminalPdb, Pdb
27 29 from .magics import TerminalMagics
28 30 from .pt_inputhooks import get_inputhook_func
29 31 from .prompts import Prompts, ClassicPrompts, RichPromptDisplayHook
30 32 from .ptutils import IPythonPTCompleter, IPythonPTLexer
31 33 from .shortcuts import register_ipython_shortcuts
32 34
33 35 DISPLAY_BANNER_DEPRECATED = object()
34 36
35 37
36 38 from pygments.style import Style
37 39
38 40 class _NoStyle(Style): pass
39 41
40 42
41 43
42 44 _style_overrides_light_bg = {
43 45 Token.Prompt: '#0000ff',
44 46 Token.PromptNum: '#0000ee bold',
45 47 Token.OutPrompt: '#cc0000',
46 48 Token.OutPromptNum: '#bb0000 bold',
47 49 }
48 50
49 51 _style_overrides_linux = {
50 52 Token.Prompt: '#00cc00',
51 53 Token.PromptNum: '#00bb00 bold',
52 54 Token.OutPrompt: '#cc0000',
53 55 Token.OutPromptNum: '#bb0000 bold',
54 56 }
55 57
56 58
57 59
58 60 def get_default_editor():
59 61 try:
60 62 ed = os.environ['EDITOR']
61 63 if not PY3:
62 64 ed = ed.decode()
63 65 return ed
64 66 except KeyError:
65 67 pass
66 68 except UnicodeError:
67 69 warn("$EDITOR environment variable is not pure ASCII. Using platform "
68 70 "default editor.")
69 71
70 72 if os.name == 'posix':
71 73 return 'vi' # the only one guaranteed to be there!
72 74 else:
73 75 return 'notepad' # same in Windows!
74 76
75 77
76 78 if sys.stdin and sys.stdout and sys.stderr:
77 79 _is_tty = (sys.stdin.isatty()) and (sys.stdout.isatty()) and (sys.stderr.isatty())
78 80 else:
79 81 _is_tty = False
80 82
81 83
82 84 _use_simple_prompt = ('IPY_TEST_SIMPLE_PROMPT' in os.environ) or (not _is_tty)
83 85
84 86 class TerminalInteractiveShell(InteractiveShell):
85 87 space_for_menu = Integer(6, help='Number of line at the bottom of the screen '
86 88 'to reserve for the completion menu'
87 89 ).tag(config=True)
88 90
89 91 def _space_for_menu_changed(self, old, new):
90 92 self._update_layout()
91 93
92 94 pt_cli = None
93 95 debugger_history = None
94 96 _pt_app = None
95 97
96 98 simple_prompt = Bool(_use_simple_prompt,
97 99 help="""Use `raw_input` for the REPL, without completion, multiline input, and prompt colors.
98 100
99 101 Useful when controlling IPython as a subprocess, and piping STDIN/OUT/ERR. Known usage are:
100 102 IPython own testing machinery, and emacs inferior-shell integration through elpy.
101 103
102 104 This mode default to `True` if the `IPY_TEST_SIMPLE_PROMPT`
103 105 environment variable is set, or the current terminal is not a tty.
104 106
105 107 """
106 108 ).tag(config=True)
107 109
108 110 @property
109 111 def debugger_cls(self):
110 112 return Pdb if self.simple_prompt else TerminalPdb
111 113
112 114 confirm_exit = Bool(True,
113 115 help="""
114 116 Set to confirm when you try to exit IPython with an EOF (Control-D
115 117 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
116 118 you can force a direct exit without any confirmation.""",
117 119 ).tag(config=True)
118 120
119 121 editing_mode = Unicode('emacs',
120 122 help="Shortcut style to use at the prompt. 'vi' or 'emacs'.",
121 123 ).tag(config=True)
122 124
123 125 mouse_support = Bool(False,
124 126 help="Enable mouse support in the prompt"
125 127 ).tag(config=True)
126 128
127 129 highlighting_style = Unicode('legacy',
128 130 help="The name of a Pygments style to use for syntax highlighting: \n %s" % ', '.join(get_all_styles())
129 131 ).tag(config=True)
130 132
131 133
132 134 @observe('highlighting_style')
133 135 @observe('colors')
134 136 def _highlighting_style_changed(self, change):
135 137 self.refresh_style()
136 138
137 139 def refresh_style(self):
138 140 self._style = self._make_style_from_name(self.highlighting_style)
139 141
140 142
141 143 highlighting_style_overrides = Dict(
142 144 help="Override highlighting format for specific tokens"
143 145 ).tag(config=True)
144 146
145 147 true_color = Bool(False,
146 148 help=("Use 24bit colors instead of 256 colors in prompt highlighting. "
147 149 "If your terminal supports true color, the following command "
148 150 "should print 'TRUECOLOR' in orange: "
149 151 "printf \"\\x1b[38;2;255;100;0mTRUECOLOR\\x1b[0m\\n\"")
150 152 ).tag(config=True)
151 153
152 154 editor = Unicode(get_default_editor(),
153 155 help="Set the editor used by IPython (default to $EDITOR/vi/notepad)."
154 156 ).tag(config=True)
155 157
156 158 prompts_class = Type(Prompts, help='Class used to generate Prompt token for prompt_toolkit').tag(config=True)
157 159
158 160 prompts = Instance(Prompts)
159 161
160 162 @default('prompts')
161 163 def _prompts_default(self):
162 164 return self.prompts_class(self)
163 165
164 166 @observe('prompts')
165 167 def _(self, change):
166 168 self._update_layout()
167 169
168 170 @default('displayhook_class')
169 171 def _displayhook_class_default(self):
170 172 return RichPromptDisplayHook
171 173
172 174 term_title = Bool(True,
173 175 help="Automatically set the terminal title"
174 176 ).tag(config=True)
175 177
176 178 display_completions = Enum(('column', 'multicolumn','readlinelike'),
177 179 help= ( "Options for displaying tab completions, 'column', 'multicolumn', and "
178 180 "'readlinelike'. These options are for `prompt_toolkit`, see "
179 181 "`prompt_toolkit` documentation for more information."
180 182 ),
181 183 default_value='multicolumn').tag(config=True)
182 184
183 185 highlight_matching_brackets = Bool(True,
184 186 help="Highlight matching brackets .",
185 187 ).tag(config=True)
186 188
187 189 @observe('term_title')
188 190 def init_term_title(self, change=None):
189 191 # Enable or disable the terminal title.
190 192 if self.term_title:
191 193 toggle_set_term_title(True)
192 194 set_term_title('IPython: ' + abbrev_cwd())
193 195 else:
194 196 toggle_set_term_title(False)
195 197
196 198 def init_display_formatter(self):
197 199 super(TerminalInteractiveShell, self).init_display_formatter()
198 200 # terminal only supports plain text
199 201 self.display_formatter.active_types = ['text/plain']
200 202
201 203 def init_prompt_toolkit_cli(self):
202 204 if self.simple_prompt:
203 205 # Fall back to plain non-interactive output for tests.
204 206 # This is very limited, and only accepts a single line.
205 207 def prompt():
206 208 return cast_unicode_py2(input('In [%d]: ' % self.execution_count))
207 209 self.prompt_for_code = prompt
208 210 return
209 211
210 212 # Set up keyboard shortcuts
211 213 kbmanager = KeyBindingManager.for_prompt()
212 214 register_ipython_shortcuts(kbmanager.registry, self)
213 215
214 216 # Pre-populate history from IPython's history database
215 217 history = InMemoryHistory()
216 218 last_cell = u""
217 219 for __, ___, cell in self.history_manager.get_tail(self.history_load_length,
218 220 include_latest=True):
219 221 # Ignore blank lines and consecutive duplicates
220 222 cell = cell.rstrip()
221 223 if cell and (cell != last_cell):
222 224 history.append(cell)
223 225
224 226 self._style = self._make_style_from_name(self.highlighting_style)
225 227 style = DynamicStyle(lambda: self._style)
226 228
227 229 editing_mode = getattr(EditingMode, self.editing_mode.upper())
228 230
229 231 self._pt_app = create_prompt_application(
230 232 editing_mode=editing_mode,
231 233 key_bindings_registry=kbmanager.registry,
232 234 history=history,
233 235 completer=IPythonPTCompleter(self.Completer),
234 236 enable_history_search=True,
235 237 style=style,
236 238 mouse_support=self.mouse_support,
237 239 **self._layout_options()
238 240 )
239 241 self._eventloop = create_eventloop(self.inputhook)
240 242 self.pt_cli = CommandLineInterface(
241 243 self._pt_app, eventloop=self._eventloop,
242 244 output=create_output(true_color=self.true_color))
243 245
244 246 def _make_style_from_name(self, name):
245 247 """
246 248 Small wrapper that make an IPython compatible style from a style name
247 249
248 250 We need that to add style for prompt ... etc.
249 251 """
250 252 style_overrides = {}
251 253 if name == 'legacy':
252 254 legacy = self.colors.lower()
253 255 if legacy == 'linux':
254 256 style_cls = get_style_by_name('monokai')
255 257 style_overrides = _style_overrides_linux
256 258 elif legacy == 'lightbg':
257 259 style_overrides = _style_overrides_light_bg
258 260 style_cls = get_style_by_name('pastie')
259 261 elif legacy == 'neutral':
260 262 # The default theme needs to be visible on both a dark background
261 263 # and a light background, because we can't tell what the terminal
262 264 # looks like. These tweaks to the default theme help with that.
263 265 style_cls = get_style_by_name('default')
264 266 style_overrides.update({
265 267 Token.Number: '#007700',
266 268 Token.Operator: 'noinherit',
267 269 Token.String: '#BB6622',
268 270 Token.Name.Function: '#2080D0',
269 271 Token.Name.Class: 'bold #2080D0',
270 272 Token.Name.Namespace: 'bold #2080D0',
271 273 Token.Prompt: '#009900',
272 274 Token.PromptNum: '#00ff00 bold',
273 275 Token.OutPrompt: '#990000',
274 276 Token.OutPromptNum: '#ff0000 bold',
275 277 })
276 278 elif legacy =='nocolor':
277 279 style_cls=_NoStyle
278 280 style_overrides = {}
279 281 else :
280 282 raise ValueError('Got unknown colors: ', legacy)
281 283 else :
282 284 style_cls = get_style_by_name(name)
283 285 style_overrides = {
284 286 Token.Prompt: '#009900',
285 287 Token.PromptNum: '#00ff00 bold',
286 288 Token.OutPrompt: '#990000',
287 289 Token.OutPromptNum: '#ff0000 bold',
288 290 }
289 291 style_overrides.update(self.highlighting_style_overrides)
290 292 style = PygmentsStyle.from_defaults(pygments_style_cls=style_cls,
291 293 style_dict=style_overrides)
292 294
293 295 return style
294 296
295 297 def _layout_options(self):
296 298 """
297 299 Return the current layout option for the current Terminal InteractiveShell
298 300 """
299 301 return {
300 302 'lexer':IPythonPTLexer(),
301 303 'reserve_space_for_menu':self.space_for_menu,
302 304 'get_prompt_tokens':self.prompts.in_prompt_tokens,
303 305 'get_continuation_tokens':self.prompts.continuation_prompt_tokens,
304 306 'multiline':True,
305 307 'display_completions_in_columns': (self.display_completions == 'multicolumn'),
306 308
307 309 # Highlight matching brackets, but only when this setting is
308 310 # enabled, and only when the DEFAULT_BUFFER has the focus.
309 311 'extra_input_processors': [ConditionalProcessor(
310 312 processor=HighlightMatchingBracketProcessor(chars='[](){}'),
311 313 filter=HasFocus(DEFAULT_BUFFER) & ~IsDone() &
312 314 Condition(lambda cli: self.highlight_matching_brackets))],
313 315 }
314 316
315 317 def _update_layout(self):
316 318 """
317 319 Ask for a re computation of the application layout, if for example ,
318 320 some configuration options have changed.
319 321 """
320 322 if self._pt_app:
321 323 self._pt_app.layout = create_prompt_layout(**self._layout_options())
322 324
323 325 def prompt_for_code(self):
324 326 document = self.pt_cli.run(
325 327 pre_run=self.pre_prompt, reset_current_buffer=True)
326 328 return document.text
327 329
328 330 def enable_win_unicode_console(self):
329 331 import win_unicode_console
330 332
331 333 if PY3:
332 334 win_unicode_console.enable()
333 335 else:
334 336 # https://github.com/ipython/ipython/issues/9768
335 337 from win_unicode_console.streams import (TextStreamWrapper,
336 338 stdout_text_transcoded, stderr_text_transcoded)
337 339
338 340 class LenientStrStreamWrapper(TextStreamWrapper):
339 341 def write(self, s):
340 342 if isinstance(s, bytes):
341 343 s = s.decode(self.encoding, 'replace')
342 344
343 345 self.base.write(s)
344 346
345 347 stdout_text_str = LenientStrStreamWrapper(stdout_text_transcoded)
346 348 stderr_text_str = LenientStrStreamWrapper(stderr_text_transcoded)
347 349
348 350 win_unicode_console.enable(stdout=stdout_text_str,
349 351 stderr=stderr_text_str)
350 352
351 353 def init_io(self):
352 354 if sys.platform not in {'win32', 'cli'}:
353 355 return
354 356
355 357 self.enable_win_unicode_console()
356 358
357 359 import colorama
358 360 colorama.init()
359 361
360 362 # For some reason we make these wrappers around stdout/stderr.
361 363 # For now, we need to reset them so all output gets coloured.
362 364 # https://github.com/ipython/ipython/issues/8669
363 from IPython.utils import io
364 io.stdout = io.IOStream(sys.stdout)
365 io.stderr = io.IOStream(sys.stderr)
365 # io.std* are deprecated, but don't show our own deprecation warnings
366 # during initialization of the deprecated API.
367 with warnings.catch_warnings():
368 warnings.simplefilter('ignore', DeprecationWarning)
369 io.stdout = io.IOStream(sys.stdout)
370 io.stderr = io.IOStream(sys.stderr)
366 371
367 372 def init_magics(self):
368 373 super(TerminalInteractiveShell, self).init_magics()
369 374 self.register_magics(TerminalMagics)
370 375
371 376 def init_alias(self):
372 377 # The parent class defines aliases that can be safely used with any
373 378 # frontend.
374 379 super(TerminalInteractiveShell, self).init_alias()
375 380
376 381 # Now define aliases that only make sense on the terminal, because they
377 382 # need direct access to the console in a way that we can't emulate in
378 383 # GUI or web frontend
379 384 if os.name == 'posix':
380 385 for cmd in ['clear', 'more', 'less', 'man']:
381 386 self.alias_manager.soft_define_alias(cmd, cmd)
382 387
383 388
384 389 def __init__(self, *args, **kwargs):
385 390 super(TerminalInteractiveShell, self).__init__(*args, **kwargs)
386 391 self.init_prompt_toolkit_cli()
387 392 self.init_term_title()
388 393 self.keep_running = True
389 394
390 395 self.debugger_history = InMemoryHistory()
391 396
392 397 def ask_exit(self):
393 398 self.keep_running = False
394 399
395 400 rl_next_input = None
396 401
397 402 def pre_prompt(self):
398 403 if self.rl_next_input:
399 404 self.pt_cli.application.buffer.text = cast_unicode_py2(self.rl_next_input)
400 405 self.rl_next_input = None
401 406
402 407 def interact(self, display_banner=DISPLAY_BANNER_DEPRECATED):
403 408
404 409 if display_banner is not DISPLAY_BANNER_DEPRECATED:
405 410 warn('interact `display_banner` argument is deprecated since IPython 5.0. Call `show_banner()` if needed.', DeprecationWarning, stacklevel=2)
406 411
407 412 while self.keep_running:
408 413 print(self.separate_in, end='')
409 414
410 415 try:
411 416 code = self.prompt_for_code()
412 417 except EOFError:
413 418 if (not self.confirm_exit) \
414 419 or self.ask_yes_no('Do you really want to exit ([y]/n)?','y','n'):
415 420 self.ask_exit()
416 421
417 422 else:
418 423 if code:
419 424 self.run_cell(code, store_history=True)
420 425
421 426 def mainloop(self, display_banner=DISPLAY_BANNER_DEPRECATED):
422 427 # An extra layer of protection in case someone mashing Ctrl-C breaks
423 428 # out of our internal code.
424 429 if display_banner is not DISPLAY_BANNER_DEPRECATED:
425 430 warn('mainloop `display_banner` argument is deprecated since IPython 5.0. Call `show_banner()` if needed.', DeprecationWarning, stacklevel=2)
426 431 while True:
427 432 try:
428 433 self.interact()
429 434 break
430 435 except KeyboardInterrupt:
431 436 print("\nKeyboardInterrupt escaped interact()\n")
432 437
433 438 if hasattr(self, '_eventloop'):
434 439 self._eventloop.close()
435 440
436 441 _inputhook = None
437 442 def inputhook(self, context):
438 443 if self._inputhook is not None:
439 444 self._inputhook(context)
440 445
441 446 def enable_gui(self, gui=None):
442 447 if gui:
443 448 self._inputhook = get_inputhook_func(gui)
444 449 else:
445 450 self._inputhook = None
446 451
447 452 # Run !system commands directly, not through pipes, so terminal programs
448 453 # work correctly.
449 454 system = InteractiveShell.system_raw
450 455
451 456 def auto_rewrite_input(self, cmd):
452 457 """Overridden from the parent class to use fancy rewriting prompt"""
453 458 if not self.show_rewritten_input:
454 459 return
455 460
456 461 tokens = self.prompts.rewrite_prompt_tokens()
457 462 if self.pt_cli:
458 463 self.pt_cli.print_tokens(tokens)
459 464 print(cmd)
460 465 else:
461 466 prompt = ''.join(s for t, s in tokens)
462 467 print(prompt, cmd, sep='')
463 468
464 469 _prompts_before = None
465 470 def switch_doctest_mode(self, mode):
466 471 """Switch prompts to classic for %doctest_mode"""
467 472 if mode:
468 473 self._prompts_before = self.prompts
469 474 self.prompts = ClassicPrompts(self)
470 475 elif self._prompts_before:
471 476 self.prompts = self._prompts_before
472 477 self._prompts_before = None
473 478 self._update_layout()
474 479
475 480
476 481 InteractiveShellABC.register(TerminalInteractiveShell)
477 482
478 483 if __name__ == '__main__':
479 484 TerminalInteractiveShell.instance().interact()
@@ -1,151 +1,138 b''
1 1 """Global IPython app to support test running.
2 2
3 3 We must start our own ipython object and heavily muck with it so that all the
4 4 modifications IPython makes to system behavior don't send the doctest machinery
5 5 into a fit. This code should be considered a gross hack, but it gets the job
6 6 done.
7 7 """
8 8 from __future__ import absolute_import
9 9 from __future__ import print_function
10 10
11 #-----------------------------------------------------------------------------
12 # Copyright (C) 2009-2011 The IPython Development Team
13 #
14 # Distributed under the terms of the BSD License. The full license is in
15 # the file COPYING, distributed as part of this software.
16 #-----------------------------------------------------------------------------
17
18 #-----------------------------------------------------------------------------
19 # Imports
20 #-----------------------------------------------------------------------------
21
22 # stdlib
11 # Copyright (c) IPython Development Team.
12 # Distributed under the terms of the Modified BSD License.
13
23 14 import sys
15 import warnings
24 16
25 # our own
26 17 from . import tools
27 18
28 19 from IPython.core import page
29 20 from IPython.utils import io
30 21 from IPython.utils import py3compat
31 22 from IPython.utils.py3compat import builtin_mod
32 23 from IPython.terminal.interactiveshell import TerminalInteractiveShell
33 24
34 #-----------------------------------------------------------------------------
35 # Functions
36 #-----------------------------------------------------------------------------
37 25
38 26 class StreamProxy(io.IOStream):
39 27 """Proxy for sys.stdout/err. This will request the stream *at call time*
40 28 allowing for nose's Capture plugin's redirection of sys.stdout/err.
41 29
42 30 Parameters
43 31 ----------
44 32 name : str
45 33 The name of the stream. This will be requested anew at every call
46 34 """
47 35
48 36 def __init__(self, name):
37 warnings.warn("StreamProxy is deprecated and unused as of IPython 5", DeprecationWarning,
38 stacklevel=2,
39 )
49 40 self.name=name
50 41
51 42 @property
52 43 def stream(self):
53 44 return getattr(sys, self.name)
54 45
55 46 def flush(self):
56 47 self.stream.flush()
57 48
58 49
59 50 def get_ipython():
60 51 # This will get replaced by the real thing once we start IPython below
61 52 return start_ipython()
62 53
63 54
64 55 # A couple of methods to override those in the running IPython to interact
65 56 # better with doctest (doctest captures on raw stdout, so we need to direct
66 57 # various types of output there otherwise it will miss them).
67 58
68 59 def xsys(self, cmd):
69 60 """Replace the default system call with a capturing one for doctest.
70 61 """
71 62 # We use getoutput, but we need to strip it because pexpect captures
72 63 # the trailing newline differently from commands.getoutput
73 64 print(self.getoutput(cmd, split=False, depth=1).rstrip(), end='', file=sys.stdout)
74 65 sys.stdout.flush()
75 66
76 67
77 68 def _showtraceback(self, etype, evalue, stb):
78 69 """Print the traceback purely on stdout for doctest to capture it.
79 70 """
80 71 print(self.InteractiveTB.stb2text(stb), file=sys.stdout)
81 72
82 73
83 74 def start_ipython():
84 75 """Start a global IPython shell, which we need for IPython-specific syntax.
85 76 """
86 77 global get_ipython
87 78
88 79 # This function should only ever run once!
89 80 if hasattr(start_ipython, 'already_called'):
90 81 return
91 82 start_ipython.already_called = True
92 83
93 84 # Store certain global objects that IPython modifies
94 85 _displayhook = sys.displayhook
95 86 _excepthook = sys.excepthook
96 87 _main = sys.modules.get('__main__')
97 88
98 89 # Create custom argv and namespaces for our IPython to be test-friendly
99 90 config = tools.default_config()
100 91 config.TerminalInteractiveShell.simple_prompt = True
101 92
102 93 # Create and initialize our test-friendly IPython instance.
103 94 shell = TerminalInteractiveShell.instance(config=config,
104 95 )
105 96
106 97 # A few more tweaks needed for playing nicely with doctests...
107 98
108 99 # remove history file
109 100 shell.tempfiles.append(config.HistoryManager.hist_file)
110 101
111 102 # These traps are normally only active for interactive use, set them
112 103 # permanently since we'll be mocking interactive sessions.
113 104 shell.builtin_trap.activate()
114 105
115 106 # Modify the IPython system call with one that uses getoutput, so that we
116 107 # can capture subcommands and print them to Python's stdout, otherwise the
117 108 # doctest machinery would miss them.
118 109 shell.system = py3compat.MethodType(xsys, shell)
119 110
120 111 shell._showtraceback = py3compat.MethodType(_showtraceback, shell)
121 112
122 113 # IPython is ready, now clean up some global state...
123 114
124 115 # Deactivate the various python system hooks added by ipython for
125 116 # interactive convenience so we don't confuse the doctest system
126 117 sys.modules['__main__'] = _main
127 118 sys.displayhook = _displayhook
128 119 sys.excepthook = _excepthook
129 120
130 121 # So that ipython magics and aliases can be doctested (they work by making
131 122 # a call into a global _ip object). Also make the top-level get_ipython
132 123 # now return this without recursively calling here again.
133 124 _ip = shell
134 125 get_ipython = _ip.get_ipython
135 126 builtin_mod._ip = _ip
136 127 builtin_mod.get_ipython = get_ipython
137 128
138 # To avoid extra IPython messages during testing, suppress io.stdout/stderr
139 io.stdout = StreamProxy('stdout')
140 io.stderr = StreamProxy('stderr')
141
142 129 # Override paging, so we don't require user interaction during the tests.
143 130 def nopage(strng, start=0, screen_lines=0, pager_cmd=None):
144 131 if isinstance(strng, dict):
145 132 strng = strng.get('text/plain', '')
146 133 print(strng)
147 134
148 135 page.orig_page = page.pager_page
149 136 page.pager_page = nopage
150 137
151 138 return _ip
@@ -1,235 +1,241 b''
1 1 # encoding: utf-8
2 2 """
3 3 IO related utilities.
4 4 """
5 5
6 6 # Copyright (c) IPython Development Team.
7 7 # Distributed under the terms of the Modified BSD License.
8 8
9 9 from __future__ import print_function
10 10 from __future__ import absolute_import
11 11
12 12
13 13 import atexit
14 14 import os
15 15 import sys
16 16 import tempfile
17 import warnings
17 18 from warnings import warn
18 19
19 20 from IPython.utils.decorators import undoc
20 21 from .capture import CapturedIO, capture_output
21 22 from .py3compat import string_types, input, PY3
22 23
23 24 @undoc
24 25 class IOStream:
25 26
26 27 def __init__(self, stream, fallback=None):
27 28 warn('IOStream is deprecated since IPython 5.0, use sys.{stdin,stdout,stderr} instead',
28 29 DeprecationWarning, stacklevel=2)
29 30 if not hasattr(stream,'write') or not hasattr(stream,'flush'):
30 31 if fallback is not None:
31 32 stream = fallback
32 33 else:
33 34 raise ValueError("fallback required, but not specified")
34 35 self.stream = stream
35 36 self._swrite = stream.write
36 37
37 38 # clone all methods not overridden:
38 39 def clone(meth):
39 40 return not hasattr(self, meth) and not meth.startswith('_')
40 41 for meth in filter(clone, dir(stream)):
41 42 setattr(self, meth, getattr(stream, meth))
42 43
43 44 def __repr__(self):
44 45 cls = self.__class__
45 46 tpl = '{mod}.{cls}({args})'
46 47 return tpl.format(mod=cls.__module__, cls=cls.__name__, args=self.stream)
47 48
48 49 def write(self,data):
49 50 warn('IOStream is deprecated since IPython 5.0, use sys.{stdin,stdout,stderr} instead',
50 51 DeprecationWarning, stacklevel=2)
51 52 try:
52 53 self._swrite(data)
53 54 except:
54 55 try:
55 56 # print handles some unicode issues which may trip a plain
56 57 # write() call. Emulate write() by using an empty end
57 58 # argument.
58 59 print(data, end='', file=self.stream)
59 60 except:
60 61 # if we get here, something is seriously broken.
61 62 print('ERROR - failed to write data to stream:', self.stream,
62 63 file=sys.stderr)
63 64
64 65 def writelines(self, lines):
65 66 warn('IOStream is deprecated since IPython 5.0, use sys.{stdin,stdout,stderr} instead',
66 67 DeprecationWarning, stacklevel=2)
67 68 if isinstance(lines, string_types):
68 69 lines = [lines]
69 70 for line in lines:
70 71 self.write(line)
71 72
72 73 # This class used to have a writeln method, but regular files and streams
73 74 # in Python don't have this method. We need to keep this completely
74 75 # compatible so we removed it.
75 76
76 77 @property
77 78 def closed(self):
78 79 return self.stream.closed
79 80
80 81 def close(self):
81 82 pass
82 83
83 84 # setup stdin/stdout/stderr to sys.stdin/sys.stdout/sys.stderr
84 devnull = open(os.devnull, 'w')
85 devnull = open(os.devnull, 'w')
85 86 atexit.register(devnull.close)
86 stdin = IOStream(sys.stdin, fallback=devnull)
87 stdout = IOStream(sys.stdout, fallback=devnull)
88 stderr = IOStream(sys.stderr, fallback=devnull)
87
88 # io.std* are deprecated, but don't show our own deprecation warnings
89 # during initialization of the deprecated API.
90 with warnings.catch_warnings():
91 warnings.simplefilter('ignore', DeprecationWarning)
92 stdin = IOStream(sys.stdin, fallback=devnull)
93 stdout = IOStream(sys.stdout, fallback=devnull)
94 stderr = IOStream(sys.stderr, fallback=devnull)
89 95
90 96 class Tee(object):
91 97 """A class to duplicate an output stream to stdout/err.
92 98
93 99 This works in a manner very similar to the Unix 'tee' command.
94 100
95 101 When the object is closed or deleted, it closes the original file given to
96 102 it for duplication.
97 103 """
98 104 # Inspired by:
99 105 # http://mail.python.org/pipermail/python-list/2007-May/442737.html
100 106
101 107 def __init__(self, file_or_name, mode="w", channel='stdout'):
102 108 """Construct a new Tee object.
103 109
104 110 Parameters
105 111 ----------
106 112 file_or_name : filename or open filehandle (writable)
107 113 File that will be duplicated
108 114
109 115 mode : optional, valid mode for open().
110 116 If a filename was give, open with this mode.
111 117
112 118 channel : str, one of ['stdout', 'stderr']
113 119 """
114 120 if channel not in ['stdout', 'stderr']:
115 121 raise ValueError('Invalid channel spec %s' % channel)
116 122
117 123 if hasattr(file_or_name, 'write') and hasattr(file_or_name, 'seek'):
118 124 self.file = file_or_name
119 125 else:
120 126 self.file = open(file_or_name, mode)
121 127 self.channel = channel
122 128 self.ostream = getattr(sys, channel)
123 129 setattr(sys, channel, self)
124 130 self._closed = False
125 131
126 132 def close(self):
127 133 """Close the file and restore the channel."""
128 134 self.flush()
129 135 setattr(sys, self.channel, self.ostream)
130 136 self.file.close()
131 137 self._closed = True
132 138
133 139 def write(self, data):
134 140 """Write data to both channels."""
135 141 self.file.write(data)
136 142 self.ostream.write(data)
137 143 self.ostream.flush()
138 144
139 145 def flush(self):
140 146 """Flush both channels."""
141 147 self.file.flush()
142 148 self.ostream.flush()
143 149
144 150 def __del__(self):
145 151 if not self._closed:
146 152 self.close()
147 153
148 154
149 155 def ask_yes_no(prompt, default=None, interrupt=None):
150 156 """Asks a question and returns a boolean (y/n) answer.
151 157
152 158 If default is given (one of 'y','n'), it is used if the user input is
153 159 empty. If interrupt is given (one of 'y','n'), it is used if the user
154 160 presses Ctrl-C. Otherwise the question is repeated until an answer is
155 161 given.
156 162
157 163 An EOF is treated as the default answer. If there is no default, an
158 164 exception is raised to prevent infinite loops.
159 165
160 166 Valid answers are: y/yes/n/no (match is not case sensitive)."""
161 167
162 168 answers = {'y':True,'n':False,'yes':True,'no':False}
163 169 ans = None
164 170 while ans not in answers.keys():
165 171 try:
166 172 ans = input(prompt+' ').lower()
167 173 if not ans: # response was an empty string
168 174 ans = default
169 175 except KeyboardInterrupt:
170 176 if interrupt:
171 177 ans = interrupt
172 178 except EOFError:
173 179 if default in answers.keys():
174 180 ans = default
175 181 print()
176 182 else:
177 183 raise
178 184
179 185 return answers[ans]
180 186
181 187
182 188 def temp_pyfile(src, ext='.py'):
183 189 """Make a temporary python file, return filename and filehandle.
184 190
185 191 Parameters
186 192 ----------
187 193 src : string or list of strings (no need for ending newlines if list)
188 194 Source code to be written to the file.
189 195
190 196 ext : optional, string
191 197 Extension for the generated file.
192 198
193 199 Returns
194 200 -------
195 201 (filename, open filehandle)
196 202 It is the caller's responsibility to close the open file and unlink it.
197 203 """
198 204 fname = tempfile.mkstemp(ext)[1]
199 205 f = open(fname,'w')
200 206 f.write(src)
201 207 f.flush()
202 208 return fname, f
203 209
204 210 def atomic_writing(*args, **kwargs):
205 211 """DEPRECATED: moved to notebook.services.contents.fileio"""
206 212 warn("IPython.utils.io.atomic_writing has moved to notebook.services.contents.fileio")
207 213 from notebook.services.contents.fileio import atomic_writing
208 214 return atomic_writing(*args, **kwargs)
209 215
210 216 def raw_print(*args, **kw):
211 217 """Raw print to sys.__stdout__, otherwise identical interface to print()."""
212 218
213 219 print(*args, sep=kw.get('sep', ' '), end=kw.get('end', '\n'),
214 220 file=sys.__stdout__)
215 221 sys.__stdout__.flush()
216 222
217 223
218 224 def raw_print_err(*args, **kw):
219 225 """Raw print to sys.__stderr__, otherwise identical interface to print()."""
220 226
221 227 print(*args, sep=kw.get('sep', ' '), end=kw.get('end', '\n'),
222 228 file=sys.__stderr__)
223 229 sys.__stderr__.flush()
224 230
225 231
226 232 # Short aliases for quick debugging, do NOT use these in production code.
227 233 rprint = raw_print
228 234 rprinte = raw_print_err
229 235
230 236
231 237 def unicode_std_stream(stream='stdout'):
232 238 """DEPRECATED, moved to nbconvert.utils.io"""
233 239 warn("IPython.utils.io.unicode_std_stream has moved to nbconvert.utils.io")
234 240 from nbconvert.utils.io import unicode_std_stream
235 241 return unicode_std_stream(stream)
@@ -1,65 +1,65 b''
1 1 # encoding: utf-8
2 2 """
3 3 Utilities for warnings. Shoudn't we just use the built in warnings module.
4 4 """
5 5
6 6 # Copyright (c) IPython Development Team.
7 7 # Distributed under the terms of the Modified BSD License.
8 8
9 9 from __future__ import print_function
10 10
11 11 import sys
12 12 import warnings
13 13
14 14 warnings.warn("The module IPython.utils.warn is deprecated since IPython 4.0, use the standard warnings module instead", DeprecationWarning)
15 15
16 16 def warn(msg,level=2,exit_val=1):
17 17 """Deprecated
18 18
19 19 Standard warning printer. Gives formatting consistency.
20 20
21 Output is sent to io.stderr (sys.stderr by default).
21 Output is sent to sys.stderr.
22 22
23 23 Options:
24 24
25 25 -level(2): allows finer control:
26 26 0 -> Do nothing, dummy function.
27 27 1 -> Print message.
28 28 2 -> Print 'WARNING:' + message. (Default level).
29 29 3 -> Print 'ERROR:' + message.
30 30 4 -> Print 'FATAL ERROR:' + message and trigger a sys.exit(exit_val).
31 31
32 32 -exit_val (1): exit value returned by sys.exit() for a level 4
33 33 warning. Ignored for all other levels."""
34 34
35 35 warnings.warn("The module IPython.utils.warn is deprecated since IPython 4.0, use the standard warnings module instead", DeprecationWarning)
36 36 if level>0:
37 37 header = ['','','WARNING: ','ERROR: ','FATAL ERROR: ']
38 38 print(header[level], msg, sep='', file=sys.stderr)
39 39 if level == 4:
40 40 print('Exiting.\n', file=sys.stderr)
41 41 sys.exit(exit_val)
42 42
43 43
44 44 def info(msg):
45 45 """Deprecated
46 46
47 47 Equivalent to warn(msg,level=1)."""
48 48
49 49 warn(msg,level=1)
50 50
51 51
52 52 def error(msg):
53 53 """Deprecated
54 54
55 55 Equivalent to warn(msg,level=3)."""
56 56
57 57 warn(msg,level=3)
58 58
59 59
60 60 def fatal(msg,exit_val=1):
61 61 """Deprecated
62 62
63 63 Equivalent to warn(msg,exit_val=exit_val,level=4)."""
64 64
65 65 warn(msg,exit_val=exit_val,level=4)
General Comments 0
You need to be logged in to leave comments. Login now