##// END OF EJS Templates
Implementing decorator
nfgf -
Show More

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

@@ -1,325 +1,331 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 import builtins as builtin_mod
11 11 import sys
12 12 import io as _io
13 13 import tokenize
14 14
15 15 from traitlets.config.configurable import Configurable
16 16 from traitlets import Instance, Float
17 17 from warnings import warn
18 18
19 19 # TODO: Move the various attributes (cache_size, [others now moved]). Some
20 20 # of these are also attributes of InteractiveShell. They should be on ONE object
21 21 # only and the other objects should ask that one object for their values.
22 22
23 23 class DisplayHook(Configurable):
24 24 """The custom IPython displayhook to replace sys.displayhook.
25 25
26 26 This class does many things, but the basic idea is that it is a callable
27 27 that gets called anytime user code returns a value.
28 28 """
29 29
30 30 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC',
31 31 allow_none=True)
32 32 exec_result = Instance('IPython.core.interactiveshell.ExecutionResult',
33 33 allow_none=True)
34 34 cull_fraction = Float(0.2)
35 35
36 36 def __init__(self, shell=None, cache_size=1000, **kwargs):
37 37 super(DisplayHook, self).__init__(shell=shell, **kwargs)
38 38 cache_size_min = 3
39 39 if cache_size <= 0:
40 40 self.do_full_cache = 0
41 41 cache_size = 0
42 42 elif cache_size < cache_size_min:
43 43 self.do_full_cache = 0
44 44 cache_size = 0
45 45 warn('caching was disabled (min value for cache size is %s).' %
46 46 cache_size_min,stacklevel=3)
47 47 else:
48 48 self.do_full_cache = 1
49 49
50 50 self.cache_size = cache_size
51 51
52 52 # we need a reference to the user-level namespace
53 53 self.shell = shell
54 54
55 55 self._,self.__,self.___ = '','',''
56 56
57 57 # these are deliberately global:
58 58 to_user_ns = {'_':self._,'__':self.__,'___':self.___}
59 59 self.shell.user_ns.update(to_user_ns)
60 60
61 61 @property
62 62 def prompt_count(self):
63 63 return self.shell.execution_count
64 64
65 65 #-------------------------------------------------------------------------
66 66 # Methods used in __call__. Override these methods to modify the behavior
67 67 # of the displayhook.
68 68 #-------------------------------------------------------------------------
69 69
70 70 def check_for_underscore(self):
71 71 """Check if the user has set the '_' variable by hand."""
72 72 # If something injected a '_' variable in __builtin__, delete
73 73 # ipython's automatic one so we don't clobber that. gettext() in
74 74 # particular uses _, so we need to stay away from it.
75 75 if '_' in builtin_mod.__dict__:
76 76 try:
77 77 user_value = self.shell.user_ns['_']
78 78 if user_value is not self._:
79 79 return
80 80 del self.shell.user_ns['_']
81 81 except KeyError:
82 82 pass
83 83
84 84 def quiet(self):
85 85 """Should we silence the display hook because of ';'?"""
86 86 # do not print output if input ends in ';'
87 87
88 88 try:
89 89 cell = self.shell.history_manager.input_hist_parsed[-1]
90 90 except IndexError:
91 91 # some uses of ipshellembed may fail here
92 92 return False
93 93
94 sio = _io.StringIO(cell)
94 return self.semicolon_at_end_of_expression(cell)
95
96 @staticmethod
97 def semicolon_at_end_of_expression(expression):
98 """Parse Python expression and detects whether last token is ';'"""
99
100 sio = _io.StringIO(expression)
95 101 tokens = list(tokenize.generate_tokens(sio.readline))
96 102
97 103 for token in reversed(tokens):
98 104 if token[0] in (tokenize.ENDMARKER, tokenize.NL, tokenize.NEWLINE, tokenize.COMMENT):
99 105 continue
100 106 if (token[0] == tokenize.OP) and (token[1] == ';'):
101 107 return True
102 108 else:
103 109 return False
104 110
105 111 def start_displayhook(self):
106 112 """Start the displayhook, initializing resources."""
107 113 pass
108 114
109 115 def write_output_prompt(self):
110 116 """Write the output prompt.
111 117
112 118 The default implementation simply writes the prompt to
113 119 ``sys.stdout``.
114 120 """
115 121 # Use write, not print which adds an extra space.
116 122 sys.stdout.write(self.shell.separate_out)
117 123 outprompt = 'Out[{}]: '.format(self.shell.execution_count)
118 124 if self.do_full_cache:
119 125 sys.stdout.write(outprompt)
120 126
121 127 def compute_format_data(self, result):
122 128 """Compute format data of the object to be displayed.
123 129
124 130 The format data is a generalization of the :func:`repr` of an object.
125 131 In the default implementation the format data is a :class:`dict` of
126 132 key value pair where the keys are valid MIME types and the values
127 133 are JSON'able data structure containing the raw data for that MIME
128 134 type. It is up to frontends to determine pick a MIME to to use and
129 135 display that data in an appropriate manner.
130 136
131 137 This method only computes the format data for the object and should
132 138 NOT actually print or write that to a stream.
133 139
134 140 Parameters
135 141 ----------
136 142 result : object
137 143 The Python object passed to the display hook, whose format will be
138 144 computed.
139 145
140 146 Returns
141 147 -------
142 148 (format_dict, md_dict) : dict
143 149 format_dict is a :class:`dict` whose keys are valid MIME types and values are
144 150 JSON'able raw data for that MIME type. It is recommended that
145 151 all return values of this should always include the "text/plain"
146 152 MIME type representation of the object.
147 153 md_dict is a :class:`dict` with the same MIME type keys
148 154 of metadata associated with each output.
149 155
150 156 """
151 157 return self.shell.display_formatter.format(result)
152 158
153 159 # This can be set to True by the write_output_prompt method in a subclass
154 160 prompt_end_newline = False
155 161
156 162 def write_format_data(self, format_dict, md_dict=None) -> None:
157 163 """Write the format data dict to the frontend.
158 164
159 165 This default version of this method simply writes the plain text
160 166 representation of the object to ``sys.stdout``. Subclasses should
161 167 override this method to send the entire `format_dict` to the
162 168 frontends.
163 169
164 170 Parameters
165 171 ----------
166 172 format_dict : dict
167 173 The format dict for the object passed to `sys.displayhook`.
168 174 md_dict : dict (optional)
169 175 The metadata dict to be associated with the display data.
170 176 """
171 177 if 'text/plain' not in format_dict:
172 178 # nothing to do
173 179 return
174 180 # We want to print because we want to always make sure we have a
175 181 # newline, even if all the prompt separators are ''. This is the
176 182 # standard IPython behavior.
177 183 result_repr = format_dict['text/plain']
178 184 if '\n' in result_repr:
179 185 # So that multi-line strings line up with the left column of
180 186 # the screen, instead of having the output prompt mess up
181 187 # their first line.
182 188 # We use the prompt template instead of the expanded prompt
183 189 # because the expansion may add ANSI escapes that will interfere
184 190 # with our ability to determine whether or not we should add
185 191 # a newline.
186 192 if not self.prompt_end_newline:
187 193 # But avoid extraneous empty lines.
188 194 result_repr = '\n' + result_repr
189 195
190 196 try:
191 197 print(result_repr)
192 198 except UnicodeEncodeError:
193 199 # If a character is not supported by the terminal encoding replace
194 200 # it with its \u or \x representation
195 201 print(result_repr.encode(sys.stdout.encoding,'backslashreplace').decode(sys.stdout.encoding))
196 202
197 203 def update_user_ns(self, result):
198 204 """Update user_ns with various things like _, __, _1, etc."""
199 205
200 206 # Avoid recursive reference when displaying _oh/Out
201 207 if self.cache_size and result is not self.shell.user_ns['_oh']:
202 208 if len(self.shell.user_ns['_oh']) >= self.cache_size and self.do_full_cache:
203 209 self.cull_cache()
204 210
205 211 # Don't overwrite '_' and friends if '_' is in __builtin__
206 212 # (otherwise we cause buggy behavior for things like gettext). and
207 213 # do not overwrite _, __ or ___ if one of these has been assigned
208 214 # by the user.
209 215 update_unders = True
210 216 for unders in ['_'*i for i in range(1,4)]:
211 217 if not unders in self.shell.user_ns:
212 218 continue
213 219 if getattr(self, unders) is not self.shell.user_ns.get(unders):
214 220 update_unders = False
215 221
216 222 self.___ = self.__
217 223 self.__ = self._
218 224 self._ = result
219 225
220 226 if ('_' not in builtin_mod.__dict__) and (update_unders):
221 227 self.shell.push({'_':self._,
222 228 '__':self.__,
223 229 '___':self.___}, interactive=False)
224 230
225 231 # hackish access to top-level namespace to create _1,_2... dynamically
226 232 to_main = {}
227 233 if self.do_full_cache:
228 234 new_result = '_%s' % self.prompt_count
229 235 to_main[new_result] = result
230 236 self.shell.push(to_main, interactive=False)
231 237 self.shell.user_ns['_oh'][self.prompt_count] = result
232 238
233 239 def fill_exec_result(self, result):
234 240 if self.exec_result is not None:
235 241 self.exec_result.result = result
236 242
237 243 def log_output(self, format_dict):
238 244 """Log the output."""
239 245 if 'text/plain' not in format_dict:
240 246 # nothing to do
241 247 return
242 248 if self.shell.logger.log_output:
243 249 self.shell.logger.log_write(format_dict['text/plain'], 'output')
244 250 self.shell.history_manager.output_hist_reprs[self.prompt_count] = \
245 251 format_dict['text/plain']
246 252
247 253 def finish_displayhook(self):
248 254 """Finish up all displayhook activities."""
249 255 sys.stdout.write(self.shell.separate_out2)
250 256 sys.stdout.flush()
251 257
252 258 def __call__(self, result=None):
253 259 """Printing with history cache management.
254 260
255 261 This is invoked every time the interpreter needs to print, and is
256 262 activated by setting the variable sys.displayhook to it.
257 263 """
258 264 self.check_for_underscore()
259 265 if result is not None and not self.quiet():
260 266 self.start_displayhook()
261 267 self.write_output_prompt()
262 268 format_dict, md_dict = self.compute_format_data(result)
263 269 self.update_user_ns(result)
264 270 self.fill_exec_result(result)
265 271 if format_dict:
266 272 self.write_format_data(format_dict, md_dict)
267 273 self.log_output(format_dict)
268 274 self.finish_displayhook()
269 275
270 276 def cull_cache(self):
271 277 """Output cache is full, cull the oldest entries"""
272 278 oh = self.shell.user_ns.get('_oh', {})
273 279 sz = len(oh)
274 280 cull_count = max(int(sz * self.cull_fraction), 2)
275 281 warn('Output cache limit (currently {sz} entries) hit.\n'
276 282 'Flushing oldest {cull_count} entries.'.format(sz=sz, cull_count=cull_count))
277 283
278 284 for i, n in enumerate(sorted(oh)):
279 285 if i >= cull_count:
280 286 break
281 287 self.shell.user_ns.pop('_%i' % n, None)
282 288 oh.pop(n, None)
283 289
284 290
285 291 def flush(self):
286 292 if not self.do_full_cache:
287 293 raise ValueError("You shouldn't have reached the cache flush "
288 294 "if full caching is not enabled!")
289 295 # delete auto-generated vars from global namespace
290 296
291 297 for n in range(1,self.prompt_count + 1):
292 298 key = '_'+repr(n)
293 299 try:
294 300 del self.shell.user_ns[key]
295 301 except: pass
296 302 # In some embedded circumstances, the user_ns doesn't have the
297 303 # '_oh' key set up.
298 304 oh = self.shell.user_ns.get('_oh', None)
299 305 if oh is not None:
300 306 oh.clear()
301 307
302 308 # Release our own references to objects:
303 309 self._, self.__, self.___ = '', '', ''
304 310
305 311 if '_' not in builtin_mod.__dict__:
306 312 self.shell.user_ns.update({'_':self._,'__':self.__,'___':self.___})
307 313 import gc
308 314 # TODO: Is this really needed?
309 315 # IronPython blocks here forever
310 316 if sys.platform != "cli":
311 317 gc.collect()
312 318
313 319
314 320 class CapturingDisplayHook(object):
315 321 def __init__(self, shell, outputs=None):
316 322 self.shell = shell
317 323 if outputs is None:
318 324 outputs = []
319 325 self.outputs = outputs
320 326
321 327 def __call__(self, result=None):
322 328 if result is None:
323 329 return
324 330 format_dict, md_dict = self.shell.display_formatter.format(result)
325 331 self.outputs.append({ 'data': format_dict, 'metadata': md_dict })
1 NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
@@ -1,746 +1,755 b''
1 1 # encoding: utf-8
2 2 """Magic functions for InteractiveShell.
3 3 """
4 4
5 5 #-----------------------------------------------------------------------------
6 6 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and
7 7 # Copyright (C) 2001 Fernando Perez <fperez@colorado.edu>
8 8 # Copyright (C) 2008 The IPython Development Team
9 9
10 10 # Distributed under the terms of the BSD License. The full license is in
11 11 # the file COPYING, distributed as part of this software.
12 12 #-----------------------------------------------------------------------------
13 13
14 14 import os
15 15 import re
16 16 import sys
17 17 from getopt import getopt, GetoptError
18 18
19 19 from traitlets.config.configurable import Configurable
20 20 from . import oinspect
21 21 from .error import UsageError
22 22 from .inputtransformer2 import ESC_MAGIC, ESC_MAGIC2
23 23 from ..utils.ipstruct import Struct
24 24 from ..utils.process import arg_split
25 25 from ..utils.text import dedent
26 26 from traitlets import Bool, Dict, Instance, observe
27 27 from logging import error
28 28
29 29 #-----------------------------------------------------------------------------
30 30 # Globals
31 31 #-----------------------------------------------------------------------------
32 32
33 33 # A dict we'll use for each class that has magics, used as temporary storage to
34 34 # pass information between the @line/cell_magic method decorators and the
35 35 # @magics_class class decorator, because the method decorators have no
36 36 # access to the class when they run. See for more details:
37 37 # http://stackoverflow.com/questions/2366713/can-a-python-decorator-of-an-instance-method-access-the-class
38 38
39 39 magics = dict(line={}, cell={})
40 40
41 41 magic_kinds = ('line', 'cell')
42 42 magic_spec = ('line', 'cell', 'line_cell')
43 43 magic_escapes = dict(line=ESC_MAGIC, cell=ESC_MAGIC2)
44 44
45 45 #-----------------------------------------------------------------------------
46 46 # Utility classes and functions
47 47 #-----------------------------------------------------------------------------
48 48
49 49 class Bunch: pass
50 50
51 51
52 52 def on_off(tag):
53 53 """Return an ON/OFF string for a 1/0 input. Simple utility function."""
54 54 return ['OFF','ON'][tag]
55 55
56 56
57 57 def compress_dhist(dh):
58 58 """Compress a directory history into a new one with at most 20 entries.
59 59
60 60 Return a new list made from the first and last 10 elements of dhist after
61 61 removal of duplicates.
62 62 """
63 63 head, tail = dh[:-10], dh[-10:]
64 64
65 65 newhead = []
66 66 done = set()
67 67 for h in head:
68 68 if h in done:
69 69 continue
70 70 newhead.append(h)
71 71 done.add(h)
72 72
73 73 return newhead + tail
74 74
75 75
76 76 def needs_local_scope(func):
77 77 """Decorator to mark magic functions which need to local scope to run."""
78 78 func.needs_local_scope = True
79 79 return func
80 80
81 81 #-----------------------------------------------------------------------------
82 82 # Class and method decorators for registering magics
83 83 #-----------------------------------------------------------------------------
84 84
85 85 def magics_class(cls):
86 86 """Class decorator for all subclasses of the main Magics class.
87 87
88 88 Any class that subclasses Magics *must* also apply this decorator, to
89 89 ensure that all the methods that have been decorated as line/cell magics
90 90 get correctly registered in the class instance. This is necessary because
91 91 when method decorators run, the class does not exist yet, so they
92 92 temporarily store their information into a module global. Application of
93 93 this class decorator copies that global data to the class instance and
94 94 clears the global.
95 95
96 96 Obviously, this mechanism is not thread-safe, which means that the
97 97 *creation* of subclasses of Magic should only be done in a single-thread
98 98 context. Instantiation of the classes has no restrictions. Given that
99 99 these classes are typically created at IPython startup time and before user
100 100 application code becomes active, in practice this should not pose any
101 101 problems.
102 102 """
103 103 cls.registered = True
104 104 cls.magics = dict(line = magics['line'],
105 105 cell = magics['cell'])
106 106 magics['line'] = {}
107 107 magics['cell'] = {}
108 108 return cls
109 109
110 110
111 111 def record_magic(dct, magic_kind, magic_name, func):
112 112 """Utility function to store a function as a magic of a specific kind.
113 113
114 114 Parameters
115 115 ----------
116 116 dct : dict
117 117 A dictionary with 'line' and 'cell' subdicts.
118 118 magic_kind : str
119 119 Kind of magic to be stored.
120 120 magic_name : str
121 121 Key to store the magic as.
122 122 func : function
123 123 Callable object to store.
124 124 """
125 125 if magic_kind == 'line_cell':
126 126 dct['line'][magic_name] = dct['cell'][magic_name] = func
127 127 else:
128 128 dct[magic_kind][magic_name] = func
129 129
130 130
131 131 def validate_type(magic_kind):
132 132 """Ensure that the given magic_kind is valid.
133 133
134 134 Check that the given magic_kind is one of the accepted spec types (stored
135 135 in the global `magic_spec`), raise ValueError otherwise.
136 136 """
137 137 if magic_kind not in magic_spec:
138 138 raise ValueError('magic_kind must be one of %s, %s given' %
139 139 magic_kinds, magic_kind)
140 140
141 141
142 142 # The docstrings for the decorator below will be fairly similar for the two
143 143 # types (method and function), so we generate them here once and reuse the
144 144 # templates below.
145 145 _docstring_template = \
146 146 """Decorate the given {0} as {1} magic.
147 147
148 148 The decorator can be used with or without arguments, as follows.
149 149
150 150 i) without arguments: it will create a {1} magic named as the {0} being
151 151 decorated::
152 152
153 153 @deco
154 154 def foo(...)
155 155
156 156 will create a {1} magic named `foo`.
157 157
158 158 ii) with one string argument: which will be used as the actual name of the
159 159 resulting magic::
160 160
161 161 @deco('bar')
162 162 def foo(...)
163 163
164 164 will create a {1} magic named `bar`.
165 165
166 166 To register a class magic use ``Interactiveshell.register_magic(class or instance)``.
167 167 """
168 168
169 169 # These two are decorator factories. While they are conceptually very similar,
170 170 # there are enough differences in the details that it's simpler to have them
171 171 # written as completely standalone functions rather than trying to share code
172 172 # and make a single one with convoluted logic.
173 173
174 174 def _method_magic_marker(magic_kind):
175 175 """Decorator factory for methods in Magics subclasses.
176 176 """
177 177
178 178 validate_type(magic_kind)
179 179
180 180 # This is a closure to capture the magic_kind. We could also use a class,
181 181 # but it's overkill for just that one bit of state.
182 182 def magic_deco(arg):
183 183 if callable(arg):
184 184 # "Naked" decorator call (just @foo, no args)
185 185 func = arg
186 186 name = func.__name__
187 187 retval = arg
188 188 record_magic(magics, magic_kind, name, name)
189 189 elif isinstance(arg, str):
190 190 # Decorator called with arguments (@foo('bar'))
191 191 name = arg
192 192 def mark(func, *a, **kw):
193 193 record_magic(magics, magic_kind, name, func.__name__)
194 194 return func
195 195 retval = mark
196 196 else:
197 197 raise TypeError("Decorator can only be called with "
198 198 "string or function")
199 199 return retval
200 200
201 201 # Ensure the resulting decorator has a usable docstring
202 202 magic_deco.__doc__ = _docstring_template.format('method', magic_kind)
203 203 return magic_deco
204 204
205 205
206 206 def _function_magic_marker(magic_kind):
207 207 """Decorator factory for standalone functions.
208 208 """
209 209 validate_type(magic_kind)
210 210
211 211 # This is a closure to capture the magic_kind. We could also use a class,
212 212 # but it's overkill for just that one bit of state.
213 213 def magic_deco(arg):
214 214 # Find get_ipython() in the caller's namespace
215 215 caller = sys._getframe(1)
216 216 for ns in ['f_locals', 'f_globals', 'f_builtins']:
217 217 get_ipython = getattr(caller, ns).get('get_ipython')
218 218 if get_ipython is not None:
219 219 break
220 220 else:
221 221 raise NameError('Decorator can only run in context where '
222 222 '`get_ipython` exists')
223 223
224 224 ip = get_ipython()
225 225
226 226 if callable(arg):
227 227 # "Naked" decorator call (just @foo, no args)
228 228 func = arg
229 229 name = func.__name__
230 230 ip.register_magic_function(func, magic_kind, name)
231 231 retval = arg
232 232 elif isinstance(arg, str):
233 233 # Decorator called with arguments (@foo('bar'))
234 234 name = arg
235 235 def mark(func, *a, **kw):
236 236 ip.register_magic_function(func, magic_kind, name)
237 237 return func
238 238 retval = mark
239 239 else:
240 240 raise TypeError("Decorator can only be called with "
241 241 "string or function")
242 242 return retval
243 243
244 244 # Ensure the resulting decorator has a usable docstring
245 245 ds = _docstring_template.format('function', magic_kind)
246 246
247 247 ds += dedent("""
248 248 Note: this decorator can only be used in a context where IPython is already
249 249 active, so that the `get_ipython()` call succeeds. You can therefore use
250 250 it in your startup files loaded after IPython initializes, but *not* in the
251 251 IPython configuration file itself, which is executed before IPython is
252 252 fully up and running. Any file located in the `startup` subdirectory of
253 253 your configuration profile will be OK in this sense.
254 254 """)
255 255
256 256 magic_deco.__doc__ = ds
257 257 return magic_deco
258 258
259 259
260 260 MAGIC_NO_VAR_EXPAND_ATTR = '_ipython_magic_no_var_expand'
261
261 MAGIC_OUTPUT_CAN_BE_DISABLED = '_ipython_magic_output_can_be_disabled'
262 262
263 263 def no_var_expand(magic_func):
264 264 """Mark a magic function as not needing variable expansion
265 265
266 266 By default, IPython interprets `{a}` or `$a` in the line passed to magics
267 267 as variables that should be interpolated from the interactive namespace
268 268 before passing the line to the magic function.
269 269 This is not always desirable, e.g. when the magic executes Python code
270 270 (%timeit, %time, etc.).
271 271 Decorate magics with `@no_var_expand` to opt-out of variable expansion.
272 272
273 273 .. versionadded:: 7.3
274 274 """
275 275 setattr(magic_func, MAGIC_NO_VAR_EXPAND_ATTR, True)
276 276 return magic_func
277 277
278 def output_can_be_disabled(magic_func):
279 """Mark a magic function so its output may be disabled.
280
281 The output is disabled if the Python expression used as a parameter of
282 the magic ends in a semicolon, not counting a Python comment that can
283 follows it.
284 """
285 setattr(magic_func, MAGIC_OUTPUT_CAN_BE_DISABLED, True)
286 return magic_func
278 287
279 288 # Create the actual decorators for public use
280 289
281 290 # These three are used to decorate methods in class definitions
282 291 line_magic = _method_magic_marker('line')
283 292 cell_magic = _method_magic_marker('cell')
284 293 line_cell_magic = _method_magic_marker('line_cell')
285 294
286 295 # These three decorate standalone functions and perform the decoration
287 296 # immediately. They can only run where get_ipython() works
288 297 register_line_magic = _function_magic_marker('line')
289 298 register_cell_magic = _function_magic_marker('cell')
290 299 register_line_cell_magic = _function_magic_marker('line_cell')
291 300
292 301 #-----------------------------------------------------------------------------
293 302 # Core Magic classes
294 303 #-----------------------------------------------------------------------------
295 304
296 305 class MagicsManager(Configurable):
297 306 """Object that handles all magic-related functionality for IPython.
298 307 """
299 308 # Non-configurable class attributes
300 309
301 310 # A two-level dict, first keyed by magic type, then by magic function, and
302 311 # holding the actual callable object as value. This is the dict used for
303 312 # magic function dispatch
304 313 magics = Dict()
305 314 lazy_magics = Dict(
306 315 help="""
307 316 Mapping from magic names to modules to load.
308 317
309 318 This can be used in IPython/IPykernel configuration to declare lazy magics
310 319 that will only be imported/registered on first use.
311 320
312 321 For example::
313 322
314 323 c.MagicsManager.lazy_magics = {
315 324 "my_magic": "slow.to.import",
316 325 "my_other_magic": "also.slow",
317 326 }
318 327
319 328 On first invocation of `%my_magic`, `%%my_magic`, `%%my_other_magic` or
320 329 `%%my_other_magic`, the corresponding module will be loaded as an ipython
321 330 extensions as if you had previously done `%load_ext ipython`.
322 331
323 332 Magics names should be without percent(s) as magics can be both cell
324 333 and line magics.
325 334
326 335 Lazy loading happen relatively late in execution process, and
327 336 complex extensions that manipulate Python/IPython internal state or global state
328 337 might not support lazy loading.
329 338 """
330 339 ).tag(
331 340 config=True,
332 341 )
333 342
334 343 # A registry of the original objects that we've been given holding magics.
335 344 registry = Dict()
336 345
337 346 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
338 347
339 348 auto_magic = Bool(True, help=
340 349 "Automatically call line magics without requiring explicit % prefix"
341 350 ).tag(config=True)
342 351 @observe('auto_magic')
343 352 def _auto_magic_changed(self, change):
344 353 self.shell.automagic = change['new']
345 354
346 355 _auto_status = [
347 356 'Automagic is OFF, % prefix IS needed for line magics.',
348 357 'Automagic is ON, % prefix IS NOT needed for line magics.']
349 358
350 359 user_magics = Instance('IPython.core.magics.UserMagics', allow_none=True)
351 360
352 361 def __init__(self, shell=None, config=None, user_magics=None, **traits):
353 362
354 363 super(MagicsManager, self).__init__(shell=shell, config=config,
355 364 user_magics=user_magics, **traits)
356 365 self.magics = dict(line={}, cell={})
357 366 # Let's add the user_magics to the registry for uniformity, so *all*
358 367 # registered magic containers can be found there.
359 368 self.registry[user_magics.__class__.__name__] = user_magics
360 369
361 370 def auto_status(self):
362 371 """Return descriptive string with automagic status."""
363 372 return self._auto_status[self.auto_magic]
364 373
365 374 def lsmagic(self):
366 375 """Return a dict of currently available magic functions.
367 376
368 377 The return dict has the keys 'line' and 'cell', corresponding to the
369 378 two types of magics we support. Each value is a list of names.
370 379 """
371 380 return self.magics
372 381
373 382 def lsmagic_docs(self, brief=False, missing=''):
374 383 """Return dict of documentation of magic functions.
375 384
376 385 The return dict has the keys 'line' and 'cell', corresponding to the
377 386 two types of magics we support. Each value is a dict keyed by magic
378 387 name whose value is the function docstring. If a docstring is
379 388 unavailable, the value of `missing` is used instead.
380 389
381 390 If brief is True, only the first line of each docstring will be returned.
382 391 """
383 392 docs = {}
384 393 for m_type in self.magics:
385 394 m_docs = {}
386 395 for m_name, m_func in self.magics[m_type].items():
387 396 if m_func.__doc__:
388 397 if brief:
389 398 m_docs[m_name] = m_func.__doc__.split('\n', 1)[0]
390 399 else:
391 400 m_docs[m_name] = m_func.__doc__.rstrip()
392 401 else:
393 402 m_docs[m_name] = missing
394 403 docs[m_type] = m_docs
395 404 return docs
396 405
397 406 def register_lazy(self, name: str, fully_qualified_name: str):
398 407 """
399 408 Lazily register a magic via an extension.
400 409
401 410
402 411 Parameters
403 412 ----------
404 413 name : str
405 414 Name of the magic you wish to register.
406 415 fully_qualified_name :
407 416 Fully qualified name of the module/submodule that should be loaded
408 417 as an extensions when the magic is first called.
409 418 It is assumed that loading this extensions will register the given
410 419 magic.
411 420 """
412 421
413 422 self.lazy_magics[name] = fully_qualified_name
414 423
415 424 def register(self, *magic_objects):
416 425 """Register one or more instances of Magics.
417 426
418 427 Take one or more classes or instances of classes that subclass the main
419 428 `core.Magic` class, and register them with IPython to use the magic
420 429 functions they provide. The registration process will then ensure that
421 430 any methods that have decorated to provide line and/or cell magics will
422 431 be recognized with the `%x`/`%%x` syntax as a line/cell magic
423 432 respectively.
424 433
425 434 If classes are given, they will be instantiated with the default
426 435 constructor. If your classes need a custom constructor, you should
427 436 instanitate them first and pass the instance.
428 437
429 438 The provided arguments can be an arbitrary mix of classes and instances.
430 439
431 440 Parameters
432 441 ----------
433 442 *magic_objects : one or more classes or instances
434 443 """
435 444 # Start by validating them to ensure they have all had their magic
436 445 # methods registered at the instance level
437 446 for m in magic_objects:
438 447 if not m.registered:
439 448 raise ValueError("Class of magics %r was constructed without "
440 449 "the @register_magics class decorator")
441 450 if isinstance(m, type):
442 451 # If we're given an uninstantiated class
443 452 m = m(shell=self.shell)
444 453
445 454 # Now that we have an instance, we can register it and update the
446 455 # table of callables
447 456 self.registry[m.__class__.__name__] = m
448 457 for mtype in magic_kinds:
449 458 self.magics[mtype].update(m.magics[mtype])
450 459
451 460 def register_function(self, func, magic_kind='line', magic_name=None):
452 461 """Expose a standalone function as magic function for IPython.
453 462
454 463 This will create an IPython magic (line, cell or both) from a
455 464 standalone function. The functions should have the following
456 465 signatures:
457 466
458 467 * For line magics: `def f(line)`
459 468 * For cell magics: `def f(line, cell)`
460 469 * For a function that does both: `def f(line, cell=None)`
461 470
462 471 In the latter case, the function will be called with `cell==None` when
463 472 invoked as `%f`, and with cell as a string when invoked as `%%f`.
464 473
465 474 Parameters
466 475 ----------
467 476 func : callable
468 477 Function to be registered as a magic.
469 478 magic_kind : str
470 479 Kind of magic, one of 'line', 'cell' or 'line_cell'
471 480 magic_name : optional str
472 481 If given, the name the magic will have in the IPython namespace. By
473 482 default, the name of the function itself is used.
474 483 """
475 484
476 485 # Create the new method in the user_magics and register it in the
477 486 # global table
478 487 validate_type(magic_kind)
479 488 magic_name = func.__name__ if magic_name is None else magic_name
480 489 setattr(self.user_magics, magic_name, func)
481 490 record_magic(self.magics, magic_kind, magic_name, func)
482 491
483 492 def register_alias(self, alias_name, magic_name, magic_kind='line', magic_params=None):
484 493 """Register an alias to a magic function.
485 494
486 495 The alias is an instance of :class:`MagicAlias`, which holds the
487 496 name and kind of the magic it should call. Binding is done at
488 497 call time, so if the underlying magic function is changed the alias
489 498 will call the new function.
490 499
491 500 Parameters
492 501 ----------
493 502 alias_name : str
494 503 The name of the magic to be registered.
495 504 magic_name : str
496 505 The name of an existing magic.
497 506 magic_kind : str
498 507 Kind of magic, one of 'line' or 'cell'
499 508 """
500 509
501 510 # `validate_type` is too permissive, as it allows 'line_cell'
502 511 # which we do not handle.
503 512 if magic_kind not in magic_kinds:
504 513 raise ValueError('magic_kind must be one of %s, %s given' %
505 514 magic_kinds, magic_kind)
506 515
507 516 alias = MagicAlias(self.shell, magic_name, magic_kind, magic_params)
508 517 setattr(self.user_magics, alias_name, alias)
509 518 record_magic(self.magics, magic_kind, alias_name, alias)
510 519
511 520 # Key base class that provides the central functionality for magics.
512 521
513 522
514 523 class Magics(Configurable):
515 524 """Base class for implementing magic functions.
516 525
517 526 Shell functions which can be reached as %function_name. All magic
518 527 functions should accept a string, which they can parse for their own
519 528 needs. This can make some functions easier to type, eg `%cd ../`
520 529 vs. `%cd("../")`
521 530
522 531 Classes providing magic functions need to subclass this class, and they
523 532 MUST:
524 533
525 534 - Use the method decorators `@line_magic` and `@cell_magic` to decorate
526 535 individual methods as magic functions, AND
527 536
528 537 - Use the class decorator `@magics_class` to ensure that the magic
529 538 methods are properly registered at the instance level upon instance
530 539 initialization.
531 540
532 541 See :mod:`magic_functions` for examples of actual implementation classes.
533 542 """
534 543 # Dict holding all command-line options for each magic.
535 544 options_table = None
536 545 # Dict for the mapping of magic names to methods, set by class decorator
537 546 magics = None
538 547 # Flag to check that the class decorator was properly applied
539 548 registered = False
540 549 # Instance of IPython shell
541 550 shell = None
542 551
543 552 def __init__(self, shell=None, **kwargs):
544 553 if not(self.__class__.registered):
545 554 raise ValueError('Magics subclass without registration - '
546 555 'did you forget to apply @magics_class?')
547 556 if shell is not None:
548 557 if hasattr(shell, 'configurables'):
549 558 shell.configurables.append(self)
550 559 if hasattr(shell, 'config'):
551 560 kwargs.setdefault('parent', shell)
552 561
553 562 self.shell = shell
554 563 self.options_table = {}
555 564 # The method decorators are run when the instance doesn't exist yet, so
556 565 # they can only record the names of the methods they are supposed to
557 566 # grab. Only now, that the instance exists, can we create the proper
558 567 # mapping to bound methods. So we read the info off the original names
559 568 # table and replace each method name by the actual bound method.
560 569 # But we mustn't clobber the *class* mapping, in case of multiple instances.
561 570 class_magics = self.magics
562 571 self.magics = {}
563 572 for mtype in magic_kinds:
564 573 tab = self.magics[mtype] = {}
565 574 cls_tab = class_magics[mtype]
566 575 for magic_name, meth_name in cls_tab.items():
567 576 if isinstance(meth_name, str):
568 577 # it's a method name, grab it
569 578 tab[magic_name] = getattr(self, meth_name)
570 579 else:
571 580 # it's the real thing
572 581 tab[magic_name] = meth_name
573 582 # Configurable **needs** to be initiated at the end or the config
574 583 # magics get screwed up.
575 584 super(Magics, self).__init__(**kwargs)
576 585
577 586 def arg_err(self,func):
578 587 """Print docstring if incorrect arguments were passed"""
579 588 print('Error in arguments:')
580 589 print(oinspect.getdoc(func))
581 590
582 591 def format_latex(self, strng):
583 592 """Format a string for latex inclusion."""
584 593
585 594 # Characters that need to be escaped for latex:
586 595 escape_re = re.compile(r'(%|_|\$|#|&)',re.MULTILINE)
587 596 # Magic command names as headers:
588 597 cmd_name_re = re.compile(r'^(%s.*?):' % ESC_MAGIC,
589 598 re.MULTILINE)
590 599 # Magic commands
591 600 cmd_re = re.compile(r'(?P<cmd>%s.+?\b)(?!\}\}:)' % ESC_MAGIC,
592 601 re.MULTILINE)
593 602 # Paragraph continue
594 603 par_re = re.compile(r'\\$',re.MULTILINE)
595 604
596 605 # The "\n" symbol
597 606 newline_re = re.compile(r'\\n')
598 607
599 608 # Now build the string for output:
600 609 #strng = cmd_name_re.sub(r'\n\\texttt{\\textsl{\\large \1}}:',strng)
601 610 strng = cmd_name_re.sub(r'\n\\bigskip\n\\texttt{\\textbf{ \1}}:',
602 611 strng)
603 612 strng = cmd_re.sub(r'\\texttt{\g<cmd>}',strng)
604 613 strng = par_re.sub(r'\\\\',strng)
605 614 strng = escape_re.sub(r'\\\1',strng)
606 615 strng = newline_re.sub(r'\\textbackslash{}n',strng)
607 616 return strng
608 617
609 618 def parse_options(self, arg_str, opt_str, *long_opts, **kw):
610 619 """Parse options passed to an argument string.
611 620
612 621 The interface is similar to that of :func:`getopt.getopt`, but it
613 622 returns a :class:`~IPython.utils.struct.Struct` with the options as keys
614 623 and the stripped argument string still as a string.
615 624
616 625 arg_str is quoted as a true sys.argv vector by using shlex.split.
617 626 This allows us to easily expand variables, glob files, quote
618 627 arguments, etc.
619 628
620 629 Parameters
621 630 ----------
622 631 arg_str : str
623 632 The arguments to parse.
624 633 opt_str : str
625 634 The options specification.
626 635 mode : str, default 'string'
627 636 If given as 'list', the argument string is returned as a list (split
628 637 on whitespace) instead of a string.
629 638 list_all : bool, default False
630 639 Put all option values in lists. Normally only options
631 640 appearing more than once are put in a list.
632 641 posix : bool, default True
633 642 Whether to split the input line in POSIX mode or not, as per the
634 643 conventions outlined in the :mod:`shlex` module from the standard
635 644 library.
636 645 """
637 646
638 647 # inject default options at the beginning of the input line
639 648 caller = sys._getframe(1).f_code.co_name
640 649 arg_str = '%s %s' % (self.options_table.get(caller,''),arg_str)
641 650
642 651 mode = kw.get('mode','string')
643 652 if mode not in ['string','list']:
644 653 raise ValueError('incorrect mode given: %s' % mode)
645 654 # Get options
646 655 list_all = kw.get('list_all',0)
647 656 posix = kw.get('posix', os.name == 'posix')
648 657 strict = kw.get('strict', True)
649 658
650 659 preserve_non_opts = kw.get("preserve_non_opts", False)
651 660 remainder_arg_str = arg_str
652 661
653 662 # Check if we have more than one argument to warrant extra processing:
654 663 odict = {} # Dictionary with options
655 664 args = arg_str.split()
656 665 if len(args) >= 1:
657 666 # If the list of inputs only has 0 or 1 thing in it, there's no
658 667 # need to look for options
659 668 argv = arg_split(arg_str, posix, strict)
660 669 # Do regular option processing
661 670 try:
662 671 opts,args = getopt(argv, opt_str, long_opts)
663 672 except GetoptError as e:
664 673 raise UsageError(
665 674 '%s ( allowed: "%s" %s)' % (e.msg, opt_str, " ".join(long_opts))
666 675 ) from e
667 676 for o, a in opts:
668 677 if mode == "string" and preserve_non_opts:
669 678 # remove option-parts from the original args-string and preserve remaining-part.
670 679 # This relies on the arg_split(...) and getopt(...)'s impl spec, that the parsed options are
671 680 # returned in the original order.
672 681 remainder_arg_str = remainder_arg_str.replace(o, "", 1).replace(
673 682 a, "", 1
674 683 )
675 684 if o.startswith("--"):
676 685 o = o[2:]
677 686 else:
678 687 o = o[1:]
679 688 try:
680 689 odict[o].append(a)
681 690 except AttributeError:
682 691 odict[o] = [odict[o],a]
683 692 except KeyError:
684 693 if list_all:
685 694 odict[o] = [a]
686 695 else:
687 696 odict[o] = a
688 697
689 698 # Prepare opts,args for return
690 699 opts = Struct(odict)
691 700 if mode == 'string':
692 701 if preserve_non_opts:
693 702 args = remainder_arg_str.lstrip()
694 703 else:
695 704 args = " ".join(args)
696 705
697 706 return opts,args
698 707
699 708 def default_option(self, fn, optstr):
700 709 """Make an entry in the options_table for fn, with value optstr"""
701 710
702 711 if fn not in self.lsmagic():
703 712 error("%s is not a magic function" % fn)
704 713 self.options_table[fn] = optstr
705 714
706 715
707 716 class MagicAlias(object):
708 717 """An alias to another magic function.
709 718
710 719 An alias is determined by its magic name and magic kind. Lookup
711 720 is done at call time, so if the underlying magic changes the alias
712 721 will call the new function.
713 722
714 723 Use the :meth:`MagicsManager.register_alias` method or the
715 724 `%alias_magic` magic function to create and register a new alias.
716 725 """
717 726 def __init__(self, shell, magic_name, magic_kind, magic_params=None):
718 727 self.shell = shell
719 728 self.magic_name = magic_name
720 729 self.magic_params = magic_params
721 730 self.magic_kind = magic_kind
722 731
723 732 self.pretty_target = '%s%s' % (magic_escapes[self.magic_kind], self.magic_name)
724 733 self.__doc__ = "Alias for `%s`." % self.pretty_target
725 734
726 735 self._in_call = False
727 736
728 737 def __call__(self, *args, **kwargs):
729 738 """Call the magic alias."""
730 739 fn = self.shell.find_magic(self.magic_name, self.magic_kind)
731 740 if fn is None:
732 741 raise UsageError("Magic `%s` not found." % self.pretty_target)
733 742
734 743 # Protect against infinite recursion.
735 744 if self._in_call:
736 745 raise UsageError("Infinite recursion detected; "
737 746 "magic aliases cannot call themselves.")
738 747 self._in_call = True
739 748 try:
740 749 if self.magic_params:
741 750 args_list = list(args)
742 751 args_list[0] = self.magic_params + " " + args[0]
743 752 args = tuple(args_list)
744 753 return fn(*args, **kwargs)
745 754 finally:
746 755 self._in_call = False
@@ -1,1510 +1,1512 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Implementation of execution-related magic functions."""
3 3
4 4 # Copyright (c) IPython Development Team.
5 5 # Distributed under the terms of the Modified BSD License.
6 6
7 7
8 8 import ast
9 9 import bdb
10 10 import builtins as builtin_mod
11 11 import cProfile as profile
12 12 import gc
13 13 import itertools
14 14 import math
15 15 import os
16 16 import pstats
17 17 import re
18 18 import shlex
19 19 import sys
20 20 import time
21 21 import timeit
22 22 from ast import Module
23 23 from io import StringIO
24 24 from logging import error
25 25 from pathlib import Path
26 26 from pdb import Restart
27 27 from warnings import warn
28 28
29 29 from IPython.core import magic_arguments, oinspect, page
30 30 from IPython.core.error import UsageError
31 31 from IPython.core.macro import Macro
32 32 from IPython.core.magic import (
33 33 Magics,
34 34 cell_magic,
35 35 line_cell_magic,
36 36 line_magic,
37 37 magics_class,
38 38 needs_local_scope,
39 39 no_var_expand,
40 output_can_be_disabled,
40 41 on_off,
41 42 )
42 43 from IPython.testing.skipdoctest import skip_doctest
43 44 from IPython.utils.capture import capture_output
44 45 from IPython.utils.contexts import preserve_keys
45 46 from IPython.utils.ipstruct import Struct
46 47 from IPython.utils.module_paths import find_mod
47 48 from IPython.utils.path import get_py_filename, shellglob
48 49 from IPython.utils.timing import clock, clock2
49 50
50 51 #-----------------------------------------------------------------------------
51 52 # Magic implementation classes
52 53 #-----------------------------------------------------------------------------
53 54
54 55
55 56 class TimeitResult(object):
56 57 """
57 58 Object returned by the timeit magic with info about the run.
58 59
59 60 Contains the following attributes :
60 61
61 62 loops: (int) number of loops done per measurement
62 63 repeat: (int) number of times the measurement has been repeated
63 64 best: (float) best execution time / number
64 65 all_runs: (list of float) execution time of each run (in s)
65 66 compile_time: (float) time of statement compilation (s)
66 67
67 68 """
68 69 def __init__(self, loops, repeat, best, worst, all_runs, compile_time, precision):
69 70 self.loops = loops
70 71 self.repeat = repeat
71 72 self.best = best
72 73 self.worst = worst
73 74 self.all_runs = all_runs
74 75 self.compile_time = compile_time
75 76 self._precision = precision
76 77 self.timings = [ dt / self.loops for dt in all_runs]
77 78
78 79 @property
79 80 def average(self):
80 81 return math.fsum(self.timings) / len(self.timings)
81 82
82 83 @property
83 84 def stdev(self):
84 85 mean = self.average
85 86 return (math.fsum([(x - mean) ** 2 for x in self.timings]) / len(self.timings)) ** 0.5
86 87
87 88 def __str__(self):
88 89 pm = '+-'
89 90 if hasattr(sys.stdout, 'encoding') and sys.stdout.encoding:
90 91 try:
91 92 u'\xb1'.encode(sys.stdout.encoding)
92 93 pm = u'\xb1'
93 94 except:
94 95 pass
95 96 return "{mean} {pm} {std} per loop (mean {pm} std. dev. of {runs} run{run_plural}, {loops:,} loop{loop_plural} each)".format(
96 97 pm=pm,
97 98 runs=self.repeat,
98 99 loops=self.loops,
99 100 loop_plural="" if self.loops == 1 else "s",
100 101 run_plural="" if self.repeat == 1 else "s",
101 102 mean=_format_time(self.average, self._precision),
102 103 std=_format_time(self.stdev, self._precision),
103 104 )
104 105
105 106 def _repr_pretty_(self, p , cycle):
106 107 unic = self.__str__()
107 108 p.text(u'<TimeitResult : '+unic+u'>')
108 109
109 110
110 111 class TimeitTemplateFiller(ast.NodeTransformer):
111 112 """Fill in the AST template for timing execution.
112 113
113 114 This is quite closely tied to the template definition, which is in
114 115 :meth:`ExecutionMagics.timeit`.
115 116 """
116 117 def __init__(self, ast_setup, ast_stmt):
117 118 self.ast_setup = ast_setup
118 119 self.ast_stmt = ast_stmt
119 120
120 121 def visit_FunctionDef(self, node):
121 122 "Fill in the setup statement"
122 123 self.generic_visit(node)
123 124 if node.name == "inner":
124 125 node.body[:1] = self.ast_setup.body
125 126
126 127 return node
127 128
128 129 def visit_For(self, node):
129 130 "Fill in the statement to be timed"
130 131 if getattr(getattr(node.body[0], 'value', None), 'id', None) == 'stmt':
131 132 node.body = self.ast_stmt.body
132 133 return node
133 134
134 135
135 136 class Timer(timeit.Timer):
136 137 """Timer class that explicitly uses self.inner
137 138
138 139 which is an undocumented implementation detail of CPython,
139 140 not shared by PyPy.
140 141 """
141 142 # Timer.timeit copied from CPython 3.4.2
142 143 def timeit(self, number=timeit.default_number):
143 144 """Time 'number' executions of the main statement.
144 145
145 146 To be precise, this executes the setup statement once, and
146 147 then returns the time it takes to execute the main statement
147 148 a number of times, as a float measured in seconds. The
148 149 argument is the number of times through the loop, defaulting
149 150 to one million. The main statement, the setup statement and
150 151 the timer function to be used are passed to the constructor.
151 152 """
152 153 it = itertools.repeat(None, number)
153 154 gcold = gc.isenabled()
154 155 gc.disable()
155 156 try:
156 157 timing = self.inner(it, self.timer)
157 158 finally:
158 159 if gcold:
159 160 gc.enable()
160 161 return timing
161 162
162 163
163 164 @magics_class
164 165 class ExecutionMagics(Magics):
165 166 """Magics related to code execution, debugging, profiling, etc.
166 167
167 168 """
168 169
169 170 def __init__(self, shell):
170 171 super(ExecutionMagics, self).__init__(shell)
171 172 # Default execution function used to actually run user code.
172 173 self.default_runner = None
173 174
174 175 @skip_doctest
175 176 @no_var_expand
176 177 @line_cell_magic
177 178 def prun(self, parameter_s='', cell=None):
178 179
179 180 """Run a statement through the python code profiler.
180 181
181 182 Usage, in line mode:
182 183 %prun [options] statement
183 184
184 185 Usage, in cell mode:
185 186 %%prun [options] [statement]
186 187 code...
187 188 code...
188 189
189 190 In cell mode, the additional code lines are appended to the (possibly
190 191 empty) statement in the first line. Cell mode allows you to easily
191 192 profile multiline blocks without having to put them in a separate
192 193 function.
193 194
194 195 The given statement (which doesn't require quote marks) is run via the
195 196 python profiler in a manner similar to the profile.run() function.
196 197 Namespaces are internally managed to work correctly; profile.run
197 198 cannot be used in IPython because it makes certain assumptions about
198 199 namespaces which do not hold under IPython.
199 200
200 201 Options:
201 202
202 203 -l <limit>
203 204 you can place restrictions on what or how much of the
204 205 profile gets printed. The limit value can be:
205 206
206 207 * A string: only information for function names containing this string
207 208 is printed.
208 209
209 210 * An integer: only these many lines are printed.
210 211
211 212 * A float (between 0 and 1): this fraction of the report is printed
212 213 (for example, use a limit of 0.4 to see the topmost 40% only).
213 214
214 215 You can combine several limits with repeated use of the option. For
215 216 example, ``-l __init__ -l 5`` will print only the topmost 5 lines of
216 217 information about class constructors.
217 218
218 219 -r
219 220 return the pstats.Stats object generated by the profiling. This
220 221 object has all the information about the profile in it, and you can
221 222 later use it for further analysis or in other functions.
222 223
223 224 -s <key>
224 225 sort profile by given key. You can provide more than one key
225 226 by using the option several times: '-s key1 -s key2 -s key3...'. The
226 227 default sorting key is 'time'.
227 228
228 229 The following is copied verbatim from the profile documentation
229 230 referenced below:
230 231
231 232 When more than one key is provided, additional keys are used as
232 233 secondary criteria when the there is equality in all keys selected
233 234 before them.
234 235
235 236 Abbreviations can be used for any key names, as long as the
236 237 abbreviation is unambiguous. The following are the keys currently
237 238 defined:
238 239
239 240 ============ =====================
240 241 Valid Arg Meaning
241 242 ============ =====================
242 243 "calls" call count
243 244 "cumulative" cumulative time
244 245 "file" file name
245 246 "module" file name
246 247 "pcalls" primitive call count
247 248 "line" line number
248 249 "name" function name
249 250 "nfl" name/file/line
250 251 "stdname" standard name
251 252 "time" internal time
252 253 ============ =====================
253 254
254 255 Note that all sorts on statistics are in descending order (placing
255 256 most time consuming items first), where as name, file, and line number
256 257 searches are in ascending order (i.e., alphabetical). The subtle
257 258 distinction between "nfl" and "stdname" is that the standard name is a
258 259 sort of the name as printed, which means that the embedded line
259 260 numbers get compared in an odd way. For example, lines 3, 20, and 40
260 261 would (if the file names were the same) appear in the string order
261 262 "20" "3" and "40". In contrast, "nfl" does a numeric compare of the
262 263 line numbers. In fact, sort_stats("nfl") is the same as
263 264 sort_stats("name", "file", "line").
264 265
265 266 -T <filename>
266 267 save profile results as shown on screen to a text
267 268 file. The profile is still shown on screen.
268 269
269 270 -D <filename>
270 271 save (via dump_stats) profile statistics to given
271 272 filename. This data is in a format understood by the pstats module, and
272 273 is generated by a call to the dump_stats() method of profile
273 274 objects. The profile is still shown on screen.
274 275
275 276 -q
276 277 suppress output to the pager. Best used with -T and/or -D above.
277 278
278 279 If you want to run complete programs under the profiler's control, use
279 280 ``%run -p [prof_opts] filename.py [args to program]`` where prof_opts
280 281 contains profiler specific options as described here.
281 282
282 283 You can read the complete documentation for the profile module with::
283 284
284 285 In [1]: import profile; profile.help()
285 286
286 287 .. versionchanged:: 7.3
287 288 User variables are no longer expanded,
288 289 the magic line is always left unmodified.
289 290
290 291 """
291 292 opts, arg_str = self.parse_options(parameter_s, 'D:l:rs:T:q',
292 293 list_all=True, posix=False)
293 294 if cell is not None:
294 295 arg_str += '\n' + cell
295 296 arg_str = self.shell.transform_cell(arg_str)
296 297 return self._run_with_profiler(arg_str, opts, self.shell.user_ns)
297 298
298 299 def _run_with_profiler(self, code, opts, namespace):
299 300 """
300 301 Run `code` with profiler. Used by ``%prun`` and ``%run -p``.
301 302
302 303 Parameters
303 304 ----------
304 305 code : str
305 306 Code to be executed.
306 307 opts : Struct
307 308 Options parsed by `self.parse_options`.
308 309 namespace : dict
309 310 A dictionary for Python namespace (e.g., `self.shell.user_ns`).
310 311
311 312 """
312 313
313 314 # Fill default values for unspecified options:
314 315 opts.merge(Struct(D=[''], l=[], s=['time'], T=['']))
315 316
316 317 prof = profile.Profile()
317 318 try:
318 319 prof = prof.runctx(code, namespace, namespace)
319 320 sys_exit = ''
320 321 except SystemExit:
321 322 sys_exit = """*** SystemExit exception caught in code being profiled."""
322 323
323 324 stats = pstats.Stats(prof).strip_dirs().sort_stats(*opts.s)
324 325
325 326 lims = opts.l
326 327 if lims:
327 328 lims = [] # rebuild lims with ints/floats/strings
328 329 for lim in opts.l:
329 330 try:
330 331 lims.append(int(lim))
331 332 except ValueError:
332 333 try:
333 334 lims.append(float(lim))
334 335 except ValueError:
335 336 lims.append(lim)
336 337
337 338 # Trap output.
338 339 stdout_trap = StringIO()
339 340 stats_stream = stats.stream
340 341 try:
341 342 stats.stream = stdout_trap
342 343 stats.print_stats(*lims)
343 344 finally:
344 345 stats.stream = stats_stream
345 346
346 347 output = stdout_trap.getvalue()
347 348 output = output.rstrip()
348 349
349 350 if 'q' not in opts:
350 351 page.page(output)
351 352 print(sys_exit, end=' ')
352 353
353 354 dump_file = opts.D[0]
354 355 text_file = opts.T[0]
355 356 if dump_file:
356 357 prof.dump_stats(dump_file)
357 358 print(
358 359 f"\n*** Profile stats marshalled to file {repr(dump_file)}.{sys_exit}"
359 360 )
360 361 if text_file:
361 362 pfile = Path(text_file)
362 363 pfile.touch(exist_ok=True)
363 364 pfile.write_text(output, encoding="utf-8")
364 365
365 366 print(
366 367 f"\n*** Profile printout saved to text file {repr(text_file)}.{sys_exit}"
367 368 )
368 369
369 370 if 'r' in opts:
370 371 return stats
371 372
372 373 return None
373 374
374 375 @line_magic
375 376 def pdb(self, parameter_s=''):
376 377 """Control the automatic calling of the pdb interactive debugger.
377 378
378 379 Call as '%pdb on', '%pdb 1', '%pdb off' or '%pdb 0'. If called without
379 380 argument it works as a toggle.
380 381
381 382 When an exception is triggered, IPython can optionally call the
382 383 interactive pdb debugger after the traceback printout. %pdb toggles
383 384 this feature on and off.
384 385
385 386 The initial state of this feature is set in your configuration
386 387 file (the option is ``InteractiveShell.pdb``).
387 388
388 389 If you want to just activate the debugger AFTER an exception has fired,
389 390 without having to type '%pdb on' and rerunning your code, you can use
390 391 the %debug magic."""
391 392
392 393 par = parameter_s.strip().lower()
393 394
394 395 if par:
395 396 try:
396 397 new_pdb = {'off':0,'0':0,'on':1,'1':1}[par]
397 398 except KeyError:
398 399 print ('Incorrect argument. Use on/1, off/0, '
399 400 'or nothing for a toggle.')
400 401 return
401 402 else:
402 403 # toggle
403 404 new_pdb = not self.shell.call_pdb
404 405
405 406 # set on the shell
406 407 self.shell.call_pdb = new_pdb
407 408 print('Automatic pdb calling has been turned',on_off(new_pdb))
408 409
409 410 @magic_arguments.magic_arguments()
410 411 @magic_arguments.argument('--breakpoint', '-b', metavar='FILE:LINE',
411 412 help="""
412 413 Set break point at LINE in FILE.
413 414 """
414 415 )
415 416 @magic_arguments.argument('statement', nargs='*',
416 417 help="""
417 418 Code to run in debugger.
418 419 You can omit this in cell magic mode.
419 420 """
420 421 )
421 422 @no_var_expand
422 423 @line_cell_magic
423 424 def debug(self, line='', cell=None):
424 425 """Activate the interactive debugger.
425 426
426 427 This magic command support two ways of activating debugger.
427 428 One is to activate debugger before executing code. This way, you
428 429 can set a break point, to step through the code from the point.
429 430 You can use this mode by giving statements to execute and optionally
430 431 a breakpoint.
431 432
432 433 The other one is to activate debugger in post-mortem mode. You can
433 434 activate this mode simply running %debug without any argument.
434 435 If an exception has just occurred, this lets you inspect its stack
435 436 frames interactively. Note that this will always work only on the last
436 437 traceback that occurred, so you must call this quickly after an
437 438 exception that you wish to inspect has fired, because if another one
438 439 occurs, it clobbers the previous one.
439 440
440 441 If you want IPython to automatically do this on every exception, see
441 442 the %pdb magic for more details.
442 443
443 444 .. versionchanged:: 7.3
444 445 When running code, user variables are no longer expanded,
445 446 the magic line is always left unmodified.
446 447
447 448 """
448 449 args = magic_arguments.parse_argstring(self.debug, line)
449 450
450 451 if not (args.breakpoint or args.statement or cell):
451 452 self._debug_post_mortem()
452 453 elif not (args.breakpoint or cell):
453 454 # If there is no breakpoints, the line is just code to execute
454 455 self._debug_exec(line, None)
455 456 else:
456 457 # Here we try to reconstruct the code from the output of
457 458 # parse_argstring. This might not work if the code has spaces
458 459 # For example this fails for `print("a b")`
459 460 code = "\n".join(args.statement)
460 461 if cell:
461 462 code += "\n" + cell
462 463 self._debug_exec(code, args.breakpoint)
463 464
464 465 def _debug_post_mortem(self):
465 466 self.shell.debugger(force=True)
466 467
467 468 def _debug_exec(self, code, breakpoint):
468 469 if breakpoint:
469 470 (filename, bp_line) = breakpoint.rsplit(':', 1)
470 471 bp_line = int(bp_line)
471 472 else:
472 473 (filename, bp_line) = (None, None)
473 474 self._run_with_debugger(code, self.shell.user_ns, filename, bp_line)
474 475
475 476 @line_magic
476 477 def tb(self, s):
477 478 """Print the last traceback.
478 479
479 480 Optionally, specify an exception reporting mode, tuning the
480 481 verbosity of the traceback. By default the currently-active exception
481 482 mode is used. See %xmode for changing exception reporting modes.
482 483
483 484 Valid modes: Plain, Context, Verbose, and Minimal.
484 485 """
485 486 interactive_tb = self.shell.InteractiveTB
486 487 if s:
487 488 # Switch exception reporting mode for this one call.
488 489 # Ensure it is switched back.
489 490 def xmode_switch_err(name):
490 491 warn('Error changing %s exception modes.\n%s' %
491 492 (name,sys.exc_info()[1]))
492 493
493 494 new_mode = s.strip().capitalize()
494 495 original_mode = interactive_tb.mode
495 496 try:
496 497 try:
497 498 interactive_tb.set_mode(mode=new_mode)
498 499 except Exception:
499 500 xmode_switch_err('user')
500 501 else:
501 502 self.shell.showtraceback()
502 503 finally:
503 504 interactive_tb.set_mode(mode=original_mode)
504 505 else:
505 506 self.shell.showtraceback()
506 507
507 508 @skip_doctest
508 509 @line_magic
509 510 def run(self, parameter_s='', runner=None,
510 511 file_finder=get_py_filename):
511 512 """Run the named file inside IPython as a program.
512 513
513 514 Usage::
514 515
515 516 %run [-n -i -e -G]
516 517 [( -t [-N<N>] | -d [-b<N>] | -p [profile options] )]
517 518 ( -m mod | filename ) [args]
518 519
519 520 The filename argument should be either a pure Python script (with
520 521 extension ``.py``), or a file with custom IPython syntax (such as
521 522 magics). If the latter, the file can be either a script with ``.ipy``
522 523 extension, or a Jupyter notebook with ``.ipynb`` extension. When running
523 524 a Jupyter notebook, the output from print statements and other
524 525 displayed objects will appear in the terminal (even matplotlib figures
525 526 will open, if a terminal-compliant backend is being used). Note that,
526 527 at the system command line, the ``jupyter run`` command offers similar
527 528 functionality for executing notebooks (albeit currently with some
528 529 differences in supported options).
529 530
530 531 Parameters after the filename are passed as command-line arguments to
531 532 the program (put in sys.argv). Then, control returns to IPython's
532 533 prompt.
533 534
534 535 This is similar to running at a system prompt ``python file args``,
535 536 but with the advantage of giving you IPython's tracebacks, and of
536 537 loading all variables into your interactive namespace for further use
537 538 (unless -p is used, see below).
538 539
539 540 The file is executed in a namespace initially consisting only of
540 541 ``__name__=='__main__'`` and sys.argv constructed as indicated. It thus
541 542 sees its environment as if it were being run as a stand-alone program
542 543 (except for sharing global objects such as previously imported
543 544 modules). But after execution, the IPython interactive namespace gets
544 545 updated with all variables defined in the program (except for __name__
545 546 and sys.argv). This allows for very convenient loading of code for
546 547 interactive work, while giving each program a 'clean sheet' to run in.
547 548
548 549 Arguments are expanded using shell-like glob match. Patterns
549 550 '*', '?', '[seq]' and '[!seq]' can be used. Additionally,
550 551 tilde '~' will be expanded into user's home directory. Unlike
551 552 real shells, quotation does not suppress expansions. Use
552 553 *two* back slashes (e.g. ``\\\\*``) to suppress expansions.
553 554 To completely disable these expansions, you can use -G flag.
554 555
555 556 On Windows systems, the use of single quotes `'` when specifying
556 557 a file is not supported. Use double quotes `"`.
557 558
558 559 Options:
559 560
560 561 -n
561 562 __name__ is NOT set to '__main__', but to the running file's name
562 563 without extension (as python does under import). This allows running
563 564 scripts and reloading the definitions in them without calling code
564 565 protected by an ``if __name__ == "__main__"`` clause.
565 566
566 567 -i
567 568 run the file in IPython's namespace instead of an empty one. This
568 569 is useful if you are experimenting with code written in a text editor
569 570 which depends on variables defined interactively.
570 571
571 572 -e
572 573 ignore sys.exit() calls or SystemExit exceptions in the script
573 574 being run. This is particularly useful if IPython is being used to
574 575 run unittests, which always exit with a sys.exit() call. In such
575 576 cases you are interested in the output of the test results, not in
576 577 seeing a traceback of the unittest module.
577 578
578 579 -t
579 580 print timing information at the end of the run. IPython will give
580 581 you an estimated CPU time consumption for your script, which under
581 582 Unix uses the resource module to avoid the wraparound problems of
582 583 time.clock(). Under Unix, an estimate of time spent on system tasks
583 584 is also given (for Windows platforms this is reported as 0.0).
584 585
585 586 If -t is given, an additional ``-N<N>`` option can be given, where <N>
586 587 must be an integer indicating how many times you want the script to
587 588 run. The final timing report will include total and per run results.
588 589
589 590 For example (testing the script uniq_stable.py)::
590 591
591 592 In [1]: run -t uniq_stable
592 593
593 594 IPython CPU timings (estimated):
594 595 User : 0.19597 s.
595 596 System: 0.0 s.
596 597
597 598 In [2]: run -t -N5 uniq_stable
598 599
599 600 IPython CPU timings (estimated):
600 601 Total runs performed: 5
601 602 Times : Total Per run
602 603 User : 0.910862 s, 0.1821724 s.
603 604 System: 0.0 s, 0.0 s.
604 605
605 606 -d
606 607 run your program under the control of pdb, the Python debugger.
607 608 This allows you to execute your program step by step, watch variables,
608 609 etc. Internally, what IPython does is similar to calling::
609 610
610 611 pdb.run('execfile("YOURFILENAME")')
611 612
612 613 with a breakpoint set on line 1 of your file. You can change the line
613 614 number for this automatic breakpoint to be <N> by using the -bN option
614 615 (where N must be an integer). For example::
615 616
616 617 %run -d -b40 myscript
617 618
618 619 will set the first breakpoint at line 40 in myscript.py. Note that
619 620 the first breakpoint must be set on a line which actually does
620 621 something (not a comment or docstring) for it to stop execution.
621 622
622 623 Or you can specify a breakpoint in a different file::
623 624
624 625 %run -d -b myotherfile.py:20 myscript
625 626
626 627 When the pdb debugger starts, you will see a (Pdb) prompt. You must
627 628 first enter 'c' (without quotes) to start execution up to the first
628 629 breakpoint.
629 630
630 631 Entering 'help' gives information about the use of the debugger. You
631 632 can easily see pdb's full documentation with "import pdb;pdb.help()"
632 633 at a prompt.
633 634
634 635 -p
635 636 run program under the control of the Python profiler module (which
636 637 prints a detailed report of execution times, function calls, etc).
637 638
638 639 You can pass other options after -p which affect the behavior of the
639 640 profiler itself. See the docs for %prun for details.
640 641
641 642 In this mode, the program's variables do NOT propagate back to the
642 643 IPython interactive namespace (because they remain in the namespace
643 644 where the profiler executes them).
644 645
645 646 Internally this triggers a call to %prun, see its documentation for
646 647 details on the options available specifically for profiling.
647 648
648 649 There is one special usage for which the text above doesn't apply:
649 650 if the filename ends with .ipy[nb], the file is run as ipython script,
650 651 just as if the commands were written on IPython prompt.
651 652
652 653 -m
653 654 specify module name to load instead of script path. Similar to
654 655 the -m option for the python interpreter. Use this option last if you
655 656 want to combine with other %run options. Unlike the python interpreter
656 657 only source modules are allowed no .pyc or .pyo files.
657 658 For example::
658 659
659 660 %run -m example
660 661
661 662 will run the example module.
662 663
663 664 -G
664 665 disable shell-like glob expansion of arguments.
665 666
666 667 """
667 668
668 669 # Logic to handle issue #3664
669 670 # Add '--' after '-m <module_name>' to ignore additional args passed to a module.
670 671 if '-m' in parameter_s and '--' not in parameter_s:
671 672 argv = shlex.split(parameter_s, posix=(os.name == 'posix'))
672 673 for idx, arg in enumerate(argv):
673 674 if arg and arg.startswith('-') and arg != '-':
674 675 if arg == '-m':
675 676 argv.insert(idx + 2, '--')
676 677 break
677 678 else:
678 679 # Positional arg, break
679 680 break
680 681 parameter_s = ' '.join(shlex.quote(arg) for arg in argv)
681 682
682 683 # get arguments and set sys.argv for program to be run.
683 684 opts, arg_lst = self.parse_options(parameter_s,
684 685 'nidtN:b:pD:l:rs:T:em:G',
685 686 mode='list', list_all=1)
686 687 if "m" in opts:
687 688 modulename = opts["m"][0]
688 689 modpath = find_mod(modulename)
689 690 if modpath is None:
690 691 msg = '%r is not a valid modulename on sys.path'%modulename
691 692 raise Exception(msg)
692 693 arg_lst = [modpath] + arg_lst
693 694 try:
694 695 fpath = None # initialize to make sure fpath is in scope later
695 696 fpath = arg_lst[0]
696 697 filename = file_finder(fpath)
697 698 except IndexError as e:
698 699 msg = 'you must provide at least a filename.'
699 700 raise Exception(msg) from e
700 701 except IOError as e:
701 702 try:
702 703 msg = str(e)
703 704 except UnicodeError:
704 705 msg = e.message
705 706 if os.name == 'nt' and re.match(r"^'.*'$",fpath):
706 707 warn('For Windows, use double quotes to wrap a filename: %run "mypath\\myfile.py"')
707 708 raise Exception(msg) from e
708 709 except TypeError:
709 710 if fpath in sys.meta_path:
710 711 filename = ""
711 712 else:
712 713 raise
713 714
714 715 if filename.lower().endswith(('.ipy', '.ipynb')):
715 716 with preserve_keys(self.shell.user_ns, '__file__'):
716 717 self.shell.user_ns['__file__'] = filename
717 718 self.shell.safe_execfile_ipy(filename, raise_exceptions=True)
718 719 return
719 720
720 721 # Control the response to exit() calls made by the script being run
721 722 exit_ignore = 'e' in opts
722 723
723 724 # Make sure that the running script gets a proper sys.argv as if it
724 725 # were run from a system shell.
725 726 save_argv = sys.argv # save it for later restoring
726 727
727 728 if 'G' in opts:
728 729 args = arg_lst[1:]
729 730 else:
730 731 # tilde and glob expansion
731 732 args = shellglob(map(os.path.expanduser, arg_lst[1:]))
732 733
733 734 sys.argv = [filename] + args # put in the proper filename
734 735
735 736 if 'n' in opts:
736 737 name = Path(filename).stem
737 738 else:
738 739 name = '__main__'
739 740
740 741 if 'i' in opts:
741 742 # Run in user's interactive namespace
742 743 prog_ns = self.shell.user_ns
743 744 __name__save = self.shell.user_ns['__name__']
744 745 prog_ns['__name__'] = name
745 746 main_mod = self.shell.user_module
746 747
747 748 # Since '%run foo' emulates 'python foo.py' at the cmd line, we must
748 749 # set the __file__ global in the script's namespace
749 750 # TK: Is this necessary in interactive mode?
750 751 prog_ns['__file__'] = filename
751 752 else:
752 753 # Run in a fresh, empty namespace
753 754
754 755 # The shell MUST hold a reference to prog_ns so after %run
755 756 # exits, the python deletion mechanism doesn't zero it out
756 757 # (leaving dangling references). See interactiveshell for details
757 758 main_mod = self.shell.new_main_mod(filename, name)
758 759 prog_ns = main_mod.__dict__
759 760
760 761 # pickle fix. See interactiveshell for an explanation. But we need to
761 762 # make sure that, if we overwrite __main__, we replace it at the end
762 763 main_mod_name = prog_ns['__name__']
763 764
764 765 if main_mod_name == '__main__':
765 766 restore_main = sys.modules['__main__']
766 767 else:
767 768 restore_main = False
768 769
769 770 # This needs to be undone at the end to prevent holding references to
770 771 # every single object ever created.
771 772 sys.modules[main_mod_name] = main_mod
772 773
773 774 if 'p' in opts or 'd' in opts:
774 775 if 'm' in opts:
775 776 code = 'run_module(modulename, prog_ns)'
776 777 code_ns = {
777 778 'run_module': self.shell.safe_run_module,
778 779 'prog_ns': prog_ns,
779 780 'modulename': modulename,
780 781 }
781 782 else:
782 783 if 'd' in opts:
783 784 # allow exceptions to raise in debug mode
784 785 code = 'execfile(filename, prog_ns, raise_exceptions=True)'
785 786 else:
786 787 code = 'execfile(filename, prog_ns)'
787 788 code_ns = {
788 789 'execfile': self.shell.safe_execfile,
789 790 'prog_ns': prog_ns,
790 791 'filename': get_py_filename(filename),
791 792 }
792 793
793 794 try:
794 795 stats = None
795 796 if 'p' in opts:
796 797 stats = self._run_with_profiler(code, opts, code_ns)
797 798 else:
798 799 if 'd' in opts:
799 800 bp_file, bp_line = parse_breakpoint(
800 801 opts.get('b', ['1'])[0], filename)
801 802 self._run_with_debugger(
802 803 code, code_ns, filename, bp_line, bp_file)
803 804 else:
804 805 if 'm' in opts:
805 806 def run():
806 807 self.shell.safe_run_module(modulename, prog_ns)
807 808 else:
808 809 if runner is None:
809 810 runner = self.default_runner
810 811 if runner is None:
811 812 runner = self.shell.safe_execfile
812 813
813 814 def run():
814 815 runner(filename, prog_ns, prog_ns,
815 816 exit_ignore=exit_ignore)
816 817
817 818 if 't' in opts:
818 819 # timed execution
819 820 try:
820 821 nruns = int(opts['N'][0])
821 822 if nruns < 1:
822 823 error('Number of runs must be >=1')
823 824 return
824 825 except (KeyError):
825 826 nruns = 1
826 827 self._run_with_timing(run, nruns)
827 828 else:
828 829 # regular execution
829 830 run()
830 831
831 832 if 'i' in opts:
832 833 self.shell.user_ns['__name__'] = __name__save
833 834 else:
834 835 # update IPython interactive namespace
835 836
836 837 # Some forms of read errors on the file may mean the
837 838 # __name__ key was never set; using pop we don't have to
838 839 # worry about a possible KeyError.
839 840 prog_ns.pop('__name__', None)
840 841
841 842 with preserve_keys(self.shell.user_ns, '__file__'):
842 843 self.shell.user_ns.update(prog_ns)
843 844 finally:
844 845 # It's a bit of a mystery why, but __builtins__ can change from
845 846 # being a module to becoming a dict missing some key data after
846 847 # %run. As best I can see, this is NOT something IPython is doing
847 848 # at all, and similar problems have been reported before:
848 849 # http://coding.derkeiler.com/Archive/Python/comp.lang.python/2004-10/0188.html
849 850 # Since this seems to be done by the interpreter itself, the best
850 851 # we can do is to at least restore __builtins__ for the user on
851 852 # exit.
852 853 self.shell.user_ns['__builtins__'] = builtin_mod
853 854
854 855 # Ensure key global structures are restored
855 856 sys.argv = save_argv
856 857 if restore_main:
857 858 sys.modules['__main__'] = restore_main
858 859 if '__mp_main__' in sys.modules:
859 860 sys.modules['__mp_main__'] = restore_main
860 861 else:
861 862 # Remove from sys.modules the reference to main_mod we'd
862 863 # added. Otherwise it will trap references to objects
863 864 # contained therein.
864 865 del sys.modules[main_mod_name]
865 866
866 867 return stats
867 868
868 869 def _run_with_debugger(self, code, code_ns, filename=None,
869 870 bp_line=None, bp_file=None):
870 871 """
871 872 Run `code` in debugger with a break point.
872 873
873 874 Parameters
874 875 ----------
875 876 code : str
876 877 Code to execute.
877 878 code_ns : dict
878 879 A namespace in which `code` is executed.
879 880 filename : str
880 881 `code` is ran as if it is in `filename`.
881 882 bp_line : int, optional
882 883 Line number of the break point.
883 884 bp_file : str, optional
884 885 Path to the file in which break point is specified.
885 886 `filename` is used if not given.
886 887
887 888 Raises
888 889 ------
889 890 UsageError
890 891 If the break point given by `bp_line` is not valid.
891 892
892 893 """
893 894 deb = self.shell.InteractiveTB.pdb
894 895 if not deb:
895 896 self.shell.InteractiveTB.pdb = self.shell.InteractiveTB.debugger_cls()
896 897 deb = self.shell.InteractiveTB.pdb
897 898
898 899 # deb.checkline() fails if deb.curframe exists but is None; it can
899 900 # handle it not existing. https://github.com/ipython/ipython/issues/10028
900 901 if hasattr(deb, 'curframe'):
901 902 del deb.curframe
902 903
903 904 # reset Breakpoint state, which is moronically kept
904 905 # in a class
905 906 bdb.Breakpoint.next = 1
906 907 bdb.Breakpoint.bplist = {}
907 908 bdb.Breakpoint.bpbynumber = [None]
908 909 deb.clear_all_breaks()
909 910 if bp_line is not None:
910 911 # Set an initial breakpoint to stop execution
911 912 maxtries = 10
912 913 bp_file = bp_file or filename
913 914 checkline = deb.checkline(bp_file, bp_line)
914 915 if not checkline:
915 916 for bp in range(bp_line + 1, bp_line + maxtries + 1):
916 917 if deb.checkline(bp_file, bp):
917 918 break
918 919 else:
919 920 msg = ("\nI failed to find a valid line to set "
920 921 "a breakpoint\n"
921 922 "after trying up to line: %s.\n"
922 923 "Please set a valid breakpoint manually "
923 924 "with the -b option." % bp)
924 925 raise UsageError(msg)
925 926 # if we find a good linenumber, set the breakpoint
926 927 deb.do_break('%s:%s' % (bp_file, bp_line))
927 928
928 929 if filename:
929 930 # Mimic Pdb._runscript(...)
930 931 deb._wait_for_mainpyfile = True
931 932 deb.mainpyfile = deb.canonic(filename)
932 933
933 934 # Start file run
934 935 print("NOTE: Enter 'c' at the %s prompt to continue execution." % deb.prompt)
935 936 try:
936 937 if filename:
937 938 # save filename so it can be used by methods on the deb object
938 939 deb._exec_filename = filename
939 940 while True:
940 941 try:
941 942 trace = sys.gettrace()
942 943 deb.run(code, code_ns)
943 944 except Restart:
944 945 print("Restarting")
945 946 if filename:
946 947 deb._wait_for_mainpyfile = True
947 948 deb.mainpyfile = deb.canonic(filename)
948 949 continue
949 950 else:
950 951 break
951 952 finally:
952 953 sys.settrace(trace)
953 954
954 955
955 956 except:
956 957 etype, value, tb = sys.exc_info()
957 958 # Skip three frames in the traceback: the %run one,
958 959 # one inside bdb.py, and the command-line typed by the
959 960 # user (run by exec in pdb itself).
960 961 self.shell.InteractiveTB(etype, value, tb, tb_offset=3)
961 962
962 963 @staticmethod
963 964 def _run_with_timing(run, nruns):
964 965 """
965 966 Run function `run` and print timing information.
966 967
967 968 Parameters
968 969 ----------
969 970 run : callable
970 971 Any callable object which takes no argument.
971 972 nruns : int
972 973 Number of times to execute `run`.
973 974
974 975 """
975 976 twall0 = time.perf_counter()
976 977 if nruns == 1:
977 978 t0 = clock2()
978 979 run()
979 980 t1 = clock2()
980 981 t_usr = t1[0] - t0[0]
981 982 t_sys = t1[1] - t0[1]
982 983 print("\nIPython CPU timings (estimated):")
983 984 print(" User : %10.2f s." % t_usr)
984 985 print(" System : %10.2f s." % t_sys)
985 986 else:
986 987 runs = range(nruns)
987 988 t0 = clock2()
988 989 for nr in runs:
989 990 run()
990 991 t1 = clock2()
991 992 t_usr = t1[0] - t0[0]
992 993 t_sys = t1[1] - t0[1]
993 994 print("\nIPython CPU timings (estimated):")
994 995 print("Total runs performed:", nruns)
995 996 print(" Times : %10s %10s" % ('Total', 'Per run'))
996 997 print(" User : %10.2f s, %10.2f s." % (t_usr, t_usr / nruns))
997 998 print(" System : %10.2f s, %10.2f s." % (t_sys, t_sys / nruns))
998 999 twall1 = time.perf_counter()
999 1000 print("Wall time: %10.2f s." % (twall1 - twall0))
1000 1001
1001 1002 @skip_doctest
1002 1003 @no_var_expand
1003 1004 @line_cell_magic
1004 1005 @needs_local_scope
1005 1006 def timeit(self, line='', cell=None, local_ns=None):
1006 1007 """Time execution of a Python statement or expression
1007 1008
1008 1009 Usage, in line mode:
1009 1010 %timeit [-n<N> -r<R> [-t|-c] -q -p<P> -o] statement
1010 1011 or in cell mode:
1011 1012 %%timeit [-n<N> -r<R> [-t|-c] -q -p<P> -o] setup_code
1012 1013 code
1013 1014 code...
1014 1015
1015 1016 Time execution of a Python statement or expression using the timeit
1016 1017 module. This function can be used both as a line and cell magic:
1017 1018
1018 1019 - In line mode you can time a single-line statement (though multiple
1019 1020 ones can be chained with using semicolons).
1020 1021
1021 1022 - In cell mode, the statement in the first line is used as setup code
1022 1023 (executed but not timed) and the body of the cell is timed. The cell
1023 1024 body has access to any variables created in the setup code.
1024 1025
1025 1026 Options:
1026 1027 -n<N>: execute the given statement <N> times in a loop. If <N> is not
1027 1028 provided, <N> is determined so as to get sufficient accuracy.
1028 1029
1029 1030 -r<R>: number of repeats <R>, each consisting of <N> loops, and take the
1030 1031 best result.
1031 1032 Default: 7
1032 1033
1033 1034 -t: use time.time to measure the time, which is the default on Unix.
1034 1035 This function measures wall time.
1035 1036
1036 1037 -c: use time.clock to measure the time, which is the default on
1037 1038 Windows and measures wall time. On Unix, resource.getrusage is used
1038 1039 instead and returns the CPU user time.
1039 1040
1040 1041 -p<P>: use a precision of <P> digits to display the timing result.
1041 1042 Default: 3
1042 1043
1043 1044 -q: Quiet, do not print result.
1044 1045
1045 1046 -o: return a TimeitResult that can be stored in a variable to inspect
1046 1047 the result in more details.
1047 1048
1048 1049 .. versionchanged:: 7.3
1049 1050 User variables are no longer expanded,
1050 1051 the magic line is always left unmodified.
1051 1052
1052 1053 Examples
1053 1054 --------
1054 1055 ::
1055 1056
1056 1057 In [1]: %timeit pass
1057 1058 8.26 ns Β± 0.12 ns per loop (mean Β± std. dev. of 7 runs, 100000000 loops each)
1058 1059
1059 1060 In [2]: u = None
1060 1061
1061 1062 In [3]: %timeit u is None
1062 1063 29.9 ns Β± 0.643 ns per loop (mean Β± std. dev. of 7 runs, 10000000 loops each)
1063 1064
1064 1065 In [4]: %timeit -r 4 u == None
1065 1066
1066 1067 In [5]: import time
1067 1068
1068 1069 In [6]: %timeit -n1 time.sleep(2)
1069 1070
1070 1071 The times reported by %timeit will be slightly higher than those
1071 1072 reported by the timeit.py script when variables are accessed. This is
1072 1073 due to the fact that %timeit executes the statement in the namespace
1073 1074 of the shell, compared with timeit.py, which uses a single setup
1074 1075 statement to import function or create variables. Generally, the bias
1075 1076 does not matter as long as results from timeit.py are not mixed with
1076 1077 those from %timeit."""
1077 1078
1078 1079 opts, stmt = self.parse_options(
1079 1080 line, "n:r:tcp:qo", posix=False, strict=False, preserve_non_opts=True
1080 1081 )
1081 1082 if stmt == "" and cell is None:
1082 1083 return
1083 1084
1084 1085 timefunc = timeit.default_timer
1085 1086 number = int(getattr(opts, "n", 0))
1086 1087 default_repeat = 7 if timeit.default_repeat < 7 else timeit.default_repeat
1087 1088 repeat = int(getattr(opts, "r", default_repeat))
1088 1089 precision = int(getattr(opts, "p", 3))
1089 1090 quiet = 'q' in opts
1090 1091 return_result = 'o' in opts
1091 1092 if hasattr(opts, "t"):
1092 1093 timefunc = time.time
1093 1094 if hasattr(opts, "c"):
1094 1095 timefunc = clock
1095 1096
1096 1097 timer = Timer(timer=timefunc)
1097 1098 # this code has tight coupling to the inner workings of timeit.Timer,
1098 1099 # but is there a better way to achieve that the code stmt has access
1099 1100 # to the shell namespace?
1100 1101 transform = self.shell.transform_cell
1101 1102
1102 1103 if cell is None:
1103 1104 # called as line magic
1104 1105 ast_setup = self.shell.compile.ast_parse("pass")
1105 1106 ast_stmt = self.shell.compile.ast_parse(transform(stmt))
1106 1107 else:
1107 1108 ast_setup = self.shell.compile.ast_parse(transform(stmt))
1108 1109 ast_stmt = self.shell.compile.ast_parse(transform(cell))
1109 1110
1110 1111 ast_setup = self.shell.transform_ast(ast_setup)
1111 1112 ast_stmt = self.shell.transform_ast(ast_stmt)
1112 1113
1113 1114 # Check that these compile to valid Python code *outside* the timer func
1114 1115 # Invalid code may become valid when put inside the function & loop,
1115 1116 # which messes up error messages.
1116 1117 # https://github.com/ipython/ipython/issues/10636
1117 1118 self.shell.compile(ast_setup, "<magic-timeit-setup>", "exec")
1118 1119 self.shell.compile(ast_stmt, "<magic-timeit-stmt>", "exec")
1119 1120
1120 1121 # This codestring is taken from timeit.template - we fill it in as an
1121 1122 # AST, so that we can apply our AST transformations to the user code
1122 1123 # without affecting the timing code.
1123 1124 timeit_ast_template = ast.parse('def inner(_it, _timer):\n'
1124 1125 ' setup\n'
1125 1126 ' _t0 = _timer()\n'
1126 1127 ' for _i in _it:\n'
1127 1128 ' stmt\n'
1128 1129 ' _t1 = _timer()\n'
1129 1130 ' return _t1 - _t0\n')
1130 1131
1131 1132 timeit_ast = TimeitTemplateFiller(ast_setup, ast_stmt).visit(timeit_ast_template)
1132 1133 timeit_ast = ast.fix_missing_locations(timeit_ast)
1133 1134
1134 1135 # Track compilation time so it can be reported if too long
1135 1136 # Minimum time above which compilation time will be reported
1136 1137 tc_min = 0.1
1137 1138
1138 1139 t0 = clock()
1139 1140 code = self.shell.compile(timeit_ast, "<magic-timeit>", "exec")
1140 1141 tc = clock()-t0
1141 1142
1142 1143 ns = {}
1143 1144 glob = self.shell.user_ns
1144 1145 # handles global vars with same name as local vars. We store them in conflict_globs.
1145 1146 conflict_globs = {}
1146 1147 if local_ns and cell is None:
1147 1148 for var_name, var_val in glob.items():
1148 1149 if var_name in local_ns:
1149 1150 conflict_globs[var_name] = var_val
1150 1151 glob.update(local_ns)
1151 1152
1152 1153 exec(code, glob, ns)
1153 1154 timer.inner = ns["inner"]
1154 1155
1155 1156 # This is used to check if there is a huge difference between the
1156 1157 # best and worst timings.
1157 1158 # Issue: https://github.com/ipython/ipython/issues/6471
1158 1159 if number == 0:
1159 1160 # determine number so that 0.2 <= total time < 2.0
1160 1161 for index in range(0, 10):
1161 1162 number = 10 ** index
1162 1163 time_number = timer.timeit(number)
1163 1164 if time_number >= 0.2:
1164 1165 break
1165 1166
1166 1167 all_runs = timer.repeat(repeat, number)
1167 1168 best = min(all_runs) / number
1168 1169 worst = max(all_runs) / number
1169 1170 timeit_result = TimeitResult(number, repeat, best, worst, all_runs, tc, precision)
1170 1171
1171 1172 # Restore global vars from conflict_globs
1172 1173 if conflict_globs:
1173 1174 glob.update(conflict_globs)
1174 1175
1175 1176 if not quiet :
1176 1177 # Check best timing is greater than zero to avoid a
1177 1178 # ZeroDivisionError.
1178 1179 # In cases where the slowest timing is lesser than a microsecond
1179 1180 # we assume that it does not really matter if the fastest
1180 1181 # timing is 4 times faster than the slowest timing or not.
1181 1182 if worst > 4 * best and best > 0 and worst > 1e-6:
1182 1183 print("The slowest run took %0.2f times longer than the "
1183 1184 "fastest. This could mean that an intermediate result "
1184 1185 "is being cached." % (worst / best))
1185 1186
1186 1187 print( timeit_result )
1187 1188
1188 1189 if tc > tc_min:
1189 1190 print("Compiler time: %.2f s" % tc)
1190 1191 if return_result:
1191 1192 return timeit_result
1192 1193
1193 1194 @skip_doctest
1194 1195 @no_var_expand
1195 1196 @needs_local_scope
1196 1197 @line_cell_magic
1198 @output_can_be_disabled
1197 1199 def time(self,line='', cell=None, local_ns=None):
1198 1200 """Time execution of a Python statement or expression.
1199 1201
1200 1202 The CPU and wall clock times are printed, and the value of the
1201 1203 expression (if any) is returned. Note that under Win32, system time
1202 1204 is always reported as 0, since it can not be measured.
1203 1205
1204 1206 This function can be used both as a line and cell magic:
1205 1207
1206 1208 - In line mode you can time a single-line statement (though multiple
1207 1209 ones can be chained with using semicolons).
1208 1210
1209 1211 - In cell mode, you can time the cell body (a directly
1210 1212 following statement raises an error).
1211 1213
1212 1214 This function provides very basic timing functionality. Use the timeit
1213 1215 magic for more control over the measurement.
1214 1216
1215 1217 .. versionchanged:: 7.3
1216 1218 User variables are no longer expanded,
1217 1219 the magic line is always left unmodified.
1218 1220
1219 1221 Examples
1220 1222 --------
1221 1223 ::
1222 1224
1223 1225 In [1]: %time 2**128
1224 1226 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1225 1227 Wall time: 0.00
1226 1228 Out[1]: 340282366920938463463374607431768211456L
1227 1229
1228 1230 In [2]: n = 1000000
1229 1231
1230 1232 In [3]: %time sum(range(n))
1231 1233 CPU times: user 1.20 s, sys: 0.05 s, total: 1.25 s
1232 1234 Wall time: 1.37
1233 1235 Out[3]: 499999500000L
1234 1236
1235 1237 In [4]: %time print 'hello world'
1236 1238 hello world
1237 1239 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1238 1240 Wall time: 0.00
1239 1241
1240 1242 .. note::
1241 1243 The time needed by Python to compile the given expression will be
1242 1244 reported if it is more than 0.1s.
1243 1245
1244 1246 In the example below, the actual exponentiation is done by Python
1245 1247 at compilation time, so while the expression can take a noticeable
1246 1248 amount of time to compute, that time is purely due to the
1247 1249 compilation::
1248 1250
1249 1251 In [5]: %time 3**9999;
1250 1252 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1251 1253 Wall time: 0.00 s
1252 1254
1253 1255 In [6]: %time 3**999999;
1254 1256 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
1255 1257 Wall time: 0.00 s
1256 1258 Compiler : 0.78 s
1257 1259 """
1258 1260 # fail immediately if the given expression can't be compiled
1259 1261
1260 1262 if line and cell:
1261 1263 raise UsageError("Can't use statement directly after '%%time'!")
1262 1264
1263 1265 if cell:
1264 1266 expr = self.shell.transform_cell(cell)
1265 1267 else:
1266 1268 expr = self.shell.transform_cell(line)
1267 1269
1268 1270 # Minimum time above which parse time will be reported
1269 1271 tp_min = 0.1
1270 1272
1271 1273 t0 = clock()
1272 1274 expr_ast = self.shell.compile.ast_parse(expr)
1273 1275 tp = clock()-t0
1274 1276
1275 1277 # Apply AST transformations
1276 1278 expr_ast = self.shell.transform_ast(expr_ast)
1277 1279
1278 1280 # Minimum time above which compilation time will be reported
1279 1281 tc_min = 0.1
1280 1282
1281 1283 expr_val=None
1282 1284 if len(expr_ast.body)==1 and isinstance(expr_ast.body[0], ast.Expr):
1283 1285 mode = 'eval'
1284 1286 source = '<timed eval>'
1285 1287 expr_ast = ast.Expression(expr_ast.body[0].value)
1286 1288 else:
1287 1289 mode = 'exec'
1288 1290 source = '<timed exec>'
1289 1291 # multi-line %%time case
1290 1292 if len(expr_ast.body) > 1 and isinstance(expr_ast.body[-1], ast.Expr):
1291 1293 expr_val= expr_ast.body[-1]
1292 1294 expr_ast = expr_ast.body[:-1]
1293 1295 expr_ast = Module(expr_ast, [])
1294 1296 expr_val = ast.Expression(expr_val.value)
1295 1297
1296 1298 t0 = clock()
1297 1299 code = self.shell.compile(expr_ast, source, mode)
1298 1300 tc = clock()-t0
1299 1301
1300 1302 # skew measurement as little as possible
1301 1303 glob = self.shell.user_ns
1302 1304 wtime = time.time
1303 1305 # time execution
1304 1306 wall_st = wtime()
1305 1307 if mode=='eval':
1306 1308 st = clock2()
1307 1309 try:
1308 1310 out = eval(code, glob, local_ns)
1309 1311 except:
1310 1312 self.shell.showtraceback()
1311 1313 return
1312 1314 end = clock2()
1313 1315 else:
1314 1316 st = clock2()
1315 1317 try:
1316 1318 exec(code, glob, local_ns)
1317 1319 out=None
1318 1320 # multi-line %%time case
1319 1321 if expr_val is not None:
1320 1322 code_2 = self.shell.compile(expr_val, source, 'eval')
1321 1323 out = eval(code_2, glob, local_ns)
1322 1324 except:
1323 1325 self.shell.showtraceback()
1324 1326 return
1325 1327 end = clock2()
1326 1328
1327 1329 wall_end = wtime()
1328 1330 # Compute actual times and report
1329 1331 wall_time = wall_end - wall_st
1330 1332 cpu_user = end[0] - st[0]
1331 1333 cpu_sys = end[1] - st[1]
1332 1334 cpu_tot = cpu_user + cpu_sys
1333 1335 # On windows cpu_sys is always zero, so only total is displayed
1334 1336 if sys.platform != "win32":
1335 1337 print(
1336 1338 f"CPU times: user {_format_time(cpu_user)}, sys: {_format_time(cpu_sys)}, total: {_format_time(cpu_tot)}"
1337 1339 )
1338 1340 else:
1339 1341 print(f"CPU times: total: {_format_time(cpu_tot)}")
1340 1342 print(f"Wall time: {_format_time(wall_time)}")
1341 1343 if tc > tc_min:
1342 1344 print(f"Compiler : {_format_time(tc)}")
1343 1345 if tp > tp_min:
1344 1346 print(f"Parser : {_format_time(tp)}")
1345 1347 return out
1346 1348
1347 1349 @skip_doctest
1348 1350 @line_magic
1349 1351 def macro(self, parameter_s=''):
1350 1352 """Define a macro for future re-execution. It accepts ranges of history,
1351 1353 filenames or string objects.
1352 1354
1353 1355 Usage:\\
1354 1356 %macro [options] name n1-n2 n3-n4 ... n5 .. n6 ...
1355 1357
1356 1358 Options:
1357 1359
1358 1360 -r: use 'raw' input. By default, the 'processed' history is used,
1359 1361 so that magics are loaded in their transformed version to valid
1360 1362 Python. If this option is given, the raw input as typed at the
1361 1363 command line is used instead.
1362 1364
1363 1365 -q: quiet macro definition. By default, a tag line is printed
1364 1366 to indicate the macro has been created, and then the contents of
1365 1367 the macro are printed. If this option is given, then no printout
1366 1368 is produced once the macro is created.
1367 1369
1368 1370 This will define a global variable called `name` which is a string
1369 1371 made of joining the slices and lines you specify (n1,n2,... numbers
1370 1372 above) from your input history into a single string. This variable
1371 1373 acts like an automatic function which re-executes those lines as if
1372 1374 you had typed them. You just type 'name' at the prompt and the code
1373 1375 executes.
1374 1376
1375 1377 The syntax for indicating input ranges is described in %history.
1376 1378
1377 1379 Note: as a 'hidden' feature, you can also use traditional python slice
1378 1380 notation, where N:M means numbers N through M-1.
1379 1381
1380 1382 For example, if your history contains (print using %hist -n )::
1381 1383
1382 1384 44: x=1
1383 1385 45: y=3
1384 1386 46: z=x+y
1385 1387 47: print x
1386 1388 48: a=5
1387 1389 49: print 'x',x,'y',y
1388 1390
1389 1391 you can create a macro with lines 44 through 47 (included) and line 49
1390 1392 called my_macro with::
1391 1393
1392 1394 In [55]: %macro my_macro 44-47 49
1393 1395
1394 1396 Now, typing `my_macro` (without quotes) will re-execute all this code
1395 1397 in one pass.
1396 1398
1397 1399 You don't need to give the line-numbers in order, and any given line
1398 1400 number can appear multiple times. You can assemble macros with any
1399 1401 lines from your input history in any order.
1400 1402
1401 1403 The macro is a simple object which holds its value in an attribute,
1402 1404 but IPython's display system checks for macros and executes them as
1403 1405 code instead of printing them when you type their name.
1404 1406
1405 1407 You can view a macro's contents by explicitly printing it with::
1406 1408
1407 1409 print macro_name
1408 1410
1409 1411 """
1410 1412 opts,args = self.parse_options(parameter_s,'rq',mode='list')
1411 1413 if not args: # List existing macros
1412 1414 return sorted(k for k,v in self.shell.user_ns.items() if isinstance(v, Macro))
1413 1415 if len(args) == 1:
1414 1416 raise UsageError(
1415 1417 "%macro insufficient args; usage '%macro name n1-n2 n3-4...")
1416 1418 name, codefrom = args[0], " ".join(args[1:])
1417 1419
1418 1420 #print 'rng',ranges # dbg
1419 1421 try:
1420 1422 lines = self.shell.find_user_code(codefrom, 'r' in opts)
1421 1423 except (ValueError, TypeError) as e:
1422 1424 print(e.args[0])
1423 1425 return
1424 1426 macro = Macro(lines)
1425 1427 self.shell.define_macro(name, macro)
1426 1428 if not ( 'q' in opts) :
1427 1429 print('Macro `%s` created. To execute, type its name (without quotes).' % name)
1428 1430 print('=== Macro contents: ===')
1429 1431 print(macro, end=' ')
1430 1432
1431 1433 @magic_arguments.magic_arguments()
1432 1434 @magic_arguments.argument('output', type=str, default='', nargs='?',
1433 1435 help="""The name of the variable in which to store output.
1434 1436 This is a utils.io.CapturedIO object with stdout/err attributes
1435 1437 for the text of the captured output.
1436 1438
1437 1439 CapturedOutput also has a show() method for displaying the output,
1438 1440 and __call__ as well, so you can use that to quickly display the
1439 1441 output.
1440 1442
1441 1443 If unspecified, captured output is discarded.
1442 1444 """
1443 1445 )
1444 1446 @magic_arguments.argument('--no-stderr', action="store_true",
1445 1447 help="""Don't capture stderr."""
1446 1448 )
1447 1449 @magic_arguments.argument('--no-stdout', action="store_true",
1448 1450 help="""Don't capture stdout."""
1449 1451 )
1450 1452 @magic_arguments.argument('--no-display', action="store_true",
1451 1453 help="""Don't capture IPython's rich display."""
1452 1454 )
1453 1455 @cell_magic
1454 1456 def capture(self, line, cell):
1455 1457 """run the cell, capturing stdout, stderr, and IPython's rich display() calls."""
1456 1458 args = magic_arguments.parse_argstring(self.capture, line)
1457 1459 out = not args.no_stdout
1458 1460 err = not args.no_stderr
1459 1461 disp = not args.no_display
1460 1462 with capture_output(out, err, disp) as io:
1461 1463 self.shell.run_cell(cell)
1462 1464 if args.output:
1463 1465 self.shell.user_ns[args.output] = io
1464 1466
1465 1467 def parse_breakpoint(text, current_file):
1466 1468 '''Returns (file, line) for file:line and (current_file, line) for line'''
1467 1469 colon = text.find(':')
1468 1470 if colon == -1:
1469 1471 return current_file, int(text)
1470 1472 else:
1471 1473 return text[:colon], int(text[colon+1:])
1472 1474
1473 1475 def _format_time(timespan, precision=3):
1474 1476 """Formats the timespan in a human readable form"""
1475 1477
1476 1478 if timespan >= 60.0:
1477 1479 # we have more than a minute, format that in a human readable form
1478 1480 # Idea from http://snipplr.com/view/5713/
1479 1481 parts = [("d", 60*60*24),("h", 60*60),("min", 60), ("s", 1)]
1480 1482 time = []
1481 1483 leftover = timespan
1482 1484 for suffix, length in parts:
1483 1485 value = int(leftover / length)
1484 1486 if value > 0:
1485 1487 leftover = leftover % length
1486 1488 time.append(u'%s%s' % (str(value), suffix))
1487 1489 if leftover < 1:
1488 1490 break
1489 1491 return " ".join(time)
1490 1492
1491 1493
1492 1494 # Unfortunately the unicode 'micro' symbol can cause problems in
1493 1495 # certain terminals.
1494 1496 # See bug: https://bugs.launchpad.net/ipython/+bug/348466
1495 1497 # Try to prevent crashes by being more secure than it needs to
1496 1498 # E.g. eclipse is able to print a Β΅, but has no sys.stdout.encoding set.
1497 1499 units = [u"s", u"ms",u'us',"ns"] # the save value
1498 1500 if hasattr(sys.stdout, 'encoding') and sys.stdout.encoding:
1499 1501 try:
1500 1502 u'\xb5'.encode(sys.stdout.encoding)
1501 1503 units = [u"s", u"ms",u'\xb5s',"ns"]
1502 1504 except:
1503 1505 pass
1504 1506 scaling = [1, 1e3, 1e6, 1e9]
1505 1507
1506 1508 if timespan > 0.0:
1507 1509 order = min(-int(math.floor(math.log10(timespan)) // 3), 3)
1508 1510 else:
1509 1511 order = 3
1510 1512 return u"%.*g %s" % (precision, timespan * scaling[order], units[order])
@@ -1,1471 +1,1486 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Tests for various magic functions."""
3 3
4 4 import gc
5 5 import io
6 6 import os
7 7 import re
8 8 import shlex
9 9 import sys
10 10 import warnings
11 11 from importlib import invalidate_caches
12 12 from io import StringIO
13 13 from pathlib import Path
14 14 from textwrap import dedent
15 15 from unittest import TestCase, mock
16 16
17 17 import pytest
18 18
19 19 from IPython import get_ipython
20 20 from IPython.core import magic
21 21 from IPython.core.error import UsageError
22 22 from IPython.core.magic import (
23 23 Magics,
24 24 cell_magic,
25 25 line_magic,
26 26 magics_class,
27 27 register_cell_magic,
28 28 register_line_magic,
29 29 )
30 30 from IPython.core.magics import code, execution, logging, osm, script
31 31 from IPython.testing import decorators as dec
32 32 from IPython.testing import tools as tt
33 33 from IPython.utils.io import capture_output
34 34 from IPython.utils.process import find_cmd
35 35 from IPython.utils.tempdir import TemporaryDirectory, TemporaryWorkingDirectory
36 36 from IPython.utils.syspathcontext import prepended_to_syspath
37 37
38 38 from .test_debugger import PdbTestInput
39 39
40 40 from tempfile import NamedTemporaryFile
41 41
42 42 @magic.magics_class
43 43 class DummyMagics(magic.Magics): pass
44 44
45 45 def test_extract_code_ranges():
46 46 instr = "1 3 5-6 7-9 10:15 17: :10 10- -13 :"
47 47 expected = [
48 48 (0, 1),
49 49 (2, 3),
50 50 (4, 6),
51 51 (6, 9),
52 52 (9, 14),
53 53 (16, None),
54 54 (None, 9),
55 55 (9, None),
56 56 (None, 13),
57 57 (None, None),
58 58 ]
59 59 actual = list(code.extract_code_ranges(instr))
60 60 assert actual == expected
61 61
62 62 def test_extract_symbols():
63 63 source = """import foo\na = 10\ndef b():\n return 42\n\n\nclass A: pass\n\n\n"""
64 64 symbols_args = ["a", "b", "A", "A,b", "A,a", "z"]
65 65 expected = [([], ['a']),
66 66 (["def b():\n return 42\n"], []),
67 67 (["class A: pass\n"], []),
68 68 (["class A: pass\n", "def b():\n return 42\n"], []),
69 69 (["class A: pass\n"], ['a']),
70 70 ([], ['z'])]
71 71 for symbols, exp in zip(symbols_args, expected):
72 72 assert code.extract_symbols(source, symbols) == exp
73 73
74 74
75 75 def test_extract_symbols_raises_exception_with_non_python_code():
76 76 source = ("=begin A Ruby program :)=end\n"
77 77 "def hello\n"
78 78 "puts 'Hello world'\n"
79 79 "end")
80 80 with pytest.raises(SyntaxError):
81 81 code.extract_symbols(source, "hello")
82 82
83 83
84 84 def test_magic_not_found():
85 85 # magic not found raises UsageError
86 86 with pytest.raises(UsageError):
87 87 _ip.run_line_magic("doesntexist", "")
88 88
89 89 # ensure result isn't success when a magic isn't found
90 90 result = _ip.run_cell('%doesntexist')
91 91 assert isinstance(result.error_in_exec, UsageError)
92 92
93 93
94 94 def test_cell_magic_not_found():
95 95 # magic not found raises UsageError
96 96 with pytest.raises(UsageError):
97 97 _ip.run_cell_magic('doesntexist', 'line', 'cell')
98 98
99 99 # ensure result isn't success when a magic isn't found
100 100 result = _ip.run_cell('%%doesntexist')
101 101 assert isinstance(result.error_in_exec, UsageError)
102 102
103 103
104 104 def test_magic_error_status():
105 105 def fail(shell):
106 106 1/0
107 107 _ip.register_magic_function(fail)
108 108 result = _ip.run_cell('%fail')
109 109 assert isinstance(result.error_in_exec, ZeroDivisionError)
110 110
111 111
112 112 def test_config():
113 113 """ test that config magic does not raise
114 114 can happen if Configurable init is moved too early into
115 115 Magics.__init__ as then a Config object will be registered as a
116 116 magic.
117 117 """
118 118 ## should not raise.
119 119 _ip.run_line_magic("config", "")
120 120
121 121
122 122 def test_config_available_configs():
123 123 """ test that config magic prints available configs in unique and
124 124 sorted order. """
125 125 with capture_output() as captured:
126 126 _ip.run_line_magic("config", "")
127 127
128 128 stdout = captured.stdout
129 129 config_classes = stdout.strip().split('\n')[1:]
130 130 assert config_classes == sorted(set(config_classes))
131 131
132 132 def test_config_print_class():
133 133 """ test that config with a classname prints the class's options. """
134 134 with capture_output() as captured:
135 135 _ip.run_line_magic("config", "TerminalInteractiveShell")
136 136
137 137 stdout = captured.stdout
138 138 assert re.match(
139 139 "TerminalInteractiveShell.* options", stdout.splitlines()[0]
140 140 ), f"{stdout}\n\n1st line of stdout not like 'TerminalInteractiveShell.* options'"
141 141
142 142
143 143 def test_rehashx():
144 144 # clear up everything
145 145 _ip.alias_manager.clear_aliases()
146 146 del _ip.db['syscmdlist']
147 147
148 148 _ip.run_line_magic("rehashx", "")
149 149 # Practically ALL ipython development systems will have more than 10 aliases
150 150
151 151 assert len(_ip.alias_manager.aliases) > 10
152 152 for name, cmd in _ip.alias_manager.aliases:
153 153 # we must strip dots from alias names
154 154 assert "." not in name
155 155
156 156 # rehashx must fill up syscmdlist
157 157 scoms = _ip.db['syscmdlist']
158 158 assert len(scoms) > 10
159 159
160 160
161 161 def test_magic_parse_options():
162 162 """Test that we don't mangle paths when parsing magic options."""
163 163 ip = get_ipython()
164 164 path = 'c:\\x'
165 165 m = DummyMagics(ip)
166 166 opts = m.parse_options('-f %s' % path,'f:')[0]
167 167 # argv splitting is os-dependent
168 168 if os.name == 'posix':
169 169 expected = 'c:x'
170 170 else:
171 171 expected = path
172 172 assert opts["f"] == expected
173 173
174 174
175 175 def test_magic_parse_long_options():
176 176 """Magic.parse_options can handle --foo=bar long options"""
177 177 ip = get_ipython()
178 178 m = DummyMagics(ip)
179 179 opts, _ = m.parse_options("--foo --bar=bubble", "a", "foo", "bar=")
180 180 assert "foo" in opts
181 181 assert "bar" in opts
182 182 assert opts["bar"] == "bubble"
183 183
184 184
185 185 def doctest_hist_f():
186 186 """Test %hist -f with temporary filename.
187 187
188 188 In [9]: import tempfile
189 189
190 190 In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-')
191 191
192 192 In [11]: %hist -nl -f $tfile 3
193 193
194 194 In [13]: import os; os.unlink(tfile)
195 195 """
196 196
197 197
198 198 def doctest_hist_op():
199 199 """Test %hist -op
200 200
201 201 In [1]: class b(float):
202 202 ...: pass
203 203 ...:
204 204
205 205 In [2]: class s(object):
206 206 ...: def __str__(self):
207 207 ...: return 's'
208 208 ...:
209 209
210 210 In [3]:
211 211
212 212 In [4]: class r(b):
213 213 ...: def __repr__(self):
214 214 ...: return 'r'
215 215 ...:
216 216
217 217 In [5]: class sr(s,r): pass
218 218 ...:
219 219
220 220 In [6]:
221 221
222 222 In [7]: bb=b()
223 223
224 224 In [8]: ss=s()
225 225
226 226 In [9]: rr=r()
227 227
228 228 In [10]: ssrr=sr()
229 229
230 230 In [11]: 4.5
231 231 Out[11]: 4.5
232 232
233 233 In [12]: str(ss)
234 234 Out[12]: 's'
235 235
236 236 In [13]:
237 237
238 238 In [14]: %hist -op
239 239 >>> class b:
240 240 ... pass
241 241 ...
242 242 >>> class s(b):
243 243 ... def __str__(self):
244 244 ... return 's'
245 245 ...
246 246 >>>
247 247 >>> class r(b):
248 248 ... def __repr__(self):
249 249 ... return 'r'
250 250 ...
251 251 >>> class sr(s,r): pass
252 252 >>>
253 253 >>> bb=b()
254 254 >>> ss=s()
255 255 >>> rr=r()
256 256 >>> ssrr=sr()
257 257 >>> 4.5
258 258 4.5
259 259 >>> str(ss)
260 260 's'
261 261 >>>
262 262 """
263 263
264 264 def test_hist_pof():
265 265 ip = get_ipython()
266 266 ip.run_cell("1+2", store_history=True)
267 267 #raise Exception(ip.history_manager.session_number)
268 268 #raise Exception(list(ip.history_manager._get_range_session()))
269 269 with TemporaryDirectory() as td:
270 270 tf = os.path.join(td, 'hist.py')
271 271 ip.run_line_magic('history', '-pof %s' % tf)
272 272 assert os.path.isfile(tf)
273 273
274 274
275 275 def test_macro():
276 276 ip = get_ipython()
277 277 ip.history_manager.reset() # Clear any existing history.
278 278 cmds = ["a=1", "def b():\n return a**2", "print(a,b())"]
279 279 for i, cmd in enumerate(cmds, start=1):
280 280 ip.history_manager.store_inputs(i, cmd)
281 281 ip.run_line_magic("macro", "test 1-3")
282 282 assert ip.user_ns["test"].value == "\n".join(cmds) + "\n"
283 283
284 284 # List macros
285 285 assert "test" in ip.run_line_magic("macro", "")
286 286
287 287
288 288 def test_macro_run():
289 289 """Test that we can run a multi-line macro successfully."""
290 290 ip = get_ipython()
291 291 ip.history_manager.reset()
292 292 cmds = ["a=10", "a+=1", "print(a)", "%macro test 2-3"]
293 293 for cmd in cmds:
294 294 ip.run_cell(cmd, store_history=True)
295 295 assert ip.user_ns["test"].value == "a+=1\nprint(a)\n"
296 296 with tt.AssertPrints("12"):
297 297 ip.run_cell("test")
298 298 with tt.AssertPrints("13"):
299 299 ip.run_cell("test")
300 300
301 301
302 302 def test_magic_magic():
303 303 """Test %magic"""
304 304 ip = get_ipython()
305 305 with capture_output() as captured:
306 306 ip.run_line_magic("magic", "")
307 307
308 308 stdout = captured.stdout
309 309 assert "%magic" in stdout
310 310 assert "IPython" in stdout
311 311 assert "Available" in stdout
312 312
313 313
314 314 @dec.skipif_not_numpy
315 315 def test_numpy_reset_array_undec():
316 316 "Test '%reset array' functionality"
317 317 _ip.ex("import numpy as np")
318 318 _ip.ex("a = np.empty(2)")
319 319 assert "a" in _ip.user_ns
320 320 _ip.run_line_magic("reset", "-f array")
321 321 assert "a" not in _ip.user_ns
322 322
323 323
324 324 def test_reset_out():
325 325 "Test '%reset out' magic"
326 326 _ip.run_cell("parrot = 'dead'", store_history=True)
327 327 # test '%reset -f out', make an Out prompt
328 328 _ip.run_cell("parrot", store_history=True)
329 329 assert "dead" in [_ip.user_ns[x] for x in ("_", "__", "___")]
330 330 _ip.run_line_magic("reset", "-f out")
331 331 assert "dead" not in [_ip.user_ns[x] for x in ("_", "__", "___")]
332 332 assert len(_ip.user_ns["Out"]) == 0
333 333
334 334
335 335 def test_reset_in():
336 336 "Test '%reset in' magic"
337 337 # test '%reset -f in'
338 338 _ip.run_cell("parrot", store_history=True)
339 339 assert "parrot" in [_ip.user_ns[x] for x in ("_i", "_ii", "_iii")]
340 340 _ip.run_line_magic("reset", "-f in")
341 341 assert "parrot" not in [_ip.user_ns[x] for x in ("_i", "_ii", "_iii")]
342 342 assert len(set(_ip.user_ns["In"])) == 1
343 343
344 344
345 345 def test_reset_dhist():
346 346 "Test '%reset dhist' magic"
347 347 _ip.run_cell("tmp = [d for d in _dh]") # copy before clearing
348 348 _ip.run_line_magic("cd", os.path.dirname(pytest.__file__))
349 349 _ip.run_line_magic("cd", "-")
350 350 assert len(_ip.user_ns["_dh"]) > 0
351 351 _ip.run_line_magic("reset", "-f dhist")
352 352 assert len(_ip.user_ns["_dh"]) == 0
353 353 _ip.run_cell("_dh = [d for d in tmp]") # restore
354 354
355 355
356 356 def test_reset_in_length():
357 357 "Test that '%reset in' preserves In[] length"
358 358 _ip.run_cell("print 'foo'")
359 359 _ip.run_cell("reset -f in")
360 360 assert len(_ip.user_ns["In"]) == _ip.displayhook.prompt_count + 1
361 361
362 362
363 363 class TestResetErrors(TestCase):
364 364
365 365 def test_reset_redefine(self):
366 366
367 367 @magics_class
368 368 class KernelMagics(Magics):
369 369 @line_magic
370 370 def less(self, shell): pass
371 371
372 372 _ip.register_magics(KernelMagics)
373 373
374 374 with self.assertLogs() as cm:
375 375 # hack, we want to just capture logs, but assertLogs fails if not
376 376 # logs get produce.
377 377 # so log one things we ignore.
378 378 import logging as log_mod
379 379 log = log_mod.getLogger()
380 380 log.info('Nothing')
381 381 # end hack.
382 382 _ip.run_cell("reset -f")
383 383
384 384 assert len(cm.output) == 1
385 385 for out in cm.output:
386 386 assert "Invalid alias" not in out
387 387
388 388 def test_tb_syntaxerror():
389 389 """test %tb after a SyntaxError"""
390 390 ip = get_ipython()
391 391 ip.run_cell("for")
392 392
393 393 # trap and validate stdout
394 394 save_stdout = sys.stdout
395 395 try:
396 396 sys.stdout = StringIO()
397 397 ip.run_cell("%tb")
398 398 out = sys.stdout.getvalue()
399 399 finally:
400 400 sys.stdout = save_stdout
401 401 # trim output, and only check the last line
402 402 last_line = out.rstrip().splitlines()[-1].strip()
403 403 assert last_line == "SyntaxError: invalid syntax"
404 404
405 405
406 406 def test_time():
407 407 ip = get_ipython()
408 408
409 409 with tt.AssertPrints("Wall time: "):
410 410 ip.run_cell("%time None")
411 411
412 412 ip.run_cell("def f(kmjy):\n"
413 413 " %time print (2*kmjy)")
414 414
415 415 with tt.AssertPrints("Wall time: "):
416 416 with tt.AssertPrints("hihi", suppress=False):
417 417 ip.run_cell("f('hi')")
418 418
419 419
420 420 # ';' at the end of %time prevents instruction value to be printed.
421 421 # This tests fix for #13837.
422 def test_time_no_outputwith_semicolon():
422 def test_time_no_output_with_semicolon():
423 423 ip = get_ipython()
424 424
425 425 with tt.AssertPrints(" 123456"):
426 426 with tt.AssertPrints("Wall time: ", suppress=False):
427 427 with tt.AssertPrints("CPU times: ", suppress=False):
428 428 ip.run_cell("%time 123000+456")
429 429
430 430 with tt.AssertNotPrints(" 123456"):
431 431 with tt.AssertPrints("Wall time: ", suppress=False):
432 432 with tt.AssertPrints("CPU times: ", suppress=False):
433 433 ip.run_cell("%time 123000+456;")
434 434
435 with tt.AssertPrints(" 123456"):
436 with tt.AssertPrints("Wall time: ", suppress=False):
437 with tt.AssertPrints("CPU times: ", suppress=False):
438 ip.run_cell("%time 123000+456 # Comment")
439
440 with tt.AssertNotPrints(" 123456"):
441 with tt.AssertPrints("Wall time: ", suppress=False):
442 with tt.AssertPrints("CPU times: ", suppress=False):
443 ip.run_cell("%time 123000+456; # Comment")
444
445 with tt.AssertPrints(" 123456"):
446 with tt.AssertPrints("Wall time: ", suppress=False):
447 with tt.AssertPrints("CPU times: ", suppress=False):
448 ip.run_cell("%time 123000+456 # ;Comment")
449
435 450
436 451 def test_time_last_not_expression():
437 452 ip.run_cell("%%time\n"
438 453 "var_1 = 1\n"
439 454 "var_2 = 2\n")
440 455 assert ip.user_ns['var_1'] == 1
441 456 del ip.user_ns['var_1']
442 457 assert ip.user_ns['var_2'] == 2
443 458 del ip.user_ns['var_2']
444 459
445 460
446 461 @dec.skip_win32
447 462 def test_time2():
448 463 ip = get_ipython()
449 464
450 465 with tt.AssertPrints("CPU times: user "):
451 466 ip.run_cell("%time None")
452 467
453 468 def test_time3():
454 469 """Erroneous magic function calls, issue gh-3334"""
455 470 ip = get_ipython()
456 471 ip.user_ns.pop('run', None)
457 472
458 473 with tt.AssertNotPrints("not found", channel='stderr'):
459 474 ip.run_cell("%%time\n"
460 475 "run = 0\n"
461 476 "run += 1")
462 477
463 478 def test_multiline_time():
464 479 """Make sure last statement from time return a value."""
465 480 ip = get_ipython()
466 481 ip.user_ns.pop('run', None)
467 482
468 483 ip.run_cell(
469 484 dedent(
470 485 """\
471 486 %%time
472 487 a = "ho"
473 488 b = "hey"
474 489 a+b
475 490 """
476 491 )
477 492 )
478 493 assert ip.user_ns_hidden["_"] == "hohey"
479 494
480 495
481 496 def test_time_local_ns():
482 497 """
483 498 Test that local_ns is actually global_ns when running a cell magic
484 499 """
485 500 ip = get_ipython()
486 501 ip.run_cell("%%time\n" "myvar = 1")
487 502 assert ip.user_ns["myvar"] == 1
488 503 del ip.user_ns["myvar"]
489 504
490 505
491 506 def test_doctest_mode():
492 507 "Toggle doctest_mode twice, it should be a no-op and run without error"
493 508 _ip.run_line_magic("doctest_mode", "")
494 509 _ip.run_line_magic("doctest_mode", "")
495 510
496 511
497 512 def test_parse_options():
498 513 """Tests for basic options parsing in magics."""
499 514 # These are only the most minimal of tests, more should be added later. At
500 515 # the very least we check that basic text/unicode calls work OK.
501 516 m = DummyMagics(_ip)
502 517 assert m.parse_options("foo", "")[1] == "foo"
503 518 assert m.parse_options("foo", "")[1] == "foo"
504 519
505 520
506 521 def test_parse_options_preserve_non_option_string():
507 522 """Test to assert preservation of non-option part of magic-block, while parsing magic options."""
508 523 m = DummyMagics(_ip)
509 524 opts, stmt = m.parse_options(
510 525 " -n1 -r 13 _ = 314 + foo", "n:r:", preserve_non_opts=True
511 526 )
512 527 assert opts == {"n": "1", "r": "13"}
513 528 assert stmt == "_ = 314 + foo"
514 529
515 530
516 531 def test_run_magic_preserve_code_block():
517 532 """Test to assert preservation of non-option part of magic-block, while running magic."""
518 533 _ip.user_ns["spaces"] = []
519 534 _ip.run_line_magic(
520 535 "timeit", "-n1 -r1 spaces.append([s.count(' ') for s in ['document']])"
521 536 )
522 537 assert _ip.user_ns["spaces"] == [[0]]
523 538
524 539
525 540 def test_dirops():
526 541 """Test various directory handling operations."""
527 542 # curpath = lambda :os.path.splitdrive(os.getcwd())[1].replace('\\','/')
528 543 curpath = os.getcwd
529 544 startdir = os.getcwd()
530 545 ipdir = os.path.realpath(_ip.ipython_dir)
531 546 try:
532 547 _ip.run_line_magic("cd", '"%s"' % ipdir)
533 548 assert curpath() == ipdir
534 549 _ip.run_line_magic("cd", "-")
535 550 assert curpath() == startdir
536 551 _ip.run_line_magic("pushd", '"%s"' % ipdir)
537 552 assert curpath() == ipdir
538 553 _ip.run_line_magic("popd", "")
539 554 assert curpath() == startdir
540 555 finally:
541 556 os.chdir(startdir)
542 557
543 558
544 559 def test_cd_force_quiet():
545 560 """Test OSMagics.cd_force_quiet option"""
546 561 _ip.config.OSMagics.cd_force_quiet = True
547 562 osmagics = osm.OSMagics(shell=_ip)
548 563
549 564 startdir = os.getcwd()
550 565 ipdir = os.path.realpath(_ip.ipython_dir)
551 566
552 567 try:
553 568 with tt.AssertNotPrints(ipdir):
554 569 osmagics.cd('"%s"' % ipdir)
555 570 with tt.AssertNotPrints(startdir):
556 571 osmagics.cd('-')
557 572 finally:
558 573 os.chdir(startdir)
559 574
560 575
561 576 def test_xmode():
562 577 # Calling xmode three times should be a no-op
563 578 xmode = _ip.InteractiveTB.mode
564 579 for i in range(4):
565 580 _ip.run_line_magic("xmode", "")
566 581 assert _ip.InteractiveTB.mode == xmode
567 582
568 583 def test_reset_hard():
569 584 monitor = []
570 585 class A(object):
571 586 def __del__(self):
572 587 monitor.append(1)
573 588 def __repr__(self):
574 589 return "<A instance>"
575 590
576 591 _ip.user_ns["a"] = A()
577 592 _ip.run_cell("a")
578 593
579 594 assert monitor == []
580 595 _ip.run_line_magic("reset", "-f")
581 596 assert monitor == [1]
582 597
583 598 class TestXdel(tt.TempFileMixin):
584 599 def test_xdel(self):
585 600 """Test that references from %run are cleared by xdel."""
586 601 src = ("class A(object):\n"
587 602 " monitor = []\n"
588 603 " def __del__(self):\n"
589 604 " self.monitor.append(1)\n"
590 605 "a = A()\n")
591 606 self.mktmp(src)
592 607 # %run creates some hidden references...
593 608 _ip.run_line_magic("run", "%s" % self.fname)
594 609 # ... as does the displayhook.
595 610 _ip.run_cell("a")
596 611
597 612 monitor = _ip.user_ns["A"].monitor
598 613 assert monitor == []
599 614
600 615 _ip.run_line_magic("xdel", "a")
601 616
602 617 # Check that a's __del__ method has been called.
603 618 gc.collect(0)
604 619 assert monitor == [1]
605 620
606 621 def doctest_who():
607 622 """doctest for %who
608 623
609 624 In [1]: %reset -sf
610 625
611 626 In [2]: alpha = 123
612 627
613 628 In [3]: beta = 'beta'
614 629
615 630 In [4]: %who int
616 631 alpha
617 632
618 633 In [5]: %who str
619 634 beta
620 635
621 636 In [6]: %whos
622 637 Variable Type Data/Info
623 638 ----------------------------
624 639 alpha int 123
625 640 beta str beta
626 641
627 642 In [7]: %who_ls
628 643 Out[7]: ['alpha', 'beta']
629 644 """
630 645
631 646 def test_whos():
632 647 """Check that whos is protected against objects where repr() fails."""
633 648 class A(object):
634 649 def __repr__(self):
635 650 raise Exception()
636 651 _ip.user_ns['a'] = A()
637 652 _ip.run_line_magic("whos", "")
638 653
639 654 def doctest_precision():
640 655 """doctest for %precision
641 656
642 657 In [1]: f = get_ipython().display_formatter.formatters['text/plain']
643 658
644 659 In [2]: %precision 5
645 660 Out[2]: '%.5f'
646 661
647 662 In [3]: f.float_format
648 663 Out[3]: '%.5f'
649 664
650 665 In [4]: %precision %e
651 666 Out[4]: '%e'
652 667
653 668 In [5]: f(3.1415927)
654 669 Out[5]: '3.141593e+00'
655 670 """
656 671
657 672 def test_debug_magic():
658 673 """Test debugging a small code with %debug
659 674
660 675 In [1]: with PdbTestInput(['c']):
661 676 ...: %debug print("a b") #doctest: +ELLIPSIS
662 677 ...:
663 678 ...
664 679 ipdb> c
665 680 a b
666 681 In [2]:
667 682 """
668 683
669 684 def test_psearch():
670 685 with tt.AssertPrints("dict.fromkeys"):
671 686 _ip.run_cell("dict.fr*?")
672 687 with tt.AssertPrints("Ο€.is_integer"):
673 688 _ip.run_cell("Ο€ = 3.14;\nΟ€.is_integ*?")
674 689
675 690 def test_timeit_shlex():
676 691 """test shlex issues with timeit (#1109)"""
677 692 _ip.ex("def f(*a,**kw): pass")
678 693 _ip.run_line_magic("timeit", '-n1 "this is a bug".count(" ")')
679 694 _ip.run_line_magic("timeit", '-r1 -n1 f(" ", 1)')
680 695 _ip.run_line_magic("timeit", '-r1 -n1 f(" ", 1, " ", 2, " ")')
681 696 _ip.run_line_magic("timeit", '-r1 -n1 ("a " + "b")')
682 697 _ip.run_line_magic("timeit", '-r1 -n1 f("a " + "b")')
683 698 _ip.run_line_magic("timeit", '-r1 -n1 f("a " + "b ")')
684 699
685 700
686 701 def test_timeit_special_syntax():
687 702 "Test %%timeit with IPython special syntax"
688 703 @register_line_magic
689 704 def lmagic(line):
690 705 ip = get_ipython()
691 706 ip.user_ns['lmagic_out'] = line
692 707
693 708 # line mode test
694 709 _ip.run_line_magic("timeit", "-n1 -r1 %lmagic my line")
695 710 assert _ip.user_ns["lmagic_out"] == "my line"
696 711 # cell mode test
697 712 _ip.run_cell_magic("timeit", "-n1 -r1", "%lmagic my line2")
698 713 assert _ip.user_ns["lmagic_out"] == "my line2"
699 714
700 715
701 716 def test_timeit_return():
702 717 """
703 718 test whether timeit -o return object
704 719 """
705 720
706 721 res = _ip.run_line_magic('timeit','-n10 -r10 -o 1')
707 722 assert(res is not None)
708 723
709 724 def test_timeit_quiet():
710 725 """
711 726 test quiet option of timeit magic
712 727 """
713 728 with tt.AssertNotPrints("loops"):
714 729 _ip.run_cell("%timeit -n1 -r1 -q 1")
715 730
716 731 def test_timeit_return_quiet():
717 732 with tt.AssertNotPrints("loops"):
718 733 res = _ip.run_line_magic('timeit', '-n1 -r1 -q -o 1')
719 734 assert (res is not None)
720 735
721 736 def test_timeit_invalid_return():
722 737 with pytest.raises(SyntaxError):
723 738 _ip.run_line_magic('timeit', 'return')
724 739
725 740 @dec.skipif(execution.profile is None)
726 741 def test_prun_special_syntax():
727 742 "Test %%prun with IPython special syntax"
728 743 @register_line_magic
729 744 def lmagic(line):
730 745 ip = get_ipython()
731 746 ip.user_ns['lmagic_out'] = line
732 747
733 748 # line mode test
734 749 _ip.run_line_magic("prun", "-q %lmagic my line")
735 750 assert _ip.user_ns["lmagic_out"] == "my line"
736 751 # cell mode test
737 752 _ip.run_cell_magic("prun", "-q", "%lmagic my line2")
738 753 assert _ip.user_ns["lmagic_out"] == "my line2"
739 754
740 755
741 756 @dec.skipif(execution.profile is None)
742 757 def test_prun_quotes():
743 758 "Test that prun does not clobber string escapes (GH #1302)"
744 759 _ip.magic(r"prun -q x = '\t'")
745 760 assert _ip.user_ns["x"] == "\t"
746 761
747 762
748 763 def test_extension():
749 764 # Debugging information for failures of this test
750 765 print('sys.path:')
751 766 for p in sys.path:
752 767 print(' ', p)
753 768 print('CWD', os.getcwd())
754 769
755 770 pytest.raises(ImportError, _ip.magic, "load_ext daft_extension")
756 771 daft_path = os.path.join(os.path.dirname(__file__), "daft_extension")
757 772 sys.path.insert(0, daft_path)
758 773 try:
759 774 _ip.user_ns.pop('arq', None)
760 775 invalidate_caches() # Clear import caches
761 776 _ip.run_line_magic("load_ext", "daft_extension")
762 777 assert _ip.user_ns["arq"] == 185
763 778 _ip.run_line_magic("unload_ext", "daft_extension")
764 779 assert 'arq' not in _ip.user_ns
765 780 finally:
766 781 sys.path.remove(daft_path)
767 782
768 783
769 784 def test_notebook_export_json():
770 785 pytest.importorskip("nbformat")
771 786 _ip = get_ipython()
772 787 _ip.history_manager.reset() # Clear any existing history.
773 788 cmds = ["a=1", "def b():\n return a**2", "print('noΓ«l, Γ©tΓ©', b())"]
774 789 for i, cmd in enumerate(cmds, start=1):
775 790 _ip.history_manager.store_inputs(i, cmd)
776 791 with TemporaryDirectory() as td:
777 792 outfile = os.path.join(td, "nb.ipynb")
778 793 _ip.run_line_magic("notebook", "%s" % outfile)
779 794
780 795
781 796 class TestEnv(TestCase):
782 797
783 798 def test_env(self):
784 799 env = _ip.run_line_magic("env", "")
785 800 self.assertTrue(isinstance(env, dict))
786 801
787 802 def test_env_secret(self):
788 803 env = _ip.run_line_magic("env", "")
789 804 hidden = "<hidden>"
790 805 with mock.patch.dict(
791 806 os.environ,
792 807 {
793 808 "API_KEY": "abc123",
794 809 "SECRET_THING": "ssshhh",
795 810 "JUPYTER_TOKEN": "",
796 811 "VAR": "abc"
797 812 }
798 813 ):
799 814 env = _ip.run_line_magic("env", "")
800 815 assert env["API_KEY"] == hidden
801 816 assert env["SECRET_THING"] == hidden
802 817 assert env["JUPYTER_TOKEN"] == hidden
803 818 assert env["VAR"] == "abc"
804 819
805 820 def test_env_get_set_simple(self):
806 821 env = _ip.run_line_magic("env", "var val1")
807 822 self.assertEqual(env, None)
808 823 self.assertEqual(os.environ["var"], "val1")
809 824 self.assertEqual(_ip.run_line_magic("env", "var"), "val1")
810 825 env = _ip.run_line_magic("env", "var=val2")
811 826 self.assertEqual(env, None)
812 827 self.assertEqual(os.environ['var'], 'val2')
813 828
814 829 def test_env_get_set_complex(self):
815 830 env = _ip.run_line_magic("env", "var 'val1 '' 'val2")
816 831 self.assertEqual(env, None)
817 832 self.assertEqual(os.environ['var'], "'val1 '' 'val2")
818 833 self.assertEqual(_ip.run_line_magic("env", "var"), "'val1 '' 'val2")
819 834 env = _ip.run_line_magic("env", 'var=val2 val3="val4')
820 835 self.assertEqual(env, None)
821 836 self.assertEqual(os.environ['var'], 'val2 val3="val4')
822 837
823 838 def test_env_set_bad_input(self):
824 839 self.assertRaises(UsageError, lambda: _ip.run_line_magic("set_env", "var"))
825 840
826 841 def test_env_set_whitespace(self):
827 842 self.assertRaises(UsageError, lambda: _ip.run_line_magic("env", "var A=B"))
828 843
829 844
830 845 class CellMagicTestCase(TestCase):
831 846
832 847 def check_ident(self, magic):
833 848 # Manually called, we get the result
834 849 out = _ip.run_cell_magic(magic, "a", "b")
835 850 assert out == ("a", "b")
836 851 # Via run_cell, it goes into the user's namespace via displayhook
837 852 _ip.run_cell("%%" + magic + " c\nd\n")
838 853 assert _ip.user_ns["_"] == ("c", "d\n")
839 854
840 855 def test_cell_magic_func_deco(self):
841 856 "Cell magic using simple decorator"
842 857 @register_cell_magic
843 858 def cellm(line, cell):
844 859 return line, cell
845 860
846 861 self.check_ident('cellm')
847 862
848 863 def test_cell_magic_reg(self):
849 864 "Cell magic manually registered"
850 865 def cellm(line, cell):
851 866 return line, cell
852 867
853 868 _ip.register_magic_function(cellm, 'cell', 'cellm2')
854 869 self.check_ident('cellm2')
855 870
856 871 def test_cell_magic_class(self):
857 872 "Cell magics declared via a class"
858 873 @magics_class
859 874 class MyMagics(Magics):
860 875
861 876 @cell_magic
862 877 def cellm3(self, line, cell):
863 878 return line, cell
864 879
865 880 _ip.register_magics(MyMagics)
866 881 self.check_ident('cellm3')
867 882
868 883 def test_cell_magic_class2(self):
869 884 "Cell magics declared via a class, #2"
870 885 @magics_class
871 886 class MyMagics2(Magics):
872 887
873 888 @cell_magic('cellm4')
874 889 def cellm33(self, line, cell):
875 890 return line, cell
876 891
877 892 _ip.register_magics(MyMagics2)
878 893 self.check_ident('cellm4')
879 894 # Check that nothing is registered as 'cellm33'
880 895 c33 = _ip.find_cell_magic('cellm33')
881 896 assert c33 == None
882 897
883 898 def test_file():
884 899 """Basic %%writefile"""
885 900 ip = get_ipython()
886 901 with TemporaryDirectory() as td:
887 902 fname = os.path.join(td, "file1")
888 903 ip.run_cell_magic(
889 904 "writefile",
890 905 fname,
891 906 "\n".join(
892 907 [
893 908 "line1",
894 909 "line2",
895 910 ]
896 911 ),
897 912 )
898 913 s = Path(fname).read_text(encoding="utf-8")
899 914 assert "line1\n" in s
900 915 assert "line2" in s
901 916
902 917
903 918 @dec.skip_win32
904 919 def test_file_single_quote():
905 920 """Basic %%writefile with embedded single quotes"""
906 921 ip = get_ipython()
907 922 with TemporaryDirectory() as td:
908 923 fname = os.path.join(td, "'file1'")
909 924 ip.run_cell_magic(
910 925 "writefile",
911 926 fname,
912 927 "\n".join(
913 928 [
914 929 "line1",
915 930 "line2",
916 931 ]
917 932 ),
918 933 )
919 934 s = Path(fname).read_text(encoding="utf-8")
920 935 assert "line1\n" in s
921 936 assert "line2" in s
922 937
923 938
924 939 @dec.skip_win32
925 940 def test_file_double_quote():
926 941 """Basic %%writefile with embedded double quotes"""
927 942 ip = get_ipython()
928 943 with TemporaryDirectory() as td:
929 944 fname = os.path.join(td, '"file1"')
930 945 ip.run_cell_magic(
931 946 "writefile",
932 947 fname,
933 948 "\n".join(
934 949 [
935 950 "line1",
936 951 "line2",
937 952 ]
938 953 ),
939 954 )
940 955 s = Path(fname).read_text(encoding="utf-8")
941 956 assert "line1\n" in s
942 957 assert "line2" in s
943 958
944 959
945 960 def test_file_var_expand():
946 961 """%%writefile $filename"""
947 962 ip = get_ipython()
948 963 with TemporaryDirectory() as td:
949 964 fname = os.path.join(td, "file1")
950 965 ip.user_ns["filename"] = fname
951 966 ip.run_cell_magic(
952 967 "writefile",
953 968 "$filename",
954 969 "\n".join(
955 970 [
956 971 "line1",
957 972 "line2",
958 973 ]
959 974 ),
960 975 )
961 976 s = Path(fname).read_text(encoding="utf-8")
962 977 assert "line1\n" in s
963 978 assert "line2" in s
964 979
965 980
966 981 def test_file_unicode():
967 982 """%%writefile with unicode cell"""
968 983 ip = get_ipython()
969 984 with TemporaryDirectory() as td:
970 985 fname = os.path.join(td, 'file1')
971 986 ip.run_cell_magic("writefile", fname, u'\n'.join([
972 987 u'linΓ©1',
973 988 u'linΓ©2',
974 989 ]))
975 990 with io.open(fname, encoding='utf-8') as f:
976 991 s = f.read()
977 992 assert "linΓ©1\n" in s
978 993 assert "linΓ©2" in s
979 994
980 995
981 996 def test_file_amend():
982 997 """%%writefile -a amends files"""
983 998 ip = get_ipython()
984 999 with TemporaryDirectory() as td:
985 1000 fname = os.path.join(td, "file2")
986 1001 ip.run_cell_magic(
987 1002 "writefile",
988 1003 fname,
989 1004 "\n".join(
990 1005 [
991 1006 "line1",
992 1007 "line2",
993 1008 ]
994 1009 ),
995 1010 )
996 1011 ip.run_cell_magic(
997 1012 "writefile",
998 1013 "-a %s" % fname,
999 1014 "\n".join(
1000 1015 [
1001 1016 "line3",
1002 1017 "line4",
1003 1018 ]
1004 1019 ),
1005 1020 )
1006 1021 s = Path(fname).read_text(encoding="utf-8")
1007 1022 assert "line1\n" in s
1008 1023 assert "line3\n" in s
1009 1024
1010 1025
1011 1026 def test_file_spaces():
1012 1027 """%%file with spaces in filename"""
1013 1028 ip = get_ipython()
1014 1029 with TemporaryWorkingDirectory() as td:
1015 1030 fname = "file name"
1016 1031 ip.run_cell_magic(
1017 1032 "file",
1018 1033 '"%s"' % fname,
1019 1034 "\n".join(
1020 1035 [
1021 1036 "line1",
1022 1037 "line2",
1023 1038 ]
1024 1039 ),
1025 1040 )
1026 1041 s = Path(fname).read_text(encoding="utf-8")
1027 1042 assert "line1\n" in s
1028 1043 assert "line2" in s
1029 1044
1030 1045
1031 1046 def test_script_config():
1032 1047 ip = get_ipython()
1033 1048 ip.config.ScriptMagics.script_magics = ['whoda']
1034 1049 sm = script.ScriptMagics(shell=ip)
1035 1050 assert "whoda" in sm.magics["cell"]
1036 1051
1037 1052
1038 1053 def test_script_out():
1039 1054 ip = get_ipython()
1040 1055 ip.run_cell_magic("script", f"--out output {sys.executable}", "print('hi')")
1041 1056 assert ip.user_ns["output"].strip() == "hi"
1042 1057
1043 1058
1044 1059 def test_script_err():
1045 1060 ip = get_ipython()
1046 1061 ip.run_cell_magic(
1047 1062 "script",
1048 1063 f"--err error {sys.executable}",
1049 1064 "import sys; print('hello', file=sys.stderr)",
1050 1065 )
1051 1066 assert ip.user_ns["error"].strip() == "hello"
1052 1067
1053 1068
1054 1069 def test_script_out_err():
1055 1070
1056 1071 ip = get_ipython()
1057 1072 ip.run_cell_magic(
1058 1073 "script",
1059 1074 f"--out output --err error {sys.executable}",
1060 1075 "\n".join(
1061 1076 [
1062 1077 "import sys",
1063 1078 "print('hi')",
1064 1079 "print('hello', file=sys.stderr)",
1065 1080 ]
1066 1081 ),
1067 1082 )
1068 1083 assert ip.user_ns["output"].strip() == "hi"
1069 1084 assert ip.user_ns["error"].strip() == "hello"
1070 1085
1071 1086
1072 1087 async def test_script_bg_out():
1073 1088 ip = get_ipython()
1074 1089 ip.run_cell_magic("script", f"--bg --out output {sys.executable}", "print('hi')")
1075 1090 assert (await ip.user_ns["output"].read()).strip() == b"hi"
1076 1091 assert ip.user_ns["output"].at_eof()
1077 1092
1078 1093
1079 1094 async def test_script_bg_err():
1080 1095 ip = get_ipython()
1081 1096 ip.run_cell_magic(
1082 1097 "script",
1083 1098 f"--bg --err error {sys.executable}",
1084 1099 "import sys; print('hello', file=sys.stderr)",
1085 1100 )
1086 1101 assert (await ip.user_ns["error"].read()).strip() == b"hello"
1087 1102 assert ip.user_ns["error"].at_eof()
1088 1103
1089 1104
1090 1105 async def test_script_bg_out_err():
1091 1106 ip = get_ipython()
1092 1107 ip.run_cell_magic(
1093 1108 "script",
1094 1109 f"--bg --out output --err error {sys.executable}",
1095 1110 "\n".join(
1096 1111 [
1097 1112 "import sys",
1098 1113 "print('hi')",
1099 1114 "print('hello', file=sys.stderr)",
1100 1115 ]
1101 1116 ),
1102 1117 )
1103 1118 assert (await ip.user_ns["output"].read()).strip() == b"hi"
1104 1119 assert (await ip.user_ns["error"].read()).strip() == b"hello"
1105 1120 assert ip.user_ns["output"].at_eof()
1106 1121 assert ip.user_ns["error"].at_eof()
1107 1122
1108 1123
1109 1124 async def test_script_bg_proc():
1110 1125 ip = get_ipython()
1111 1126 ip.run_cell_magic(
1112 1127 "script",
1113 1128 f"--bg --out output --proc p {sys.executable}",
1114 1129 "\n".join(
1115 1130 [
1116 1131 "import sys",
1117 1132 "print('hi')",
1118 1133 "print('hello', file=sys.stderr)",
1119 1134 ]
1120 1135 ),
1121 1136 )
1122 1137 p = ip.user_ns["p"]
1123 1138 await p.wait()
1124 1139 assert p.returncode == 0
1125 1140 assert (await p.stdout.read()).strip() == b"hi"
1126 1141 # not captured, so empty
1127 1142 assert (await p.stderr.read()) == b""
1128 1143 assert p.stdout.at_eof()
1129 1144 assert p.stderr.at_eof()
1130 1145
1131 1146
1132 1147 def test_script_defaults():
1133 1148 ip = get_ipython()
1134 1149 for cmd in ['sh', 'bash', 'perl', 'ruby']:
1135 1150 try:
1136 1151 find_cmd(cmd)
1137 1152 except Exception:
1138 1153 pass
1139 1154 else:
1140 1155 assert cmd in ip.magics_manager.magics["cell"]
1141 1156
1142 1157
1143 1158 @magics_class
1144 1159 class FooFoo(Magics):
1145 1160 """class with both %foo and %%foo magics"""
1146 1161 @line_magic('foo')
1147 1162 def line_foo(self, line):
1148 1163 "I am line foo"
1149 1164 pass
1150 1165
1151 1166 @cell_magic("foo")
1152 1167 def cell_foo(self, line, cell):
1153 1168 "I am cell foo, not line foo"
1154 1169 pass
1155 1170
1156 1171 def test_line_cell_info():
1157 1172 """%%foo and %foo magics are distinguishable to inspect"""
1158 1173 ip = get_ipython()
1159 1174 ip.magics_manager.register(FooFoo)
1160 1175 oinfo = ip.object_inspect("foo")
1161 1176 assert oinfo["found"] is True
1162 1177 assert oinfo["ismagic"] is True
1163 1178
1164 1179 oinfo = ip.object_inspect("%%foo")
1165 1180 assert oinfo["found"] is True
1166 1181 assert oinfo["ismagic"] is True
1167 1182 assert oinfo["docstring"] == FooFoo.cell_foo.__doc__
1168 1183
1169 1184 oinfo = ip.object_inspect("%foo")
1170 1185 assert oinfo["found"] is True
1171 1186 assert oinfo["ismagic"] is True
1172 1187 assert oinfo["docstring"] == FooFoo.line_foo.__doc__
1173 1188
1174 1189
1175 1190 def test_multiple_magics():
1176 1191 ip = get_ipython()
1177 1192 foo1 = FooFoo(ip)
1178 1193 foo2 = FooFoo(ip)
1179 1194 mm = ip.magics_manager
1180 1195 mm.register(foo1)
1181 1196 assert mm.magics["line"]["foo"].__self__ is foo1
1182 1197 mm.register(foo2)
1183 1198 assert mm.magics["line"]["foo"].__self__ is foo2
1184 1199
1185 1200
1186 1201 def test_alias_magic():
1187 1202 """Test %alias_magic."""
1188 1203 ip = get_ipython()
1189 1204 mm = ip.magics_manager
1190 1205
1191 1206 # Basic operation: both cell and line magics are created, if possible.
1192 1207 ip.run_line_magic("alias_magic", "timeit_alias timeit")
1193 1208 assert "timeit_alias" in mm.magics["line"]
1194 1209 assert "timeit_alias" in mm.magics["cell"]
1195 1210
1196 1211 # --cell is specified, line magic not created.
1197 1212 ip.run_line_magic("alias_magic", "--cell timeit_cell_alias timeit")
1198 1213 assert "timeit_cell_alias" not in mm.magics["line"]
1199 1214 assert "timeit_cell_alias" in mm.magics["cell"]
1200 1215
1201 1216 # Test that line alias is created successfully.
1202 1217 ip.run_line_magic("alias_magic", "--line env_alias env")
1203 1218 assert ip.run_line_magic("env", "") == ip.run_line_magic("env_alias", "")
1204 1219
1205 1220 # Test that line alias with parameters passed in is created successfully.
1206 1221 ip.run_line_magic(
1207 1222 "alias_magic", "--line history_alias history --params " + shlex.quote("3")
1208 1223 )
1209 1224 assert "history_alias" in mm.magics["line"]
1210 1225
1211 1226
1212 1227 def test_save():
1213 1228 """Test %save."""
1214 1229 ip = get_ipython()
1215 1230 ip.history_manager.reset() # Clear any existing history.
1216 1231 cmds = ["a=1", "def b():\n return a**2", "print(a, b())"]
1217 1232 for i, cmd in enumerate(cmds, start=1):
1218 1233 ip.history_manager.store_inputs(i, cmd)
1219 1234 with TemporaryDirectory() as tmpdir:
1220 1235 file = os.path.join(tmpdir, "testsave.py")
1221 1236 ip.run_line_magic("save", "%s 1-10" % file)
1222 1237 content = Path(file).read_text(encoding="utf-8")
1223 1238 assert content.count(cmds[0]) == 1
1224 1239 assert "coding: utf-8" in content
1225 1240 ip.run_line_magic("save", "-a %s 1-10" % file)
1226 1241 content = Path(file).read_text(encoding="utf-8")
1227 1242 assert content.count(cmds[0]) == 2
1228 1243 assert "coding: utf-8" in content
1229 1244
1230 1245
1231 1246 def test_save_with_no_args():
1232 1247 ip = get_ipython()
1233 1248 ip.history_manager.reset() # Clear any existing history.
1234 1249 cmds = ["a=1", "def b():\n return a**2", "print(a, b())", "%save"]
1235 1250 for i, cmd in enumerate(cmds, start=1):
1236 1251 ip.history_manager.store_inputs(i, cmd)
1237 1252
1238 1253 with TemporaryDirectory() as tmpdir:
1239 1254 path = os.path.join(tmpdir, "testsave.py")
1240 1255 ip.run_line_magic("save", path)
1241 1256 content = Path(path).read_text(encoding="utf-8")
1242 1257 expected_content = dedent(
1243 1258 """\
1244 1259 # coding: utf-8
1245 1260 a=1
1246 1261 def b():
1247 1262 return a**2
1248 1263 print(a, b())
1249 1264 """
1250 1265 )
1251 1266 assert content == expected_content
1252 1267
1253 1268
1254 1269 def test_store():
1255 1270 """Test %store."""
1256 1271 ip = get_ipython()
1257 1272 ip.run_line_magic('load_ext', 'storemagic')
1258 1273
1259 1274 # make sure the storage is empty
1260 1275 ip.run_line_magic("store", "-z")
1261 1276 ip.user_ns["var"] = 42
1262 1277 ip.run_line_magic("store", "var")
1263 1278 ip.user_ns["var"] = 39
1264 1279 ip.run_line_magic("store", "-r")
1265 1280 assert ip.user_ns["var"] == 42
1266 1281
1267 1282 ip.run_line_magic("store", "-d var")
1268 1283 ip.user_ns["var"] = 39
1269 1284 ip.run_line_magic("store", "-r")
1270 1285 assert ip.user_ns["var"] == 39
1271 1286
1272 1287
1273 1288 def _run_edit_test(arg_s, exp_filename=None,
1274 1289 exp_lineno=-1,
1275 1290 exp_contents=None,
1276 1291 exp_is_temp=None):
1277 1292 ip = get_ipython()
1278 1293 M = code.CodeMagics(ip)
1279 1294 last_call = ['','']
1280 1295 opts,args = M.parse_options(arg_s,'prxn:')
1281 1296 filename, lineno, is_temp = M._find_edit_target(ip, args, opts, last_call)
1282 1297
1283 1298 if exp_filename is not None:
1284 1299 assert exp_filename == filename
1285 1300 if exp_contents is not None:
1286 1301 with io.open(filename, 'r', encoding='utf-8') as f:
1287 1302 contents = f.read()
1288 1303 assert exp_contents == contents
1289 1304 if exp_lineno != -1:
1290 1305 assert exp_lineno == lineno
1291 1306 if exp_is_temp is not None:
1292 1307 assert exp_is_temp == is_temp
1293 1308
1294 1309
1295 1310 def test_edit_interactive():
1296 1311 """%edit on interactively defined objects"""
1297 1312 ip = get_ipython()
1298 1313 n = ip.execution_count
1299 1314 ip.run_cell("def foo(): return 1", store_history=True)
1300 1315
1301 1316 with pytest.raises(code.InteractivelyDefined) as e:
1302 1317 _run_edit_test("foo")
1303 1318 assert e.value.index == n
1304 1319
1305 1320
1306 1321 def test_edit_cell():
1307 1322 """%edit [cell id]"""
1308 1323 ip = get_ipython()
1309 1324
1310 1325 ip.run_cell("def foo(): return 1", store_history=True)
1311 1326
1312 1327 # test
1313 1328 _run_edit_test("1", exp_contents=ip.user_ns['In'][1], exp_is_temp=True)
1314 1329
1315 1330 def test_edit_fname():
1316 1331 """%edit file"""
1317 1332 # test
1318 1333 _run_edit_test("test file.py", exp_filename="test file.py")
1319 1334
1320 1335 def test_bookmark():
1321 1336 ip = get_ipython()
1322 1337 ip.run_line_magic('bookmark', 'bmname')
1323 1338 with tt.AssertPrints('bmname'):
1324 1339 ip.run_line_magic('bookmark', '-l')
1325 1340 ip.run_line_magic('bookmark', '-d bmname')
1326 1341
1327 1342 def test_ls_magic():
1328 1343 ip = get_ipython()
1329 1344 json_formatter = ip.display_formatter.formatters['application/json']
1330 1345 json_formatter.enabled = True
1331 1346 lsmagic = ip.run_line_magic("lsmagic", "")
1332 1347 with warnings.catch_warnings(record=True) as w:
1333 1348 j = json_formatter(lsmagic)
1334 1349 assert sorted(j) == ["cell", "line"]
1335 1350 assert w == [] # no warnings
1336 1351
1337 1352
1338 1353 def test_strip_initial_indent():
1339 1354 def sii(s):
1340 1355 lines = s.splitlines()
1341 1356 return '\n'.join(code.strip_initial_indent(lines))
1342 1357
1343 1358 assert sii(" a = 1\nb = 2") == "a = 1\nb = 2"
1344 1359 assert sii(" a\n b\nc") == "a\n b\nc"
1345 1360 assert sii("a\n b") == "a\n b"
1346 1361
1347 1362 def test_logging_magic_quiet_from_arg():
1348 1363 _ip.config.LoggingMagics.quiet = False
1349 1364 lm = logging.LoggingMagics(shell=_ip)
1350 1365 with TemporaryDirectory() as td:
1351 1366 try:
1352 1367 with tt.AssertNotPrints(re.compile("Activating.*")):
1353 1368 lm.logstart('-q {}'.format(
1354 1369 os.path.join(td, "quiet_from_arg.log")))
1355 1370 finally:
1356 1371 _ip.logger.logstop()
1357 1372
1358 1373 def test_logging_magic_quiet_from_config():
1359 1374 _ip.config.LoggingMagics.quiet = True
1360 1375 lm = logging.LoggingMagics(shell=_ip)
1361 1376 with TemporaryDirectory() as td:
1362 1377 try:
1363 1378 with tt.AssertNotPrints(re.compile("Activating.*")):
1364 1379 lm.logstart(os.path.join(td, "quiet_from_config.log"))
1365 1380 finally:
1366 1381 _ip.logger.logstop()
1367 1382
1368 1383
1369 1384 def test_logging_magic_not_quiet():
1370 1385 _ip.config.LoggingMagics.quiet = False
1371 1386 lm = logging.LoggingMagics(shell=_ip)
1372 1387 with TemporaryDirectory() as td:
1373 1388 try:
1374 1389 with tt.AssertPrints(re.compile("Activating.*")):
1375 1390 lm.logstart(os.path.join(td, "not_quiet.log"))
1376 1391 finally:
1377 1392 _ip.logger.logstop()
1378 1393
1379 1394
1380 1395 def test_time_no_var_expand():
1381 1396 _ip.user_ns["a"] = 5
1382 1397 _ip.user_ns["b"] = []
1383 1398 _ip.run_line_magic("time", 'b.append("{a}")')
1384 1399 assert _ip.user_ns["b"] == ["{a}"]
1385 1400
1386 1401
1387 1402 # this is slow, put at the end for local testing.
1388 1403 def test_timeit_arguments():
1389 1404 "Test valid timeit arguments, should not cause SyntaxError (GH #1269)"
1390 1405 _ip.run_line_magic("timeit", "-n1 -r1 a=('#')")
1391 1406
1392 1407
1393 1408 MINIMAL_LAZY_MAGIC = """
1394 1409 from IPython.core.magic import (
1395 1410 Magics,
1396 1411 magics_class,
1397 1412 line_magic,
1398 1413 cell_magic,
1399 1414 )
1400 1415
1401 1416
1402 1417 @magics_class
1403 1418 class LazyMagics(Magics):
1404 1419 @line_magic
1405 1420 def lazy_line(self, line):
1406 1421 print("Lazy Line")
1407 1422
1408 1423 @cell_magic
1409 1424 def lazy_cell(self, line, cell):
1410 1425 print("Lazy Cell")
1411 1426
1412 1427
1413 1428 def load_ipython_extension(ipython):
1414 1429 ipython.register_magics(LazyMagics)
1415 1430 """
1416 1431
1417 1432
1418 1433 def test_lazy_magics():
1419 1434 with pytest.raises(UsageError):
1420 1435 ip.run_line_magic("lazy_line", "")
1421 1436
1422 1437 startdir = os.getcwd()
1423 1438
1424 1439 with TemporaryDirectory() as tmpdir:
1425 1440 with prepended_to_syspath(tmpdir):
1426 1441 ptempdir = Path(tmpdir)
1427 1442 tf = ptempdir / "lazy_magic_module.py"
1428 1443 tf.write_text(MINIMAL_LAZY_MAGIC)
1429 1444 ip.magics_manager.register_lazy("lazy_line", Path(tf.name).name[:-3])
1430 1445 with tt.AssertPrints("Lazy Line"):
1431 1446 ip.run_line_magic("lazy_line", "")
1432 1447
1433 1448
1434 1449 TEST_MODULE = """
1435 1450 print('Loaded my_tmp')
1436 1451 if __name__ == "__main__":
1437 1452 print('I just ran a script')
1438 1453 """
1439 1454
1440 1455 def test_run_module_from_import_hook():
1441 1456 "Test that a module can be loaded via an import hook"
1442 1457 with TemporaryDirectory() as tmpdir:
1443 1458 fullpath = os.path.join(tmpdir, "my_tmp.py")
1444 1459 Path(fullpath).write_text(TEST_MODULE, encoding="utf-8")
1445 1460
1446 1461 import importlib.abc
1447 1462 import importlib.util
1448 1463
1449 1464 class MyTempImporter(importlib.abc.MetaPathFinder, importlib.abc.SourceLoader):
1450 1465 def find_spec(self, fullname, path, target=None):
1451 1466 if fullname == "my_tmp":
1452 1467 return importlib.util.spec_from_loader(fullname, self)
1453 1468
1454 1469 def get_filename(self, fullname):
1455 1470 assert fullname == "my_tmp"
1456 1471 return fullpath
1457 1472
1458 1473 def get_data(self, path):
1459 1474 assert Path(path).samefile(fullpath)
1460 1475 return Path(fullpath).read_text(encoding="utf-8")
1461 1476
1462 1477 sys.meta_path.insert(0, MyTempImporter())
1463 1478
1464 1479 with capture_output() as captured:
1465 1480 _ip.run_line_magic("run", "-m my_tmp")
1466 1481 _ip.run_cell("import my_tmp")
1467 1482
1468 1483 output = "Loaded my_tmp\nI just ran a script\nLoaded my_tmp\n"
1469 1484 assert output == captured.stdout
1470 1485
1471 1486 sys.meta_path.pop(0)
General Comments 0
You need to be logged in to leave comments. Login now