##// END OF EJS Templates
Preserve function/method identity in magic decorators...
Nikita Kniazev -
Show More
@@ -1,717 +1,712 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """Magic functions for InteractiveShell.
2 """Magic functions for InteractiveShell.
3 """
3 """
4
4
5 #-----------------------------------------------------------------------------
5 #-----------------------------------------------------------------------------
6 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and
6 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de> and
7 # Copyright (C) 2001 Fernando Perez <fperez@colorado.edu>
7 # Copyright (C) 2001 Fernando Perez <fperez@colorado.edu>
8 # Copyright (C) 2008 The IPython Development Team
8 # Copyright (C) 2008 The IPython Development Team
9
9
10 # Distributed under the terms of the BSD License. The full license is in
10 # Distributed under the terms of the BSD License. The full license is in
11 # the file COPYING, distributed as part of this software.
11 # the file COPYING, distributed as part of this software.
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13
13
14 import os
14 import os
15 import re
15 import re
16 import sys
16 import sys
17 from getopt import getopt, GetoptError
17 from getopt import getopt, GetoptError
18
18
19 from traitlets.config.configurable import Configurable
19 from traitlets.config.configurable import Configurable
20 from . import oinspect
20 from . import oinspect
21 from .error import UsageError
21 from .error import UsageError
22 from .inputtransformer2 import ESC_MAGIC, ESC_MAGIC2
22 from .inputtransformer2 import ESC_MAGIC, ESC_MAGIC2
23 from decorator import decorator
24 from ..utils.ipstruct import Struct
23 from ..utils.ipstruct import Struct
25 from ..utils.process import arg_split
24 from ..utils.process import arg_split
26 from ..utils.text import dedent
25 from ..utils.text import dedent
27 from traitlets import Bool, Dict, Instance, observe
26 from traitlets import Bool, Dict, Instance, observe
28 from logging import error
27 from logging import error
29
28
30 #-----------------------------------------------------------------------------
29 #-----------------------------------------------------------------------------
31 # Globals
30 # Globals
32 #-----------------------------------------------------------------------------
31 #-----------------------------------------------------------------------------
33
32
34 # A dict we'll use for each class that has magics, used as temporary storage to
33 # A dict we'll use for each class that has magics, used as temporary storage to
35 # pass information between the @line/cell_magic method decorators and the
34 # pass information between the @line/cell_magic method decorators and the
36 # @magics_class class decorator, because the method decorators have no
35 # @magics_class class decorator, because the method decorators have no
37 # access to the class when they run. See for more details:
36 # access to the class when they run. See for more details:
38 # http://stackoverflow.com/questions/2366713/can-a-python-decorator-of-an-instance-method-access-the-class
37 # http://stackoverflow.com/questions/2366713/can-a-python-decorator-of-an-instance-method-access-the-class
39
38
40 magics = dict(line={}, cell={})
39 magics = dict(line={}, cell={})
41
40
42 magic_kinds = ('line', 'cell')
41 magic_kinds = ('line', 'cell')
43 magic_spec = ('line', 'cell', 'line_cell')
42 magic_spec = ('line', 'cell', 'line_cell')
44 magic_escapes = dict(line=ESC_MAGIC, cell=ESC_MAGIC2)
43 magic_escapes = dict(line=ESC_MAGIC, cell=ESC_MAGIC2)
45
44
46 #-----------------------------------------------------------------------------
45 #-----------------------------------------------------------------------------
47 # Utility classes and functions
46 # Utility classes and functions
48 #-----------------------------------------------------------------------------
47 #-----------------------------------------------------------------------------
49
48
50 class Bunch: pass
49 class Bunch: pass
51
50
52
51
53 def on_off(tag):
52 def on_off(tag):
54 """Return an ON/OFF string for a 1/0 input. Simple utility function."""
53 """Return an ON/OFF string for a 1/0 input. Simple utility function."""
55 return ['OFF','ON'][tag]
54 return ['OFF','ON'][tag]
56
55
57
56
58 def compress_dhist(dh):
57 def compress_dhist(dh):
59 """Compress a directory history into a new one with at most 20 entries.
58 """Compress a directory history into a new one with at most 20 entries.
60
59
61 Return a new list made from the first and last 10 elements of dhist after
60 Return a new list made from the first and last 10 elements of dhist after
62 removal of duplicates.
61 removal of duplicates.
63 """
62 """
64 head, tail = dh[:-10], dh[-10:]
63 head, tail = dh[:-10], dh[-10:]
65
64
66 newhead = []
65 newhead = []
67 done = set()
66 done = set()
68 for h in head:
67 for h in head:
69 if h in done:
68 if h in done:
70 continue
69 continue
71 newhead.append(h)
70 newhead.append(h)
72 done.add(h)
71 done.add(h)
73
72
74 return newhead + tail
73 return newhead + tail
75
74
76
75
77 def needs_local_scope(func):
76 def needs_local_scope(func):
78 """Decorator to mark magic functions which need to local scope to run."""
77 """Decorator to mark magic functions which need to local scope to run."""
79 func.needs_local_scope = True
78 func.needs_local_scope = True
80 return func
79 return func
81
80
82 #-----------------------------------------------------------------------------
81 #-----------------------------------------------------------------------------
83 # Class and method decorators for registering magics
82 # Class and method decorators for registering magics
84 #-----------------------------------------------------------------------------
83 #-----------------------------------------------------------------------------
85
84
86 def magics_class(cls):
85 def magics_class(cls):
87 """Class decorator for all subclasses of the main Magics class.
86 """Class decorator for all subclasses of the main Magics class.
88
87
89 Any class that subclasses Magics *must* also apply this decorator, to
88 Any class that subclasses Magics *must* also apply this decorator, to
90 ensure that all the methods that have been decorated as line/cell magics
89 ensure that all the methods that have been decorated as line/cell magics
91 get correctly registered in the class instance. This is necessary because
90 get correctly registered in the class instance. This is necessary because
92 when method decorators run, the class does not exist yet, so they
91 when method decorators run, the class does not exist yet, so they
93 temporarily store their information into a module global. Application of
92 temporarily store their information into a module global. Application of
94 this class decorator copies that global data to the class instance and
93 this class decorator copies that global data to the class instance and
95 clears the global.
94 clears the global.
96
95
97 Obviously, this mechanism is not thread-safe, which means that the
96 Obviously, this mechanism is not thread-safe, which means that the
98 *creation* of subclasses of Magic should only be done in a single-thread
97 *creation* of subclasses of Magic should only be done in a single-thread
99 context. Instantiation of the classes has no restrictions. Given that
98 context. Instantiation of the classes has no restrictions. Given that
100 these classes are typically created at IPython startup time and before user
99 these classes are typically created at IPython startup time and before user
101 application code becomes active, in practice this should not pose any
100 application code becomes active, in practice this should not pose any
102 problems.
101 problems.
103 """
102 """
104 cls.registered = True
103 cls.registered = True
105 cls.magics = dict(line = magics['line'],
104 cls.magics = dict(line = magics['line'],
106 cell = magics['cell'])
105 cell = magics['cell'])
107 magics['line'] = {}
106 magics['line'] = {}
108 magics['cell'] = {}
107 magics['cell'] = {}
109 return cls
108 return cls
110
109
111
110
112 def record_magic(dct, magic_kind, magic_name, func):
111 def record_magic(dct, magic_kind, magic_name, func):
113 """Utility function to store a function as a magic of a specific kind.
112 """Utility function to store a function as a magic of a specific kind.
114
113
115 Parameters
114 Parameters
116 ----------
115 ----------
117 dct : dict
116 dct : dict
118 A dictionary with 'line' and 'cell' subdicts.
117 A dictionary with 'line' and 'cell' subdicts.
119
118
120 magic_kind : str
119 magic_kind : str
121 Kind of magic to be stored.
120 Kind of magic to be stored.
122
121
123 magic_name : str
122 magic_name : str
124 Key to store the magic as.
123 Key to store the magic as.
125
124
126 func : function
125 func : function
127 Callable object to store.
126 Callable object to store.
128 """
127 """
129 if magic_kind == 'line_cell':
128 if magic_kind == 'line_cell':
130 dct['line'][magic_name] = dct['cell'][magic_name] = func
129 dct['line'][magic_name] = dct['cell'][magic_name] = func
131 else:
130 else:
132 dct[magic_kind][magic_name] = func
131 dct[magic_kind][magic_name] = func
133
132
134
133
135 def validate_type(magic_kind):
134 def validate_type(magic_kind):
136 """Ensure that the given magic_kind is valid.
135 """Ensure that the given magic_kind is valid.
137
136
138 Check that the given magic_kind is one of the accepted spec types (stored
137 Check that the given magic_kind is one of the accepted spec types (stored
139 in the global `magic_spec`), raise ValueError otherwise.
138 in the global `magic_spec`), raise ValueError otherwise.
140 """
139 """
141 if magic_kind not in magic_spec:
140 if magic_kind not in magic_spec:
142 raise ValueError('magic_kind must be one of %s, %s given' %
141 raise ValueError('magic_kind must be one of %s, %s given' %
143 magic_kinds, magic_kind)
142 magic_kinds, magic_kind)
144
143
145
144
146 # The docstrings for the decorator below will be fairly similar for the two
145 # The docstrings for the decorator below will be fairly similar for the two
147 # types (method and function), so we generate them here once and reuse the
146 # types (method and function), so we generate them here once and reuse the
148 # templates below.
147 # templates below.
149 _docstring_template = \
148 _docstring_template = \
150 """Decorate the given {0} as {1} magic.
149 """Decorate the given {0} as {1} magic.
151
150
152 The decorator can be used with or without arguments, as follows.
151 The decorator can be used with or without arguments, as follows.
153
152
154 i) without arguments: it will create a {1} magic named as the {0} being
153 i) without arguments: it will create a {1} magic named as the {0} being
155 decorated::
154 decorated::
156
155
157 @deco
156 @deco
158 def foo(...)
157 def foo(...)
159
158
160 will create a {1} magic named `foo`.
159 will create a {1} magic named `foo`.
161
160
162 ii) with one string argument: which will be used as the actual name of the
161 ii) with one string argument: which will be used as the actual name of the
163 resulting magic::
162 resulting magic::
164
163
165 @deco('bar')
164 @deco('bar')
166 def foo(...)
165 def foo(...)
167
166
168 will create a {1} magic named `bar`.
167 will create a {1} magic named `bar`.
169
168
170 To register a class magic use ``Interactiveshell.register_magic(class or instance)``.
169 To register a class magic use ``Interactiveshell.register_magic(class or instance)``.
171 """
170 """
172
171
173 # These two are decorator factories. While they are conceptually very similar,
172 # These two are decorator factories. While they are conceptually very similar,
174 # there are enough differences in the details that it's simpler to have them
173 # there are enough differences in the details that it's simpler to have them
175 # written as completely standalone functions rather than trying to share code
174 # written as completely standalone functions rather than trying to share code
176 # and make a single one with convoluted logic.
175 # and make a single one with convoluted logic.
177
176
178 def _method_magic_marker(magic_kind):
177 def _method_magic_marker(magic_kind):
179 """Decorator factory for methods in Magics subclasses.
178 """Decorator factory for methods in Magics subclasses.
180 """
179 """
181
180
182 validate_type(magic_kind)
181 validate_type(magic_kind)
183
182
184 # This is a closure to capture the magic_kind. We could also use a class,
183 # This is a closure to capture the magic_kind. We could also use a class,
185 # but it's overkill for just that one bit of state.
184 # but it's overkill for just that one bit of state.
186 def magic_deco(arg):
185 def magic_deco(arg):
187 call = lambda f, *a, **k: f(*a, **k)
188
189 if callable(arg):
186 if callable(arg):
190 # "Naked" decorator call (just @foo, no args)
187 # "Naked" decorator call (just @foo, no args)
191 func = arg
188 func = arg
192 name = func.__name__
189 name = func.__name__
193 retval = decorator(call, func)
190 retval = arg
194 record_magic(magics, magic_kind, name, name)
191 record_magic(magics, magic_kind, name, name)
195 elif isinstance(arg, str):
192 elif isinstance(arg, str):
196 # Decorator called with arguments (@foo('bar'))
193 # Decorator called with arguments (@foo('bar'))
197 name = arg
194 name = arg
198 def mark(func, *a, **kw):
195 def mark(func, *a, **kw):
199 record_magic(magics, magic_kind, name, func.__name__)
196 record_magic(magics, magic_kind, name, func.__name__)
200 return decorator(call, func)
197 return func
201 retval = mark
198 retval = mark
202 else:
199 else:
203 raise TypeError("Decorator can only be called with "
200 raise TypeError("Decorator can only be called with "
204 "string or function")
201 "string or function")
205 return retval
202 return retval
206
203
207 # Ensure the resulting decorator has a usable docstring
204 # Ensure the resulting decorator has a usable docstring
208 magic_deco.__doc__ = _docstring_template.format('method', magic_kind)
205 magic_deco.__doc__ = _docstring_template.format('method', magic_kind)
209 return magic_deco
206 return magic_deco
210
207
211
208
212 def _function_magic_marker(magic_kind):
209 def _function_magic_marker(magic_kind):
213 """Decorator factory for standalone functions.
210 """Decorator factory for standalone functions.
214 """
211 """
215 validate_type(magic_kind)
212 validate_type(magic_kind)
216
213
217 # This is a closure to capture the magic_kind. We could also use a class,
214 # This is a closure to capture the magic_kind. We could also use a class,
218 # but it's overkill for just that one bit of state.
215 # but it's overkill for just that one bit of state.
219 def magic_deco(arg):
216 def magic_deco(arg):
220 call = lambda f, *a, **k: f(*a, **k)
221
222 # Find get_ipython() in the caller's namespace
217 # Find get_ipython() in the caller's namespace
223 caller = sys._getframe(1)
218 caller = sys._getframe(1)
224 for ns in ['f_locals', 'f_globals', 'f_builtins']:
219 for ns in ['f_locals', 'f_globals', 'f_builtins']:
225 get_ipython = getattr(caller, ns).get('get_ipython')
220 get_ipython = getattr(caller, ns).get('get_ipython')
226 if get_ipython is not None:
221 if get_ipython is not None:
227 break
222 break
228 else:
223 else:
229 raise NameError('Decorator can only run in context where '
224 raise NameError('Decorator can only run in context where '
230 '`get_ipython` exists')
225 '`get_ipython` exists')
231
226
232 ip = get_ipython()
227 ip = get_ipython()
233
228
234 if callable(arg):
229 if callable(arg):
235 # "Naked" decorator call (just @foo, no args)
230 # "Naked" decorator call (just @foo, no args)
236 func = arg
231 func = arg
237 name = func.__name__
232 name = func.__name__
238 ip.register_magic_function(func, magic_kind, name)
233 ip.register_magic_function(func, magic_kind, name)
239 retval = decorator(call, func)
234 retval = arg
240 elif isinstance(arg, str):
235 elif isinstance(arg, str):
241 # Decorator called with arguments (@foo('bar'))
236 # Decorator called with arguments (@foo('bar'))
242 name = arg
237 name = arg
243 def mark(func, *a, **kw):
238 def mark(func, *a, **kw):
244 ip.register_magic_function(func, magic_kind, name)
239 ip.register_magic_function(func, magic_kind, name)
245 return decorator(call, func)
240 return func
246 retval = mark
241 retval = mark
247 else:
242 else:
248 raise TypeError("Decorator can only be called with "
243 raise TypeError("Decorator can only be called with "
249 "string or function")
244 "string or function")
250 return retval
245 return retval
251
246
252 # Ensure the resulting decorator has a usable docstring
247 # Ensure the resulting decorator has a usable docstring
253 ds = _docstring_template.format('function', magic_kind)
248 ds = _docstring_template.format('function', magic_kind)
254
249
255 ds += dedent("""
250 ds += dedent("""
256 Note: this decorator can only be used in a context where IPython is already
251 Note: this decorator can only be used in a context where IPython is already
257 active, so that the `get_ipython()` call succeeds. You can therefore use
252 active, so that the `get_ipython()` call succeeds. You can therefore use
258 it in your startup files loaded after IPython initializes, but *not* in the
253 it in your startup files loaded after IPython initializes, but *not* in the
259 IPython configuration file itself, which is executed before IPython is
254 IPython configuration file itself, which is executed before IPython is
260 fully up and running. Any file located in the `startup` subdirectory of
255 fully up and running. Any file located in the `startup` subdirectory of
261 your configuration profile will be OK in this sense.
256 your configuration profile will be OK in this sense.
262 """)
257 """)
263
258
264 magic_deco.__doc__ = ds
259 magic_deco.__doc__ = ds
265 return magic_deco
260 return magic_deco
266
261
267
262
268 MAGIC_NO_VAR_EXPAND_ATTR = '_ipython_magic_no_var_expand'
263 MAGIC_NO_VAR_EXPAND_ATTR = '_ipython_magic_no_var_expand'
269
264
270
265
271 def no_var_expand(magic_func):
266 def no_var_expand(magic_func):
272 """Mark a magic function as not needing variable expansion
267 """Mark a magic function as not needing variable expansion
273
268
274 By default, IPython interprets `{a}` or `$a` in the line passed to magics
269 By default, IPython interprets `{a}` or `$a` in the line passed to magics
275 as variables that should be interpolated from the interactive namespace
270 as variables that should be interpolated from the interactive namespace
276 before passing the line to the magic function.
271 before passing the line to the magic function.
277 This is not always desirable, e.g. when the magic executes Python code
272 This is not always desirable, e.g. when the magic executes Python code
278 (%timeit, %time, etc.).
273 (%timeit, %time, etc.).
279 Decorate magics with `@no_var_expand` to opt-out of variable expansion.
274 Decorate magics with `@no_var_expand` to opt-out of variable expansion.
280
275
281 .. versionadded:: 7.3
276 .. versionadded:: 7.3
282 """
277 """
283 setattr(magic_func, MAGIC_NO_VAR_EXPAND_ATTR, True)
278 setattr(magic_func, MAGIC_NO_VAR_EXPAND_ATTR, True)
284 return magic_func
279 return magic_func
285
280
286
281
287 # Create the actual decorators for public use
282 # Create the actual decorators for public use
288
283
289 # These three are used to decorate methods in class definitions
284 # These three are used to decorate methods in class definitions
290 line_magic = _method_magic_marker('line')
285 line_magic = _method_magic_marker('line')
291 cell_magic = _method_magic_marker('cell')
286 cell_magic = _method_magic_marker('cell')
292 line_cell_magic = _method_magic_marker('line_cell')
287 line_cell_magic = _method_magic_marker('line_cell')
293
288
294 # These three decorate standalone functions and perform the decoration
289 # These three decorate standalone functions and perform the decoration
295 # immediately. They can only run where get_ipython() works
290 # immediately. They can only run where get_ipython() works
296 register_line_magic = _function_magic_marker('line')
291 register_line_magic = _function_magic_marker('line')
297 register_cell_magic = _function_magic_marker('cell')
292 register_cell_magic = _function_magic_marker('cell')
298 register_line_cell_magic = _function_magic_marker('line_cell')
293 register_line_cell_magic = _function_magic_marker('line_cell')
299
294
300 #-----------------------------------------------------------------------------
295 #-----------------------------------------------------------------------------
301 # Core Magic classes
296 # Core Magic classes
302 #-----------------------------------------------------------------------------
297 #-----------------------------------------------------------------------------
303
298
304 class MagicsManager(Configurable):
299 class MagicsManager(Configurable):
305 """Object that handles all magic-related functionality for IPython.
300 """Object that handles all magic-related functionality for IPython.
306 """
301 """
307 # Non-configurable class attributes
302 # Non-configurable class attributes
308
303
309 # A two-level dict, first keyed by magic type, then by magic function, and
304 # A two-level dict, first keyed by magic type, then by magic function, and
310 # holding the actual callable object as value. This is the dict used for
305 # holding the actual callable object as value. This is the dict used for
311 # magic function dispatch
306 # magic function dispatch
312 magics = Dict()
307 magics = Dict()
313
308
314 # A registry of the original objects that we've been given holding magics.
309 # A registry of the original objects that we've been given holding magics.
315 registry = Dict()
310 registry = Dict()
316
311
317 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
312 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
318
313
319 auto_magic = Bool(True, help=
314 auto_magic = Bool(True, help=
320 "Automatically call line magics without requiring explicit % prefix"
315 "Automatically call line magics without requiring explicit % prefix"
321 ).tag(config=True)
316 ).tag(config=True)
322 @observe('auto_magic')
317 @observe('auto_magic')
323 def _auto_magic_changed(self, change):
318 def _auto_magic_changed(self, change):
324 self.shell.automagic = change['new']
319 self.shell.automagic = change['new']
325
320
326 _auto_status = [
321 _auto_status = [
327 'Automagic is OFF, % prefix IS needed for line magics.',
322 'Automagic is OFF, % prefix IS needed for line magics.',
328 'Automagic is ON, % prefix IS NOT needed for line magics.']
323 'Automagic is ON, % prefix IS NOT needed for line magics.']
329
324
330 user_magics = Instance('IPython.core.magics.UserMagics', allow_none=True)
325 user_magics = Instance('IPython.core.magics.UserMagics', allow_none=True)
331
326
332 def __init__(self, shell=None, config=None, user_magics=None, **traits):
327 def __init__(self, shell=None, config=None, user_magics=None, **traits):
333
328
334 super(MagicsManager, self).__init__(shell=shell, config=config,
329 super(MagicsManager, self).__init__(shell=shell, config=config,
335 user_magics=user_magics, **traits)
330 user_magics=user_magics, **traits)
336 self.magics = dict(line={}, cell={})
331 self.magics = dict(line={}, cell={})
337 # Let's add the user_magics to the registry for uniformity, so *all*
332 # Let's add the user_magics to the registry for uniformity, so *all*
338 # registered magic containers can be found there.
333 # registered magic containers can be found there.
339 self.registry[user_magics.__class__.__name__] = user_magics
334 self.registry[user_magics.__class__.__name__] = user_magics
340
335
341 def auto_status(self):
336 def auto_status(self):
342 """Return descriptive string with automagic status."""
337 """Return descriptive string with automagic status."""
343 return self._auto_status[self.auto_magic]
338 return self._auto_status[self.auto_magic]
344
339
345 def lsmagic(self):
340 def lsmagic(self):
346 """Return a dict of currently available magic functions.
341 """Return a dict of currently available magic functions.
347
342
348 The return dict has the keys 'line' and 'cell', corresponding to the
343 The return dict has the keys 'line' and 'cell', corresponding to the
349 two types of magics we support. Each value is a list of names.
344 two types of magics we support. Each value is a list of names.
350 """
345 """
351 return self.magics
346 return self.magics
352
347
353 def lsmagic_docs(self, brief=False, missing=''):
348 def lsmagic_docs(self, brief=False, missing=''):
354 """Return dict of documentation of magic functions.
349 """Return dict of documentation of magic functions.
355
350
356 The return dict has the keys 'line' and 'cell', corresponding to the
351 The return dict has the keys 'line' and 'cell', corresponding to the
357 two types of magics we support. Each value is a dict keyed by magic
352 two types of magics we support. Each value is a dict keyed by magic
358 name whose value is the function docstring. If a docstring is
353 name whose value is the function docstring. If a docstring is
359 unavailable, the value of `missing` is used instead.
354 unavailable, the value of `missing` is used instead.
360
355
361 If brief is True, only the first line of each docstring will be returned.
356 If brief is True, only the first line of each docstring will be returned.
362 """
357 """
363 docs = {}
358 docs = {}
364 for m_type in self.magics:
359 for m_type in self.magics:
365 m_docs = {}
360 m_docs = {}
366 for m_name, m_func in self.magics[m_type].items():
361 for m_name, m_func in self.magics[m_type].items():
367 if m_func.__doc__:
362 if m_func.__doc__:
368 if brief:
363 if brief:
369 m_docs[m_name] = m_func.__doc__.split('\n', 1)[0]
364 m_docs[m_name] = m_func.__doc__.split('\n', 1)[0]
370 else:
365 else:
371 m_docs[m_name] = m_func.__doc__.rstrip()
366 m_docs[m_name] = m_func.__doc__.rstrip()
372 else:
367 else:
373 m_docs[m_name] = missing
368 m_docs[m_name] = missing
374 docs[m_type] = m_docs
369 docs[m_type] = m_docs
375 return docs
370 return docs
376
371
377 def register(self, *magic_objects):
372 def register(self, *magic_objects):
378 """Register one or more instances of Magics.
373 """Register one or more instances of Magics.
379
374
380 Take one or more classes or instances of classes that subclass the main
375 Take one or more classes or instances of classes that subclass the main
381 `core.Magic` class, and register them with IPython to use the magic
376 `core.Magic` class, and register them with IPython to use the magic
382 functions they provide. The registration process will then ensure that
377 functions they provide. The registration process will then ensure that
383 any methods that have decorated to provide line and/or cell magics will
378 any methods that have decorated to provide line and/or cell magics will
384 be recognized with the `%x`/`%%x` syntax as a line/cell magic
379 be recognized with the `%x`/`%%x` syntax as a line/cell magic
385 respectively.
380 respectively.
386
381
387 If classes are given, they will be instantiated with the default
382 If classes are given, they will be instantiated with the default
388 constructor. If your classes need a custom constructor, you should
383 constructor. If your classes need a custom constructor, you should
389 instanitate them first and pass the instance.
384 instanitate them first and pass the instance.
390
385
391 The provided arguments can be an arbitrary mix of classes and instances.
386 The provided arguments can be an arbitrary mix of classes and instances.
392
387
393 Parameters
388 Parameters
394 ----------
389 ----------
395 magic_objects : one or more classes or instances
390 magic_objects : one or more classes or instances
396 """
391 """
397 # Start by validating them to ensure they have all had their magic
392 # Start by validating them to ensure they have all had their magic
398 # methods registered at the instance level
393 # methods registered at the instance level
399 for m in magic_objects:
394 for m in magic_objects:
400 if not m.registered:
395 if not m.registered:
401 raise ValueError("Class of magics %r was constructed without "
396 raise ValueError("Class of magics %r was constructed without "
402 "the @register_magics class decorator")
397 "the @register_magics class decorator")
403 if isinstance(m, type):
398 if isinstance(m, type):
404 # If we're given an uninstantiated class
399 # If we're given an uninstantiated class
405 m = m(shell=self.shell)
400 m = m(shell=self.shell)
406
401
407 # Now that we have an instance, we can register it and update the
402 # Now that we have an instance, we can register it and update the
408 # table of callables
403 # table of callables
409 self.registry[m.__class__.__name__] = m
404 self.registry[m.__class__.__name__] = m
410 for mtype in magic_kinds:
405 for mtype in magic_kinds:
411 self.magics[mtype].update(m.magics[mtype])
406 self.magics[mtype].update(m.magics[mtype])
412
407
413 def register_function(self, func, magic_kind='line', magic_name=None):
408 def register_function(self, func, magic_kind='line', magic_name=None):
414 """Expose a standalone function as magic function for IPython.
409 """Expose a standalone function as magic function for IPython.
415
410
416 This will create an IPython magic (line, cell or both) from a
411 This will create an IPython magic (line, cell or both) from a
417 standalone function. The functions should have the following
412 standalone function. The functions should have the following
418 signatures:
413 signatures:
419
414
420 * For line magics: `def f(line)`
415 * For line magics: `def f(line)`
421 * For cell magics: `def f(line, cell)`
416 * For cell magics: `def f(line, cell)`
422 * For a function that does both: `def f(line, cell=None)`
417 * For a function that does both: `def f(line, cell=None)`
423
418
424 In the latter case, the function will be called with `cell==None` when
419 In the latter case, the function will be called with `cell==None` when
425 invoked as `%f`, and with cell as a string when invoked as `%%f`.
420 invoked as `%f`, and with cell as a string when invoked as `%%f`.
426
421
427 Parameters
422 Parameters
428 ----------
423 ----------
429 func : callable
424 func : callable
430 Function to be registered as a magic.
425 Function to be registered as a magic.
431
426
432 magic_kind : str
427 magic_kind : str
433 Kind of magic, one of 'line', 'cell' or 'line_cell'
428 Kind of magic, one of 'line', 'cell' or 'line_cell'
434
429
435 magic_name : optional str
430 magic_name : optional str
436 If given, the name the magic will have in the IPython namespace. By
431 If given, the name the magic will have in the IPython namespace. By
437 default, the name of the function itself is used.
432 default, the name of the function itself is used.
438 """
433 """
439
434
440 # Create the new method in the user_magics and register it in the
435 # Create the new method in the user_magics and register it in the
441 # global table
436 # global table
442 validate_type(magic_kind)
437 validate_type(magic_kind)
443 magic_name = func.__name__ if magic_name is None else magic_name
438 magic_name = func.__name__ if magic_name is None else magic_name
444 setattr(self.user_magics, magic_name, func)
439 setattr(self.user_magics, magic_name, func)
445 record_magic(self.magics, magic_kind, magic_name, func)
440 record_magic(self.magics, magic_kind, magic_name, func)
446
441
447 def register_alias(self, alias_name, magic_name, magic_kind='line', magic_params=None):
442 def register_alias(self, alias_name, magic_name, magic_kind='line', magic_params=None):
448 """Register an alias to a magic function.
443 """Register an alias to a magic function.
449
444
450 The alias is an instance of :class:`MagicAlias`, which holds the
445 The alias is an instance of :class:`MagicAlias`, which holds the
451 name and kind of the magic it should call. Binding is done at
446 name and kind of the magic it should call. Binding is done at
452 call time, so if the underlying magic function is changed the alias
447 call time, so if the underlying magic function is changed the alias
453 will call the new function.
448 will call the new function.
454
449
455 Parameters
450 Parameters
456 ----------
451 ----------
457 alias_name : str
452 alias_name : str
458 The name of the magic to be registered.
453 The name of the magic to be registered.
459
454
460 magic_name : str
455 magic_name : str
461 The name of an existing magic.
456 The name of an existing magic.
462
457
463 magic_kind : str
458 magic_kind : str
464 Kind of magic, one of 'line' or 'cell'
459 Kind of magic, one of 'line' or 'cell'
465 """
460 """
466
461
467 # `validate_type` is too permissive, as it allows 'line_cell'
462 # `validate_type` is too permissive, as it allows 'line_cell'
468 # which we do not handle.
463 # which we do not handle.
469 if magic_kind not in magic_kinds:
464 if magic_kind not in magic_kinds:
470 raise ValueError('magic_kind must be one of %s, %s given' %
465 raise ValueError('magic_kind must be one of %s, %s given' %
471 magic_kinds, magic_kind)
466 magic_kinds, magic_kind)
472
467
473 alias = MagicAlias(self.shell, magic_name, magic_kind, magic_params)
468 alias = MagicAlias(self.shell, magic_name, magic_kind, magic_params)
474 setattr(self.user_magics, alias_name, alias)
469 setattr(self.user_magics, alias_name, alias)
475 record_magic(self.magics, magic_kind, alias_name, alias)
470 record_magic(self.magics, magic_kind, alias_name, alias)
476
471
477 # Key base class that provides the central functionality for magics.
472 # Key base class that provides the central functionality for magics.
478
473
479
474
480 class Magics(Configurable):
475 class Magics(Configurable):
481 """Base class for implementing magic functions.
476 """Base class for implementing magic functions.
482
477
483 Shell functions which can be reached as %function_name. All magic
478 Shell functions which can be reached as %function_name. All magic
484 functions should accept a string, which they can parse for their own
479 functions should accept a string, which they can parse for their own
485 needs. This can make some functions easier to type, eg `%cd ../`
480 needs. This can make some functions easier to type, eg `%cd ../`
486 vs. `%cd("../")`
481 vs. `%cd("../")`
487
482
488 Classes providing magic functions need to subclass this class, and they
483 Classes providing magic functions need to subclass this class, and they
489 MUST:
484 MUST:
490
485
491 - Use the method decorators `@line_magic` and `@cell_magic` to decorate
486 - Use the method decorators `@line_magic` and `@cell_magic` to decorate
492 individual methods as magic functions, AND
487 individual methods as magic functions, AND
493
488
494 - Use the class decorator `@magics_class` to ensure that the magic
489 - Use the class decorator `@magics_class` to ensure that the magic
495 methods are properly registered at the instance level upon instance
490 methods are properly registered at the instance level upon instance
496 initialization.
491 initialization.
497
492
498 See :mod:`magic_functions` for examples of actual implementation classes.
493 See :mod:`magic_functions` for examples of actual implementation classes.
499 """
494 """
500 # Dict holding all command-line options for each magic.
495 # Dict holding all command-line options for each magic.
501 options_table = None
496 options_table = None
502 # Dict for the mapping of magic names to methods, set by class decorator
497 # Dict for the mapping of magic names to methods, set by class decorator
503 magics = None
498 magics = None
504 # Flag to check that the class decorator was properly applied
499 # Flag to check that the class decorator was properly applied
505 registered = False
500 registered = False
506 # Instance of IPython shell
501 # Instance of IPython shell
507 shell = None
502 shell = None
508
503
509 def __init__(self, shell=None, **kwargs):
504 def __init__(self, shell=None, **kwargs):
510 if not(self.__class__.registered):
505 if not(self.__class__.registered):
511 raise ValueError('Magics subclass without registration - '
506 raise ValueError('Magics subclass without registration - '
512 'did you forget to apply @magics_class?')
507 'did you forget to apply @magics_class?')
513 if shell is not None:
508 if shell is not None:
514 if hasattr(shell, 'configurables'):
509 if hasattr(shell, 'configurables'):
515 shell.configurables.append(self)
510 shell.configurables.append(self)
516 if hasattr(shell, 'config'):
511 if hasattr(shell, 'config'):
517 kwargs.setdefault('parent', shell)
512 kwargs.setdefault('parent', shell)
518
513
519 self.shell = shell
514 self.shell = shell
520 self.options_table = {}
515 self.options_table = {}
521 # The method decorators are run when the instance doesn't exist yet, so
516 # The method decorators are run when the instance doesn't exist yet, so
522 # they can only record the names of the methods they are supposed to
517 # they can only record the names of the methods they are supposed to
523 # grab. Only now, that the instance exists, can we create the proper
518 # grab. Only now, that the instance exists, can we create the proper
524 # mapping to bound methods. So we read the info off the original names
519 # mapping to bound methods. So we read the info off the original names
525 # table and replace each method name by the actual bound method.
520 # table and replace each method name by the actual bound method.
526 # But we mustn't clobber the *class* mapping, in case of multiple instances.
521 # But we mustn't clobber the *class* mapping, in case of multiple instances.
527 class_magics = self.magics
522 class_magics = self.magics
528 self.magics = {}
523 self.magics = {}
529 for mtype in magic_kinds:
524 for mtype in magic_kinds:
530 tab = self.magics[mtype] = {}
525 tab = self.magics[mtype] = {}
531 cls_tab = class_magics[mtype]
526 cls_tab = class_magics[mtype]
532 for magic_name, meth_name in cls_tab.items():
527 for magic_name, meth_name in cls_tab.items():
533 if isinstance(meth_name, str):
528 if isinstance(meth_name, str):
534 # it's a method name, grab it
529 # it's a method name, grab it
535 tab[magic_name] = getattr(self, meth_name)
530 tab[magic_name] = getattr(self, meth_name)
536 else:
531 else:
537 # it's the real thing
532 # it's the real thing
538 tab[magic_name] = meth_name
533 tab[magic_name] = meth_name
539 # Configurable **needs** to be initiated at the end or the config
534 # Configurable **needs** to be initiated at the end or the config
540 # magics get screwed up.
535 # magics get screwed up.
541 super(Magics, self).__init__(**kwargs)
536 super(Magics, self).__init__(**kwargs)
542
537
543 def arg_err(self,func):
538 def arg_err(self,func):
544 """Print docstring if incorrect arguments were passed"""
539 """Print docstring if incorrect arguments were passed"""
545 print('Error in arguments:')
540 print('Error in arguments:')
546 print(oinspect.getdoc(func))
541 print(oinspect.getdoc(func))
547
542
548 def format_latex(self, strng):
543 def format_latex(self, strng):
549 """Format a string for latex inclusion."""
544 """Format a string for latex inclusion."""
550
545
551 # Characters that need to be escaped for latex:
546 # Characters that need to be escaped for latex:
552 escape_re = re.compile(r'(%|_|\$|#|&)',re.MULTILINE)
547 escape_re = re.compile(r'(%|_|\$|#|&)',re.MULTILINE)
553 # Magic command names as headers:
548 # Magic command names as headers:
554 cmd_name_re = re.compile(r'^(%s.*?):' % ESC_MAGIC,
549 cmd_name_re = re.compile(r'^(%s.*?):' % ESC_MAGIC,
555 re.MULTILINE)
550 re.MULTILINE)
556 # Magic commands
551 # Magic commands
557 cmd_re = re.compile(r'(?P<cmd>%s.+?\b)(?!\}\}:)' % ESC_MAGIC,
552 cmd_re = re.compile(r'(?P<cmd>%s.+?\b)(?!\}\}:)' % ESC_MAGIC,
558 re.MULTILINE)
553 re.MULTILINE)
559 # Paragraph continue
554 # Paragraph continue
560 par_re = re.compile(r'\\$',re.MULTILINE)
555 par_re = re.compile(r'\\$',re.MULTILINE)
561
556
562 # The "\n" symbol
557 # The "\n" symbol
563 newline_re = re.compile(r'\\n')
558 newline_re = re.compile(r'\\n')
564
559
565 # Now build the string for output:
560 # Now build the string for output:
566 #strng = cmd_name_re.sub(r'\n\\texttt{\\textsl{\\large \1}}:',strng)
561 #strng = cmd_name_re.sub(r'\n\\texttt{\\textsl{\\large \1}}:',strng)
567 strng = cmd_name_re.sub(r'\n\\bigskip\n\\texttt{\\textbf{ \1}}:',
562 strng = cmd_name_re.sub(r'\n\\bigskip\n\\texttt{\\textbf{ \1}}:',
568 strng)
563 strng)
569 strng = cmd_re.sub(r'\\texttt{\g<cmd>}',strng)
564 strng = cmd_re.sub(r'\\texttt{\g<cmd>}',strng)
570 strng = par_re.sub(r'\\\\',strng)
565 strng = par_re.sub(r'\\\\',strng)
571 strng = escape_re.sub(r'\\\1',strng)
566 strng = escape_re.sub(r'\\\1',strng)
572 strng = newline_re.sub(r'\\textbackslash{}n',strng)
567 strng = newline_re.sub(r'\\textbackslash{}n',strng)
573 return strng
568 return strng
574
569
575 def parse_options(self, arg_str, opt_str, *long_opts, **kw):
570 def parse_options(self, arg_str, opt_str, *long_opts, **kw):
576 """Parse options passed to an argument string.
571 """Parse options passed to an argument string.
577
572
578 The interface is similar to that of :func:`getopt.getopt`, but it
573 The interface is similar to that of :func:`getopt.getopt`, but it
579 returns a :class:`~IPython.utils.struct.Struct` with the options as keys
574 returns a :class:`~IPython.utils.struct.Struct` with the options as keys
580 and the stripped argument string still as a string.
575 and the stripped argument string still as a string.
581
576
582 arg_str is quoted as a true sys.argv vector by using shlex.split.
577 arg_str is quoted as a true sys.argv vector by using shlex.split.
583 This allows us to easily expand variables, glob files, quote
578 This allows us to easily expand variables, glob files, quote
584 arguments, etc.
579 arguments, etc.
585
580
586 Parameters
581 Parameters
587 ----------
582 ----------
588
583
589 arg_str : str
584 arg_str : str
590 The arguments to parse.
585 The arguments to parse.
591
586
592 opt_str : str
587 opt_str : str
593 The options specification.
588 The options specification.
594
589
595 mode : str, default 'string'
590 mode : str, default 'string'
596 If given as 'list', the argument string is returned as a list (split
591 If given as 'list', the argument string is returned as a list (split
597 on whitespace) instead of a string.
592 on whitespace) instead of a string.
598
593
599 list_all : bool, default False
594 list_all : bool, default False
600 Put all option values in lists. Normally only options
595 Put all option values in lists. Normally only options
601 appearing more than once are put in a list.
596 appearing more than once are put in a list.
602
597
603 posix : bool, default True
598 posix : bool, default True
604 Whether to split the input line in POSIX mode or not, as per the
599 Whether to split the input line in POSIX mode or not, as per the
605 conventions outlined in the :mod:`shlex` module from the standard
600 conventions outlined in the :mod:`shlex` module from the standard
606 library.
601 library.
607 """
602 """
608
603
609 # inject default options at the beginning of the input line
604 # inject default options at the beginning of the input line
610 caller = sys._getframe(1).f_code.co_name
605 caller = sys._getframe(1).f_code.co_name
611 arg_str = '%s %s' % (self.options_table.get(caller,''),arg_str)
606 arg_str = '%s %s' % (self.options_table.get(caller,''),arg_str)
612
607
613 mode = kw.get('mode','string')
608 mode = kw.get('mode','string')
614 if mode not in ['string','list']:
609 if mode not in ['string','list']:
615 raise ValueError('incorrect mode given: %s' % mode)
610 raise ValueError('incorrect mode given: %s' % mode)
616 # Get options
611 # Get options
617 list_all = kw.get('list_all',0)
612 list_all = kw.get('list_all',0)
618 posix = kw.get('posix', os.name == 'posix')
613 posix = kw.get('posix', os.name == 'posix')
619 strict = kw.get('strict', True)
614 strict = kw.get('strict', True)
620
615
621 preserve_non_opts = kw.get("preserve_non_opts", False)
616 preserve_non_opts = kw.get("preserve_non_opts", False)
622 remainder_arg_str = arg_str
617 remainder_arg_str = arg_str
623
618
624 # Check if we have more than one argument to warrant extra processing:
619 # Check if we have more than one argument to warrant extra processing:
625 odict = {} # Dictionary with options
620 odict = {} # Dictionary with options
626 args = arg_str.split()
621 args = arg_str.split()
627 if len(args) >= 1:
622 if len(args) >= 1:
628 # If the list of inputs only has 0 or 1 thing in it, there's no
623 # If the list of inputs only has 0 or 1 thing in it, there's no
629 # need to look for options
624 # need to look for options
630 argv = arg_split(arg_str, posix, strict)
625 argv = arg_split(arg_str, posix, strict)
631 # Do regular option processing
626 # Do regular option processing
632 try:
627 try:
633 opts,args = getopt(argv, opt_str, long_opts)
628 opts,args = getopt(argv, opt_str, long_opts)
634 except GetoptError as e:
629 except GetoptError as e:
635 raise UsageError(
630 raise UsageError(
636 '%s ( allowed: "%s" %s)' % (e.msg, opt_str, " ".join(long_opts))
631 '%s ( allowed: "%s" %s)' % (e.msg, opt_str, " ".join(long_opts))
637 ) from e
632 ) from e
638 for o, a in opts:
633 for o, a in opts:
639 if mode == "string" and preserve_non_opts:
634 if mode == "string" and preserve_non_opts:
640 # remove option-parts from the original args-string and preserve remaining-part.
635 # remove option-parts from the original args-string and preserve remaining-part.
641 # This relies on the arg_split(...) and getopt(...)'s impl spec, that the parsed options are
636 # This relies on the arg_split(...) and getopt(...)'s impl spec, that the parsed options are
642 # returned in the original order.
637 # returned in the original order.
643 remainder_arg_str = remainder_arg_str.replace(o, "", 1).replace(
638 remainder_arg_str = remainder_arg_str.replace(o, "", 1).replace(
644 a, "", 1
639 a, "", 1
645 )
640 )
646 if o.startswith("--"):
641 if o.startswith("--"):
647 o = o[2:]
642 o = o[2:]
648 else:
643 else:
649 o = o[1:]
644 o = o[1:]
650 try:
645 try:
651 odict[o].append(a)
646 odict[o].append(a)
652 except AttributeError:
647 except AttributeError:
653 odict[o] = [odict[o],a]
648 odict[o] = [odict[o],a]
654 except KeyError:
649 except KeyError:
655 if list_all:
650 if list_all:
656 odict[o] = [a]
651 odict[o] = [a]
657 else:
652 else:
658 odict[o] = a
653 odict[o] = a
659
654
660 # Prepare opts,args for return
655 # Prepare opts,args for return
661 opts = Struct(odict)
656 opts = Struct(odict)
662 if mode == 'string':
657 if mode == 'string':
663 if preserve_non_opts:
658 if preserve_non_opts:
664 args = remainder_arg_str.lstrip()
659 args = remainder_arg_str.lstrip()
665 else:
660 else:
666 args = " ".join(args)
661 args = " ".join(args)
667
662
668 return opts,args
663 return opts,args
669
664
670 def default_option(self, fn, optstr):
665 def default_option(self, fn, optstr):
671 """Make an entry in the options_table for fn, with value optstr"""
666 """Make an entry in the options_table for fn, with value optstr"""
672
667
673 if fn not in self.lsmagic():
668 if fn not in self.lsmagic():
674 error("%s is not a magic function" % fn)
669 error("%s is not a magic function" % fn)
675 self.options_table[fn] = optstr
670 self.options_table[fn] = optstr
676
671
677
672
678 class MagicAlias(object):
673 class MagicAlias(object):
679 """An alias to another magic function.
674 """An alias to another magic function.
680
675
681 An alias is determined by its magic name and magic kind. Lookup
676 An alias is determined by its magic name and magic kind. Lookup
682 is done at call time, so if the underlying magic changes the alias
677 is done at call time, so if the underlying magic changes the alias
683 will call the new function.
678 will call the new function.
684
679
685 Use the :meth:`MagicsManager.register_alias` method or the
680 Use the :meth:`MagicsManager.register_alias` method or the
686 `%alias_magic` magic function to create and register a new alias.
681 `%alias_magic` magic function to create and register a new alias.
687 """
682 """
688 def __init__(self, shell, magic_name, magic_kind, magic_params=None):
683 def __init__(self, shell, magic_name, magic_kind, magic_params=None):
689 self.shell = shell
684 self.shell = shell
690 self.magic_name = magic_name
685 self.magic_name = magic_name
691 self.magic_params = magic_params
686 self.magic_params = magic_params
692 self.magic_kind = magic_kind
687 self.magic_kind = magic_kind
693
688
694 self.pretty_target = '%s%s' % (magic_escapes[self.magic_kind], self.magic_name)
689 self.pretty_target = '%s%s' % (magic_escapes[self.magic_kind], self.magic_name)
695 self.__doc__ = "Alias for `%s`." % self.pretty_target
690 self.__doc__ = "Alias for `%s`." % self.pretty_target
696
691
697 self._in_call = False
692 self._in_call = False
698
693
699 def __call__(self, *args, **kwargs):
694 def __call__(self, *args, **kwargs):
700 """Call the magic alias."""
695 """Call the magic alias."""
701 fn = self.shell.find_magic(self.magic_name, self.magic_kind)
696 fn = self.shell.find_magic(self.magic_name, self.magic_kind)
702 if fn is None:
697 if fn is None:
703 raise UsageError("Magic `%s` not found." % self.pretty_target)
698 raise UsageError("Magic `%s` not found." % self.pretty_target)
704
699
705 # Protect against infinite recursion.
700 # Protect against infinite recursion.
706 if self._in_call:
701 if self._in_call:
707 raise UsageError("Infinite recursion detected; "
702 raise UsageError("Infinite recursion detected; "
708 "magic aliases cannot call themselves.")
703 "magic aliases cannot call themselves.")
709 self._in_call = True
704 self._in_call = True
710 try:
705 try:
711 if self.magic_params:
706 if self.magic_params:
712 args_list = list(args)
707 args_list = list(args)
713 args_list[0] = self.magic_params + " " + args[0]
708 args_list[0] = self.magic_params + " " + args[0]
714 args = tuple(args_list)
709 args = tuple(args_list)
715 return fn(*args, **kwargs)
710 return fn(*args, **kwargs)
716 finally:
711 finally:
717 self._in_call = False
712 self._in_call = False
@@ -1,664 +1,665 b''
1 """Implementation of basic magic functions."""
1 """Implementation of basic magic functions."""
2
2
3
3
4 import argparse
4 import argparse
5 from logging import error
5 from logging import error
6 import io
6 import io
7 from pprint import pformat
7 from pprint import pformat
8 import sys
8 import sys
9 from warnings import warn
9 from warnings import warn
10
10
11 from traitlets.utils.importstring import import_item
11 from traitlets.utils.importstring import import_item
12 from IPython.core import magic_arguments, page
12 from IPython.core import magic_arguments, page
13 from IPython.core.error import UsageError
13 from IPython.core.error import UsageError
14 from IPython.core.magic import Magics, magics_class, line_magic, magic_escapes
14 from IPython.core.magic import Magics, magics_class, line_magic, magic_escapes
15 from IPython.utils.text import format_screen, dedent, indent
15 from IPython.utils.text import format_screen, dedent, indent
16 from IPython.testing.skipdoctest import skip_doctest
16 from IPython.testing.skipdoctest import skip_doctest
17 from IPython.utils.ipstruct import Struct
17 from IPython.utils.ipstruct import Struct
18
18
19
19
20 class MagicsDisplay(object):
20 class MagicsDisplay(object):
21 def __init__(self, magics_manager, ignore=None):
21 def __init__(self, magics_manager, ignore=None):
22 self.ignore = ignore if ignore else []
22 self.ignore = ignore if ignore else []
23 self.magics_manager = magics_manager
23 self.magics_manager = magics_manager
24
24
25 def _lsmagic(self):
25 def _lsmagic(self):
26 """The main implementation of the %lsmagic"""
26 """The main implementation of the %lsmagic"""
27 mesc = magic_escapes['line']
27 mesc = magic_escapes['line']
28 cesc = magic_escapes['cell']
28 cesc = magic_escapes['cell']
29 mman = self.magics_manager
29 mman = self.magics_manager
30 magics = mman.lsmagic()
30 magics = mman.lsmagic()
31 out = ['Available line magics:',
31 out = ['Available line magics:',
32 mesc + (' '+mesc).join(sorted([m for m,v in magics['line'].items() if (v not in self.ignore)])),
32 mesc + (' '+mesc).join(sorted([m for m,v in magics['line'].items() if (v not in self.ignore)])),
33 '',
33 '',
34 'Available cell magics:',
34 'Available cell magics:',
35 cesc + (' '+cesc).join(sorted([m for m,v in magics['cell'].items() if (v not in self.ignore)])),
35 cesc + (' '+cesc).join(sorted([m for m,v in magics['cell'].items() if (v not in self.ignore)])),
36 '',
36 '',
37 mman.auto_status()]
37 mman.auto_status()]
38 return '\n'.join(out)
38 return '\n'.join(out)
39
39
40 def _repr_pretty_(self, p, cycle):
40 def _repr_pretty_(self, p, cycle):
41 p.text(self._lsmagic())
41 p.text(self._lsmagic())
42
42
43 def __str__(self):
43 def __str__(self):
44 return self._lsmagic()
44 return self._lsmagic()
45
45
46 def _jsonable(self):
46 def _jsonable(self):
47 """turn magics dict into jsonable dict of the same structure
47 """turn magics dict into jsonable dict of the same structure
48
48
49 replaces object instances with their class names as strings
49 replaces object instances with their class names as strings
50 """
50 """
51 magic_dict = {}
51 magic_dict = {}
52 mman = self.magics_manager
52 mman = self.magics_manager
53 magics = mman.lsmagic()
53 magics = mman.lsmagic()
54 for key, subdict in magics.items():
54 for key, subdict in magics.items():
55 d = {}
55 d = {}
56 magic_dict[key] = d
56 magic_dict[key] = d
57 for name, obj in subdict.items():
57 for name, obj in subdict.items():
58 try:
58 try:
59 classname = obj.__self__.__class__.__name__
59 classname = obj.__self__.__class__.__name__
60 except AttributeError:
60 except AttributeError:
61 classname = 'Other'
61 classname = 'Other'
62
62
63 d[name] = classname
63 d[name] = classname
64 return magic_dict
64 return magic_dict
65
65
66 def _repr_json_(self):
66 def _repr_json_(self):
67 return self._jsonable()
67 return self._jsonable()
68
68
69
69
70 @magics_class
70 @magics_class
71 class BasicMagics(Magics):
71 class BasicMagics(Magics):
72 """Magics that provide central IPython functionality.
72 """Magics that provide central IPython functionality.
73
73
74 These are various magics that don't fit into specific categories but that
74 These are various magics that don't fit into specific categories but that
75 are all part of the base 'IPython experience'."""
75 are all part of the base 'IPython experience'."""
76
76
77 @skip_doctest
77 @magic_arguments.magic_arguments()
78 @magic_arguments.magic_arguments()
78 @magic_arguments.argument(
79 @magic_arguments.argument(
79 '-l', '--line', action='store_true',
80 '-l', '--line', action='store_true',
80 help="""Create a line magic alias."""
81 help="""Create a line magic alias."""
81 )
82 )
82 @magic_arguments.argument(
83 @magic_arguments.argument(
83 '-c', '--cell', action='store_true',
84 '-c', '--cell', action='store_true',
84 help="""Create a cell magic alias."""
85 help="""Create a cell magic alias."""
85 )
86 )
86 @magic_arguments.argument(
87 @magic_arguments.argument(
87 'name',
88 'name',
88 help="""Name of the magic to be created."""
89 help="""Name of the magic to be created."""
89 )
90 )
90 @magic_arguments.argument(
91 @magic_arguments.argument(
91 'target',
92 'target',
92 help="""Name of the existing line or cell magic."""
93 help="""Name of the existing line or cell magic."""
93 )
94 )
94 @magic_arguments.argument(
95 @magic_arguments.argument(
95 '-p', '--params', default=None,
96 '-p', '--params', default=None,
96 help="""Parameters passed to the magic function."""
97 help="""Parameters passed to the magic function."""
97 )
98 )
98 @line_magic
99 @line_magic
99 def alias_magic(self, line=''):
100 def alias_magic(self, line=''):
100 """Create an alias for an existing line or cell magic.
101 """Create an alias for an existing line or cell magic.
101
102
102 Examples
103 Examples
103 --------
104 --------
104 ::
105 ::
105
106
106 In [1]: %alias_magic t timeit
107 In [1]: %alias_magic t timeit
107 Created `%t` as an alias for `%timeit`.
108 Created `%t` as an alias for `%timeit`.
108 Created `%%t` as an alias for `%%timeit`.
109 Created `%%t` as an alias for `%%timeit`.
109
110
110 In [2]: %t -n1 pass
111 In [2]: %t -n1 pass
111 1 loops, best of 3: 954 ns per loop
112 1 loops, best of 3: 954 ns per loop
112
113
113 In [3]: %%t -n1
114 In [3]: %%t -n1
114 ...: pass
115 ...: pass
115 ...:
116 ...:
116 1 loops, best of 3: 954 ns per loop
117 1 loops, best of 3: 954 ns per loop
117
118
118 In [4]: %alias_magic --cell whereami pwd
119 In [4]: %alias_magic --cell whereami pwd
119 UsageError: Cell magic function `%%pwd` not found.
120 UsageError: Cell magic function `%%pwd` not found.
120 In [5]: %alias_magic --line whereami pwd
121 In [5]: %alias_magic --line whereami pwd
121 Created `%whereami` as an alias for `%pwd`.
122 Created `%whereami` as an alias for `%pwd`.
122
123
123 In [6]: %whereami
124 In [6]: %whereami
124 Out[6]: u'/home/testuser'
125 Out[6]: u'/home/testuser'
125
126
126 In [7]: %alias_magic h history "-p -l 30" --line
127 In [7]: %alias_magic h history "-p -l 30" --line
127 Created `%h` as an alias for `%history -l 30`.
128 Created `%h` as an alias for `%history -l 30`.
128 """
129 """
129
130
130 args = magic_arguments.parse_argstring(self.alias_magic, line)
131 args = magic_arguments.parse_argstring(self.alias_magic, line)
131 shell = self.shell
132 shell = self.shell
132 mman = self.shell.magics_manager
133 mman = self.shell.magics_manager
133 escs = ''.join(magic_escapes.values())
134 escs = ''.join(magic_escapes.values())
134
135
135 target = args.target.lstrip(escs)
136 target = args.target.lstrip(escs)
136 name = args.name.lstrip(escs)
137 name = args.name.lstrip(escs)
137
138
138 params = args.params
139 params = args.params
139 if (params and
140 if (params and
140 ((params.startswith('"') and params.endswith('"'))
141 ((params.startswith('"') and params.endswith('"'))
141 or (params.startswith("'") and params.endswith("'")))):
142 or (params.startswith("'") and params.endswith("'")))):
142 params = params[1:-1]
143 params = params[1:-1]
143
144
144 # Find the requested magics.
145 # Find the requested magics.
145 m_line = shell.find_magic(target, 'line')
146 m_line = shell.find_magic(target, 'line')
146 m_cell = shell.find_magic(target, 'cell')
147 m_cell = shell.find_magic(target, 'cell')
147 if args.line and m_line is None:
148 if args.line and m_line is None:
148 raise UsageError('Line magic function `%s%s` not found.' %
149 raise UsageError('Line magic function `%s%s` not found.' %
149 (magic_escapes['line'], target))
150 (magic_escapes['line'], target))
150 if args.cell and m_cell is None:
151 if args.cell and m_cell is None:
151 raise UsageError('Cell magic function `%s%s` not found.' %
152 raise UsageError('Cell magic function `%s%s` not found.' %
152 (magic_escapes['cell'], target))
153 (magic_escapes['cell'], target))
153
154
154 # If --line and --cell are not specified, default to the ones
155 # If --line and --cell are not specified, default to the ones
155 # that are available.
156 # that are available.
156 if not args.line and not args.cell:
157 if not args.line and not args.cell:
157 if not m_line and not m_cell:
158 if not m_line and not m_cell:
158 raise UsageError(
159 raise UsageError(
159 'No line or cell magic with name `%s` found.' % target
160 'No line or cell magic with name `%s` found.' % target
160 )
161 )
161 args.line = bool(m_line)
162 args.line = bool(m_line)
162 args.cell = bool(m_cell)
163 args.cell = bool(m_cell)
163
164
164 params_str = "" if params is None else " " + params
165 params_str = "" if params is None else " " + params
165
166
166 if args.line:
167 if args.line:
167 mman.register_alias(name, target, 'line', params)
168 mman.register_alias(name, target, 'line', params)
168 print('Created `%s%s` as an alias for `%s%s%s`.' % (
169 print('Created `%s%s` as an alias for `%s%s%s`.' % (
169 magic_escapes['line'], name,
170 magic_escapes['line'], name,
170 magic_escapes['line'], target, params_str))
171 magic_escapes['line'], target, params_str))
171
172
172 if args.cell:
173 if args.cell:
173 mman.register_alias(name, target, 'cell', params)
174 mman.register_alias(name, target, 'cell', params)
174 print('Created `%s%s` as an alias for `%s%s%s`.' % (
175 print('Created `%s%s` as an alias for `%s%s%s`.' % (
175 magic_escapes['cell'], name,
176 magic_escapes['cell'], name,
176 magic_escapes['cell'], target, params_str))
177 magic_escapes['cell'], target, params_str))
177
178
178 @line_magic
179 @line_magic
179 def lsmagic(self, parameter_s=''):
180 def lsmagic(self, parameter_s=''):
180 """List currently available magic functions."""
181 """List currently available magic functions."""
181 return MagicsDisplay(self.shell.magics_manager, ignore=[])
182 return MagicsDisplay(self.shell.magics_manager, ignore=[])
182
183
183 def _magic_docs(self, brief=False, rest=False):
184 def _magic_docs(self, brief=False, rest=False):
184 """Return docstrings from magic functions."""
185 """Return docstrings from magic functions."""
185 mman = self.shell.magics_manager
186 mman = self.shell.magics_manager
186 docs = mman.lsmagic_docs(brief, missing='No documentation')
187 docs = mman.lsmagic_docs(brief, missing='No documentation')
187
188
188 if rest:
189 if rest:
189 format_string = '**%s%s**::\n\n%s\n\n'
190 format_string = '**%s%s**::\n\n%s\n\n'
190 else:
191 else:
191 format_string = '%s%s:\n%s\n'
192 format_string = '%s%s:\n%s\n'
192
193
193 return ''.join(
194 return ''.join(
194 [format_string % (magic_escapes['line'], fname,
195 [format_string % (magic_escapes['line'], fname,
195 indent(dedent(fndoc)))
196 indent(dedent(fndoc)))
196 for fname, fndoc in sorted(docs['line'].items())]
197 for fname, fndoc in sorted(docs['line'].items())]
197 +
198 +
198 [format_string % (magic_escapes['cell'], fname,
199 [format_string % (magic_escapes['cell'], fname,
199 indent(dedent(fndoc)))
200 indent(dedent(fndoc)))
200 for fname, fndoc in sorted(docs['cell'].items())]
201 for fname, fndoc in sorted(docs['cell'].items())]
201 )
202 )
202
203
203 @line_magic
204 @line_magic
204 def magic(self, parameter_s=''):
205 def magic(self, parameter_s=''):
205 """Print information about the magic function system.
206 """Print information about the magic function system.
206
207
207 Supported formats: -latex, -brief, -rest
208 Supported formats: -latex, -brief, -rest
208 """
209 """
209
210
210 mode = ''
211 mode = ''
211 try:
212 try:
212 mode = parameter_s.split()[0][1:]
213 mode = parameter_s.split()[0][1:]
213 except IndexError:
214 except IndexError:
214 pass
215 pass
215
216
216 brief = (mode == 'brief')
217 brief = (mode == 'brief')
217 rest = (mode == 'rest')
218 rest = (mode == 'rest')
218 magic_docs = self._magic_docs(brief, rest)
219 magic_docs = self._magic_docs(brief, rest)
219
220
220 if mode == 'latex':
221 if mode == 'latex':
221 print(self.format_latex(magic_docs))
222 print(self.format_latex(magic_docs))
222 return
223 return
223 else:
224 else:
224 magic_docs = format_screen(magic_docs)
225 magic_docs = format_screen(magic_docs)
225
226
226 out = ["""
227 out = ["""
227 IPython's 'magic' functions
228 IPython's 'magic' functions
228 ===========================
229 ===========================
229
230
230 The magic function system provides a series of functions which allow you to
231 The magic function system provides a series of functions which allow you to
231 control the behavior of IPython itself, plus a lot of system-type
232 control the behavior of IPython itself, plus a lot of system-type
232 features. There are two kinds of magics, line-oriented and cell-oriented.
233 features. There are two kinds of magics, line-oriented and cell-oriented.
233
234
234 Line magics are prefixed with the % character and work much like OS
235 Line magics are prefixed with the % character and work much like OS
235 command-line calls: they get as an argument the rest of the line, where
236 command-line calls: they get as an argument the rest of the line, where
236 arguments are passed without parentheses or quotes. For example, this will
237 arguments are passed without parentheses or quotes. For example, this will
237 time the given statement::
238 time the given statement::
238
239
239 %timeit range(1000)
240 %timeit range(1000)
240
241
241 Cell magics are prefixed with a double %%, and they are functions that get as
242 Cell magics are prefixed with a double %%, and they are functions that get as
242 an argument not only the rest of the line, but also the lines below it in a
243 an argument not only the rest of the line, but also the lines below it in a
243 separate argument. These magics are called with two arguments: the rest of the
244 separate argument. These magics are called with two arguments: the rest of the
244 call line and the body of the cell, consisting of the lines below the first.
245 call line and the body of the cell, consisting of the lines below the first.
245 For example::
246 For example::
246
247
247 %%timeit x = numpy.random.randn((100, 100))
248 %%timeit x = numpy.random.randn((100, 100))
248 numpy.linalg.svd(x)
249 numpy.linalg.svd(x)
249
250
250 will time the execution of the numpy svd routine, running the assignment of x
251 will time the execution of the numpy svd routine, running the assignment of x
251 as part of the setup phase, which is not timed.
252 as part of the setup phase, which is not timed.
252
253
253 In a line-oriented client (the terminal or Qt console IPython), starting a new
254 In a line-oriented client (the terminal or Qt console IPython), starting a new
254 input with %% will automatically enter cell mode, and IPython will continue
255 input with %% will automatically enter cell mode, and IPython will continue
255 reading input until a blank line is given. In the notebook, simply type the
256 reading input until a blank line is given. In the notebook, simply type the
256 whole cell as one entity, but keep in mind that the %% escape can only be at
257 whole cell as one entity, but keep in mind that the %% escape can only be at
257 the very start of the cell.
258 the very start of the cell.
258
259
259 NOTE: If you have 'automagic' enabled (via the command line option or with the
260 NOTE: If you have 'automagic' enabled (via the command line option or with the
260 %automagic function), you don't need to type in the % explicitly for line
261 %automagic function), you don't need to type in the % explicitly for line
261 magics; cell magics always require an explicit '%%' escape. By default,
262 magics; cell magics always require an explicit '%%' escape. By default,
262 IPython ships with automagic on, so you should only rarely need the % escape.
263 IPython ships with automagic on, so you should only rarely need the % escape.
263
264
264 Example: typing '%cd mydir' (without the quotes) changes your working directory
265 Example: typing '%cd mydir' (without the quotes) changes your working directory
265 to 'mydir', if it exists.
266 to 'mydir', if it exists.
266
267
267 For a list of the available magic functions, use %lsmagic. For a description
268 For a list of the available magic functions, use %lsmagic. For a description
268 of any of them, type %magic_name?, e.g. '%cd?'.
269 of any of them, type %magic_name?, e.g. '%cd?'.
269
270
270 Currently the magic system has the following functions:""",
271 Currently the magic system has the following functions:""",
271 magic_docs,
272 magic_docs,
272 "Summary of magic functions (from %slsmagic):" % magic_escapes['line'],
273 "Summary of magic functions (from %slsmagic):" % magic_escapes['line'],
273 str(self.lsmagic()),
274 str(self.lsmagic()),
274 ]
275 ]
275 page.page('\n'.join(out))
276 page.page('\n'.join(out))
276
277
277
278
278 @line_magic
279 @line_magic
279 def page(self, parameter_s=''):
280 def page(self, parameter_s=''):
280 """Pretty print the object and display it through a pager.
281 """Pretty print the object and display it through a pager.
281
282
282 %page [options] OBJECT
283 %page [options] OBJECT
283
284
284 If no object is given, use _ (last output).
285 If no object is given, use _ (last output).
285
286
286 Options:
287 Options:
287
288
288 -r: page str(object), don't pretty-print it."""
289 -r: page str(object), don't pretty-print it."""
289
290
290 # After a function contributed by Olivier Aubert, slightly modified.
291 # After a function contributed by Olivier Aubert, slightly modified.
291
292
292 # Process options/args
293 # Process options/args
293 opts, args = self.parse_options(parameter_s, 'r')
294 opts, args = self.parse_options(parameter_s, 'r')
294 raw = 'r' in opts
295 raw = 'r' in opts
295
296
296 oname = args and args or '_'
297 oname = args and args or '_'
297 info = self.shell._ofind(oname)
298 info = self.shell._ofind(oname)
298 if info['found']:
299 if info['found']:
299 txt = (raw and str or pformat)( info['obj'] )
300 txt = (raw and str or pformat)( info['obj'] )
300 page.page(txt)
301 page.page(txt)
301 else:
302 else:
302 print('Object `%s` not found' % oname)
303 print('Object `%s` not found' % oname)
303
304
304 @line_magic
305 @line_magic
305 def pprint(self, parameter_s=''):
306 def pprint(self, parameter_s=''):
306 """Toggle pretty printing on/off."""
307 """Toggle pretty printing on/off."""
307 ptformatter = self.shell.display_formatter.formatters['text/plain']
308 ptformatter = self.shell.display_formatter.formatters['text/plain']
308 ptformatter.pprint = bool(1 - ptformatter.pprint)
309 ptformatter.pprint = bool(1 - ptformatter.pprint)
309 print('Pretty printing has been turned',
310 print('Pretty printing has been turned',
310 ['OFF','ON'][ptformatter.pprint])
311 ['OFF','ON'][ptformatter.pprint])
311
312
312 @line_magic
313 @line_magic
313 def colors(self, parameter_s=''):
314 def colors(self, parameter_s=''):
314 """Switch color scheme for prompts, info system and exception handlers.
315 """Switch color scheme for prompts, info system and exception handlers.
315
316
316 Currently implemented schemes: NoColor, Linux, LightBG.
317 Currently implemented schemes: NoColor, Linux, LightBG.
317
318
318 Color scheme names are not case-sensitive.
319 Color scheme names are not case-sensitive.
319
320
320 Examples
321 Examples
321 --------
322 --------
322 To get a plain black and white terminal::
323 To get a plain black and white terminal::
323
324
324 %colors nocolor
325 %colors nocolor
325 """
326 """
326 def color_switch_err(name):
327 def color_switch_err(name):
327 warn('Error changing %s color schemes.\n%s' %
328 warn('Error changing %s color schemes.\n%s' %
328 (name, sys.exc_info()[1]), stacklevel=2)
329 (name, sys.exc_info()[1]), stacklevel=2)
329
330
330
331
331 new_scheme = parameter_s.strip()
332 new_scheme = parameter_s.strip()
332 if not new_scheme:
333 if not new_scheme:
333 raise UsageError(
334 raise UsageError(
334 "%colors: you must specify a color scheme. See '%colors?'")
335 "%colors: you must specify a color scheme. See '%colors?'")
335 # local shortcut
336 # local shortcut
336 shell = self.shell
337 shell = self.shell
337
338
338 # Set shell colour scheme
339 # Set shell colour scheme
339 try:
340 try:
340 shell.colors = new_scheme
341 shell.colors = new_scheme
341 shell.refresh_style()
342 shell.refresh_style()
342 except:
343 except:
343 color_switch_err('shell')
344 color_switch_err('shell')
344
345
345 # Set exception colors
346 # Set exception colors
346 try:
347 try:
347 shell.InteractiveTB.set_colors(scheme = new_scheme)
348 shell.InteractiveTB.set_colors(scheme = new_scheme)
348 shell.SyntaxTB.set_colors(scheme = new_scheme)
349 shell.SyntaxTB.set_colors(scheme = new_scheme)
349 except:
350 except:
350 color_switch_err('exception')
351 color_switch_err('exception')
351
352
352 # Set info (for 'object?') colors
353 # Set info (for 'object?') colors
353 if shell.color_info:
354 if shell.color_info:
354 try:
355 try:
355 shell.inspector.set_active_scheme(new_scheme)
356 shell.inspector.set_active_scheme(new_scheme)
356 except:
357 except:
357 color_switch_err('object inspector')
358 color_switch_err('object inspector')
358 else:
359 else:
359 shell.inspector.set_active_scheme('NoColor')
360 shell.inspector.set_active_scheme('NoColor')
360
361
361 @line_magic
362 @line_magic
362 def xmode(self, parameter_s=''):
363 def xmode(self, parameter_s=''):
363 """Switch modes for the exception handlers.
364 """Switch modes for the exception handlers.
364
365
365 Valid modes: Plain, Context, Verbose, and Minimal.
366 Valid modes: Plain, Context, Verbose, and Minimal.
366
367
367 If called without arguments, acts as a toggle.
368 If called without arguments, acts as a toggle.
368
369
369 When in verbose mode the value --show (and --hide)
370 When in verbose mode the value --show (and --hide)
370 will respectively show (or hide) frames with ``__tracebackhide__ =
371 will respectively show (or hide) frames with ``__tracebackhide__ =
371 True`` value set.
372 True`` value set.
372 """
373 """
373
374
374 def xmode_switch_err(name):
375 def xmode_switch_err(name):
375 warn('Error changing %s exception modes.\n%s' %
376 warn('Error changing %s exception modes.\n%s' %
376 (name,sys.exc_info()[1]))
377 (name,sys.exc_info()[1]))
377
378
378 shell = self.shell
379 shell = self.shell
379 if parameter_s.strip() == "--show":
380 if parameter_s.strip() == "--show":
380 shell.InteractiveTB.skip_hidden = False
381 shell.InteractiveTB.skip_hidden = False
381 return
382 return
382 if parameter_s.strip() == "--hide":
383 if parameter_s.strip() == "--hide":
383 shell.InteractiveTB.skip_hidden = True
384 shell.InteractiveTB.skip_hidden = True
384 return
385 return
385
386
386 new_mode = parameter_s.strip().capitalize()
387 new_mode = parameter_s.strip().capitalize()
387 try:
388 try:
388 shell.InteractiveTB.set_mode(mode=new_mode)
389 shell.InteractiveTB.set_mode(mode=new_mode)
389 print('Exception reporting mode:',shell.InteractiveTB.mode)
390 print('Exception reporting mode:',shell.InteractiveTB.mode)
390 except:
391 except:
391 xmode_switch_err('user')
392 xmode_switch_err('user')
392
393
393 @line_magic
394 @line_magic
394 def quickref(self, arg):
395 def quickref(self, arg):
395 """ Show a quick reference sheet """
396 """ Show a quick reference sheet """
396 from IPython.core.usage import quick_reference
397 from IPython.core.usage import quick_reference
397 qr = quick_reference + self._magic_docs(brief=True)
398 qr = quick_reference + self._magic_docs(brief=True)
398 page.page(qr)
399 page.page(qr)
399
400
400 @line_magic
401 @line_magic
401 def doctest_mode(self, parameter_s=''):
402 def doctest_mode(self, parameter_s=''):
402 """Toggle doctest mode on and off.
403 """Toggle doctest mode on and off.
403
404
404 This mode is intended to make IPython behave as much as possible like a
405 This mode is intended to make IPython behave as much as possible like a
405 plain Python shell, from the perspective of how its prompts, exceptions
406 plain Python shell, from the perspective of how its prompts, exceptions
406 and output look. This makes it easy to copy and paste parts of a
407 and output look. This makes it easy to copy and paste parts of a
407 session into doctests. It does so by:
408 session into doctests. It does so by:
408
409
409 - Changing the prompts to the classic ``>>>`` ones.
410 - Changing the prompts to the classic ``>>>`` ones.
410 - Changing the exception reporting mode to 'Plain'.
411 - Changing the exception reporting mode to 'Plain'.
411 - Disabling pretty-printing of output.
412 - Disabling pretty-printing of output.
412
413
413 Note that IPython also supports the pasting of code snippets that have
414 Note that IPython also supports the pasting of code snippets that have
414 leading '>>>' and '...' prompts in them. This means that you can paste
415 leading '>>>' and '...' prompts in them. This means that you can paste
415 doctests from files or docstrings (even if they have leading
416 doctests from files or docstrings (even if they have leading
416 whitespace), and the code will execute correctly. You can then use
417 whitespace), and the code will execute correctly. You can then use
417 '%history -t' to see the translated history; this will give you the
418 '%history -t' to see the translated history; this will give you the
418 input after removal of all the leading prompts and whitespace, which
419 input after removal of all the leading prompts and whitespace, which
419 can be pasted back into an editor.
420 can be pasted back into an editor.
420
421
421 With these features, you can switch into this mode easily whenever you
422 With these features, you can switch into this mode easily whenever you
422 need to do testing and changes to doctests, without having to leave
423 need to do testing and changes to doctests, without having to leave
423 your existing IPython session.
424 your existing IPython session.
424 """
425 """
425
426
426 # Shorthands
427 # Shorthands
427 shell = self.shell
428 shell = self.shell
428 meta = shell.meta
429 meta = shell.meta
429 disp_formatter = self.shell.display_formatter
430 disp_formatter = self.shell.display_formatter
430 ptformatter = disp_formatter.formatters['text/plain']
431 ptformatter = disp_formatter.formatters['text/plain']
431 # dstore is a data store kept in the instance metadata bag to track any
432 # dstore is a data store kept in the instance metadata bag to track any
432 # changes we make, so we can undo them later.
433 # changes we make, so we can undo them later.
433 dstore = meta.setdefault('doctest_mode',Struct())
434 dstore = meta.setdefault('doctest_mode',Struct())
434 save_dstore = dstore.setdefault
435 save_dstore = dstore.setdefault
435
436
436 # save a few values we'll need to recover later
437 # save a few values we'll need to recover later
437 mode = save_dstore('mode',False)
438 mode = save_dstore('mode',False)
438 save_dstore('rc_pprint',ptformatter.pprint)
439 save_dstore('rc_pprint',ptformatter.pprint)
439 save_dstore('xmode',shell.InteractiveTB.mode)
440 save_dstore('xmode',shell.InteractiveTB.mode)
440 save_dstore('rc_separate_out',shell.separate_out)
441 save_dstore('rc_separate_out',shell.separate_out)
441 save_dstore('rc_separate_out2',shell.separate_out2)
442 save_dstore('rc_separate_out2',shell.separate_out2)
442 save_dstore('rc_separate_in',shell.separate_in)
443 save_dstore('rc_separate_in',shell.separate_in)
443 save_dstore('rc_active_types',disp_formatter.active_types)
444 save_dstore('rc_active_types',disp_formatter.active_types)
444
445
445 if not mode:
446 if not mode:
446 # turn on
447 # turn on
447
448
448 # Prompt separators like plain python
449 # Prompt separators like plain python
449 shell.separate_in = ''
450 shell.separate_in = ''
450 shell.separate_out = ''
451 shell.separate_out = ''
451 shell.separate_out2 = ''
452 shell.separate_out2 = ''
452
453
453
454
454 ptformatter.pprint = False
455 ptformatter.pprint = False
455 disp_formatter.active_types = ['text/plain']
456 disp_formatter.active_types = ['text/plain']
456
457
457 shell.magic('xmode Plain')
458 shell.magic('xmode Plain')
458 else:
459 else:
459 # turn off
460 # turn off
460 shell.separate_in = dstore.rc_separate_in
461 shell.separate_in = dstore.rc_separate_in
461
462
462 shell.separate_out = dstore.rc_separate_out
463 shell.separate_out = dstore.rc_separate_out
463 shell.separate_out2 = dstore.rc_separate_out2
464 shell.separate_out2 = dstore.rc_separate_out2
464
465
465 ptformatter.pprint = dstore.rc_pprint
466 ptformatter.pprint = dstore.rc_pprint
466 disp_formatter.active_types = dstore.rc_active_types
467 disp_formatter.active_types = dstore.rc_active_types
467
468
468 shell.magic('xmode ' + dstore.xmode)
469 shell.magic('xmode ' + dstore.xmode)
469
470
470 # mode here is the state before we switch; switch_doctest_mode takes
471 # mode here is the state before we switch; switch_doctest_mode takes
471 # the mode we're switching to.
472 # the mode we're switching to.
472 shell.switch_doctest_mode(not mode)
473 shell.switch_doctest_mode(not mode)
473
474
474 # Store new mode and inform
475 # Store new mode and inform
475 dstore.mode = bool(not mode)
476 dstore.mode = bool(not mode)
476 mode_label = ['OFF','ON'][dstore.mode]
477 mode_label = ['OFF','ON'][dstore.mode]
477 print('Doctest mode is:', mode_label)
478 print('Doctest mode is:', mode_label)
478
479
479 @line_magic
480 @line_magic
480 def gui(self, parameter_s=''):
481 def gui(self, parameter_s=''):
481 """Enable or disable IPython GUI event loop integration.
482 """Enable or disable IPython GUI event loop integration.
482
483
483 %gui [GUINAME]
484 %gui [GUINAME]
484
485
485 This magic replaces IPython's threaded shells that were activated
486 This magic replaces IPython's threaded shells that were activated
486 using the (pylab/wthread/etc.) command line flags. GUI toolkits
487 using the (pylab/wthread/etc.) command line flags. GUI toolkits
487 can now be enabled at runtime and keyboard
488 can now be enabled at runtime and keyboard
488 interrupts should work without any problems. The following toolkits
489 interrupts should work without any problems. The following toolkits
489 are supported: wxPython, PyQt4, PyGTK, Tk and Cocoa (OSX)::
490 are supported: wxPython, PyQt4, PyGTK, Tk and Cocoa (OSX)::
490
491
491 %gui wx # enable wxPython event loop integration
492 %gui wx # enable wxPython event loop integration
492 %gui qt4|qt # enable PyQt4 event loop integration
493 %gui qt4|qt # enable PyQt4 event loop integration
493 %gui qt5 # enable PyQt5 event loop integration
494 %gui qt5 # enable PyQt5 event loop integration
494 %gui gtk # enable PyGTK event loop integration
495 %gui gtk # enable PyGTK event loop integration
495 %gui gtk3 # enable Gtk3 event loop integration
496 %gui gtk3 # enable Gtk3 event loop integration
496 %gui gtk4 # enable Gtk4 event loop integration
497 %gui gtk4 # enable Gtk4 event loop integration
497 %gui tk # enable Tk event loop integration
498 %gui tk # enable Tk event loop integration
498 %gui osx # enable Cocoa event loop integration
499 %gui osx # enable Cocoa event loop integration
499 # (requires %matplotlib 1.1)
500 # (requires %matplotlib 1.1)
500 %gui # disable all event loop integration
501 %gui # disable all event loop integration
501
502
502 WARNING: after any of these has been called you can simply create
503 WARNING: after any of these has been called you can simply create
503 an application object, but DO NOT start the event loop yourself, as
504 an application object, but DO NOT start the event loop yourself, as
504 we have already handled that.
505 we have already handled that.
505 """
506 """
506 opts, arg = self.parse_options(parameter_s, '')
507 opts, arg = self.parse_options(parameter_s, '')
507 if arg=='': arg = None
508 if arg=='': arg = None
508 try:
509 try:
509 return self.shell.enable_gui(arg)
510 return self.shell.enable_gui(arg)
510 except Exception as e:
511 except Exception as e:
511 # print simple error message, rather than traceback if we can't
512 # print simple error message, rather than traceback if we can't
512 # hook up the GUI
513 # hook up the GUI
513 error(str(e))
514 error(str(e))
514
515
515 @skip_doctest
516 @skip_doctest
516 @line_magic
517 @line_magic
517 def precision(self, s=''):
518 def precision(self, s=''):
518 """Set floating point precision for pretty printing.
519 """Set floating point precision for pretty printing.
519
520
520 Can set either integer precision or a format string.
521 Can set either integer precision or a format string.
521
522
522 If numpy has been imported and precision is an int,
523 If numpy has been imported and precision is an int,
523 numpy display precision will also be set, via ``numpy.set_printoptions``.
524 numpy display precision will also be set, via ``numpy.set_printoptions``.
524
525
525 If no argument is given, defaults will be restored.
526 If no argument is given, defaults will be restored.
526
527
527 Examples
528 Examples
528 --------
529 --------
529 ::
530 ::
530
531
531 In [1]: from math import pi
532 In [1]: from math import pi
532
533
533 In [2]: %precision 3
534 In [2]: %precision 3
534 Out[2]: u'%.3f'
535 Out[2]: u'%.3f'
535
536
536 In [3]: pi
537 In [3]: pi
537 Out[3]: 3.142
538 Out[3]: 3.142
538
539
539 In [4]: %precision %i
540 In [4]: %precision %i
540 Out[4]: u'%i'
541 Out[4]: u'%i'
541
542
542 In [5]: pi
543 In [5]: pi
543 Out[5]: 3
544 Out[5]: 3
544
545
545 In [6]: %precision %e
546 In [6]: %precision %e
546 Out[6]: u'%e'
547 Out[6]: u'%e'
547
548
548 In [7]: pi**10
549 In [7]: pi**10
549 Out[7]: 9.364805e+04
550 Out[7]: 9.364805e+04
550
551
551 In [8]: %precision
552 In [8]: %precision
552 Out[8]: u'%r'
553 Out[8]: u'%r'
553
554
554 In [9]: pi**10
555 In [9]: pi**10
555 Out[9]: 93648.047476082982
556 Out[9]: 93648.047476082982
556 """
557 """
557 ptformatter = self.shell.display_formatter.formatters['text/plain']
558 ptformatter = self.shell.display_formatter.formatters['text/plain']
558 ptformatter.float_precision = s
559 ptformatter.float_precision = s
559 return ptformatter.float_format
560 return ptformatter.float_format
560
561
561 @magic_arguments.magic_arguments()
562 @magic_arguments.magic_arguments()
562 @magic_arguments.argument(
563 @magic_arguments.argument(
563 '-e', '--export', action='store_true', default=False,
564 '-e', '--export', action='store_true', default=False,
564 help=argparse.SUPPRESS
565 help=argparse.SUPPRESS
565 )
566 )
566 @magic_arguments.argument(
567 @magic_arguments.argument(
567 'filename', type=str,
568 'filename', type=str,
568 help='Notebook name or filename'
569 help='Notebook name or filename'
569 )
570 )
570 @line_magic
571 @line_magic
571 def notebook(self, s):
572 def notebook(self, s):
572 """Export and convert IPython notebooks.
573 """Export and convert IPython notebooks.
573
574
574 This function can export the current IPython history to a notebook file.
575 This function can export the current IPython history to a notebook file.
575 For example, to export the history to "foo.ipynb" do "%notebook foo.ipynb".
576 For example, to export the history to "foo.ipynb" do "%notebook foo.ipynb".
576
577
577 The -e or --export flag is deprecated in IPython 5.2, and will be
578 The -e or --export flag is deprecated in IPython 5.2, and will be
578 removed in the future.
579 removed in the future.
579 """
580 """
580 args = magic_arguments.parse_argstring(self.notebook, s)
581 args = magic_arguments.parse_argstring(self.notebook, s)
581
582
582 from nbformat import write, v4
583 from nbformat import write, v4
583
584
584 cells = []
585 cells = []
585 hist = list(self.shell.history_manager.get_range())
586 hist = list(self.shell.history_manager.get_range())
586 if(len(hist)<=1):
587 if(len(hist)<=1):
587 raise ValueError('History is empty, cannot export')
588 raise ValueError('History is empty, cannot export')
588 for session, execution_count, source in hist[:-1]:
589 for session, execution_count, source in hist[:-1]:
589 cells.append(v4.new_code_cell(
590 cells.append(v4.new_code_cell(
590 execution_count=execution_count,
591 execution_count=execution_count,
591 source=source
592 source=source
592 ))
593 ))
593 nb = v4.new_notebook(cells=cells)
594 nb = v4.new_notebook(cells=cells)
594 with io.open(args.filename, 'w', encoding='utf-8') as f:
595 with io.open(args.filename, 'w', encoding='utf-8') as f:
595 write(nb, f, version=4)
596 write(nb, f, version=4)
596
597
597 @magics_class
598 @magics_class
598 class AsyncMagics(BasicMagics):
599 class AsyncMagics(BasicMagics):
599
600
600 @line_magic
601 @line_magic
601 def autoawait(self, parameter_s):
602 def autoawait(self, parameter_s):
602 """
603 """
603 Allow to change the status of the autoawait option.
604 Allow to change the status of the autoawait option.
604
605
605 This allow you to set a specific asynchronous code runner.
606 This allow you to set a specific asynchronous code runner.
606
607
607 If no value is passed, print the currently used asynchronous integration
608 If no value is passed, print the currently used asynchronous integration
608 and whether it is activated.
609 and whether it is activated.
609
610
610 It can take a number of value evaluated in the following order:
611 It can take a number of value evaluated in the following order:
611
612
612 - False/false/off deactivate autoawait integration
613 - False/false/off deactivate autoawait integration
613 - True/true/on activate autoawait integration using configured default
614 - True/true/on activate autoawait integration using configured default
614 loop
615 loop
615 - asyncio/curio/trio activate autoawait integration and use integration
616 - asyncio/curio/trio activate autoawait integration and use integration
616 with said library.
617 with said library.
617
618
618 - `sync` turn on the pseudo-sync integration (mostly used for
619 - `sync` turn on the pseudo-sync integration (mostly used for
619 `IPython.embed()` which does not run IPython with a real eventloop and
620 `IPython.embed()` which does not run IPython with a real eventloop and
620 deactivate running asynchronous code. Turning on Asynchronous code with
621 deactivate running asynchronous code. Turning on Asynchronous code with
621 the pseudo sync loop is undefined behavior and may lead IPython to crash.
622 the pseudo sync loop is undefined behavior and may lead IPython to crash.
622
623
623 If the passed parameter does not match any of the above and is a python
624 If the passed parameter does not match any of the above and is a python
624 identifier, get said object from user namespace and set it as the
625 identifier, get said object from user namespace and set it as the
625 runner, and activate autoawait.
626 runner, and activate autoawait.
626
627
627 If the object is a fully qualified object name, attempt to import it and
628 If the object is a fully qualified object name, attempt to import it and
628 set it as the runner, and activate autoawait.
629 set it as the runner, and activate autoawait.
629
630
630
631
631 The exact behavior of autoawait is experimental and subject to change
632 The exact behavior of autoawait is experimental and subject to change
632 across version of IPython and Python.
633 across version of IPython and Python.
633 """
634 """
634
635
635 param = parameter_s.strip()
636 param = parameter_s.strip()
636 d = {True: "on", False: "off"}
637 d = {True: "on", False: "off"}
637
638
638 if not param:
639 if not param:
639 print("IPython autoawait is `{}`, and set to use `{}`".format(
640 print("IPython autoawait is `{}`, and set to use `{}`".format(
640 d[self.shell.autoawait],
641 d[self.shell.autoawait],
641 self.shell.loop_runner
642 self.shell.loop_runner
642 ))
643 ))
643 return None
644 return None
644
645
645 if param.lower() in ('false', 'off'):
646 if param.lower() in ('false', 'off'):
646 self.shell.autoawait = False
647 self.shell.autoawait = False
647 return None
648 return None
648 if param.lower() in ('true', 'on'):
649 if param.lower() in ('true', 'on'):
649 self.shell.autoawait = True
650 self.shell.autoawait = True
650 return None
651 return None
651
652
652 if param in self.shell.loop_runner_map:
653 if param in self.shell.loop_runner_map:
653 self.shell.loop_runner, self.shell.autoawait = self.shell.loop_runner_map[param]
654 self.shell.loop_runner, self.shell.autoawait = self.shell.loop_runner_map[param]
654 return None
655 return None
655
656
656 if param in self.shell.user_ns :
657 if param in self.shell.user_ns :
657 self.shell.loop_runner = self.shell.user_ns[param]
658 self.shell.loop_runner = self.shell.user_ns[param]
658 self.shell.autoawait = True
659 self.shell.autoawait = True
659 return None
660 return None
660
661
661 runner = import_item(param)
662 runner = import_item(param)
662
663
663 self.shell.loop_runner = runner
664 self.shell.loop_runner = runner
664 self.shell.autoawait = True
665 self.shell.autoawait = True
@@ -1,158 +1,187 b''
1 """Implementation of configuration-related magic functions.
1 """Implementation of configuration-related magic functions.
2 """
2 """
3 #-----------------------------------------------------------------------------
3 #-----------------------------------------------------------------------------
4 # Copyright (c) 2012 The IPython Development Team.
4 # Copyright (c) 2012 The IPython Development Team.
5 #
5 #
6 # Distributed under the terms of the Modified BSD License.
6 # Distributed under the terms of the Modified BSD License.
7 #
7 #
8 # The full license is in the file COPYING.txt, distributed with this software.
8 # The full license is in the file COPYING.txt, distributed with this software.
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10
10
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 # Imports
12 # Imports
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15 # Stdlib
15 # Stdlib
16 import re
16 import re
17
17
18 # Our own packages
18 # Our own packages
19 from IPython.core.error import UsageError
19 from IPython.core.error import UsageError
20 from IPython.core.magic import Magics, magics_class, line_magic
20 from IPython.core.magic import Magics, magics_class, line_magic
21 from logging import error
21 from logging import error
22
22
23 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
24 # Magic implementation classes
24 # Magic implementation classes
25 #-----------------------------------------------------------------------------
25 #-----------------------------------------------------------------------------
26
26
27 reg = re.compile(r'^\w+\.\w+$')
27 reg = re.compile(r'^\w+\.\w+$')
28 @magics_class
28 @magics_class
29 class ConfigMagics(Magics):
29 class ConfigMagics(Magics):
30
30
31 def __init__(self, shell):
31 def __init__(self, shell):
32 super(ConfigMagics, self).__init__(shell)
32 super(ConfigMagics, self).__init__(shell)
33 self.configurables = []
33 self.configurables = []
34
34
35 @line_magic
35 @line_magic
36 def config(self, s):
36 def config(self, s):
37 """configure IPython
37 """configure IPython
38
38
39 %config Class[.trait=value]
39 %config Class[.trait=value]
40
40
41 This magic exposes most of the IPython config system. Any
41 This magic exposes most of the IPython config system. Any
42 Configurable class should be able to be configured with the simple
42 Configurable class should be able to be configured with the simple
43 line::
43 line::
44
44
45 %config Class.trait=value
45 %config Class.trait=value
46
46
47 Where `value` will be resolved in the user's namespace, if it is an
47 Where `value` will be resolved in the user's namespace, if it is an
48 expression or variable name.
48 expression or variable name.
49
49
50 Examples
50 Examples
51 --------
51 --------
52
52
53 To see what classes are available for config, pass no arguments::
53 To see what classes are available for config, pass no arguments::
54
54
55 In [1]: %config
55 In [1]: %config
56 Available objects for config:
56 Available objects for config:
57 TerminalInteractiveShell
58 HistoryManager
59 PrefilterManager
60 AliasManager
57 AliasManager
61 IPCompleter
62 DisplayFormatter
58 DisplayFormatter
59 HistoryManager
60 IPCompleter
61 LoggingMagics
62 MagicsManager
63 OSMagics
64 PrefilterManager
65 ScriptMagics
66 TerminalInteractiveShell
63
67
64 To view what is configurable on a given class, just pass the class
68 To view what is configurable on a given class, just pass the class
65 name::
69 name::
66
70
67 In [2]: %config IPCompleter
71 In [2]: %config IPCompleter
68 IPCompleter options
72 IPCompleter(Completer) options
69 -----------------
73 ----------------------------
70 IPCompleter.omit__names=<Enum>
74 IPCompleter.backslash_combining_completions=<Bool>
71 Current: 2
75 Enable unicode completions, e.g. \\alpha<tab> . Includes completion of latex
72 Choices: (0, 1, 2)
76 commands, unicode names, and expanding unicode characters back to latex
73 Instruct the completer to omit private method names
77 commands.
74 Specifically, when completing on ``object.<tab>``.
75 When 2 [default]: all names that start with '_' will be excluded.
76 When 1: all 'magic' names (``__foo__``) will be excluded.
77 When 0: nothing will be excluded.
78 IPCompleter.merge_completions=<CBool>
79 Current: True
78 Current: True
80 Whether to merge completion results into a single list
79 IPCompleter.debug=<Bool>
81 If False, only the completion results from the first non-empty
80 Enable debug for the Completer. Mostly print extra information for
82 completer will be returned.
81 experimental jedi integration.
83 IPCompleter.limit_to__all__=<CBool>
82 Current: False
83 IPCompleter.greedy=<Bool>
84 Activate greedy completion
85 PENDING DEPRECTION. this is now mostly taken care of with Jedi.
86 This will enable completion on elements of lists, results of function calls, etc.,
87 but can be unsafe because the code is actually evaluated on TAB.
84 Current: False
88 Current: False
89 IPCompleter.jedi_compute_type_timeout=<Int>
90 Experimental: restrict time (in milliseconds) during which Jedi can compute types.
91 Set to 0 to stop computing types. Non-zero value lower than 100ms may hurt
92 performance by preventing jedi to build its cache.
93 Current: 400
94 IPCompleter.limit_to__all__=<Bool>
95 DEPRECATED as of version 5.0.
85 Instruct the completer to use __all__ for the completion
96 Instruct the completer to use __all__ for the completion
86 Specifically, when completing on ``object.<tab>``.
97 Specifically, when completing on ``object.<tab>``.
87 When True: only those names in obj.__all__ will be included.
98 When True: only those names in obj.__all__ will be included.
88 When False [default]: the __all__ attribute is ignored
99 When False [default]: the __all__ attribute is ignored
89 IPCompleter.greedy=<CBool>
90 Current: False
100 Current: False
91 Activate greedy completion
101 IPCompleter.merge_completions=<Bool>
92 This will enable completion on elements of lists, results of
102 Whether to merge completion results into a single list
93 function calls, etc., but can be unsafe because the code is
103 If False, only the completion results from the first non-empty
94 actually evaluated on TAB.
104 completer will be returned.
105 Current: True
106 IPCompleter.omit__names=<Enum>
107 Instruct the completer to omit private method names
108 Specifically, when completing on ``object.<tab>``.
109 When 2 [default]: all names that start with '_' will be excluded.
110 When 1: all 'magic' names (``__foo__``) will be excluded.
111 When 0: nothing will be excluded.
112 Choices: any of [0, 1, 2]
113 Current: 2
114 IPCompleter.profile_completions=<Bool>
115 If True, emit profiling data for completion subsystem using cProfile.
116 Current: False
117 IPCompleter.profiler_output_dir=<Unicode>
118 Template for path at which to output profile data for completions.
119 Current: '.completion_profiles'
120 IPCompleter.use_jedi=<Bool>
121 Experimental: Use Jedi to generate autocompletions. Default to True if jedi
122 is installed.
123 Current: True
95
124
96 but the real use is in setting values::
125 but the real use is in setting values::
97
126
98 In [3]: %config IPCompleter.greedy = True
127 In [3]: %config IPCompleter.greedy = True
99
128
100 and these values are read from the user_ns if they are variables::
129 and these values are read from the user_ns if they are variables::
101
130
102 In [4]: feeling_greedy=False
131 In [4]: feeling_greedy=False
103
132
104 In [5]: %config IPCompleter.greedy = feeling_greedy
133 In [5]: %config IPCompleter.greedy = feeling_greedy
105
134
106 """
135 """
107 from traitlets.config.loader import Config
136 from traitlets.config.loader import Config
108 # some IPython objects are Configurable, but do not yet have
137 # some IPython objects are Configurable, but do not yet have
109 # any configurable traits. Exclude them from the effects of
138 # any configurable traits. Exclude them from the effects of
110 # this magic, as their presence is just noise:
139 # this magic, as their presence is just noise:
111 configurables = sorted(set([ c for c in self.shell.configurables
140 configurables = sorted(set([ c for c in self.shell.configurables
112 if c.__class__.class_traits(config=True)
141 if c.__class__.class_traits(config=True)
113 ]), key=lambda x: x.__class__.__name__)
142 ]), key=lambda x: x.__class__.__name__)
114 classnames = [ c.__class__.__name__ for c in configurables ]
143 classnames = [ c.__class__.__name__ for c in configurables ]
115
144
116 line = s.strip()
145 line = s.strip()
117 if not line:
146 if not line:
118 # print available configurable names
147 # print available configurable names
119 print("Available objects for config:")
148 print("Available objects for config:")
120 for name in classnames:
149 for name in classnames:
121 print(" ", name)
150 print(" ", name)
122 return
151 return
123 elif line in classnames:
152 elif line in classnames:
124 # `%config TerminalInteractiveShell` will print trait info for
153 # `%config TerminalInteractiveShell` will print trait info for
125 # TerminalInteractiveShell
154 # TerminalInteractiveShell
126 c = configurables[classnames.index(line)]
155 c = configurables[classnames.index(line)]
127 cls = c.__class__
156 cls = c.__class__
128 help = cls.class_get_help(c)
157 help = cls.class_get_help(c)
129 # strip leading '--' from cl-args:
158 # strip leading '--' from cl-args:
130 help = re.sub(re.compile(r'^--', re.MULTILINE), '', help)
159 help = re.sub(re.compile(r'^--', re.MULTILINE), '', help)
131 print(help)
160 print(help)
132 return
161 return
133 elif reg.match(line):
162 elif reg.match(line):
134 cls, attr = line.split('.')
163 cls, attr = line.split('.')
135 return getattr(configurables[classnames.index(cls)],attr)
164 return getattr(configurables[classnames.index(cls)],attr)
136 elif '=' not in line:
165 elif '=' not in line:
137 msg = "Invalid config statement: %r, "\
166 msg = "Invalid config statement: %r, "\
138 "should be `Class.trait = value`."
167 "should be `Class.trait = value`."
139
168
140 ll = line.lower()
169 ll = line.lower()
141 for classname in classnames:
170 for classname in classnames:
142 if ll == classname.lower():
171 if ll == classname.lower():
143 msg = msg + '\nDid you mean %s (note the case)?' % classname
172 msg = msg + '\nDid you mean %s (note the case)?' % classname
144 break
173 break
145
174
146 raise UsageError( msg % line)
175 raise UsageError( msg % line)
147
176
148 # otherwise, assume we are setting configurables.
177 # otherwise, assume we are setting configurables.
149 # leave quotes on args when splitting, because we want
178 # leave quotes on args when splitting, because we want
150 # unquoted args to eval in user_ns
179 # unquoted args to eval in user_ns
151 cfg = Config()
180 cfg = Config()
152 exec("cfg."+line, self.shell.user_ns, locals())
181 exec("cfg."+line, self.shell.user_ns, locals())
153
182
154 for configurable in configurables:
183 for configurable in configurables:
155 try:
184 try:
156 configurable.update_config(cfg)
185 configurable.update_config(cfg)
157 except Exception as e:
186 except Exception as e:
158 error(e)
187 error(e)
@@ -1,355 +1,357 b''
1 """Magic functions for running cells in various scripts."""
1 """Magic functions for running cells in various scripts."""
2
2
3 # Copyright (c) IPython Development Team.
3 # Copyright (c) IPython Development Team.
4 # Distributed under the terms of the Modified BSD License.
4 # Distributed under the terms of the Modified BSD License.
5
5
6 import asyncio
6 import asyncio
7 import atexit
7 import atexit
8 import errno
8 import errno
9 import functools
9 import functools
10 import os
10 import os
11 import signal
11 import signal
12 import sys
12 import sys
13 import time
13 import time
14 from contextlib import contextmanager
14 from contextlib import contextmanager
15 from subprocess import CalledProcessError
15 from subprocess import CalledProcessError
16
16
17 from traitlets import Dict, List, default
17 from traitlets import Dict, List, default
18
18
19 from IPython.core import magic_arguments
19 from IPython.core import magic_arguments
20 from IPython.core.magic import Magics, cell_magic, line_magic, magics_class
20 from IPython.core.magic import Magics, cell_magic, line_magic, magics_class
21 from IPython.lib.backgroundjobs import BackgroundJobManager
21 from IPython.lib.backgroundjobs import BackgroundJobManager
22 from IPython.utils.process import arg_split
22 from IPython.utils.process import arg_split
23
23
24 #-----------------------------------------------------------------------------
24 #-----------------------------------------------------------------------------
25 # Magic implementation classes
25 # Magic implementation classes
26 #-----------------------------------------------------------------------------
26 #-----------------------------------------------------------------------------
27
27
28 def script_args(f):
28 def script_args(f):
29 """single decorator for adding script args"""
29 """single decorator for adding script args"""
30 args = [
30 args = [
31 magic_arguments.argument(
31 magic_arguments.argument(
32 '--out', type=str,
32 '--out', type=str,
33 help="""The variable in which to store stdout from the script.
33 help="""The variable in which to store stdout from the script.
34 If the script is backgrounded, this will be the stdout *pipe*,
34 If the script is backgrounded, this will be the stdout *pipe*,
35 instead of the stderr text itself and will not be auto closed.
35 instead of the stderr text itself and will not be auto closed.
36 """
36 """
37 ),
37 ),
38 magic_arguments.argument(
38 magic_arguments.argument(
39 '--err', type=str,
39 '--err', type=str,
40 help="""The variable in which to store stderr from the script.
40 help="""The variable in which to store stderr from the script.
41 If the script is backgrounded, this will be the stderr *pipe*,
41 If the script is backgrounded, this will be the stderr *pipe*,
42 instead of the stderr text itself and will not be autoclosed.
42 instead of the stderr text itself and will not be autoclosed.
43 """
43 """
44 ),
44 ),
45 magic_arguments.argument(
45 magic_arguments.argument(
46 '--bg', action="store_true",
46 '--bg', action="store_true",
47 help="""Whether to run the script in the background.
47 help="""Whether to run the script in the background.
48 If given, the only way to see the output of the command is
48 If given, the only way to see the output of the command is
49 with --out/err.
49 with --out/err.
50 """
50 """
51 ),
51 ),
52 magic_arguments.argument(
52 magic_arguments.argument(
53 '--proc', type=str,
53 '--proc', type=str,
54 help="""The variable in which to store Popen instance.
54 help="""The variable in which to store Popen instance.
55 This is used only when --bg option is given.
55 This is used only when --bg option is given.
56 """
56 """
57 ),
57 ),
58 magic_arguments.argument(
58 magic_arguments.argument(
59 '--no-raise-error', action="store_false", dest='raise_error',
59 '--no-raise-error', action="store_false", dest='raise_error',
60 help="""Whether you should raise an error message in addition to
60 help="""Whether you should raise an error message in addition to
61 a stream on stderr if you get a nonzero exit code.
61 a stream on stderr if you get a nonzero exit code.
62 """
62 """
63 )
63 )
64 ]
64 ]
65 for arg in args:
65 for arg in args:
66 f = arg(f)
66 f = arg(f)
67 return f
67 return f
68
68
69
69
70 @contextmanager
70 @contextmanager
71 def safe_watcher():
71 def safe_watcher():
72 if sys.platform == "win32":
72 if sys.platform == "win32":
73 yield
73 yield
74 return
74 return
75
75
76 from asyncio import SafeChildWatcher
76 from asyncio import SafeChildWatcher
77
77
78 policy = asyncio.get_event_loop_policy()
78 policy = asyncio.get_event_loop_policy()
79 old_watcher = policy.get_child_watcher()
79 old_watcher = policy.get_child_watcher()
80 if isinstance(old_watcher, SafeChildWatcher):
80 if isinstance(old_watcher, SafeChildWatcher):
81 yield
81 yield
82 return
82 return
83
83
84 loop = policy.get_event_loop()
84 loop = policy.get_event_loop()
85 try:
85 try:
86 watcher = asyncio.SafeChildWatcher()
86 watcher = asyncio.SafeChildWatcher()
87 watcher.attach_loop(loop)
87 watcher.attach_loop(loop)
88 policy.set_child_watcher(watcher)
88 policy.set_child_watcher(watcher)
89 yield
89 yield
90 finally:
90 finally:
91 watcher.close()
91 watcher.close()
92 policy.set_child_watcher(old_watcher)
92 policy.set_child_watcher(old_watcher)
93
93
94
94
95 def dec_safe_watcher(fun):
95 def dec_safe_watcher(fun):
96 @functools.wraps(fun)
96 @functools.wraps(fun)
97 def _inner(*args, **kwargs):
97 def _inner(*args, **kwargs):
98 with safe_watcher():
98 with safe_watcher():
99 return fun(*args, **kwargs)
99 return fun(*args, **kwargs)
100
100
101 return _inner
101 return _inner
102
102
103
103
104 @magics_class
104 @magics_class
105 class ScriptMagics(Magics):
105 class ScriptMagics(Magics):
106 """Magics for talking to scripts
106 """Magics for talking to scripts
107
107
108 This defines a base `%%script` cell magic for running a cell
108 This defines a base `%%script` cell magic for running a cell
109 with a program in a subprocess, and registers a few top-level
109 with a program in a subprocess, and registers a few top-level
110 magics that call %%script with common interpreters.
110 magics that call %%script with common interpreters.
111 """
111 """
112 script_magics = List(
112 script_magics = List(
113 help="""Extra script cell magics to define
113 help="""Extra script cell magics to define
114
114
115 This generates simple wrappers of `%%script foo` as `%%foo`.
115 This generates simple wrappers of `%%script foo` as `%%foo`.
116
116
117 If you want to add script magics that aren't on your path,
117 If you want to add script magics that aren't on your path,
118 specify them in script_paths
118 specify them in script_paths
119 """,
119 """,
120 ).tag(config=True)
120 ).tag(config=True)
121 @default('script_magics')
121 @default('script_magics')
122 def _script_magics_default(self):
122 def _script_magics_default(self):
123 """default to a common list of programs"""
123 """default to a common list of programs"""
124
124
125 defaults = [
125 defaults = [
126 'sh',
126 'sh',
127 'bash',
127 'bash',
128 'perl',
128 'perl',
129 'ruby',
129 'ruby',
130 'python',
130 'python',
131 'python2',
131 'python2',
132 'python3',
132 'python3',
133 'pypy',
133 'pypy',
134 ]
134 ]
135 if os.name == 'nt':
135 if os.name == 'nt':
136 defaults.extend([
136 defaults.extend([
137 'cmd',
137 'cmd',
138 ])
138 ])
139
139
140 return defaults
140 return defaults
141
141
142 script_paths = Dict(
142 script_paths = Dict(
143 help="""Dict mapping short 'ruby' names to full paths, such as '/opt/secret/bin/ruby'
143 help="""Dict mapping short 'ruby' names to full paths, such as '/opt/secret/bin/ruby'
144
144
145 Only necessary for items in script_magics where the default path will not
145 Only necessary for items in script_magics where the default path will not
146 find the right interpreter.
146 find the right interpreter.
147 """
147 """
148 ).tag(config=True)
148 ).tag(config=True)
149
149
150 def __init__(self, shell=None):
150 def __init__(self, shell=None):
151 super(ScriptMagics, self).__init__(shell=shell)
151 super(ScriptMagics, self).__init__(shell=shell)
152 self._generate_script_magics()
152 self._generate_script_magics()
153 self.job_manager = BackgroundJobManager()
153 self.job_manager = BackgroundJobManager()
154 self.bg_processes = []
154 self.bg_processes = []
155 atexit.register(self.kill_bg_processes)
155 atexit.register(self.kill_bg_processes)
156
156
157 def __del__(self):
157 def __del__(self):
158 self.kill_bg_processes()
158 self.kill_bg_processes()
159
159
160 def _generate_script_magics(self):
160 def _generate_script_magics(self):
161 cell_magics = self.magics['cell']
161 cell_magics = self.magics['cell']
162 for name in self.script_magics:
162 for name in self.script_magics:
163 cell_magics[name] = self._make_script_magic(name)
163 cell_magics[name] = self._make_script_magic(name)
164
164
165 def _make_script_magic(self, name):
165 def _make_script_magic(self, name):
166 """make a named magic, that calls %%script with a particular program"""
166 """make a named magic, that calls %%script with a particular program"""
167 # expand to explicit path if necessary:
167 # expand to explicit path if necessary:
168 script = self.script_paths.get(name, name)
168 script = self.script_paths.get(name, name)
169
169
170 @magic_arguments.magic_arguments()
170 @magic_arguments.magic_arguments()
171 @script_args
171 @script_args
172 def named_script_magic(line, cell):
172 def named_script_magic(line, cell):
173 # if line, add it as cl-flags
173 # if line, add it as cl-flags
174 if line:
174 if line:
175 line = "%s %s" % (script, line)
175 line = "%s %s" % (script, line)
176 else:
176 else:
177 line = script
177 line = script
178 return self.shebang(line, cell)
178 return self.shebang(line, cell)
179
179
180 # write a basic docstring:
180 # write a basic docstring:
181 named_script_magic.__doc__ = \
181 named_script_magic.__doc__ = \
182 """%%{name} script magic
182 """%%{name} script magic
183
183
184 Run cells with {script} in a subprocess.
184 Run cells with {script} in a subprocess.
185
185
186 This is a shortcut for `%%script {script}`
186 This is a shortcut for `%%script {script}`
187 """.format(**locals())
187 """.format(**locals())
188
188
189 return named_script_magic
189 return named_script_magic
190
190
191 @magic_arguments.magic_arguments()
191 @magic_arguments.magic_arguments()
192 @script_args
192 @script_args
193 @cell_magic("script")
193 @cell_magic("script")
194 @dec_safe_watcher
194 @dec_safe_watcher
195 def shebang(self, line, cell):
195 def shebang(self, line, cell):
196 """Run a cell via a shell command
196 """Run a cell via a shell command
197
197
198 The `%%script` line is like the #! line of script,
198 The `%%script` line is like the #! line of script,
199 specifying a program (bash, perl, ruby, etc.) with which to run.
199 specifying a program (bash, perl, ruby, etc.) with which to run.
200
200
201 The rest of the cell is run by that program.
201 The rest of the cell is run by that program.
202
202
203 Examples
203 Examples
204 --------
204 --------
205 ::
205 ::
206
206
207 In [1]: %%script bash
207 In [1]: %%script bash
208 ...: for i in 1 2 3; do
208 ...: for i in 1 2 3; do
209 ...: echo $i
209 ...: echo $i
210 ...: done
210 ...: done
211 1
211 1
212 2
212 2
213 3
213 3
214 """
214 """
215
215
216 async def _handle_stream(stream, stream_arg, file_object):
216 async def _handle_stream(stream, stream_arg, file_object):
217 while True:
217 while True:
218 line = (await stream.readline()).decode("utf8")
218 line = (await stream.readline()).decode("utf8")
219 if not line:
219 if not line:
220 break
220 break
221 if stream_arg:
221 if stream_arg:
222 self.shell.user_ns[stream_arg] = line
222 self.shell.user_ns[stream_arg] = line
223 else:
223 else:
224 file_object.write(line)
224 file_object.write(line)
225 file_object.flush()
225 file_object.flush()
226
226
227 async def _stream_communicate(process, cell):
227 async def _stream_communicate(process, cell):
228 process.stdin.write(cell)
228 process.stdin.write(cell)
229 process.stdin.close()
229 process.stdin.close()
230 stdout_task = asyncio.create_task(
230 stdout_task = asyncio.create_task(
231 _handle_stream(process.stdout, args.out, sys.stdout)
231 _handle_stream(process.stdout, args.out, sys.stdout)
232 )
232 )
233 stderr_task = asyncio.create_task(
233 stderr_task = asyncio.create_task(
234 _handle_stream(process.stderr, args.err, sys.stderr)
234 _handle_stream(process.stderr, args.err, sys.stderr)
235 )
235 )
236 await asyncio.wait([stdout_task, stderr_task])
236 await asyncio.wait([stdout_task, stderr_task])
237 await process.wait()
237 await process.wait()
238
238
239 if sys.platform.startswith("win"):
239 if sys.platform.startswith("win"):
240 asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy())
240 asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy())
241 loop = asyncio.get_event_loop_policy().get_event_loop()
241 loop = asyncio.get_event_loop_policy().get_event_loop()
242 argv = arg_split(line, posix=not sys.platform.startswith("win"))
242 argv = arg_split(line, posix=not sys.platform.startswith("win"))
243 args, cmd = self.shebang.parser.parse_known_args(argv)
243 args, cmd = self.shebang.parser.parse_known_args(argv)
244 try:
244 try:
245 p = loop.run_until_complete(
245 p = loop.run_until_complete(
246 asyncio.create_subprocess_exec(
246 asyncio.create_subprocess_exec(
247 *cmd,
247 *cmd,
248 stdout=asyncio.subprocess.PIPE,
248 stdout=asyncio.subprocess.PIPE,
249 stderr=asyncio.subprocess.PIPE,
249 stderr=asyncio.subprocess.PIPE,
250 stdin=asyncio.subprocess.PIPE,
250 stdin=asyncio.subprocess.PIPE,
251 )
251 )
252 )
252 )
253 except OSError as e:
253 except OSError as e:
254 if e.errno == errno.ENOENT:
254 if e.errno == errno.ENOENT:
255 print("Couldn't find program: %r" % cmd[0])
255 print("Couldn't find program: %r" % cmd[0])
256 return
256 return
257 else:
257 else:
258 raise
258 raise
259
259
260 if not cell.endswith('\n'):
260 if not cell.endswith('\n'):
261 cell += '\n'
261 cell += '\n'
262 cell = cell.encode('utf8', 'replace')
262 cell = cell.encode('utf8', 'replace')
263 if args.bg:
263 if args.bg:
264 self.bg_processes.append(p)
264 self.bg_processes.append(p)
265 self._gc_bg_processes()
265 self._gc_bg_processes()
266 to_close = []
266 to_close = []
267 if args.out:
267 if args.out:
268 self.shell.user_ns[args.out] = p.stdout
268 self.shell.user_ns[args.out] = p.stdout
269 else:
269 else:
270 to_close.append(p.stdout)
270 to_close.append(p.stdout)
271 if args.err:
271 if args.err:
272 self.shell.user_ns[args.err] = p.stderr
272 self.shell.user_ns[args.err] = p.stderr
273 else:
273 else:
274 to_close.append(p.stderr)
274 to_close.append(p.stderr)
275 self.job_manager.new(self._run_script, p, cell, to_close, daemon=True)
275 self.job_manager.new(self._run_script, p, cell, to_close, daemon=True)
276 if args.proc:
276 if args.proc:
277 self.shell.user_ns[args.proc] = p
277 self.shell.user_ns[args.proc] = p
278 return
278 return
279
279
280 try:
280 try:
281 loop.run_until_complete(_stream_communicate(p, cell))
281 loop.run_until_complete(_stream_communicate(p, cell))
282 except KeyboardInterrupt:
282 except KeyboardInterrupt:
283 try:
283 try:
284 p.send_signal(signal.SIGINT)
284 p.send_signal(signal.SIGINT)
285 time.sleep(0.1)
285 time.sleep(0.1)
286 if p.returncode is not None:
286 if p.returncode is not None:
287 print("Process is interrupted.")
287 print("Process is interrupted.")
288 return
288 return
289 p.terminate()
289 p.terminate()
290 time.sleep(0.1)
290 time.sleep(0.1)
291 if p.returncode is not None:
291 if p.returncode is not None:
292 print("Process is terminated.")
292 print("Process is terminated.")
293 return
293 return
294 p.kill()
294 p.kill()
295 print("Process is killed.")
295 print("Process is killed.")
296 except OSError:
296 except OSError:
297 pass
297 pass
298 except Exception as e:
298 except Exception as e:
299 print("Error while terminating subprocess (pid=%i): %s" % (p.pid, e))
299 print("Error while terminating subprocess (pid=%i): %s" % (p.pid, e))
300 return
300 return
301 if args.raise_error and p.returncode!=0:
301 if args.raise_error and p.returncode!=0:
302 # If we get here and p.returncode is still None, we must have
302 # If we get here and p.returncode is still None, we must have
303 # killed it but not yet seen its return code. We don't wait for it,
303 # killed it but not yet seen its return code. We don't wait for it,
304 # in case it's stuck in uninterruptible sleep. -9 = SIGKILL
304 # in case it's stuck in uninterruptible sleep. -9 = SIGKILL
305 rc = p.returncode or -9
305 rc = p.returncode or -9
306 raise CalledProcessError(rc, cell)
306 raise CalledProcessError(rc, cell)
307
307
308 shebang.__skip_doctest__ = os.name != "posix"
309
308 def _run_script(self, p, cell, to_close):
310 def _run_script(self, p, cell, to_close):
309 """callback for running the script in the background"""
311 """callback for running the script in the background"""
310 p.stdin.write(cell)
312 p.stdin.write(cell)
311 p.stdin.close()
313 p.stdin.close()
312 for s in to_close:
314 for s in to_close:
313 s.close()
315 s.close()
314 p.wait()
316 p.wait()
315
317
316 @line_magic("killbgscripts")
318 @line_magic("killbgscripts")
317 def killbgscripts(self, _nouse_=''):
319 def killbgscripts(self, _nouse_=''):
318 """Kill all BG processes started by %%script and its family."""
320 """Kill all BG processes started by %%script and its family."""
319 self.kill_bg_processes()
321 self.kill_bg_processes()
320 print("All background processes were killed.")
322 print("All background processes were killed.")
321
323
322 def kill_bg_processes(self):
324 def kill_bg_processes(self):
323 """Kill all BG processes which are still running."""
325 """Kill all BG processes which are still running."""
324 if not self.bg_processes:
326 if not self.bg_processes:
325 return
327 return
326 for p in self.bg_processes:
328 for p in self.bg_processes:
327 if p.returncode is None:
329 if p.returncode is None:
328 try:
330 try:
329 p.send_signal(signal.SIGINT)
331 p.send_signal(signal.SIGINT)
330 except:
332 except:
331 pass
333 pass
332 time.sleep(0.1)
334 time.sleep(0.1)
333 self._gc_bg_processes()
335 self._gc_bg_processes()
334 if not self.bg_processes:
336 if not self.bg_processes:
335 return
337 return
336 for p in self.bg_processes:
338 for p in self.bg_processes:
337 if p.returncode is None:
339 if p.returncode is None:
338 try:
340 try:
339 p.terminate()
341 p.terminate()
340 except:
342 except:
341 pass
343 pass
342 time.sleep(0.1)
344 time.sleep(0.1)
343 self._gc_bg_processes()
345 self._gc_bg_processes()
344 if not self.bg_processes:
346 if not self.bg_processes:
345 return
347 return
346 for p in self.bg_processes:
348 for p in self.bg_processes:
347 if p.returncode is None:
349 if p.returncode is None:
348 try:
350 try:
349 p.kill()
351 p.kill()
350 except:
352 except:
351 pass
353 pass
352 self._gc_bg_processes()
354 self._gc_bg_processes()
353
355
354 def _gc_bg_processes(self):
356 def _gc_bg_processes(self):
355 self.bg_processes = [p for p in self.bg_processes if p.returncode is None]
357 self.bg_processes = [p for p in self.bg_processes if p.returncode is None]
@@ -1,1072 +1,1082 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Tests for the key interactiveshell module.
2 """Tests for the key interactiveshell module.
3
3
4 Historically the main classes in interactiveshell have been under-tested. This
4 Historically the main classes in interactiveshell have been under-tested. This
5 module should grow as many single-method tests as possible to trap many of the
5 module should grow as many single-method tests as possible to trap many of the
6 recurring bugs we seem to encounter with high-level interaction.
6 recurring bugs we seem to encounter with high-level interaction.
7 """
7 """
8
8
9 # Copyright (c) IPython Development Team.
9 # Copyright (c) IPython Development Team.
10 # Distributed under the terms of the Modified BSD License.
10 # Distributed under the terms of the Modified BSD License.
11
11
12 import asyncio
12 import asyncio
13 import ast
13 import ast
14 import os
14 import os
15 import signal
15 import signal
16 import shutil
16 import shutil
17 import sys
17 import sys
18 import tempfile
18 import tempfile
19 import unittest
19 import unittest
20 from unittest import mock
20 from unittest import mock
21
21
22 from os.path import join
22 from os.path import join
23
23
24 from IPython.core.error import InputRejected
24 from IPython.core.error import InputRejected
25 from IPython.core.inputtransformer import InputTransformer
25 from IPython.core.inputtransformer import InputTransformer
26 from IPython.core import interactiveshell
26 from IPython.core import interactiveshell
27 from IPython.testing.decorators import (
27 from IPython.testing.decorators import (
28 skipif, skip_win32, onlyif_unicode_paths, onlyif_cmds_exist,
28 skipif, skip_win32, onlyif_unicode_paths, onlyif_cmds_exist,
29 )
29 )
30 from IPython.testing import tools as tt
30 from IPython.testing import tools as tt
31 from IPython.utils.process import find_cmd
31 from IPython.utils.process import find_cmd
32
32
33 #-----------------------------------------------------------------------------
33 #-----------------------------------------------------------------------------
34 # Globals
34 # Globals
35 #-----------------------------------------------------------------------------
35 #-----------------------------------------------------------------------------
36 # This is used by every single test, no point repeating it ad nauseam
36 # This is used by every single test, no point repeating it ad nauseam
37
37
38 #-----------------------------------------------------------------------------
38 #-----------------------------------------------------------------------------
39 # Tests
39 # Tests
40 #-----------------------------------------------------------------------------
40 #-----------------------------------------------------------------------------
41
41
42 class DerivedInterrupt(KeyboardInterrupt):
42 class DerivedInterrupt(KeyboardInterrupt):
43 pass
43 pass
44
44
45 class InteractiveShellTestCase(unittest.TestCase):
45 class InteractiveShellTestCase(unittest.TestCase):
46 def test_naked_string_cells(self):
46 def test_naked_string_cells(self):
47 """Test that cells with only naked strings are fully executed"""
47 """Test that cells with only naked strings are fully executed"""
48 # First, single-line inputs
48 # First, single-line inputs
49 ip.run_cell('"a"\n')
49 ip.run_cell('"a"\n')
50 self.assertEqual(ip.user_ns['_'], 'a')
50 self.assertEqual(ip.user_ns['_'], 'a')
51 # And also multi-line cells
51 # And also multi-line cells
52 ip.run_cell('"""a\nb"""\n')
52 ip.run_cell('"""a\nb"""\n')
53 self.assertEqual(ip.user_ns['_'], 'a\nb')
53 self.assertEqual(ip.user_ns['_'], 'a\nb')
54
54
55 def test_run_empty_cell(self):
55 def test_run_empty_cell(self):
56 """Just make sure we don't get a horrible error with a blank
56 """Just make sure we don't get a horrible error with a blank
57 cell of input. Yes, I did overlook that."""
57 cell of input. Yes, I did overlook that."""
58 old_xc = ip.execution_count
58 old_xc = ip.execution_count
59 res = ip.run_cell('')
59 res = ip.run_cell('')
60 self.assertEqual(ip.execution_count, old_xc)
60 self.assertEqual(ip.execution_count, old_xc)
61 self.assertEqual(res.execution_count, None)
61 self.assertEqual(res.execution_count, None)
62
62
63 def test_run_cell_multiline(self):
63 def test_run_cell_multiline(self):
64 """Multi-block, multi-line cells must execute correctly.
64 """Multi-block, multi-line cells must execute correctly.
65 """
65 """
66 src = '\n'.join(["x=1",
66 src = '\n'.join(["x=1",
67 "y=2",
67 "y=2",
68 "if 1:",
68 "if 1:",
69 " x += 1",
69 " x += 1",
70 " y += 1",])
70 " y += 1",])
71 res = ip.run_cell(src)
71 res = ip.run_cell(src)
72 self.assertEqual(ip.user_ns['x'], 2)
72 self.assertEqual(ip.user_ns['x'], 2)
73 self.assertEqual(ip.user_ns['y'], 3)
73 self.assertEqual(ip.user_ns['y'], 3)
74 self.assertEqual(res.success, True)
74 self.assertEqual(res.success, True)
75 self.assertEqual(res.result, None)
75 self.assertEqual(res.result, None)
76
76
77 def test_multiline_string_cells(self):
77 def test_multiline_string_cells(self):
78 "Code sprinkled with multiline strings should execute (GH-306)"
78 "Code sprinkled with multiline strings should execute (GH-306)"
79 ip.run_cell('tmp=0')
79 ip.run_cell('tmp=0')
80 self.assertEqual(ip.user_ns['tmp'], 0)
80 self.assertEqual(ip.user_ns['tmp'], 0)
81 res = ip.run_cell('tmp=1;"""a\nb"""\n')
81 res = ip.run_cell('tmp=1;"""a\nb"""\n')
82 self.assertEqual(ip.user_ns['tmp'], 1)
82 self.assertEqual(ip.user_ns['tmp'], 1)
83 self.assertEqual(res.success, True)
83 self.assertEqual(res.success, True)
84 self.assertEqual(res.result, "a\nb")
84 self.assertEqual(res.result, "a\nb")
85
85
86 def test_dont_cache_with_semicolon(self):
86 def test_dont_cache_with_semicolon(self):
87 "Ending a line with semicolon should not cache the returned object (GH-307)"
87 "Ending a line with semicolon should not cache the returned object (GH-307)"
88 oldlen = len(ip.user_ns['Out'])
88 oldlen = len(ip.user_ns['Out'])
89 for cell in ['1;', '1;1;']:
89 for cell in ['1;', '1;1;']:
90 res = ip.run_cell(cell, store_history=True)
90 res = ip.run_cell(cell, store_history=True)
91 newlen = len(ip.user_ns['Out'])
91 newlen = len(ip.user_ns['Out'])
92 self.assertEqual(oldlen, newlen)
92 self.assertEqual(oldlen, newlen)
93 self.assertIsNone(res.result)
93 self.assertIsNone(res.result)
94 i = 0
94 i = 0
95 #also test the default caching behavior
95 #also test the default caching behavior
96 for cell in ['1', '1;1']:
96 for cell in ['1', '1;1']:
97 ip.run_cell(cell, store_history=True)
97 ip.run_cell(cell, store_history=True)
98 newlen = len(ip.user_ns['Out'])
98 newlen = len(ip.user_ns['Out'])
99 i += 1
99 i += 1
100 self.assertEqual(oldlen+i, newlen)
100 self.assertEqual(oldlen+i, newlen)
101
101
102 def test_syntax_error(self):
102 def test_syntax_error(self):
103 res = ip.run_cell("raise = 3")
103 res = ip.run_cell("raise = 3")
104 self.assertIsInstance(res.error_before_exec, SyntaxError)
104 self.assertIsInstance(res.error_before_exec, SyntaxError)
105
105
106 def test_In_variable(self):
106 def test_In_variable(self):
107 "Verify that In variable grows with user input (GH-284)"
107 "Verify that In variable grows with user input (GH-284)"
108 oldlen = len(ip.user_ns['In'])
108 oldlen = len(ip.user_ns['In'])
109 ip.run_cell('1;', store_history=True)
109 ip.run_cell('1;', store_history=True)
110 newlen = len(ip.user_ns['In'])
110 newlen = len(ip.user_ns['In'])
111 self.assertEqual(oldlen+1, newlen)
111 self.assertEqual(oldlen+1, newlen)
112 self.assertEqual(ip.user_ns['In'][-1],'1;')
112 self.assertEqual(ip.user_ns['In'][-1],'1;')
113
113
114 def test_magic_names_in_string(self):
114 def test_magic_names_in_string(self):
115 ip.run_cell('a = """\n%exit\n"""')
115 ip.run_cell('a = """\n%exit\n"""')
116 self.assertEqual(ip.user_ns['a'], '\n%exit\n')
116 self.assertEqual(ip.user_ns['a'], '\n%exit\n')
117
117
118 def test_trailing_newline(self):
118 def test_trailing_newline(self):
119 """test that running !(command) does not raise a SyntaxError"""
119 """test that running !(command) does not raise a SyntaxError"""
120 ip.run_cell('!(true)\n', False)
120 ip.run_cell('!(true)\n', False)
121 ip.run_cell('!(true)\n\n\n', False)
121 ip.run_cell('!(true)\n\n\n', False)
122
122
123 def test_gh_597(self):
123 def test_gh_597(self):
124 """Pretty-printing lists of objects with non-ascii reprs may cause
124 """Pretty-printing lists of objects with non-ascii reprs may cause
125 problems."""
125 problems."""
126 class Spam(object):
126 class Spam(object):
127 def __repr__(self):
127 def __repr__(self):
128 return "\xe9"*50
128 return "\xe9"*50
129 import IPython.core.formatters
129 import IPython.core.formatters
130 f = IPython.core.formatters.PlainTextFormatter()
130 f = IPython.core.formatters.PlainTextFormatter()
131 f([Spam(),Spam()])
131 f([Spam(),Spam()])
132
132
133
133
134 def test_future_flags(self):
134 def test_future_flags(self):
135 """Check that future flags are used for parsing code (gh-777)"""
135 """Check that future flags are used for parsing code (gh-777)"""
136 ip.run_cell('from __future__ import barry_as_FLUFL')
136 ip.run_cell('from __future__ import barry_as_FLUFL')
137 try:
137 try:
138 ip.run_cell('prfunc_return_val = 1 <> 2')
138 ip.run_cell('prfunc_return_val = 1 <> 2')
139 assert 'prfunc_return_val' in ip.user_ns
139 assert 'prfunc_return_val' in ip.user_ns
140 finally:
140 finally:
141 # Reset compiler flags so we don't mess up other tests.
141 # Reset compiler flags so we don't mess up other tests.
142 ip.compile.reset_compiler_flags()
142 ip.compile.reset_compiler_flags()
143
143
144 def test_can_pickle(self):
144 def test_can_pickle(self):
145 "Can we pickle objects defined interactively (GH-29)"
145 "Can we pickle objects defined interactively (GH-29)"
146 ip = get_ipython()
146 ip = get_ipython()
147 ip.reset()
147 ip.reset()
148 ip.run_cell(("class Mylist(list):\n"
148 ip.run_cell(("class Mylist(list):\n"
149 " def __init__(self,x=[]):\n"
149 " def __init__(self,x=[]):\n"
150 " list.__init__(self,x)"))
150 " list.__init__(self,x)"))
151 ip.run_cell("w=Mylist([1,2,3])")
151 ip.run_cell("w=Mylist([1,2,3])")
152
152
153 from pickle import dumps
153 from pickle import dumps
154
154
155 # We need to swap in our main module - this is only necessary
155 # We need to swap in our main module - this is only necessary
156 # inside the test framework, because IPython puts the interactive module
156 # inside the test framework, because IPython puts the interactive module
157 # in place (but the test framework undoes this).
157 # in place (but the test framework undoes this).
158 _main = sys.modules['__main__']
158 _main = sys.modules['__main__']
159 sys.modules['__main__'] = ip.user_module
159 sys.modules['__main__'] = ip.user_module
160 try:
160 try:
161 res = dumps(ip.user_ns["w"])
161 res = dumps(ip.user_ns["w"])
162 finally:
162 finally:
163 sys.modules['__main__'] = _main
163 sys.modules['__main__'] = _main
164 self.assertTrue(isinstance(res, bytes))
164 self.assertTrue(isinstance(res, bytes))
165
165
166 def test_global_ns(self):
166 def test_global_ns(self):
167 "Code in functions must be able to access variables outside them."
167 "Code in functions must be able to access variables outside them."
168 ip = get_ipython()
168 ip = get_ipython()
169 ip.run_cell("a = 10")
169 ip.run_cell("a = 10")
170 ip.run_cell(("def f(x):\n"
170 ip.run_cell(("def f(x):\n"
171 " return x + a"))
171 " return x + a"))
172 ip.run_cell("b = f(12)")
172 ip.run_cell("b = f(12)")
173 self.assertEqual(ip.user_ns["b"], 22)
173 self.assertEqual(ip.user_ns["b"], 22)
174
174
175 def test_bad_custom_tb(self):
175 def test_bad_custom_tb(self):
176 """Check that InteractiveShell is protected from bad custom exception handlers"""
176 """Check that InteractiveShell is protected from bad custom exception handlers"""
177 ip.set_custom_exc((IOError,), lambda etype,value,tb: 1/0)
177 ip.set_custom_exc((IOError,), lambda etype,value,tb: 1/0)
178 self.assertEqual(ip.custom_exceptions, (IOError,))
178 self.assertEqual(ip.custom_exceptions, (IOError,))
179 with tt.AssertPrints("Custom TB Handler failed", channel='stderr'):
179 with tt.AssertPrints("Custom TB Handler failed", channel='stderr'):
180 ip.run_cell(u'raise IOError("foo")')
180 ip.run_cell(u'raise IOError("foo")')
181 self.assertEqual(ip.custom_exceptions, ())
181 self.assertEqual(ip.custom_exceptions, ())
182
182
183 def test_bad_custom_tb_return(self):
183 def test_bad_custom_tb_return(self):
184 """Check that InteractiveShell is protected from bad return types in custom exception handlers"""
184 """Check that InteractiveShell is protected from bad return types in custom exception handlers"""
185 ip.set_custom_exc((NameError,),lambda etype,value,tb, tb_offset=None: 1)
185 ip.set_custom_exc((NameError,),lambda etype,value,tb, tb_offset=None: 1)
186 self.assertEqual(ip.custom_exceptions, (NameError,))
186 self.assertEqual(ip.custom_exceptions, (NameError,))
187 with tt.AssertPrints("Custom TB Handler failed", channel='stderr'):
187 with tt.AssertPrints("Custom TB Handler failed", channel='stderr'):
188 ip.run_cell(u'a=abracadabra')
188 ip.run_cell(u'a=abracadabra')
189 self.assertEqual(ip.custom_exceptions, ())
189 self.assertEqual(ip.custom_exceptions, ())
190
190
191 def test_drop_by_id(self):
191 def test_drop_by_id(self):
192 myvars = {"a":object(), "b":object(), "c": object()}
192 myvars = {"a":object(), "b":object(), "c": object()}
193 ip.push(myvars, interactive=False)
193 ip.push(myvars, interactive=False)
194 for name in myvars:
194 for name in myvars:
195 assert name in ip.user_ns, name
195 assert name in ip.user_ns, name
196 assert name in ip.user_ns_hidden, name
196 assert name in ip.user_ns_hidden, name
197 ip.user_ns['b'] = 12
197 ip.user_ns['b'] = 12
198 ip.drop_by_id(myvars)
198 ip.drop_by_id(myvars)
199 for name in ["a", "c"]:
199 for name in ["a", "c"]:
200 assert name not in ip.user_ns, name
200 assert name not in ip.user_ns, name
201 assert name not in ip.user_ns_hidden, name
201 assert name not in ip.user_ns_hidden, name
202 assert ip.user_ns['b'] == 12
202 assert ip.user_ns['b'] == 12
203 ip.reset()
203 ip.reset()
204
204
205 def test_var_expand(self):
205 def test_var_expand(self):
206 ip.user_ns['f'] = u'Ca\xf1o'
206 ip.user_ns['f'] = u'Ca\xf1o'
207 self.assertEqual(ip.var_expand(u'echo $f'), u'echo Ca\xf1o')
207 self.assertEqual(ip.var_expand(u'echo $f'), u'echo Ca\xf1o')
208 self.assertEqual(ip.var_expand(u'echo {f}'), u'echo Ca\xf1o')
208 self.assertEqual(ip.var_expand(u'echo {f}'), u'echo Ca\xf1o')
209 self.assertEqual(ip.var_expand(u'echo {f[:-1]}'), u'echo Ca\xf1')
209 self.assertEqual(ip.var_expand(u'echo {f[:-1]}'), u'echo Ca\xf1')
210 self.assertEqual(ip.var_expand(u'echo {1*2}'), u'echo 2')
210 self.assertEqual(ip.var_expand(u'echo {1*2}'), u'echo 2')
211
211
212 self.assertEqual(ip.var_expand(u"grep x | awk '{print $1}'"), u"grep x | awk '{print $1}'")
212 self.assertEqual(ip.var_expand(u"grep x | awk '{print $1}'"), u"grep x | awk '{print $1}'")
213
213
214 ip.user_ns['f'] = b'Ca\xc3\xb1o'
214 ip.user_ns['f'] = b'Ca\xc3\xb1o'
215 # This should not raise any exception:
215 # This should not raise any exception:
216 ip.var_expand(u'echo $f')
216 ip.var_expand(u'echo $f')
217
217
218 def test_var_expand_local(self):
218 def test_var_expand_local(self):
219 """Test local variable expansion in !system and %magic calls"""
219 """Test local variable expansion in !system and %magic calls"""
220 # !system
220 # !system
221 ip.run_cell(
221 ip.run_cell(
222 "def test():\n"
222 "def test():\n"
223 ' lvar = "ttt"\n'
223 ' lvar = "ttt"\n'
224 " ret = !echo {lvar}\n"
224 " ret = !echo {lvar}\n"
225 " return ret[0]\n"
225 " return ret[0]\n"
226 )
226 )
227 res = ip.user_ns["test"]()
227 res = ip.user_ns["test"]()
228 self.assertIn("ttt", res)
228 self.assertIn("ttt", res)
229
229
230 # %magic
230 # %magic
231 ip.run_cell(
231 ip.run_cell(
232 "def makemacro():\n"
232 "def makemacro():\n"
233 ' macroname = "macro_var_expand_locals"\n'
233 ' macroname = "macro_var_expand_locals"\n'
234 " %macro {macroname} codestr\n"
234 " %macro {macroname} codestr\n"
235 )
235 )
236 ip.user_ns["codestr"] = "str(12)"
236 ip.user_ns["codestr"] = "str(12)"
237 ip.run_cell("makemacro()")
237 ip.run_cell("makemacro()")
238 self.assertIn("macro_var_expand_locals", ip.user_ns)
238 self.assertIn("macro_var_expand_locals", ip.user_ns)
239
239
240 def test_var_expand_self(self):
240 def test_var_expand_self(self):
241 """Test variable expansion with the name 'self', which was failing.
241 """Test variable expansion with the name 'self', which was failing.
242
242
243 See https://github.com/ipython/ipython/issues/1878#issuecomment-7698218
243 See https://github.com/ipython/ipython/issues/1878#issuecomment-7698218
244 """
244 """
245 ip.run_cell(
245 ip.run_cell(
246 "class cTest:\n"
246 "class cTest:\n"
247 ' classvar="see me"\n'
247 ' classvar="see me"\n'
248 " def test(self):\n"
248 " def test(self):\n"
249 " res = !echo Variable: {self.classvar}\n"
249 " res = !echo Variable: {self.classvar}\n"
250 " return res[0]\n"
250 " return res[0]\n"
251 )
251 )
252 self.assertIn("see me", ip.user_ns["cTest"]().test())
252 self.assertIn("see me", ip.user_ns["cTest"]().test())
253
253
254 def test_bad_var_expand(self):
254 def test_bad_var_expand(self):
255 """var_expand on invalid formats shouldn't raise"""
255 """var_expand on invalid formats shouldn't raise"""
256 # SyntaxError
256 # SyntaxError
257 self.assertEqual(ip.var_expand(u"{'a':5}"), u"{'a':5}")
257 self.assertEqual(ip.var_expand(u"{'a':5}"), u"{'a':5}")
258 # NameError
258 # NameError
259 self.assertEqual(ip.var_expand(u"{asdf}"), u"{asdf}")
259 self.assertEqual(ip.var_expand(u"{asdf}"), u"{asdf}")
260 # ZeroDivisionError
260 # ZeroDivisionError
261 self.assertEqual(ip.var_expand(u"{1/0}"), u"{1/0}")
261 self.assertEqual(ip.var_expand(u"{1/0}"), u"{1/0}")
262
262
263 def test_silent_postexec(self):
263 def test_silent_postexec(self):
264 """run_cell(silent=True) doesn't invoke pre/post_run_cell callbacks"""
264 """run_cell(silent=True) doesn't invoke pre/post_run_cell callbacks"""
265 pre_explicit = mock.Mock()
265 pre_explicit = mock.Mock()
266 pre_always = mock.Mock()
266 pre_always = mock.Mock()
267 post_explicit = mock.Mock()
267 post_explicit = mock.Mock()
268 post_always = mock.Mock()
268 post_always = mock.Mock()
269 all_mocks = [pre_explicit, pre_always, post_explicit, post_always]
269 all_mocks = [pre_explicit, pre_always, post_explicit, post_always]
270
270
271 ip.events.register('pre_run_cell', pre_explicit)
271 ip.events.register('pre_run_cell', pre_explicit)
272 ip.events.register('pre_execute', pre_always)
272 ip.events.register('pre_execute', pre_always)
273 ip.events.register('post_run_cell', post_explicit)
273 ip.events.register('post_run_cell', post_explicit)
274 ip.events.register('post_execute', post_always)
274 ip.events.register('post_execute', post_always)
275
275
276 try:
276 try:
277 ip.run_cell("1", silent=True)
277 ip.run_cell("1", silent=True)
278 assert pre_always.called
278 assert pre_always.called
279 assert not pre_explicit.called
279 assert not pre_explicit.called
280 assert post_always.called
280 assert post_always.called
281 assert not post_explicit.called
281 assert not post_explicit.called
282 # double-check that non-silent exec did what we expected
282 # double-check that non-silent exec did what we expected
283 # silent to avoid
283 # silent to avoid
284 ip.run_cell("1")
284 ip.run_cell("1")
285 assert pre_explicit.called
285 assert pre_explicit.called
286 assert post_explicit.called
286 assert post_explicit.called
287 info, = pre_explicit.call_args[0]
287 info, = pre_explicit.call_args[0]
288 result, = post_explicit.call_args[0]
288 result, = post_explicit.call_args[0]
289 self.assertEqual(info, result.info)
289 self.assertEqual(info, result.info)
290 # check that post hooks are always called
290 # check that post hooks are always called
291 [m.reset_mock() for m in all_mocks]
291 [m.reset_mock() for m in all_mocks]
292 ip.run_cell("syntax error")
292 ip.run_cell("syntax error")
293 assert pre_always.called
293 assert pre_always.called
294 assert pre_explicit.called
294 assert pre_explicit.called
295 assert post_always.called
295 assert post_always.called
296 assert post_explicit.called
296 assert post_explicit.called
297 info, = pre_explicit.call_args[0]
297 info, = pre_explicit.call_args[0]
298 result, = post_explicit.call_args[0]
298 result, = post_explicit.call_args[0]
299 self.assertEqual(info, result.info)
299 self.assertEqual(info, result.info)
300 finally:
300 finally:
301 # remove post-exec
301 # remove post-exec
302 ip.events.unregister('pre_run_cell', pre_explicit)
302 ip.events.unregister('pre_run_cell', pre_explicit)
303 ip.events.unregister('pre_execute', pre_always)
303 ip.events.unregister('pre_execute', pre_always)
304 ip.events.unregister('post_run_cell', post_explicit)
304 ip.events.unregister('post_run_cell', post_explicit)
305 ip.events.unregister('post_execute', post_always)
305 ip.events.unregister('post_execute', post_always)
306
306
307 def test_silent_noadvance(self):
307 def test_silent_noadvance(self):
308 """run_cell(silent=True) doesn't advance execution_count"""
308 """run_cell(silent=True) doesn't advance execution_count"""
309 ec = ip.execution_count
309 ec = ip.execution_count
310 # silent should force store_history=False
310 # silent should force store_history=False
311 ip.run_cell("1", store_history=True, silent=True)
311 ip.run_cell("1", store_history=True, silent=True)
312
312
313 self.assertEqual(ec, ip.execution_count)
313 self.assertEqual(ec, ip.execution_count)
314 # double-check that non-silent exec did what we expected
314 # double-check that non-silent exec did what we expected
315 # silent to avoid
315 # silent to avoid
316 ip.run_cell("1", store_history=True)
316 ip.run_cell("1", store_history=True)
317 self.assertEqual(ec+1, ip.execution_count)
317 self.assertEqual(ec+1, ip.execution_count)
318
318
319 def test_silent_nodisplayhook(self):
319 def test_silent_nodisplayhook(self):
320 """run_cell(silent=True) doesn't trigger displayhook"""
320 """run_cell(silent=True) doesn't trigger displayhook"""
321 d = dict(called=False)
321 d = dict(called=False)
322
322
323 trap = ip.display_trap
323 trap = ip.display_trap
324 save_hook = trap.hook
324 save_hook = trap.hook
325
325
326 def failing_hook(*args, **kwargs):
326 def failing_hook(*args, **kwargs):
327 d['called'] = True
327 d['called'] = True
328
328
329 try:
329 try:
330 trap.hook = failing_hook
330 trap.hook = failing_hook
331 res = ip.run_cell("1", silent=True)
331 res = ip.run_cell("1", silent=True)
332 self.assertFalse(d['called'])
332 self.assertFalse(d['called'])
333 self.assertIsNone(res.result)
333 self.assertIsNone(res.result)
334 # double-check that non-silent exec did what we expected
334 # double-check that non-silent exec did what we expected
335 # silent to avoid
335 # silent to avoid
336 ip.run_cell("1")
336 ip.run_cell("1")
337 self.assertTrue(d['called'])
337 self.assertTrue(d['called'])
338 finally:
338 finally:
339 trap.hook = save_hook
339 trap.hook = save_hook
340
340
341 def test_ofind_line_magic(self):
341 def test_ofind_line_magic(self):
342 from IPython.core.magic import register_line_magic
342 from IPython.core.magic import register_line_magic
343
343
344 @register_line_magic
344 @register_line_magic
345 def lmagic(line):
345 def lmagic(line):
346 "A line magic"
346 "A line magic"
347
347
348 # Get info on line magic
348 # Get info on line magic
349 lfind = ip._ofind('lmagic')
349 lfind = ip._ofind("lmagic")
350 info = dict(found=True, isalias=False, ismagic=True,
350 info = dict(
351 namespace = 'IPython internal', obj= lmagic.__wrapped__,
351 found=True,
352 parent = None)
352 isalias=False,
353 ismagic=True,
354 namespace="IPython internal",
355 obj=lmagic,
356 parent=None,
357 )
353 self.assertEqual(lfind, info)
358 self.assertEqual(lfind, info)
354
359
355 def test_ofind_cell_magic(self):
360 def test_ofind_cell_magic(self):
356 from IPython.core.magic import register_cell_magic
361 from IPython.core.magic import register_cell_magic
357
362
358 @register_cell_magic
363 @register_cell_magic
359 def cmagic(line, cell):
364 def cmagic(line, cell):
360 "A cell magic"
365 "A cell magic"
361
366
362 # Get info on cell magic
367 # Get info on cell magic
363 find = ip._ofind('cmagic')
368 find = ip._ofind("cmagic")
364 info = dict(found=True, isalias=False, ismagic=True,
369 info = dict(
365 namespace = 'IPython internal', obj= cmagic.__wrapped__,
370 found=True,
366 parent = None)
371 isalias=False,
372 ismagic=True,
373 namespace="IPython internal",
374 obj=cmagic,
375 parent=None,
376 )
367 self.assertEqual(find, info)
377 self.assertEqual(find, info)
368
378
369 def test_ofind_property_with_error(self):
379 def test_ofind_property_with_error(self):
370 class A(object):
380 class A(object):
371 @property
381 @property
372 def foo(self):
382 def foo(self):
373 raise NotImplementedError()
383 raise NotImplementedError()
374 a = A()
384 a = A()
375
385
376 found = ip._ofind('a.foo', [('locals', locals())])
386 found = ip._ofind('a.foo', [('locals', locals())])
377 info = dict(found=True, isalias=False, ismagic=False,
387 info = dict(found=True, isalias=False, ismagic=False,
378 namespace='locals', obj=A.foo, parent=a)
388 namespace='locals', obj=A.foo, parent=a)
379 self.assertEqual(found, info)
389 self.assertEqual(found, info)
380
390
381 def test_ofind_multiple_attribute_lookups(self):
391 def test_ofind_multiple_attribute_lookups(self):
382 class A(object):
392 class A(object):
383 @property
393 @property
384 def foo(self):
394 def foo(self):
385 raise NotImplementedError()
395 raise NotImplementedError()
386
396
387 a = A()
397 a = A()
388 a.a = A()
398 a.a = A()
389 a.a.a = A()
399 a.a.a = A()
390
400
391 found = ip._ofind('a.a.a.foo', [('locals', locals())])
401 found = ip._ofind('a.a.a.foo', [('locals', locals())])
392 info = dict(found=True, isalias=False, ismagic=False,
402 info = dict(found=True, isalias=False, ismagic=False,
393 namespace='locals', obj=A.foo, parent=a.a.a)
403 namespace='locals', obj=A.foo, parent=a.a.a)
394 self.assertEqual(found, info)
404 self.assertEqual(found, info)
395
405
396 def test_ofind_slotted_attributes(self):
406 def test_ofind_slotted_attributes(self):
397 class A(object):
407 class A(object):
398 __slots__ = ['foo']
408 __slots__ = ['foo']
399 def __init__(self):
409 def __init__(self):
400 self.foo = 'bar'
410 self.foo = 'bar'
401
411
402 a = A()
412 a = A()
403 found = ip._ofind('a.foo', [('locals', locals())])
413 found = ip._ofind('a.foo', [('locals', locals())])
404 info = dict(found=True, isalias=False, ismagic=False,
414 info = dict(found=True, isalias=False, ismagic=False,
405 namespace='locals', obj=a.foo, parent=a)
415 namespace='locals', obj=a.foo, parent=a)
406 self.assertEqual(found, info)
416 self.assertEqual(found, info)
407
417
408 found = ip._ofind('a.bar', [('locals', locals())])
418 found = ip._ofind('a.bar', [('locals', locals())])
409 info = dict(found=False, isalias=False, ismagic=False,
419 info = dict(found=False, isalias=False, ismagic=False,
410 namespace=None, obj=None, parent=a)
420 namespace=None, obj=None, parent=a)
411 self.assertEqual(found, info)
421 self.assertEqual(found, info)
412
422
413 def test_ofind_prefers_property_to_instance_level_attribute(self):
423 def test_ofind_prefers_property_to_instance_level_attribute(self):
414 class A(object):
424 class A(object):
415 @property
425 @property
416 def foo(self):
426 def foo(self):
417 return 'bar'
427 return 'bar'
418 a = A()
428 a = A()
419 a.__dict__["foo"] = "baz"
429 a.__dict__["foo"] = "baz"
420 self.assertEqual(a.foo, "bar")
430 self.assertEqual(a.foo, "bar")
421 found = ip._ofind("a.foo", [("locals", locals())])
431 found = ip._ofind("a.foo", [("locals", locals())])
422 self.assertIs(found["obj"], A.foo)
432 self.assertIs(found["obj"], A.foo)
423
433
424 def test_custom_syntaxerror_exception(self):
434 def test_custom_syntaxerror_exception(self):
425 called = []
435 called = []
426 def my_handler(shell, etype, value, tb, tb_offset=None):
436 def my_handler(shell, etype, value, tb, tb_offset=None):
427 called.append(etype)
437 called.append(etype)
428 shell.showtraceback((etype, value, tb), tb_offset=tb_offset)
438 shell.showtraceback((etype, value, tb), tb_offset=tb_offset)
429
439
430 ip.set_custom_exc((SyntaxError,), my_handler)
440 ip.set_custom_exc((SyntaxError,), my_handler)
431 try:
441 try:
432 ip.run_cell("1f")
442 ip.run_cell("1f")
433 # Check that this was called, and only once.
443 # Check that this was called, and only once.
434 self.assertEqual(called, [SyntaxError])
444 self.assertEqual(called, [SyntaxError])
435 finally:
445 finally:
436 # Reset the custom exception hook
446 # Reset the custom exception hook
437 ip.set_custom_exc((), None)
447 ip.set_custom_exc((), None)
438
448
439 def test_custom_exception(self):
449 def test_custom_exception(self):
440 called = []
450 called = []
441 def my_handler(shell, etype, value, tb, tb_offset=None):
451 def my_handler(shell, etype, value, tb, tb_offset=None):
442 called.append(etype)
452 called.append(etype)
443 shell.showtraceback((etype, value, tb), tb_offset=tb_offset)
453 shell.showtraceback((etype, value, tb), tb_offset=tb_offset)
444
454
445 ip.set_custom_exc((ValueError,), my_handler)
455 ip.set_custom_exc((ValueError,), my_handler)
446 try:
456 try:
447 res = ip.run_cell("raise ValueError('test')")
457 res = ip.run_cell("raise ValueError('test')")
448 # Check that this was called, and only once.
458 # Check that this was called, and only once.
449 self.assertEqual(called, [ValueError])
459 self.assertEqual(called, [ValueError])
450 # Check that the error is on the result object
460 # Check that the error is on the result object
451 self.assertIsInstance(res.error_in_exec, ValueError)
461 self.assertIsInstance(res.error_in_exec, ValueError)
452 finally:
462 finally:
453 # Reset the custom exception hook
463 # Reset the custom exception hook
454 ip.set_custom_exc((), None)
464 ip.set_custom_exc((), None)
455
465
456 @mock.patch("builtins.print")
466 @mock.patch("builtins.print")
457 def test_showtraceback_with_surrogates(self, mocked_print):
467 def test_showtraceback_with_surrogates(self, mocked_print):
458 values = []
468 values = []
459
469
460 def mock_print_func(value, sep=" ", end="\n", file=sys.stdout, flush=False):
470 def mock_print_func(value, sep=" ", end="\n", file=sys.stdout, flush=False):
461 values.append(value)
471 values.append(value)
462 if value == chr(0xD8FF):
472 if value == chr(0xD8FF):
463 raise UnicodeEncodeError("utf-8", chr(0xD8FF), 0, 1, "")
473 raise UnicodeEncodeError("utf-8", chr(0xD8FF), 0, 1, "")
464
474
465 # mock builtins.print
475 # mock builtins.print
466 mocked_print.side_effect = mock_print_func
476 mocked_print.side_effect = mock_print_func
467
477
468 # ip._showtraceback() is replaced in globalipapp.py.
478 # ip._showtraceback() is replaced in globalipapp.py.
469 # Call original method to test.
479 # Call original method to test.
470 interactiveshell.InteractiveShell._showtraceback(ip, None, None, chr(0xD8FF))
480 interactiveshell.InteractiveShell._showtraceback(ip, None, None, chr(0xD8FF))
471
481
472 self.assertEqual(mocked_print.call_count, 2)
482 self.assertEqual(mocked_print.call_count, 2)
473 self.assertEqual(values, [chr(0xD8FF), "\\ud8ff"])
483 self.assertEqual(values, [chr(0xD8FF), "\\ud8ff"])
474
484
475 def test_mktempfile(self):
485 def test_mktempfile(self):
476 filename = ip.mktempfile()
486 filename = ip.mktempfile()
477 # Check that we can open the file again on Windows
487 # Check that we can open the file again on Windows
478 with open(filename, 'w') as f:
488 with open(filename, 'w') as f:
479 f.write('abc')
489 f.write('abc')
480
490
481 filename = ip.mktempfile(data='blah')
491 filename = ip.mktempfile(data='blah')
482 with open(filename, 'r') as f:
492 with open(filename, 'r') as f:
483 self.assertEqual(f.read(), 'blah')
493 self.assertEqual(f.read(), 'blah')
484
494
485 def test_new_main_mod(self):
495 def test_new_main_mod(self):
486 # Smoketest to check that this accepts a unicode module name
496 # Smoketest to check that this accepts a unicode module name
487 name = u'jiefmw'
497 name = u'jiefmw'
488 mod = ip.new_main_mod(u'%s.py' % name, name)
498 mod = ip.new_main_mod(u'%s.py' % name, name)
489 self.assertEqual(mod.__name__, name)
499 self.assertEqual(mod.__name__, name)
490
500
491 def test_get_exception_only(self):
501 def test_get_exception_only(self):
492 try:
502 try:
493 raise KeyboardInterrupt
503 raise KeyboardInterrupt
494 except KeyboardInterrupt:
504 except KeyboardInterrupt:
495 msg = ip.get_exception_only()
505 msg = ip.get_exception_only()
496 self.assertEqual(msg, 'KeyboardInterrupt\n')
506 self.assertEqual(msg, 'KeyboardInterrupt\n')
497
507
498 try:
508 try:
499 raise DerivedInterrupt("foo")
509 raise DerivedInterrupt("foo")
500 except KeyboardInterrupt:
510 except KeyboardInterrupt:
501 msg = ip.get_exception_only()
511 msg = ip.get_exception_only()
502 self.assertEqual(msg, 'IPython.core.tests.test_interactiveshell.DerivedInterrupt: foo\n')
512 self.assertEqual(msg, 'IPython.core.tests.test_interactiveshell.DerivedInterrupt: foo\n')
503
513
504 def test_inspect_text(self):
514 def test_inspect_text(self):
505 ip.run_cell('a = 5')
515 ip.run_cell('a = 5')
506 text = ip.object_inspect_text('a')
516 text = ip.object_inspect_text('a')
507 self.assertIsInstance(text, str)
517 self.assertIsInstance(text, str)
508
518
509 def test_last_execution_result(self):
519 def test_last_execution_result(self):
510 """ Check that last execution result gets set correctly (GH-10702) """
520 """ Check that last execution result gets set correctly (GH-10702) """
511 result = ip.run_cell('a = 5; a')
521 result = ip.run_cell('a = 5; a')
512 self.assertTrue(ip.last_execution_succeeded)
522 self.assertTrue(ip.last_execution_succeeded)
513 self.assertEqual(ip.last_execution_result.result, 5)
523 self.assertEqual(ip.last_execution_result.result, 5)
514
524
515 result = ip.run_cell('a = x_invalid_id_x')
525 result = ip.run_cell('a = x_invalid_id_x')
516 self.assertFalse(ip.last_execution_succeeded)
526 self.assertFalse(ip.last_execution_succeeded)
517 self.assertFalse(ip.last_execution_result.success)
527 self.assertFalse(ip.last_execution_result.success)
518 self.assertIsInstance(ip.last_execution_result.error_in_exec, NameError)
528 self.assertIsInstance(ip.last_execution_result.error_in_exec, NameError)
519
529
520 def test_reset_aliasing(self):
530 def test_reset_aliasing(self):
521 """ Check that standard posix aliases work after %reset. """
531 """ Check that standard posix aliases work after %reset. """
522 if os.name != 'posix':
532 if os.name != 'posix':
523 return
533 return
524
534
525 ip.reset()
535 ip.reset()
526 for cmd in ('clear', 'more', 'less', 'man'):
536 for cmd in ('clear', 'more', 'less', 'man'):
527 res = ip.run_cell('%' + cmd)
537 res = ip.run_cell('%' + cmd)
528 self.assertEqual(res.success, True)
538 self.assertEqual(res.success, True)
529
539
530
540
531 class TestSafeExecfileNonAsciiPath(unittest.TestCase):
541 class TestSafeExecfileNonAsciiPath(unittest.TestCase):
532
542
533 @onlyif_unicode_paths
543 @onlyif_unicode_paths
534 def setUp(self):
544 def setUp(self):
535 self.BASETESTDIR = tempfile.mkdtemp()
545 self.BASETESTDIR = tempfile.mkdtemp()
536 self.TESTDIR = join(self.BASETESTDIR, u"Γ₯Àâ")
546 self.TESTDIR = join(self.BASETESTDIR, u"Γ₯Àâ")
537 os.mkdir(self.TESTDIR)
547 os.mkdir(self.TESTDIR)
538 with open(join(self.TESTDIR, u"Γ₯Àâtestscript.py"), "w") as sfile:
548 with open(join(self.TESTDIR, u"Γ₯Àâtestscript.py"), "w") as sfile:
539 sfile.write("pass\n")
549 sfile.write("pass\n")
540 self.oldpath = os.getcwd()
550 self.oldpath = os.getcwd()
541 os.chdir(self.TESTDIR)
551 os.chdir(self.TESTDIR)
542 self.fname = u"Γ₯Àâtestscript.py"
552 self.fname = u"Γ₯Àâtestscript.py"
543
553
544 def tearDown(self):
554 def tearDown(self):
545 os.chdir(self.oldpath)
555 os.chdir(self.oldpath)
546 shutil.rmtree(self.BASETESTDIR)
556 shutil.rmtree(self.BASETESTDIR)
547
557
548 @onlyif_unicode_paths
558 @onlyif_unicode_paths
549 def test_1(self):
559 def test_1(self):
550 """Test safe_execfile with non-ascii path
560 """Test safe_execfile with non-ascii path
551 """
561 """
552 ip.safe_execfile(self.fname, {}, raise_exceptions=True)
562 ip.safe_execfile(self.fname, {}, raise_exceptions=True)
553
563
554 class ExitCodeChecks(tt.TempFileMixin):
564 class ExitCodeChecks(tt.TempFileMixin):
555
565
556 def setUp(self):
566 def setUp(self):
557 self.system = ip.system_raw
567 self.system = ip.system_raw
558
568
559 def test_exit_code_ok(self):
569 def test_exit_code_ok(self):
560 self.system('exit 0')
570 self.system('exit 0')
561 self.assertEqual(ip.user_ns['_exit_code'], 0)
571 self.assertEqual(ip.user_ns['_exit_code'], 0)
562
572
563 def test_exit_code_error(self):
573 def test_exit_code_error(self):
564 self.system('exit 1')
574 self.system('exit 1')
565 self.assertEqual(ip.user_ns['_exit_code'], 1)
575 self.assertEqual(ip.user_ns['_exit_code'], 1)
566
576
567 @skipif(not hasattr(signal, 'SIGALRM'))
577 @skipif(not hasattr(signal, 'SIGALRM'))
568 def test_exit_code_signal(self):
578 def test_exit_code_signal(self):
569 self.mktmp("import signal, time\n"
579 self.mktmp("import signal, time\n"
570 "signal.setitimer(signal.ITIMER_REAL, 0.1)\n"
580 "signal.setitimer(signal.ITIMER_REAL, 0.1)\n"
571 "time.sleep(1)\n")
581 "time.sleep(1)\n")
572 self.system("%s %s" % (sys.executable, self.fname))
582 self.system("%s %s" % (sys.executable, self.fname))
573 self.assertEqual(ip.user_ns['_exit_code'], -signal.SIGALRM)
583 self.assertEqual(ip.user_ns['_exit_code'], -signal.SIGALRM)
574
584
575 @onlyif_cmds_exist("csh")
585 @onlyif_cmds_exist("csh")
576 def test_exit_code_signal_csh(self):
586 def test_exit_code_signal_csh(self):
577 SHELL = os.environ.get('SHELL', None)
587 SHELL = os.environ.get('SHELL', None)
578 os.environ['SHELL'] = find_cmd("csh")
588 os.environ['SHELL'] = find_cmd("csh")
579 try:
589 try:
580 self.test_exit_code_signal()
590 self.test_exit_code_signal()
581 finally:
591 finally:
582 if SHELL is not None:
592 if SHELL is not None:
583 os.environ['SHELL'] = SHELL
593 os.environ['SHELL'] = SHELL
584 else:
594 else:
585 del os.environ['SHELL']
595 del os.environ['SHELL']
586
596
587
597
588 class TestSystemRaw(ExitCodeChecks):
598 class TestSystemRaw(ExitCodeChecks):
589
599
590 def setUp(self):
600 def setUp(self):
591 super().setUp()
601 super().setUp()
592 self.system = ip.system_raw
602 self.system = ip.system_raw
593
603
594 @onlyif_unicode_paths
604 @onlyif_unicode_paths
595 def test_1(self):
605 def test_1(self):
596 """Test system_raw with non-ascii cmd
606 """Test system_raw with non-ascii cmd
597 """
607 """
598 cmd = u'''python -c "'Γ₯Àâ'" '''
608 cmd = u'''python -c "'Γ₯Àâ'" '''
599 ip.system_raw(cmd)
609 ip.system_raw(cmd)
600
610
601 @mock.patch('subprocess.call', side_effect=KeyboardInterrupt)
611 @mock.patch('subprocess.call', side_effect=KeyboardInterrupt)
602 @mock.patch('os.system', side_effect=KeyboardInterrupt)
612 @mock.patch('os.system', side_effect=KeyboardInterrupt)
603 def test_control_c(self, *mocks):
613 def test_control_c(self, *mocks):
604 try:
614 try:
605 self.system("sleep 1 # wont happen")
615 self.system("sleep 1 # wont happen")
606 except KeyboardInterrupt:
616 except KeyboardInterrupt:
607 self.fail(
617 self.fail(
608 "system call should intercept "
618 "system call should intercept "
609 "keyboard interrupt from subprocess.call"
619 "keyboard interrupt from subprocess.call"
610 )
620 )
611 self.assertEqual(ip.user_ns["_exit_code"], -signal.SIGINT)
621 self.assertEqual(ip.user_ns["_exit_code"], -signal.SIGINT)
612
622
613 def test_magic_warnings(self):
623 def test_magic_warnings(self):
614 for magic_cmd in ("ls", "pip", "conda", "cd"):
624 for magic_cmd in ("ls", "pip", "conda", "cd"):
615 with self.assertWarnsRegex(Warning, "You executed the system command"):
625 with self.assertWarnsRegex(Warning, "You executed the system command"):
616 ip.system_raw(magic_cmd)
626 ip.system_raw(magic_cmd)
617
627
618 # TODO: Exit codes are currently ignored on Windows.
628 # TODO: Exit codes are currently ignored on Windows.
619 class TestSystemPipedExitCode(ExitCodeChecks):
629 class TestSystemPipedExitCode(ExitCodeChecks):
620
630
621 def setUp(self):
631 def setUp(self):
622 super().setUp()
632 super().setUp()
623 self.system = ip.system_piped
633 self.system = ip.system_piped
624
634
625 @skip_win32
635 @skip_win32
626 def test_exit_code_ok(self):
636 def test_exit_code_ok(self):
627 ExitCodeChecks.test_exit_code_ok(self)
637 ExitCodeChecks.test_exit_code_ok(self)
628
638
629 @skip_win32
639 @skip_win32
630 def test_exit_code_error(self):
640 def test_exit_code_error(self):
631 ExitCodeChecks.test_exit_code_error(self)
641 ExitCodeChecks.test_exit_code_error(self)
632
642
633 @skip_win32
643 @skip_win32
634 def test_exit_code_signal(self):
644 def test_exit_code_signal(self):
635 ExitCodeChecks.test_exit_code_signal(self)
645 ExitCodeChecks.test_exit_code_signal(self)
636
646
637 class TestModules(tt.TempFileMixin):
647 class TestModules(tt.TempFileMixin):
638 def test_extraneous_loads(self):
648 def test_extraneous_loads(self):
639 """Test we're not loading modules on startup that we shouldn't.
649 """Test we're not loading modules on startup that we shouldn't.
640 """
650 """
641 self.mktmp("import sys\n"
651 self.mktmp("import sys\n"
642 "print('numpy' in sys.modules)\n"
652 "print('numpy' in sys.modules)\n"
643 "print('ipyparallel' in sys.modules)\n"
653 "print('ipyparallel' in sys.modules)\n"
644 "print('ipykernel' in sys.modules)\n"
654 "print('ipykernel' in sys.modules)\n"
645 )
655 )
646 out = "False\nFalse\nFalse\n"
656 out = "False\nFalse\nFalse\n"
647 tt.ipexec_validate(self.fname, out)
657 tt.ipexec_validate(self.fname, out)
648
658
649 class Negator(ast.NodeTransformer):
659 class Negator(ast.NodeTransformer):
650 """Negates all number literals in an AST."""
660 """Negates all number literals in an AST."""
651
661
652 # for python 3.7 and earlier
662 # for python 3.7 and earlier
653 def visit_Num(self, node):
663 def visit_Num(self, node):
654 node.n = -node.n
664 node.n = -node.n
655 return node
665 return node
656
666
657 # for python 3.8+
667 # for python 3.8+
658 def visit_Constant(self, node):
668 def visit_Constant(self, node):
659 if isinstance(node.value, int):
669 if isinstance(node.value, int):
660 return self.visit_Num(node)
670 return self.visit_Num(node)
661 return node
671 return node
662
672
663 class TestAstTransform(unittest.TestCase):
673 class TestAstTransform(unittest.TestCase):
664 def setUp(self):
674 def setUp(self):
665 self.negator = Negator()
675 self.negator = Negator()
666 ip.ast_transformers.append(self.negator)
676 ip.ast_transformers.append(self.negator)
667
677
668 def tearDown(self):
678 def tearDown(self):
669 ip.ast_transformers.remove(self.negator)
679 ip.ast_transformers.remove(self.negator)
670
680
671 def test_run_cell(self):
681 def test_run_cell(self):
672 with tt.AssertPrints('-34'):
682 with tt.AssertPrints('-34'):
673 ip.run_cell('print (12 + 22)')
683 ip.run_cell('print (12 + 22)')
674
684
675 # A named reference to a number shouldn't be transformed.
685 # A named reference to a number shouldn't be transformed.
676 ip.user_ns['n'] = 55
686 ip.user_ns['n'] = 55
677 with tt.AssertNotPrints('-55'):
687 with tt.AssertNotPrints('-55'):
678 ip.run_cell('print (n)')
688 ip.run_cell('print (n)')
679
689
680 def test_timeit(self):
690 def test_timeit(self):
681 called = set()
691 called = set()
682 def f(x):
692 def f(x):
683 called.add(x)
693 called.add(x)
684 ip.push({'f':f})
694 ip.push({'f':f})
685
695
686 with tt.AssertPrints("std. dev. of"):
696 with tt.AssertPrints("std. dev. of"):
687 ip.run_line_magic("timeit", "-n1 f(1)")
697 ip.run_line_magic("timeit", "-n1 f(1)")
688 self.assertEqual(called, {-1})
698 self.assertEqual(called, {-1})
689 called.clear()
699 called.clear()
690
700
691 with tt.AssertPrints("std. dev. of"):
701 with tt.AssertPrints("std. dev. of"):
692 ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)")
702 ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)")
693 self.assertEqual(called, {-2, -3})
703 self.assertEqual(called, {-2, -3})
694
704
695 def test_time(self):
705 def test_time(self):
696 called = []
706 called = []
697 def f(x):
707 def f(x):
698 called.append(x)
708 called.append(x)
699 ip.push({'f':f})
709 ip.push({'f':f})
700
710
701 # Test with an expression
711 # Test with an expression
702 with tt.AssertPrints("Wall time: "):
712 with tt.AssertPrints("Wall time: "):
703 ip.run_line_magic("time", "f(5+9)")
713 ip.run_line_magic("time", "f(5+9)")
704 self.assertEqual(called, [-14])
714 self.assertEqual(called, [-14])
705 called[:] = []
715 called[:] = []
706
716
707 # Test with a statement (different code path)
717 # Test with a statement (different code path)
708 with tt.AssertPrints("Wall time: "):
718 with tt.AssertPrints("Wall time: "):
709 ip.run_line_magic("time", "a = f(-3 + -2)")
719 ip.run_line_magic("time", "a = f(-3 + -2)")
710 self.assertEqual(called, [5])
720 self.assertEqual(called, [5])
711
721
712 def test_macro(self):
722 def test_macro(self):
713 ip.push({'a':10})
723 ip.push({'a':10})
714 # The AST transformation makes this do a+=-1
724 # The AST transformation makes this do a+=-1
715 ip.define_macro("amacro", "a+=1\nprint(a)")
725 ip.define_macro("amacro", "a+=1\nprint(a)")
716
726
717 with tt.AssertPrints("9"):
727 with tt.AssertPrints("9"):
718 ip.run_cell("amacro")
728 ip.run_cell("amacro")
719 with tt.AssertPrints("8"):
729 with tt.AssertPrints("8"):
720 ip.run_cell("amacro")
730 ip.run_cell("amacro")
721
731
722 class TestMiscTransform(unittest.TestCase):
732 class TestMiscTransform(unittest.TestCase):
723
733
724
734
725 def test_transform_only_once(self):
735 def test_transform_only_once(self):
726 cleanup = 0
736 cleanup = 0
727 line_t = 0
737 line_t = 0
728 def count_cleanup(lines):
738 def count_cleanup(lines):
729 nonlocal cleanup
739 nonlocal cleanup
730 cleanup += 1
740 cleanup += 1
731 return lines
741 return lines
732
742
733 def count_line_t(lines):
743 def count_line_t(lines):
734 nonlocal line_t
744 nonlocal line_t
735 line_t += 1
745 line_t += 1
736 return lines
746 return lines
737
747
738 ip.input_transformer_manager.cleanup_transforms.append(count_cleanup)
748 ip.input_transformer_manager.cleanup_transforms.append(count_cleanup)
739 ip.input_transformer_manager.line_transforms.append(count_line_t)
749 ip.input_transformer_manager.line_transforms.append(count_line_t)
740
750
741 ip.run_cell('1')
751 ip.run_cell('1')
742
752
743 assert cleanup == 1
753 assert cleanup == 1
744 assert line_t == 1
754 assert line_t == 1
745
755
746 class IntegerWrapper(ast.NodeTransformer):
756 class IntegerWrapper(ast.NodeTransformer):
747 """Wraps all integers in a call to Integer()"""
757 """Wraps all integers in a call to Integer()"""
748
758
749 # for Python 3.7 and earlier
759 # for Python 3.7 and earlier
750
760
751 # for Python 3.7 and earlier
761 # for Python 3.7 and earlier
752 def visit_Num(self, node):
762 def visit_Num(self, node):
753 if isinstance(node.n, int):
763 if isinstance(node.n, int):
754 return ast.Call(func=ast.Name(id='Integer', ctx=ast.Load()),
764 return ast.Call(func=ast.Name(id='Integer', ctx=ast.Load()),
755 args=[node], keywords=[])
765 args=[node], keywords=[])
756 return node
766 return node
757
767
758 # For Python 3.8+
768 # For Python 3.8+
759 def visit_Constant(self, node):
769 def visit_Constant(self, node):
760 if isinstance(node.value, int):
770 if isinstance(node.value, int):
761 return self.visit_Num(node)
771 return self.visit_Num(node)
762 return node
772 return node
763
773
764
774
765 class TestAstTransform2(unittest.TestCase):
775 class TestAstTransform2(unittest.TestCase):
766 def setUp(self):
776 def setUp(self):
767 self.intwrapper = IntegerWrapper()
777 self.intwrapper = IntegerWrapper()
768 ip.ast_transformers.append(self.intwrapper)
778 ip.ast_transformers.append(self.intwrapper)
769
779
770 self.calls = []
780 self.calls = []
771 def Integer(*args):
781 def Integer(*args):
772 self.calls.append(args)
782 self.calls.append(args)
773 return args
783 return args
774 ip.push({"Integer": Integer})
784 ip.push({"Integer": Integer})
775
785
776 def tearDown(self):
786 def tearDown(self):
777 ip.ast_transformers.remove(self.intwrapper)
787 ip.ast_transformers.remove(self.intwrapper)
778 del ip.user_ns['Integer']
788 del ip.user_ns['Integer']
779
789
780 def test_run_cell(self):
790 def test_run_cell(self):
781 ip.run_cell("n = 2")
791 ip.run_cell("n = 2")
782 self.assertEqual(self.calls, [(2,)])
792 self.assertEqual(self.calls, [(2,)])
783
793
784 # This shouldn't throw an error
794 # This shouldn't throw an error
785 ip.run_cell("o = 2.0")
795 ip.run_cell("o = 2.0")
786 self.assertEqual(ip.user_ns['o'], 2.0)
796 self.assertEqual(ip.user_ns['o'], 2.0)
787
797
788 def test_timeit(self):
798 def test_timeit(self):
789 called = set()
799 called = set()
790 def f(x):
800 def f(x):
791 called.add(x)
801 called.add(x)
792 ip.push({'f':f})
802 ip.push({'f':f})
793
803
794 with tt.AssertPrints("std. dev. of"):
804 with tt.AssertPrints("std. dev. of"):
795 ip.run_line_magic("timeit", "-n1 f(1)")
805 ip.run_line_magic("timeit", "-n1 f(1)")
796 self.assertEqual(called, {(1,)})
806 self.assertEqual(called, {(1,)})
797 called.clear()
807 called.clear()
798
808
799 with tt.AssertPrints("std. dev. of"):
809 with tt.AssertPrints("std. dev. of"):
800 ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)")
810 ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)")
801 self.assertEqual(called, {(2,), (3,)})
811 self.assertEqual(called, {(2,), (3,)})
802
812
803 class ErrorTransformer(ast.NodeTransformer):
813 class ErrorTransformer(ast.NodeTransformer):
804 """Throws an error when it sees a number."""
814 """Throws an error when it sees a number."""
805
815
806 # for Python 3.7 and earlier
816 # for Python 3.7 and earlier
807 def visit_Num(self, node):
817 def visit_Num(self, node):
808 raise ValueError("test")
818 raise ValueError("test")
809
819
810 # for Python 3.8+
820 # for Python 3.8+
811 def visit_Constant(self, node):
821 def visit_Constant(self, node):
812 if isinstance(node.value, int):
822 if isinstance(node.value, int):
813 return self.visit_Num(node)
823 return self.visit_Num(node)
814 return node
824 return node
815
825
816
826
817 class TestAstTransformError(unittest.TestCase):
827 class TestAstTransformError(unittest.TestCase):
818 def test_unregistering(self):
828 def test_unregistering(self):
819 err_transformer = ErrorTransformer()
829 err_transformer = ErrorTransformer()
820 ip.ast_transformers.append(err_transformer)
830 ip.ast_transformers.append(err_transformer)
821
831
822 with self.assertWarnsRegex(UserWarning, "It will be unregistered"):
832 with self.assertWarnsRegex(UserWarning, "It will be unregistered"):
823 ip.run_cell("1 + 2")
833 ip.run_cell("1 + 2")
824
834
825 # This should have been removed.
835 # This should have been removed.
826 self.assertNotIn(err_transformer, ip.ast_transformers)
836 self.assertNotIn(err_transformer, ip.ast_transformers)
827
837
828
838
829 class StringRejector(ast.NodeTransformer):
839 class StringRejector(ast.NodeTransformer):
830 """Throws an InputRejected when it sees a string literal.
840 """Throws an InputRejected when it sees a string literal.
831
841
832 Used to verify that NodeTransformers can signal that a piece of code should
842 Used to verify that NodeTransformers can signal that a piece of code should
833 not be executed by throwing an InputRejected.
843 not be executed by throwing an InputRejected.
834 """
844 """
835
845
836 #for python 3.7 and earlier
846 #for python 3.7 and earlier
837 def visit_Str(self, node):
847 def visit_Str(self, node):
838 raise InputRejected("test")
848 raise InputRejected("test")
839
849
840 # 3.8 only
850 # 3.8 only
841 def visit_Constant(self, node):
851 def visit_Constant(self, node):
842 if isinstance(node.value, str):
852 if isinstance(node.value, str):
843 raise InputRejected("test")
853 raise InputRejected("test")
844 return node
854 return node
845
855
846
856
847 class TestAstTransformInputRejection(unittest.TestCase):
857 class TestAstTransformInputRejection(unittest.TestCase):
848
858
849 def setUp(self):
859 def setUp(self):
850 self.transformer = StringRejector()
860 self.transformer = StringRejector()
851 ip.ast_transformers.append(self.transformer)
861 ip.ast_transformers.append(self.transformer)
852
862
853 def tearDown(self):
863 def tearDown(self):
854 ip.ast_transformers.remove(self.transformer)
864 ip.ast_transformers.remove(self.transformer)
855
865
856 def test_input_rejection(self):
866 def test_input_rejection(self):
857 """Check that NodeTransformers can reject input."""
867 """Check that NodeTransformers can reject input."""
858
868
859 expect_exception_tb = tt.AssertPrints("InputRejected: test")
869 expect_exception_tb = tt.AssertPrints("InputRejected: test")
860 expect_no_cell_output = tt.AssertNotPrints("'unsafe'", suppress=False)
870 expect_no_cell_output = tt.AssertNotPrints("'unsafe'", suppress=False)
861
871
862 # Run the same check twice to verify that the transformer is not
872 # Run the same check twice to verify that the transformer is not
863 # disabled after raising.
873 # disabled after raising.
864 with expect_exception_tb, expect_no_cell_output:
874 with expect_exception_tb, expect_no_cell_output:
865 ip.run_cell("'unsafe'")
875 ip.run_cell("'unsafe'")
866
876
867 with expect_exception_tb, expect_no_cell_output:
877 with expect_exception_tb, expect_no_cell_output:
868 res = ip.run_cell("'unsafe'")
878 res = ip.run_cell("'unsafe'")
869
879
870 self.assertIsInstance(res.error_before_exec, InputRejected)
880 self.assertIsInstance(res.error_before_exec, InputRejected)
871
881
872 def test__IPYTHON__():
882 def test__IPYTHON__():
873 # This shouldn't raise a NameError, that's all
883 # This shouldn't raise a NameError, that's all
874 __IPYTHON__
884 __IPYTHON__
875
885
876
886
877 class DummyRepr(object):
887 class DummyRepr(object):
878 def __repr__(self):
888 def __repr__(self):
879 return "DummyRepr"
889 return "DummyRepr"
880
890
881 def _repr_html_(self):
891 def _repr_html_(self):
882 return "<b>dummy</b>"
892 return "<b>dummy</b>"
883
893
884 def _repr_javascript_(self):
894 def _repr_javascript_(self):
885 return "console.log('hi');", {'key': 'value'}
895 return "console.log('hi');", {'key': 'value'}
886
896
887
897
888 def test_user_variables():
898 def test_user_variables():
889 # enable all formatters
899 # enable all formatters
890 ip.display_formatter.active_types = ip.display_formatter.format_types
900 ip.display_formatter.active_types = ip.display_formatter.format_types
891
901
892 ip.user_ns['dummy'] = d = DummyRepr()
902 ip.user_ns['dummy'] = d = DummyRepr()
893 keys = {'dummy', 'doesnotexist'}
903 keys = {'dummy', 'doesnotexist'}
894 r = ip.user_expressions({ key:key for key in keys})
904 r = ip.user_expressions({ key:key for key in keys})
895
905
896 assert keys == set(r.keys())
906 assert keys == set(r.keys())
897 dummy = r["dummy"]
907 dummy = r["dummy"]
898 assert {"status", "data", "metadata"} == set(dummy.keys())
908 assert {"status", "data", "metadata"} == set(dummy.keys())
899 assert dummy["status"] == "ok"
909 assert dummy["status"] == "ok"
900 data = dummy["data"]
910 data = dummy["data"]
901 metadata = dummy["metadata"]
911 metadata = dummy["metadata"]
902 assert data.get("text/html") == d._repr_html_()
912 assert data.get("text/html") == d._repr_html_()
903 js, jsmd = d._repr_javascript_()
913 js, jsmd = d._repr_javascript_()
904 assert data.get("application/javascript") == js
914 assert data.get("application/javascript") == js
905 assert metadata.get("application/javascript") == jsmd
915 assert metadata.get("application/javascript") == jsmd
906
916
907 dne = r["doesnotexist"]
917 dne = r["doesnotexist"]
908 assert dne["status"] == "error"
918 assert dne["status"] == "error"
909 assert dne["ename"] == "NameError"
919 assert dne["ename"] == "NameError"
910
920
911 # back to text only
921 # back to text only
912 ip.display_formatter.active_types = ['text/plain']
922 ip.display_formatter.active_types = ['text/plain']
913
923
914 def test_user_expression():
924 def test_user_expression():
915 # enable all formatters
925 # enable all formatters
916 ip.display_formatter.active_types = ip.display_formatter.format_types
926 ip.display_formatter.active_types = ip.display_formatter.format_types
917 query = {
927 query = {
918 'a' : '1 + 2',
928 'a' : '1 + 2',
919 'b' : '1/0',
929 'b' : '1/0',
920 }
930 }
921 r = ip.user_expressions(query)
931 r = ip.user_expressions(query)
922 import pprint
932 import pprint
923 pprint.pprint(r)
933 pprint.pprint(r)
924 assert set(r.keys()) == set(query.keys())
934 assert set(r.keys()) == set(query.keys())
925 a = r["a"]
935 a = r["a"]
926 assert {"status", "data", "metadata"} == set(a.keys())
936 assert {"status", "data", "metadata"} == set(a.keys())
927 assert a["status"] == "ok"
937 assert a["status"] == "ok"
928 data = a["data"]
938 data = a["data"]
929 metadata = a["metadata"]
939 metadata = a["metadata"]
930 assert data.get("text/plain") == "3"
940 assert data.get("text/plain") == "3"
931
941
932 b = r["b"]
942 b = r["b"]
933 assert b["status"] == "error"
943 assert b["status"] == "error"
934 assert b["ename"] == "ZeroDivisionError"
944 assert b["ename"] == "ZeroDivisionError"
935
945
936 # back to text only
946 # back to text only
937 ip.display_formatter.active_types = ['text/plain']
947 ip.display_formatter.active_types = ['text/plain']
938
948
939
949
940 class TestSyntaxErrorTransformer(unittest.TestCase):
950 class TestSyntaxErrorTransformer(unittest.TestCase):
941 """Check that SyntaxError raised by an input transformer is handled by run_cell()"""
951 """Check that SyntaxError raised by an input transformer is handled by run_cell()"""
942
952
943 @staticmethod
953 @staticmethod
944 def transformer(lines):
954 def transformer(lines):
945 for line in lines:
955 for line in lines:
946 pos = line.find('syntaxerror')
956 pos = line.find('syntaxerror')
947 if pos >= 0:
957 if pos >= 0:
948 e = SyntaxError('input contains "syntaxerror"')
958 e = SyntaxError('input contains "syntaxerror"')
949 e.text = line
959 e.text = line
950 e.offset = pos + 1
960 e.offset = pos + 1
951 raise e
961 raise e
952 return lines
962 return lines
953
963
954 def setUp(self):
964 def setUp(self):
955 ip.input_transformers_post.append(self.transformer)
965 ip.input_transformers_post.append(self.transformer)
956
966
957 def tearDown(self):
967 def tearDown(self):
958 ip.input_transformers_post.remove(self.transformer)
968 ip.input_transformers_post.remove(self.transformer)
959
969
960 def test_syntaxerror_input_transformer(self):
970 def test_syntaxerror_input_transformer(self):
961 with tt.AssertPrints('1234'):
971 with tt.AssertPrints('1234'):
962 ip.run_cell('1234')
972 ip.run_cell('1234')
963 with tt.AssertPrints('SyntaxError: invalid syntax'):
973 with tt.AssertPrints('SyntaxError: invalid syntax'):
964 ip.run_cell('1 2 3') # plain python syntax error
974 ip.run_cell('1 2 3') # plain python syntax error
965 with tt.AssertPrints('SyntaxError: input contains "syntaxerror"'):
975 with tt.AssertPrints('SyntaxError: input contains "syntaxerror"'):
966 ip.run_cell('2345 # syntaxerror') # input transformer syntax error
976 ip.run_cell('2345 # syntaxerror') # input transformer syntax error
967 with tt.AssertPrints('3456'):
977 with tt.AssertPrints('3456'):
968 ip.run_cell('3456')
978 ip.run_cell('3456')
969
979
970
980
971 class TestWarningSuppression(unittest.TestCase):
981 class TestWarningSuppression(unittest.TestCase):
972 def test_warning_suppression(self):
982 def test_warning_suppression(self):
973 ip.run_cell("import warnings")
983 ip.run_cell("import warnings")
974 try:
984 try:
975 with self.assertWarnsRegex(UserWarning, "asdf"):
985 with self.assertWarnsRegex(UserWarning, "asdf"):
976 ip.run_cell("warnings.warn('asdf')")
986 ip.run_cell("warnings.warn('asdf')")
977 # Here's the real test -- if we run that again, we should get the
987 # Here's the real test -- if we run that again, we should get the
978 # warning again. Traditionally, each warning was only issued once per
988 # warning again. Traditionally, each warning was only issued once per
979 # IPython session (approximately), even if the user typed in new and
989 # IPython session (approximately), even if the user typed in new and
980 # different code that should have also triggered the warning, leading
990 # different code that should have also triggered the warning, leading
981 # to much confusion.
991 # to much confusion.
982 with self.assertWarnsRegex(UserWarning, "asdf"):
992 with self.assertWarnsRegex(UserWarning, "asdf"):
983 ip.run_cell("warnings.warn('asdf')")
993 ip.run_cell("warnings.warn('asdf')")
984 finally:
994 finally:
985 ip.run_cell("del warnings")
995 ip.run_cell("del warnings")
986
996
987
997
988 def test_deprecation_warning(self):
998 def test_deprecation_warning(self):
989 ip.run_cell("""
999 ip.run_cell("""
990 import warnings
1000 import warnings
991 def wrn():
1001 def wrn():
992 warnings.warn(
1002 warnings.warn(
993 "I AM A WARNING",
1003 "I AM A WARNING",
994 DeprecationWarning
1004 DeprecationWarning
995 )
1005 )
996 """)
1006 """)
997 try:
1007 try:
998 with self.assertWarnsRegex(DeprecationWarning, "I AM A WARNING"):
1008 with self.assertWarnsRegex(DeprecationWarning, "I AM A WARNING"):
999 ip.run_cell("wrn()")
1009 ip.run_cell("wrn()")
1000 finally:
1010 finally:
1001 ip.run_cell("del warnings")
1011 ip.run_cell("del warnings")
1002 ip.run_cell("del wrn")
1012 ip.run_cell("del wrn")
1003
1013
1004
1014
1005 class TestImportNoDeprecate(tt.TempFileMixin):
1015 class TestImportNoDeprecate(tt.TempFileMixin):
1006
1016
1007 def setUp(self):
1017 def setUp(self):
1008 """Make a valid python temp file."""
1018 """Make a valid python temp file."""
1009 self.mktmp("""
1019 self.mktmp("""
1010 import warnings
1020 import warnings
1011 def wrn():
1021 def wrn():
1012 warnings.warn(
1022 warnings.warn(
1013 "I AM A WARNING",
1023 "I AM A WARNING",
1014 DeprecationWarning
1024 DeprecationWarning
1015 )
1025 )
1016 """)
1026 """)
1017 super().setUp()
1027 super().setUp()
1018
1028
1019 def test_no_dep(self):
1029 def test_no_dep(self):
1020 """
1030 """
1021 No deprecation warning should be raised from imported functions
1031 No deprecation warning should be raised from imported functions
1022 """
1032 """
1023 ip.run_cell("from {} import wrn".format(self.fname))
1033 ip.run_cell("from {} import wrn".format(self.fname))
1024
1034
1025 with tt.AssertNotPrints("I AM A WARNING"):
1035 with tt.AssertNotPrints("I AM A WARNING"):
1026 ip.run_cell("wrn()")
1036 ip.run_cell("wrn()")
1027 ip.run_cell("del wrn")
1037 ip.run_cell("del wrn")
1028
1038
1029
1039
1030 def test_custom_exc_count():
1040 def test_custom_exc_count():
1031 hook = mock.Mock(return_value=None)
1041 hook = mock.Mock(return_value=None)
1032 ip.set_custom_exc((SyntaxError,), hook)
1042 ip.set_custom_exc((SyntaxError,), hook)
1033 before = ip.execution_count
1043 before = ip.execution_count
1034 ip.run_cell("def foo()", store_history=True)
1044 ip.run_cell("def foo()", store_history=True)
1035 # restore default excepthook
1045 # restore default excepthook
1036 ip.set_custom_exc((), None)
1046 ip.set_custom_exc((), None)
1037 assert hook.call_count == 1
1047 assert hook.call_count == 1
1038 assert ip.execution_count == before + 1
1048 assert ip.execution_count == before + 1
1039
1049
1040
1050
1041 def test_run_cell_async():
1051 def test_run_cell_async():
1042 loop = asyncio.get_event_loop_policy().get_event_loop()
1052 loop = asyncio.get_event_loop_policy().get_event_loop()
1043 ip.run_cell("import asyncio")
1053 ip.run_cell("import asyncio")
1044 coro = ip.run_cell_async("await asyncio.sleep(0.01)\n5")
1054 coro = ip.run_cell_async("await asyncio.sleep(0.01)\n5")
1045 assert asyncio.iscoroutine(coro)
1055 assert asyncio.iscoroutine(coro)
1046 result = loop.run_until_complete(coro)
1056 result = loop.run_until_complete(coro)
1047 assert isinstance(result, interactiveshell.ExecutionResult)
1057 assert isinstance(result, interactiveshell.ExecutionResult)
1048 assert result.result == 5
1058 assert result.result == 5
1049
1059
1050
1060
1051 def test_should_run_async():
1061 def test_should_run_async():
1052 assert not ip.should_run_async("a = 5")
1062 assert not ip.should_run_async("a = 5")
1053 assert ip.should_run_async("await x")
1063 assert ip.should_run_async("await x")
1054 assert ip.should_run_async("import asyncio; await asyncio.sleep(1)")
1064 assert ip.should_run_async("import asyncio; await asyncio.sleep(1)")
1055
1065
1056
1066
1057 def test_set_custom_completer():
1067 def test_set_custom_completer():
1058 num_completers = len(ip.Completer.matchers)
1068 num_completers = len(ip.Completer.matchers)
1059
1069
1060 def foo(*args, **kwargs):
1070 def foo(*args, **kwargs):
1061 return "I'm a completer!"
1071 return "I'm a completer!"
1062
1072
1063 ip.set_custom_completer(foo, 0)
1073 ip.set_custom_completer(foo, 0)
1064
1074
1065 # check that we've really added a new completer
1075 # check that we've really added a new completer
1066 assert len(ip.Completer.matchers) == num_completers + 1
1076 assert len(ip.Completer.matchers) == num_completers + 1
1067
1077
1068 # check that the first completer is the function we defined
1078 # check that the first completer is the function we defined
1069 assert ip.Completer.matchers[0]() == "I'm a completer!"
1079 assert ip.Completer.matchers[0]() == "I'm a completer!"
1070
1080
1071 # clean up
1081 # clean up
1072 ip.Completer.custom_matchers.pop()
1082 ip.Completer.custom_matchers.pop()
@@ -1,233 +1,236 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 %store magic for lightweight persistence.
3 %store magic for lightweight persistence.
4
4
5 Stores variables, aliases and macros in IPython's database.
5 Stores variables, aliases and macros in IPython's database.
6
6
7 To automatically restore stored variables at startup, add this to your
7 To automatically restore stored variables at startup, add this to your
8 :file:`ipython_config.py` file::
8 :file:`ipython_config.py` file::
9
9
10 c.StoreMagics.autorestore = True
10 c.StoreMagics.autorestore = True
11 """
11 """
12
12
13 # Copyright (c) IPython Development Team.
13 # Copyright (c) IPython Development Team.
14 # Distributed under the terms of the Modified BSD License.
14 # Distributed under the terms of the Modified BSD License.
15
15
16 import inspect, os, sys, textwrap
16 import inspect, os, sys, textwrap
17
17
18 from IPython.core.error import UsageError
18 from IPython.core.error import UsageError
19 from IPython.core.magic import Magics, magics_class, line_magic
19 from IPython.core.magic import Magics, magics_class, line_magic
20 from IPython.testing.skipdoctest import skip_doctest
20 from traitlets import Bool
21 from traitlets import Bool
21
22
22
23
23 def restore_aliases(ip, alias=None):
24 def restore_aliases(ip, alias=None):
24 staliases = ip.db.get('stored_aliases', {})
25 staliases = ip.db.get('stored_aliases', {})
25 if alias is None:
26 if alias is None:
26 for k,v in staliases.items():
27 for k,v in staliases.items():
27 #print "restore alias",k,v # dbg
28 #print "restore alias",k,v # dbg
28 #self.alias_table[k] = v
29 #self.alias_table[k] = v
29 ip.alias_manager.define_alias(k,v)
30 ip.alias_manager.define_alias(k,v)
30 else:
31 else:
31 ip.alias_manager.define_alias(alias, staliases[alias])
32 ip.alias_manager.define_alias(alias, staliases[alias])
32
33
33
34
34 def refresh_variables(ip):
35 def refresh_variables(ip):
35 db = ip.db
36 db = ip.db
36 for key in db.keys('autorestore/*'):
37 for key in db.keys('autorestore/*'):
37 # strip autorestore
38 # strip autorestore
38 justkey = os.path.basename(key)
39 justkey = os.path.basename(key)
39 try:
40 try:
40 obj = db[key]
41 obj = db[key]
41 except KeyError:
42 except KeyError:
42 print("Unable to restore variable '%s', ignoring (use %%store -d to forget!)" % justkey)
43 print("Unable to restore variable '%s', ignoring (use %%store -d to forget!)" % justkey)
43 print("The error was:", sys.exc_info()[0])
44 print("The error was:", sys.exc_info()[0])
44 else:
45 else:
45 #print "restored",justkey,"=",obj #dbg
46 #print "restored",justkey,"=",obj #dbg
46 ip.user_ns[justkey] = obj
47 ip.user_ns[justkey] = obj
47
48
48
49
49 def restore_dhist(ip):
50 def restore_dhist(ip):
50 ip.user_ns['_dh'] = ip.db.get('dhist',[])
51 ip.user_ns['_dh'] = ip.db.get('dhist',[])
51
52
52
53
53 def restore_data(ip):
54 def restore_data(ip):
54 refresh_variables(ip)
55 refresh_variables(ip)
55 restore_aliases(ip)
56 restore_aliases(ip)
56 restore_dhist(ip)
57 restore_dhist(ip)
57
58
58
59
59 @magics_class
60 @magics_class
60 class StoreMagics(Magics):
61 class StoreMagics(Magics):
61 """Lightweight persistence for python variables.
62 """Lightweight persistence for python variables.
62
63
63 Provides the %store magic."""
64 Provides the %store magic."""
64
65
65 autorestore = Bool(False, help=
66 autorestore = Bool(False, help=
66 """If True, any %store-d variables will be automatically restored
67 """If True, any %store-d variables will be automatically restored
67 when IPython starts.
68 when IPython starts.
68 """
69 """
69 ).tag(config=True)
70 ).tag(config=True)
70
71
71 def __init__(self, shell):
72 def __init__(self, shell):
72 super(StoreMagics, self).__init__(shell=shell)
73 super(StoreMagics, self).__init__(shell=shell)
73 self.shell.configurables.append(self)
74 self.shell.configurables.append(self)
74 if self.autorestore:
75 if self.autorestore:
75 restore_data(self.shell)
76 restore_data(self.shell)
76
77
78 @skip_doctest
77 @line_magic
79 @line_magic
78 def store(self, parameter_s=''):
80 def store(self, parameter_s=''):
79 """Lightweight persistence for python variables.
81 """Lightweight persistence for python variables.
80
82
81 Example::
83 Example::
82
84
83 In [1]: l = ['hello',10,'world']
85 In [1]: l = ['hello',10,'world']
84 In [2]: %store l
86 In [2]: %store l
87 Stored 'l' (list)
85 In [3]: exit
88 In [3]: exit
86
89
87 (IPython session is closed and started again...)
90 (IPython session is closed and started again...)
88
91
89 ville@badger:~$ ipython
92 ville@badger:~$ ipython
90 In [1]: l
93 In [1]: l
91 NameError: name 'l' is not defined
94 NameError: name 'l' is not defined
92 In [2]: %store -r
95 In [2]: %store -r
93 In [3]: l
96 In [3]: l
94 Out[3]: ['hello', 10, 'world']
97 Out[3]: ['hello', 10, 'world']
95
98
96 Usage:
99 Usage:
97
100
98 * ``%store`` - Show list of all variables and their current
101 * ``%store`` - Show list of all variables and their current
99 values
102 values
100 * ``%store spam bar`` - Store the *current* value of the variables spam
103 * ``%store spam bar`` - Store the *current* value of the variables spam
101 and bar to disk
104 and bar to disk
102 * ``%store -d spam`` - Remove the variable and its value from storage
105 * ``%store -d spam`` - Remove the variable and its value from storage
103 * ``%store -z`` - Remove all variables from storage
106 * ``%store -z`` - Remove all variables from storage
104 * ``%store -r`` - Refresh all variables, aliases and directory history
107 * ``%store -r`` - Refresh all variables, aliases and directory history
105 from store (overwrite current vals)
108 from store (overwrite current vals)
106 * ``%store -r spam bar`` - Refresh specified variables and aliases from store
109 * ``%store -r spam bar`` - Refresh specified variables and aliases from store
107 (delete current val)
110 (delete current val)
108 * ``%store foo >a.txt`` - Store value of foo to new file a.txt
111 * ``%store foo >a.txt`` - Store value of foo to new file a.txt
109 * ``%store foo >>a.txt`` - Append value of foo to file a.txt
112 * ``%store foo >>a.txt`` - Append value of foo to file a.txt
110
113
111 It should be noted that if you change the value of a variable, you
114 It should be noted that if you change the value of a variable, you
112 need to %store it again if you want to persist the new value.
115 need to %store it again if you want to persist the new value.
113
116
114 Note also that the variables will need to be pickleable; most basic
117 Note also that the variables will need to be pickleable; most basic
115 python types can be safely %store'd.
118 python types can be safely %store'd.
116
119
117 Also aliases can be %store'd across sessions.
120 Also aliases can be %store'd across sessions.
118 To remove an alias from the storage, use the %unalias magic.
121 To remove an alias from the storage, use the %unalias magic.
119 """
122 """
120
123
121 opts,argsl = self.parse_options(parameter_s,'drz',mode='string')
124 opts,argsl = self.parse_options(parameter_s,'drz',mode='string')
122 args = argsl.split()
125 args = argsl.split()
123 ip = self.shell
126 ip = self.shell
124 db = ip.db
127 db = ip.db
125 # delete
128 # delete
126 if 'd' in opts:
129 if 'd' in opts:
127 try:
130 try:
128 todel = args[0]
131 todel = args[0]
129 except IndexError as e:
132 except IndexError as e:
130 raise UsageError('You must provide the variable to forget') from e
133 raise UsageError('You must provide the variable to forget') from e
131 else:
134 else:
132 try:
135 try:
133 del db['autorestore/' + todel]
136 del db['autorestore/' + todel]
134 except BaseException as e:
137 except BaseException as e:
135 raise UsageError("Can't delete variable '%s'" % todel) from e
138 raise UsageError("Can't delete variable '%s'" % todel) from e
136 # reset
139 # reset
137 elif 'z' in opts:
140 elif 'z' in opts:
138 for k in db.keys('autorestore/*'):
141 for k in db.keys('autorestore/*'):
139 del db[k]
142 del db[k]
140
143
141 elif 'r' in opts:
144 elif 'r' in opts:
142 if args:
145 if args:
143 for arg in args:
146 for arg in args:
144 try:
147 try:
145 obj = db['autorestore/' + arg]
148 obj = db['autorestore/' + arg]
146 except KeyError:
149 except KeyError:
147 try:
150 try:
148 restore_aliases(ip, alias=arg)
151 restore_aliases(ip, alias=arg)
149 except KeyError:
152 except KeyError:
150 print("no stored variable or alias %s" % arg)
153 print("no stored variable or alias %s" % arg)
151 else:
154 else:
152 ip.user_ns[arg] = obj
155 ip.user_ns[arg] = obj
153 else:
156 else:
154 restore_data(ip)
157 restore_data(ip)
155
158
156 # run without arguments -> list variables & values
159 # run without arguments -> list variables & values
157 elif not args:
160 elif not args:
158 vars = db.keys('autorestore/*')
161 vars = db.keys('autorestore/*')
159 vars.sort()
162 vars.sort()
160 if vars:
163 if vars:
161 size = max(map(len, vars))
164 size = max(map(len, vars))
162 else:
165 else:
163 size = 0
166 size = 0
164
167
165 print('Stored variables and their in-db values:')
168 print('Stored variables and their in-db values:')
166 fmt = '%-'+str(size)+'s -> %s'
169 fmt = '%-'+str(size)+'s -> %s'
167 get = db.get
170 get = db.get
168 for var in vars:
171 for var in vars:
169 justkey = os.path.basename(var)
172 justkey = os.path.basename(var)
170 # print 30 first characters from every var
173 # print 30 first characters from every var
171 print(fmt % (justkey, repr(get(var, '<unavailable>'))[:50]))
174 print(fmt % (justkey, repr(get(var, '<unavailable>'))[:50]))
172
175
173 # default action - store the variable
176 # default action - store the variable
174 else:
177 else:
175 # %store foo >file.txt or >>file.txt
178 # %store foo >file.txt or >>file.txt
176 if len(args) > 1 and args[1].startswith('>'):
179 if len(args) > 1 and args[1].startswith('>'):
177 fnam = os.path.expanduser(args[1].lstrip('>').lstrip())
180 fnam = os.path.expanduser(args[1].lstrip('>').lstrip())
178 if args[1].startswith('>>'):
181 if args[1].startswith('>>'):
179 fil = open(fnam, 'a')
182 fil = open(fnam, 'a')
180 else:
183 else:
181 fil = open(fnam, 'w')
184 fil = open(fnam, 'w')
182 with fil:
185 with fil:
183 obj = ip.ev(args[0])
186 obj = ip.ev(args[0])
184 print("Writing '%s' (%s) to file '%s'." % (args[0],
187 print("Writing '%s' (%s) to file '%s'." % (args[0],
185 obj.__class__.__name__, fnam))
188 obj.__class__.__name__, fnam))
186
189
187 if not isinstance (obj, str):
190 if not isinstance (obj, str):
188 from pprint import pprint
191 from pprint import pprint
189 pprint(obj, fil)
192 pprint(obj, fil)
190 else:
193 else:
191 fil.write(obj)
194 fil.write(obj)
192 if not obj.endswith('\n'):
195 if not obj.endswith('\n'):
193 fil.write('\n')
196 fil.write('\n')
194
197
195 return
198 return
196
199
197 # %store foo
200 # %store foo
198 for arg in args:
201 for arg in args:
199 try:
202 try:
200 obj = ip.user_ns[arg]
203 obj = ip.user_ns[arg]
201 except KeyError:
204 except KeyError:
202 # it might be an alias
205 # it might be an alias
203 name = arg
206 name = arg
204 try:
207 try:
205 cmd = ip.alias_manager.retrieve_alias(name)
208 cmd = ip.alias_manager.retrieve_alias(name)
206 except ValueError as e:
209 except ValueError as e:
207 raise UsageError("Unknown variable '%s'" % name) from e
210 raise UsageError("Unknown variable '%s'" % name) from e
208
211
209 staliases = db.get('stored_aliases',{})
212 staliases = db.get('stored_aliases',{})
210 staliases[name] = cmd
213 staliases[name] = cmd
211 db['stored_aliases'] = staliases
214 db['stored_aliases'] = staliases
212 print("Alias stored: %s (%s)" % (name, cmd))
215 print("Alias stored: %s (%s)" % (name, cmd))
213 return
216 return
214
217
215 else:
218 else:
216 modname = getattr(inspect.getmodule(obj), '__name__', '')
219 modname = getattr(inspect.getmodule(obj), '__name__', '')
217 if modname == '__main__':
220 if modname == '__main__':
218 print(textwrap.dedent("""\
221 print(textwrap.dedent("""\
219 Warning:%s is %s
222 Warning:%s is %s
220 Proper storage of interactively declared classes (or instances
223 Proper storage of interactively declared classes (or instances
221 of those classes) is not possible! Only instances
224 of those classes) is not possible! Only instances
222 of classes in real modules on file system can be %%store'd.
225 of classes in real modules on file system can be %%store'd.
223 """ % (arg, obj) ))
226 """ % (arg, obj) ))
224 return
227 return
225 #pickled = pickle.dumps(obj)
228 #pickled = pickle.dumps(obj)
226 db[ 'autorestore/' + arg ] = obj
229 db[ 'autorestore/' + arg ] = obj
227 print("Stored '%s' (%s)" % (arg, obj.__class__.__name__))
230 print("Stored '%s' (%s)" % (arg, obj.__class__.__name__))
228
231
229
232
230 def load_ipython_extension(ip):
233 def load_ipython_extension(ip):
231 """Load the extension in IPython."""
234 """Load the extension in IPython."""
232 ip.register_magics(StoreMagics)
235 ip.register_magics(StoreMagics)
233
236
@@ -1,213 +1,215 b''
1 """Extra magics for terminal use."""
1 """Extra magics for terminal use."""
2
2
3 # Copyright (c) IPython Development Team.
3 # Copyright (c) IPython Development Team.
4 # Distributed under the terms of the Modified BSD License.
4 # Distributed under the terms of the Modified BSD License.
5
5
6
6
7 from logging import error
7 from logging import error
8 import os
8 import os
9 import sys
9 import sys
10
10
11 from IPython.core.error import TryNext, UsageError
11 from IPython.core.error import TryNext, UsageError
12 from IPython.core.magic import Magics, magics_class, line_magic
12 from IPython.core.magic import Magics, magics_class, line_magic
13 from IPython.lib.clipboard import ClipboardEmpty
13 from IPython.lib.clipboard import ClipboardEmpty
14 from IPython.testing.skipdoctest import skip_doctest
14 from IPython.utils.text import SList, strip_email_quotes
15 from IPython.utils.text import SList, strip_email_quotes
15 from IPython.utils import py3compat
16 from IPython.utils import py3compat
16
17
17 def get_pasted_lines(sentinel, l_input=py3compat.input, quiet=False):
18 def get_pasted_lines(sentinel, l_input=py3compat.input, quiet=False):
18 """ Yield pasted lines until the user enters the given sentinel value.
19 """ Yield pasted lines until the user enters the given sentinel value.
19 """
20 """
20 if not quiet:
21 if not quiet:
21 print("Pasting code; enter '%s' alone on the line to stop or use Ctrl-D." \
22 print("Pasting code; enter '%s' alone on the line to stop or use Ctrl-D." \
22 % sentinel)
23 % sentinel)
23 prompt = ":"
24 prompt = ":"
24 else:
25 else:
25 prompt = ""
26 prompt = ""
26 while True:
27 while True:
27 try:
28 try:
28 l = l_input(prompt)
29 l = l_input(prompt)
29 if l == sentinel:
30 if l == sentinel:
30 return
31 return
31 else:
32 else:
32 yield l
33 yield l
33 except EOFError:
34 except EOFError:
34 print('<EOF>')
35 print('<EOF>')
35 return
36 return
36
37
37
38
38 @magics_class
39 @magics_class
39 class TerminalMagics(Magics):
40 class TerminalMagics(Magics):
40 def __init__(self, shell):
41 def __init__(self, shell):
41 super(TerminalMagics, self).__init__(shell)
42 super(TerminalMagics, self).__init__(shell)
42
43
43 def store_or_execute(self, block, name):
44 def store_or_execute(self, block, name):
44 """ Execute a block, or store it in a variable, per the user's request.
45 """ Execute a block, or store it in a variable, per the user's request.
45 """
46 """
46 if name:
47 if name:
47 # If storing it for further editing
48 # If storing it for further editing
48 self.shell.user_ns[name] = SList(block.splitlines())
49 self.shell.user_ns[name] = SList(block.splitlines())
49 print("Block assigned to '%s'" % name)
50 print("Block assigned to '%s'" % name)
50 else:
51 else:
51 b = self.preclean_input(block)
52 b = self.preclean_input(block)
52 self.shell.user_ns['pasted_block'] = b
53 self.shell.user_ns['pasted_block'] = b
53 self.shell.using_paste_magics = True
54 self.shell.using_paste_magics = True
54 try:
55 try:
55 self.shell.run_cell(b)
56 self.shell.run_cell(b)
56 finally:
57 finally:
57 self.shell.using_paste_magics = False
58 self.shell.using_paste_magics = False
58
59
59 def preclean_input(self, block):
60 def preclean_input(self, block):
60 lines = block.splitlines()
61 lines = block.splitlines()
61 while lines and not lines[0].strip():
62 while lines and not lines[0].strip():
62 lines = lines[1:]
63 lines = lines[1:]
63 return strip_email_quotes('\n'.join(lines))
64 return strip_email_quotes('\n'.join(lines))
64
65
65 def rerun_pasted(self, name='pasted_block'):
66 def rerun_pasted(self, name='pasted_block'):
66 """ Rerun a previously pasted command.
67 """ Rerun a previously pasted command.
67 """
68 """
68 b = self.shell.user_ns.get(name)
69 b = self.shell.user_ns.get(name)
69
70
70 # Sanity checks
71 # Sanity checks
71 if b is None:
72 if b is None:
72 raise UsageError('No previous pasted block available')
73 raise UsageError('No previous pasted block available')
73 if not isinstance(b, str):
74 if not isinstance(b, str):
74 raise UsageError(
75 raise UsageError(
75 "Variable 'pasted_block' is not a string, can't execute")
76 "Variable 'pasted_block' is not a string, can't execute")
76
77
77 print("Re-executing '%s...' (%d chars)"% (b.split('\n',1)[0], len(b)))
78 print("Re-executing '%s...' (%d chars)"% (b.split('\n',1)[0], len(b)))
78 self.shell.run_cell(b)
79 self.shell.run_cell(b)
79
80
80 @line_magic
81 @line_magic
81 def autoindent(self, parameter_s = ''):
82 def autoindent(self, parameter_s = ''):
82 """Toggle autoindent on/off (deprecated)"""
83 """Toggle autoindent on/off (deprecated)"""
83 self.shell.set_autoindent()
84 self.shell.set_autoindent()
84 print("Automatic indentation is:",['OFF','ON'][self.shell.autoindent])
85 print("Automatic indentation is:",['OFF','ON'][self.shell.autoindent])
85
86
87 @skip_doctest
86 @line_magic
88 @line_magic
87 def cpaste(self, parameter_s=''):
89 def cpaste(self, parameter_s=''):
88 """Paste & execute a pre-formatted code block from clipboard.
90 """Paste & execute a pre-formatted code block from clipboard.
89
91
90 You must terminate the block with '--' (two minus-signs) or Ctrl-D
92 You must terminate the block with '--' (two minus-signs) or Ctrl-D
91 alone on the line. You can also provide your own sentinel with '%paste
93 alone on the line. You can also provide your own sentinel with '%paste
92 -s %%' ('%%' is the new sentinel for this operation).
94 -s %%' ('%%' is the new sentinel for this operation).
93
95
94 The block is dedented prior to execution to enable execution of method
96 The block is dedented prior to execution to enable execution of method
95 definitions. '>' and '+' characters at the beginning of a line are
97 definitions. '>' and '+' characters at the beginning of a line are
96 ignored, to allow pasting directly from e-mails, diff files and
98 ignored, to allow pasting directly from e-mails, diff files and
97 doctests (the '...' continuation prompt is also stripped). The
99 doctests (the '...' continuation prompt is also stripped). The
98 executed block is also assigned to variable named 'pasted_block' for
100 executed block is also assigned to variable named 'pasted_block' for
99 later editing with '%edit pasted_block'.
101 later editing with '%edit pasted_block'.
100
102
101 You can also pass a variable name as an argument, e.g. '%cpaste foo'.
103 You can also pass a variable name as an argument, e.g. '%cpaste foo'.
102 This assigns the pasted block to variable 'foo' as string, without
104 This assigns the pasted block to variable 'foo' as string, without
103 dedenting or executing it (preceding >>> and + is still stripped)
105 dedenting or executing it (preceding >>> and + is still stripped)
104
106
105 '%cpaste -r' re-executes the block previously entered by cpaste.
107 '%cpaste -r' re-executes the block previously entered by cpaste.
106 '%cpaste -q' suppresses any additional output messages.
108 '%cpaste -q' suppresses any additional output messages.
107
109
108 Do not be alarmed by garbled output on Windows (it's a readline bug).
110 Do not be alarmed by garbled output on Windows (it's a readline bug).
109 Just press enter and type -- (and press enter again) and the block
111 Just press enter and type -- (and press enter again) and the block
110 will be what was just pasted.
112 will be what was just pasted.
111
113
112 Shell escapes are not supported (yet).
114 Shell escapes are not supported (yet).
113
115
114 See also
116 See also
115 --------
117 --------
116 paste: automatically pull code from clipboard.
118 paste: automatically pull code from clipboard.
117
119
118 Examples
120 Examples
119 --------
121 --------
120 ::
122 ::
121
123
122 In [8]: %cpaste
124 In [8]: %cpaste
123 Pasting code; enter '--' alone on the line to stop.
125 Pasting code; enter '--' alone on the line to stop.
124 :>>> a = ["world!", "Hello"]
126 :>>> a = ["world!", "Hello"]
125 :>>> print(" ".join(sorted(a)))
127 :>>> print(" ".join(sorted(a)))
126 :--
128 :--
127 Hello world!
129 Hello world!
128
130
129 ::
131 ::
130 In [8]: %cpaste
132 In [8]: %cpaste
131 Pasting code; enter '--' alone on the line to stop.
133 Pasting code; enter '--' alone on the line to stop.
132 :>>> %alias_magic t timeit
134 :>>> %alias_magic t timeit
133 :>>> %t -n1 pass
135 :>>> %t -n1 pass
134 :--
136 :--
135 Created `%t` as an alias for `%timeit`.
137 Created `%t` as an alias for `%timeit`.
136 Created `%%t` as an alias for `%%timeit`.
138 Created `%%t` as an alias for `%%timeit`.
137 354 ns Β± 224 ns per loop (mean Β± std. dev. of 7 runs, 1 loop each)
139 354 ns Β± 224 ns per loop (mean Β± std. dev. of 7 runs, 1 loop each)
138 """
140 """
139 opts, name = self.parse_options(parameter_s, 'rqs:', mode='string')
141 opts, name = self.parse_options(parameter_s, 'rqs:', mode='string')
140 if 'r' in opts:
142 if 'r' in opts:
141 self.rerun_pasted()
143 self.rerun_pasted()
142 return
144 return
143
145
144 quiet = ('q' in opts)
146 quiet = ('q' in opts)
145
147
146 sentinel = opts.get('s', u'--')
148 sentinel = opts.get('s', u'--')
147 block = '\n'.join(get_pasted_lines(sentinel, quiet=quiet))
149 block = '\n'.join(get_pasted_lines(sentinel, quiet=quiet))
148 self.store_or_execute(block, name)
150 self.store_or_execute(block, name)
149
151
150 @line_magic
152 @line_magic
151 def paste(self, parameter_s=''):
153 def paste(self, parameter_s=''):
152 """Paste & execute a pre-formatted code block from clipboard.
154 """Paste & execute a pre-formatted code block from clipboard.
153
155
154 The text is pulled directly from the clipboard without user
156 The text is pulled directly from the clipboard without user
155 intervention and printed back on the screen before execution (unless
157 intervention and printed back on the screen before execution (unless
156 the -q flag is given to force quiet mode).
158 the -q flag is given to force quiet mode).
157
159
158 The block is dedented prior to execution to enable execution of method
160 The block is dedented prior to execution to enable execution of method
159 definitions. '>' and '+' characters at the beginning of a line are
161 definitions. '>' and '+' characters at the beginning of a line are
160 ignored, to allow pasting directly from e-mails, diff files and
162 ignored, to allow pasting directly from e-mails, diff files and
161 doctests (the '...' continuation prompt is also stripped). The
163 doctests (the '...' continuation prompt is also stripped). The
162 executed block is also assigned to variable named 'pasted_block' for
164 executed block is also assigned to variable named 'pasted_block' for
163 later editing with '%edit pasted_block'.
165 later editing with '%edit pasted_block'.
164
166
165 You can also pass a variable name as an argument, e.g. '%paste foo'.
167 You can also pass a variable name as an argument, e.g. '%paste foo'.
166 This assigns the pasted block to variable 'foo' as string, without
168 This assigns the pasted block to variable 'foo' as string, without
167 executing it (preceding >>> and + is still stripped).
169 executing it (preceding >>> and + is still stripped).
168
170
169 Options:
171 Options:
170
172
171 -r: re-executes the block previously entered by cpaste.
173 -r: re-executes the block previously entered by cpaste.
172
174
173 -q: quiet mode: do not echo the pasted text back to the terminal.
175 -q: quiet mode: do not echo the pasted text back to the terminal.
174
176
175 IPython statements (magics, shell escapes) are not supported (yet).
177 IPython statements (magics, shell escapes) are not supported (yet).
176
178
177 See also
179 See also
178 --------
180 --------
179 cpaste: manually paste code into terminal until you mark its end.
181 cpaste: manually paste code into terminal until you mark its end.
180 """
182 """
181 opts, name = self.parse_options(parameter_s, 'rq', mode='string')
183 opts, name = self.parse_options(parameter_s, 'rq', mode='string')
182 if 'r' in opts:
184 if 'r' in opts:
183 self.rerun_pasted()
185 self.rerun_pasted()
184 return
186 return
185 try:
187 try:
186 block = self.shell.hooks.clipboard_get()
188 block = self.shell.hooks.clipboard_get()
187 except TryNext as clipboard_exc:
189 except TryNext as clipboard_exc:
188 message = getattr(clipboard_exc, 'args')
190 message = getattr(clipboard_exc, 'args')
189 if message:
191 if message:
190 error(message[0])
192 error(message[0])
191 else:
193 else:
192 error('Could not get text from the clipboard.')
194 error('Could not get text from the clipboard.')
193 return
195 return
194 except ClipboardEmpty as e:
196 except ClipboardEmpty as e:
195 raise UsageError("The clipboard appears to be empty") from e
197 raise UsageError("The clipboard appears to be empty") from e
196
198
197 # By default, echo back to terminal unless quiet mode is requested
199 # By default, echo back to terminal unless quiet mode is requested
198 if 'q' not in opts:
200 if 'q' not in opts:
199 write = self.shell.write
201 write = self.shell.write
200 write(self.shell.pycolorize(block))
202 write(self.shell.pycolorize(block))
201 if not block.endswith('\n'):
203 if not block.endswith('\n'):
202 write('\n')
204 write('\n')
203 write("## -- End pasted text --\n")
205 write("## -- End pasted text --\n")
204
206
205 self.store_or_execute(block, name)
207 self.store_or_execute(block, name)
206
208
207 # Class-level: add a '%cls' magic only on Windows
209 # Class-level: add a '%cls' magic only on Windows
208 if sys.platform == 'win32':
210 if sys.platform == 'win32':
209 @line_magic
211 @line_magic
210 def cls(self, s):
212 def cls(self, s):
211 """Clear screen.
213 """Clear screen.
212 """
214 """
213 os.system("cls")
215 os.system("cls")
General Comments 0
You need to be logged in to leave comments. Login now