##// END OF EJS Templates
ENH: Add alias_magic parameters
Nick Weseman -
Show More
@@ -0,0 +1,22 b''
1 Added the ability to add parameters to alias_magic.
2
3 e.g.:
4
5 In [2]: %alias_magic hist history --params "-l 2" --line
6 Created `%hist` as an alias for `%history -l 2`.
7
8 In [3]: hist
9 %alias_magic hist history --params "-l 30" --line
10 %alias_magic hist history --params "-l 2" --line
11
12 Previously it was only possible to have an alias attached to a single function, and you would have to pass in the given parameters every time.
13
14 e.g.:
15
16 In [4]: %alias_magic hist history --line
17 Created `%hist` as an alias for `%history`.
18
19 In [5]: hist -l 2
20 hist
21 %alias_magic hist history --line
22
@@ -1,680 +1,685 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 import types
17 import types
18 from getopt import getopt, GetoptError
18 from getopt import getopt, GetoptError
19
19
20 from traitlets.config.configurable import Configurable
20 from traitlets.config.configurable import Configurable
21 from IPython.core import oinspect
21 from IPython.core import oinspect
22 from IPython.core.error import UsageError
22 from IPython.core.error import UsageError
23 from IPython.core.inputsplitter import ESC_MAGIC, ESC_MAGIC2
23 from IPython.core.inputsplitter import ESC_MAGIC, ESC_MAGIC2
24 from decorator import decorator
24 from decorator import decorator
25 from IPython.utils.ipstruct import Struct
25 from IPython.utils.ipstruct import Struct
26 from IPython.utils.process import arg_split
26 from IPython.utils.process import arg_split
27 from IPython.utils.text import dedent
27 from IPython.utils.text import dedent
28 from traitlets import Bool, Dict, Instance, observe
28 from traitlets import Bool, Dict, Instance, observe
29 from logging import error
29 from logging import error
30
30
31 #-----------------------------------------------------------------------------
31 #-----------------------------------------------------------------------------
32 # Globals
32 # Globals
33 #-----------------------------------------------------------------------------
33 #-----------------------------------------------------------------------------
34
34
35 # A dict we'll use for each class that has magics, used as temporary storage to
35 # A dict we'll use for each class that has magics, used as temporary storage to
36 # pass information between the @line/cell_magic method decorators and the
36 # pass information between the @line/cell_magic method decorators and the
37 # @magics_class class decorator, because the method decorators have no
37 # @magics_class class decorator, because the method decorators have no
38 # access to the class when they run. See for more details:
38 # access to the class when they run. See for more details:
39 # http://stackoverflow.com/questions/2366713/can-a-python-decorator-of-an-instance-method-access-the-class
39 # http://stackoverflow.com/questions/2366713/can-a-python-decorator-of-an-instance-method-access-the-class
40
40
41 magics = dict(line={}, cell={})
41 magics = dict(line={}, cell={})
42
42
43 magic_kinds = ('line', 'cell')
43 magic_kinds = ('line', 'cell')
44 magic_spec = ('line', 'cell', 'line_cell')
44 magic_spec = ('line', 'cell', 'line_cell')
45 magic_escapes = dict(line=ESC_MAGIC, cell=ESC_MAGIC2)
45 magic_escapes = dict(line=ESC_MAGIC, cell=ESC_MAGIC2)
46
46
47 #-----------------------------------------------------------------------------
47 #-----------------------------------------------------------------------------
48 # Utility classes and functions
48 # Utility classes and functions
49 #-----------------------------------------------------------------------------
49 #-----------------------------------------------------------------------------
50
50
51 class Bunch: pass
51 class Bunch: pass
52
52
53
53
54 def on_off(tag):
54 def on_off(tag):
55 """Return an ON/OFF string for a 1/0 input. Simple utility function."""
55 """Return an ON/OFF string for a 1/0 input. Simple utility function."""
56 return ['OFF','ON'][tag]
56 return ['OFF','ON'][tag]
57
57
58
58
59 def compress_dhist(dh):
59 def compress_dhist(dh):
60 """Compress a directory history into a new one with at most 20 entries.
60 """Compress a directory history into a new one with at most 20 entries.
61
61
62 Return a new list made from the first and last 10 elements of dhist after
62 Return a new list made from the first and last 10 elements of dhist after
63 removal of duplicates.
63 removal of duplicates.
64 """
64 """
65 head, tail = dh[:-10], dh[-10:]
65 head, tail = dh[:-10], dh[-10:]
66
66
67 newhead = []
67 newhead = []
68 done = set()
68 done = set()
69 for h in head:
69 for h in head:
70 if h in done:
70 if h in done:
71 continue
71 continue
72 newhead.append(h)
72 newhead.append(h)
73 done.add(h)
73 done.add(h)
74
74
75 return newhead + tail
75 return newhead + tail
76
76
77
77
78 def needs_local_scope(func):
78 def needs_local_scope(func):
79 """Decorator to mark magic functions which need to local scope to run."""
79 """Decorator to mark magic functions which need to local scope to run."""
80 func.needs_local_scope = True
80 func.needs_local_scope = True
81 return func
81 return func
82
82
83 #-----------------------------------------------------------------------------
83 #-----------------------------------------------------------------------------
84 # Class and method decorators for registering magics
84 # Class and method decorators for registering magics
85 #-----------------------------------------------------------------------------
85 #-----------------------------------------------------------------------------
86
86
87 def magics_class(cls):
87 def magics_class(cls):
88 """Class decorator for all subclasses of the main Magics class.
88 """Class decorator for all subclasses of the main Magics class.
89
89
90 Any class that subclasses Magics *must* also apply this decorator, to
90 Any class that subclasses Magics *must* also apply this decorator, to
91 ensure that all the methods that have been decorated as line/cell magics
91 ensure that all the methods that have been decorated as line/cell magics
92 get correctly registered in the class instance. This is necessary because
92 get correctly registered in the class instance. This is necessary because
93 when method decorators run, the class does not exist yet, so they
93 when method decorators run, the class does not exist yet, so they
94 temporarily store their information into a module global. Application of
94 temporarily store their information into a module global. Application of
95 this class decorator copies that global data to the class instance and
95 this class decorator copies that global data to the class instance and
96 clears the global.
96 clears the global.
97
97
98 Obviously, this mechanism is not thread-safe, which means that the
98 Obviously, this mechanism is not thread-safe, which means that the
99 *creation* of subclasses of Magic should only be done in a single-thread
99 *creation* of subclasses of Magic should only be done in a single-thread
100 context. Instantiation of the classes has no restrictions. Given that
100 context. Instantiation of the classes has no restrictions. Given that
101 these classes are typically created at IPython startup time and before user
101 these classes are typically created at IPython startup time and before user
102 application code becomes active, in practice this should not pose any
102 application code becomes active, in practice this should not pose any
103 problems.
103 problems.
104 """
104 """
105 cls.registered = True
105 cls.registered = True
106 cls.magics = dict(line = magics['line'],
106 cls.magics = dict(line = magics['line'],
107 cell = magics['cell'])
107 cell = magics['cell'])
108 magics['line'] = {}
108 magics['line'] = {}
109 magics['cell'] = {}
109 magics['cell'] = {}
110 return cls
110 return cls
111
111
112
112
113 def record_magic(dct, magic_kind, magic_name, func):
113 def record_magic(dct, magic_kind, magic_name, func):
114 """Utility function to store a function as a magic of a specific kind.
114 """Utility function to store a function as a magic of a specific kind.
115
115
116 Parameters
116 Parameters
117 ----------
117 ----------
118 dct : dict
118 dct : dict
119 A dictionary with 'line' and 'cell' subdicts.
119 A dictionary with 'line' and 'cell' subdicts.
120
120
121 magic_kind : str
121 magic_kind : str
122 Kind of magic to be stored.
122 Kind of magic to be stored.
123
123
124 magic_name : str
124 magic_name : str
125 Key to store the magic as.
125 Key to store the magic as.
126
126
127 func : function
127 func : function
128 Callable object to store.
128 Callable object to store.
129 """
129 """
130 if magic_kind == 'line_cell':
130 if magic_kind == 'line_cell':
131 dct['line'][magic_name] = dct['cell'][magic_name] = func
131 dct['line'][magic_name] = dct['cell'][magic_name] = func
132 else:
132 else:
133 dct[magic_kind][magic_name] = func
133 dct[magic_kind][magic_name] = func
134
134
135
135
136 def validate_type(magic_kind):
136 def validate_type(magic_kind):
137 """Ensure that the given magic_kind is valid.
137 """Ensure that the given magic_kind is valid.
138
138
139 Check that the given magic_kind is one of the accepted spec types (stored
139 Check that the given magic_kind is one of the accepted spec types (stored
140 in the global `magic_spec`), raise ValueError otherwise.
140 in the global `magic_spec`), raise ValueError otherwise.
141 """
141 """
142 if magic_kind not in magic_spec:
142 if magic_kind not in magic_spec:
143 raise ValueError('magic_kind must be one of %s, %s given' %
143 raise ValueError('magic_kind must be one of %s, %s given' %
144 magic_kinds, magic_kind)
144 magic_kinds, magic_kind)
145
145
146
146
147 # The docstrings for the decorator below will be fairly similar for the two
147 # The docstrings for the decorator below will be fairly similar for the two
148 # types (method and function), so we generate them here once and reuse the
148 # types (method and function), so we generate them here once and reuse the
149 # templates below.
149 # templates below.
150 _docstring_template = \
150 _docstring_template = \
151 """Decorate the given {0} as {1} magic.
151 """Decorate the given {0} as {1} magic.
152
152
153 The decorator can be used with or without arguments, as follows.
153 The decorator can be used with or without arguments, as follows.
154
154
155 i) without arguments: it will create a {1} magic named as the {0} being
155 i) without arguments: it will create a {1} magic named as the {0} being
156 decorated::
156 decorated::
157
157
158 @deco
158 @deco
159 def foo(...)
159 def foo(...)
160
160
161 will create a {1} magic named `foo`.
161 will create a {1} magic named `foo`.
162
162
163 ii) with one string argument: which will be used as the actual name of the
163 ii) with one string argument: which will be used as the actual name of the
164 resulting magic::
164 resulting magic::
165
165
166 @deco('bar')
166 @deco('bar')
167 def foo(...)
167 def foo(...)
168
168
169 will create a {1} magic named `bar`.
169 will create a {1} magic named `bar`.
170
170
171 To register a class magic use ``Interactiveshell.register_magic(class or instance)``.
171 To register a class magic use ``Interactiveshell.register_magic(class or instance)``.
172 """
172 """
173
173
174 # These two are decorator factories. While they are conceptually very similar,
174 # These two are decorator factories. While they are conceptually very similar,
175 # there are enough differences in the details that it's simpler to have them
175 # there are enough differences in the details that it's simpler to have them
176 # written as completely standalone functions rather than trying to share code
176 # written as completely standalone functions rather than trying to share code
177 # and make a single one with convoluted logic.
177 # and make a single one with convoluted logic.
178
178
179 def _method_magic_marker(magic_kind):
179 def _method_magic_marker(magic_kind):
180 """Decorator factory for methods in Magics subclasses.
180 """Decorator factory for methods in Magics subclasses.
181 """
181 """
182
182
183 validate_type(magic_kind)
183 validate_type(magic_kind)
184
184
185 # This is a closure to capture the magic_kind. We could also use a class,
185 # This is a closure to capture the magic_kind. We could also use a class,
186 # but it's overkill for just that one bit of state.
186 # but it's overkill for just that one bit of state.
187 def magic_deco(arg):
187 def magic_deco(arg):
188 call = lambda f, *a, **k: f(*a, **k)
188 call = lambda f, *a, **k: f(*a, **k)
189
189
190 if callable(arg):
190 if callable(arg):
191 # "Naked" decorator call (just @foo, no args)
191 # "Naked" decorator call (just @foo, no args)
192 func = arg
192 func = arg
193 name = func.__name__
193 name = func.__name__
194 retval = decorator(call, func)
194 retval = decorator(call, func)
195 record_magic(magics, magic_kind, name, name)
195 record_magic(magics, magic_kind, name, name)
196 elif isinstance(arg, str):
196 elif isinstance(arg, str):
197 # Decorator called with arguments (@foo('bar'))
197 # Decorator called with arguments (@foo('bar'))
198 name = arg
198 name = arg
199 def mark(func, *a, **kw):
199 def mark(func, *a, **kw):
200 record_magic(magics, magic_kind, name, func.__name__)
200 record_magic(magics, magic_kind, name, func.__name__)
201 return decorator(call, func)
201 return decorator(call, func)
202 retval = mark
202 retval = mark
203 else:
203 else:
204 raise TypeError("Decorator can only be called with "
204 raise TypeError("Decorator can only be called with "
205 "string or function")
205 "string or function")
206 return retval
206 return retval
207
207
208 # Ensure the resulting decorator has a usable docstring
208 # Ensure the resulting decorator has a usable docstring
209 magic_deco.__doc__ = _docstring_template.format('method', magic_kind)
209 magic_deco.__doc__ = _docstring_template.format('method', magic_kind)
210 return magic_deco
210 return magic_deco
211
211
212
212
213 def _function_magic_marker(magic_kind):
213 def _function_magic_marker(magic_kind):
214 """Decorator factory for standalone functions.
214 """Decorator factory for standalone functions.
215 """
215 """
216 validate_type(magic_kind)
216 validate_type(magic_kind)
217
217
218 # This is a closure to capture the magic_kind. We could also use a class,
218 # This is a closure to capture the magic_kind. We could also use a class,
219 # but it's overkill for just that one bit of state.
219 # but it's overkill for just that one bit of state.
220 def magic_deco(arg):
220 def magic_deco(arg):
221 call = lambda f, *a, **k: f(*a, **k)
221 call = lambda f, *a, **k: f(*a, **k)
222
222
223 # Find get_ipython() in the caller's namespace
223 # Find get_ipython() in the caller's namespace
224 caller = sys._getframe(1)
224 caller = sys._getframe(1)
225 for ns in ['f_locals', 'f_globals', 'f_builtins']:
225 for ns in ['f_locals', 'f_globals', 'f_builtins']:
226 get_ipython = getattr(caller, ns).get('get_ipython')
226 get_ipython = getattr(caller, ns).get('get_ipython')
227 if get_ipython is not None:
227 if get_ipython is not None:
228 break
228 break
229 else:
229 else:
230 raise NameError('Decorator can only run in context where '
230 raise NameError('Decorator can only run in context where '
231 '`get_ipython` exists')
231 '`get_ipython` exists')
232
232
233 ip = get_ipython()
233 ip = get_ipython()
234
234
235 if callable(arg):
235 if callable(arg):
236 # "Naked" decorator call (just @foo, no args)
236 # "Naked" decorator call (just @foo, no args)
237 func = arg
237 func = arg
238 name = func.__name__
238 name = func.__name__
239 ip.register_magic_function(func, magic_kind, name)
239 ip.register_magic_function(func, magic_kind, name)
240 retval = decorator(call, func)
240 retval = decorator(call, func)
241 elif isinstance(arg, str):
241 elif isinstance(arg, str):
242 # Decorator called with arguments (@foo('bar'))
242 # Decorator called with arguments (@foo('bar'))
243 name = arg
243 name = arg
244 def mark(func, *a, **kw):
244 def mark(func, *a, **kw):
245 ip.register_magic_function(func, magic_kind, name)
245 ip.register_magic_function(func, magic_kind, name)
246 return decorator(call, func)
246 return decorator(call, func)
247 retval = mark
247 retval = mark
248 else:
248 else:
249 raise TypeError("Decorator can only be called with "
249 raise TypeError("Decorator can only be called with "
250 "string or function")
250 "string or function")
251 return retval
251 return retval
252
252
253 # Ensure the resulting decorator has a usable docstring
253 # Ensure the resulting decorator has a usable docstring
254 ds = _docstring_template.format('function', magic_kind)
254 ds = _docstring_template.format('function', magic_kind)
255
255
256 ds += dedent("""
256 ds += dedent("""
257 Note: this decorator can only be used in a context where IPython is already
257 Note: this decorator can only be used in a context where IPython is already
258 active, so that the `get_ipython()` call succeeds. You can therefore use
258 active, so that the `get_ipython()` call succeeds. You can therefore use
259 it in your startup files loaded after IPython initializes, but *not* in the
259 it in your startup files loaded after IPython initializes, but *not* in the
260 IPython configuration file itself, which is executed before IPython is
260 IPython configuration file itself, which is executed before IPython is
261 fully up and running. Any file located in the `startup` subdirectory of
261 fully up and running. Any file located in the `startup` subdirectory of
262 your configuration profile will be OK in this sense.
262 your configuration profile will be OK in this sense.
263 """)
263 """)
264
264
265 magic_deco.__doc__ = ds
265 magic_deco.__doc__ = ds
266 return magic_deco
266 return magic_deco
267
267
268
268
269 # Create the actual decorators for public use
269 # Create the actual decorators for public use
270
270
271 # These three are used to decorate methods in class definitions
271 # These three are used to decorate methods in class definitions
272 line_magic = _method_magic_marker('line')
272 line_magic = _method_magic_marker('line')
273 cell_magic = _method_magic_marker('cell')
273 cell_magic = _method_magic_marker('cell')
274 line_cell_magic = _method_magic_marker('line_cell')
274 line_cell_magic = _method_magic_marker('line_cell')
275
275
276 # These three decorate standalone functions and perform the decoration
276 # These three decorate standalone functions and perform the decoration
277 # immediately. They can only run where get_ipython() works
277 # immediately. They can only run where get_ipython() works
278 register_line_magic = _function_magic_marker('line')
278 register_line_magic = _function_magic_marker('line')
279 register_cell_magic = _function_magic_marker('cell')
279 register_cell_magic = _function_magic_marker('cell')
280 register_line_cell_magic = _function_magic_marker('line_cell')
280 register_line_cell_magic = _function_magic_marker('line_cell')
281
281
282 #-----------------------------------------------------------------------------
282 #-----------------------------------------------------------------------------
283 # Core Magic classes
283 # Core Magic classes
284 #-----------------------------------------------------------------------------
284 #-----------------------------------------------------------------------------
285
285
286 class MagicsManager(Configurable):
286 class MagicsManager(Configurable):
287 """Object that handles all magic-related functionality for IPython.
287 """Object that handles all magic-related functionality for IPython.
288 """
288 """
289 # Non-configurable class attributes
289 # Non-configurable class attributes
290
290
291 # A two-level dict, first keyed by magic type, then by magic function, and
291 # A two-level dict, first keyed by magic type, then by magic function, and
292 # holding the actual callable object as value. This is the dict used for
292 # holding the actual callable object as value. This is the dict used for
293 # magic function dispatch
293 # magic function dispatch
294 magics = Dict()
294 magics = Dict()
295
295
296 # A registry of the original objects that we've been given holding magics.
296 # A registry of the original objects that we've been given holding magics.
297 registry = Dict()
297 registry = Dict()
298
298
299 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
299 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC', allow_none=True)
300
300
301 auto_magic = Bool(True, help=
301 auto_magic = Bool(True, help=
302 "Automatically call line magics without requiring explicit % prefix"
302 "Automatically call line magics without requiring explicit % prefix"
303 ).tag(config=True)
303 ).tag(config=True)
304 @observe('auto_magic')
304 @observe('auto_magic')
305 def _auto_magic_changed(self, change):
305 def _auto_magic_changed(self, change):
306 self.shell.automagic = change['new']
306 self.shell.automagic = change['new']
307
307
308 _auto_status = [
308 _auto_status = [
309 'Automagic is OFF, % prefix IS needed for line magics.',
309 'Automagic is OFF, % prefix IS needed for line magics.',
310 'Automagic is ON, % prefix IS NOT needed for line magics.']
310 'Automagic is ON, % prefix IS NOT needed for line magics.']
311
311
312 user_magics = Instance('IPython.core.magics.UserMagics', allow_none=True)
312 user_magics = Instance('IPython.core.magics.UserMagics', allow_none=True)
313
313
314 def __init__(self, shell=None, config=None, user_magics=None, **traits):
314 def __init__(self, shell=None, config=None, user_magics=None, **traits):
315
315
316 super(MagicsManager, self).__init__(shell=shell, config=config,
316 super(MagicsManager, self).__init__(shell=shell, config=config,
317 user_magics=user_magics, **traits)
317 user_magics=user_magics, **traits)
318 self.magics = dict(line={}, cell={})
318 self.magics = dict(line={}, cell={})
319 # Let's add the user_magics to the registry for uniformity, so *all*
319 # Let's add the user_magics to the registry for uniformity, so *all*
320 # registered magic containers can be found there.
320 # registered magic containers can be found there.
321 self.registry[user_magics.__class__.__name__] = user_magics
321 self.registry[user_magics.__class__.__name__] = user_magics
322
322
323 def auto_status(self):
323 def auto_status(self):
324 """Return descriptive string with automagic status."""
324 """Return descriptive string with automagic status."""
325 return self._auto_status[self.auto_magic]
325 return self._auto_status[self.auto_magic]
326
326
327 def lsmagic(self):
327 def lsmagic(self):
328 """Return a dict of currently available magic functions.
328 """Return a dict of currently available magic functions.
329
329
330 The return dict has the keys 'line' and 'cell', corresponding to the
330 The return dict has the keys 'line' and 'cell', corresponding to the
331 two types of magics we support. Each value is a list of names.
331 two types of magics we support. Each value is a list of names.
332 """
332 """
333 return self.magics
333 return self.magics
334
334
335 def lsmagic_docs(self, brief=False, missing=''):
335 def lsmagic_docs(self, brief=False, missing=''):
336 """Return dict of documentation of magic functions.
336 """Return dict of documentation of magic functions.
337
337
338 The return dict has the keys 'line' and 'cell', corresponding to the
338 The return dict has the keys 'line' and 'cell', corresponding to the
339 two types of magics we support. Each value is a dict keyed by magic
339 two types of magics we support. Each value is a dict keyed by magic
340 name whose value is the function docstring. If a docstring is
340 name whose value is the function docstring. If a docstring is
341 unavailable, the value of `missing` is used instead.
341 unavailable, the value of `missing` is used instead.
342
342
343 If brief is True, only the first line of each docstring will be returned.
343 If brief is True, only the first line of each docstring will be returned.
344 """
344 """
345 docs = {}
345 docs = {}
346 for m_type in self.magics:
346 for m_type in self.magics:
347 m_docs = {}
347 m_docs = {}
348 for m_name, m_func in self.magics[m_type].items():
348 for m_name, m_func in self.magics[m_type].items():
349 if m_func.__doc__:
349 if m_func.__doc__:
350 if brief:
350 if brief:
351 m_docs[m_name] = m_func.__doc__.split('\n', 1)[0]
351 m_docs[m_name] = m_func.__doc__.split('\n', 1)[0]
352 else:
352 else:
353 m_docs[m_name] = m_func.__doc__.rstrip()
353 m_docs[m_name] = m_func.__doc__.rstrip()
354 else:
354 else:
355 m_docs[m_name] = missing
355 m_docs[m_name] = missing
356 docs[m_type] = m_docs
356 docs[m_type] = m_docs
357 return docs
357 return docs
358
358
359 def register(self, *magic_objects):
359 def register(self, *magic_objects):
360 """Register one or more instances of Magics.
360 """Register one or more instances of Magics.
361
361
362 Take one or more classes or instances of classes that subclass the main
362 Take one or more classes or instances of classes that subclass the main
363 `core.Magic` class, and register them with IPython to use the magic
363 `core.Magic` class, and register them with IPython to use the magic
364 functions they provide. The registration process will then ensure that
364 functions they provide. The registration process will then ensure that
365 any methods that have decorated to provide line and/or cell magics will
365 any methods that have decorated to provide line and/or cell magics will
366 be recognized with the `%x`/`%%x` syntax as a line/cell magic
366 be recognized with the `%x`/`%%x` syntax as a line/cell magic
367 respectively.
367 respectively.
368
368
369 If classes are given, they will be instantiated with the default
369 If classes are given, they will be instantiated with the default
370 constructor. If your classes need a custom constructor, you should
370 constructor. If your classes need a custom constructor, you should
371 instanitate them first and pass the instance.
371 instanitate them first and pass the instance.
372
372
373 The provided arguments can be an arbitrary mix of classes and instances.
373 The provided arguments can be an arbitrary mix of classes and instances.
374
374
375 Parameters
375 Parameters
376 ----------
376 ----------
377 magic_objects : one or more classes or instances
377 magic_objects : one or more classes or instances
378 """
378 """
379 # Start by validating them to ensure they have all had their magic
379 # Start by validating them to ensure they have all had their magic
380 # methods registered at the instance level
380 # methods registered at the instance level
381 for m in magic_objects:
381 for m in magic_objects:
382 if not m.registered:
382 if not m.registered:
383 raise ValueError("Class of magics %r was constructed without "
383 raise ValueError("Class of magics %r was constructed without "
384 "the @register_magics class decorator")
384 "the @register_magics class decorator")
385 if isinstance(m, type):
385 if isinstance(m, type):
386 # If we're given an uninstantiated class
386 # If we're given an uninstantiated class
387 m = m(shell=self.shell)
387 m = m(shell=self.shell)
388
388
389 # Now that we have an instance, we can register it and update the
389 # Now that we have an instance, we can register it and update the
390 # table of callables
390 # table of callables
391 self.registry[m.__class__.__name__] = m
391 self.registry[m.__class__.__name__] = m
392 for mtype in magic_kinds:
392 for mtype in magic_kinds:
393 self.magics[mtype].update(m.magics[mtype])
393 self.magics[mtype].update(m.magics[mtype])
394
394
395 def register_function(self, func, magic_kind='line', magic_name=None):
395 def register_function(self, func, magic_kind='line', magic_name=None):
396 """Expose a standalone function as magic function for IPython.
396 """Expose a standalone function as magic function for IPython.
397
397
398 This will create an IPython magic (line, cell or both) from a
398 This will create an IPython magic (line, cell or both) from a
399 standalone function. The functions should have the following
399 standalone function. The functions should have the following
400 signatures:
400 signatures:
401
401
402 * For line magics: `def f(line)`
402 * For line magics: `def f(line)`
403 * For cell magics: `def f(line, cell)`
403 * For cell magics: `def f(line, cell)`
404 * For a function that does both: `def f(line, cell=None)`
404 * For a function that does both: `def f(line, cell=None)`
405
405
406 In the latter case, the function will be called with `cell==None` when
406 In the latter case, the function will be called with `cell==None` when
407 invoked as `%f`, and with cell as a string when invoked as `%%f`.
407 invoked as `%f`, and with cell as a string when invoked as `%%f`.
408
408
409 Parameters
409 Parameters
410 ----------
410 ----------
411 func : callable
411 func : callable
412 Function to be registered as a magic.
412 Function to be registered as a magic.
413
413
414 magic_kind : str
414 magic_kind : str
415 Kind of magic, one of 'line', 'cell' or 'line_cell'
415 Kind of magic, one of 'line', 'cell' or 'line_cell'
416
416
417 magic_name : optional str
417 magic_name : optional str
418 If given, the name the magic will have in the IPython namespace. By
418 If given, the name the magic will have in the IPython namespace. By
419 default, the name of the function itself is used.
419 default, the name of the function itself is used.
420 """
420 """
421
421
422 # Create the new method in the user_magics and register it in the
422 # Create the new method in the user_magics and register it in the
423 # global table
423 # global table
424 validate_type(magic_kind)
424 validate_type(magic_kind)
425 magic_name = func.__name__ if magic_name is None else magic_name
425 magic_name = func.__name__ if magic_name is None else magic_name
426 setattr(self.user_magics, magic_name, func)
426 setattr(self.user_magics, magic_name, func)
427 record_magic(self.magics, magic_kind, magic_name, func)
427 record_magic(self.magics, magic_kind, magic_name, func)
428
428
429 def register_alias(self, alias_name, magic_name, magic_kind='line'):
429 def register_alias(self, alias_name, magic_name, magic_kind='line', magic_params=None):
430 """Register an alias to a magic function.
430 """Register an alias to a magic function.
431
431
432 The alias is an instance of :class:`MagicAlias`, which holds the
432 The alias is an instance of :class:`MagicAlias`, which holds the
433 name and kind of the magic it should call. Binding is done at
433 name and kind of the magic it should call. Binding is done at
434 call time, so if the underlying magic function is changed the alias
434 call time, so if the underlying magic function is changed the alias
435 will call the new function.
435 will call the new function.
436
436
437 Parameters
437 Parameters
438 ----------
438 ----------
439 alias_name : str
439 alias_name : str
440 The name of the magic to be registered.
440 The name of the magic to be registered.
441
441
442 magic_name : str
442 magic_name : str
443 The name of an existing magic.
443 The name of an existing magic.
444
444
445 magic_kind : str
445 magic_kind : str
446 Kind of magic, one of 'line' or 'cell'
446 Kind of magic, one of 'line' or 'cell'
447 """
447 """
448
448
449 # `validate_type` is too permissive, as it allows 'line_cell'
449 # `validate_type` is too permissive, as it allows 'line_cell'
450 # which we do not handle.
450 # which we do not handle.
451 if magic_kind not in magic_kinds:
451 if magic_kind not in magic_kinds:
452 raise ValueError('magic_kind must be one of %s, %s given' %
452 raise ValueError('magic_kind must be one of %s, %s given' %
453 magic_kinds, magic_kind)
453 magic_kinds, magic_kind)
454
454
455 alias = MagicAlias(self.shell, magic_name, magic_kind)
455 alias = MagicAlias(self.shell, magic_name, magic_kind, magic_params)
456 setattr(self.user_magics, alias_name, alias)
456 setattr(self.user_magics, alias_name, alias)
457 record_magic(self.magics, magic_kind, alias_name, alias)
457 record_magic(self.magics, magic_kind, alias_name, alias)
458
458
459 # Key base class that provides the central functionality for magics.
459 # Key base class that provides the central functionality for magics.
460
460
461
461
462 class Magics(Configurable):
462 class Magics(Configurable):
463 """Base class for implementing magic functions.
463 """Base class for implementing magic functions.
464
464
465 Shell functions which can be reached as %function_name. All magic
465 Shell functions which can be reached as %function_name. All magic
466 functions should accept a string, which they can parse for their own
466 functions should accept a string, which they can parse for their own
467 needs. This can make some functions easier to type, eg `%cd ../`
467 needs. This can make some functions easier to type, eg `%cd ../`
468 vs. `%cd("../")`
468 vs. `%cd("../")`
469
469
470 Classes providing magic functions need to subclass this class, and they
470 Classes providing magic functions need to subclass this class, and they
471 MUST:
471 MUST:
472
472
473 - Use the method decorators `@line_magic` and `@cell_magic` to decorate
473 - Use the method decorators `@line_magic` and `@cell_magic` to decorate
474 individual methods as magic functions, AND
474 individual methods as magic functions, AND
475
475
476 - Use the class decorator `@magics_class` to ensure that the magic
476 - Use the class decorator `@magics_class` to ensure that the magic
477 methods are properly registered at the instance level upon instance
477 methods are properly registered at the instance level upon instance
478 initialization.
478 initialization.
479
479
480 See :mod:`magic_functions` for examples of actual implementation classes.
480 See :mod:`magic_functions` for examples of actual implementation classes.
481 """
481 """
482 # Dict holding all command-line options for each magic.
482 # Dict holding all command-line options for each magic.
483 options_table = None
483 options_table = None
484 # Dict for the mapping of magic names to methods, set by class decorator
484 # Dict for the mapping of magic names to methods, set by class decorator
485 magics = None
485 magics = None
486 # Flag to check that the class decorator was properly applied
486 # Flag to check that the class decorator was properly applied
487 registered = False
487 registered = False
488 # Instance of IPython shell
488 # Instance of IPython shell
489 shell = None
489 shell = None
490
490
491 def __init__(self, shell=None, **kwargs):
491 def __init__(self, shell=None, **kwargs):
492 if not(self.__class__.registered):
492 if not(self.__class__.registered):
493 raise ValueError('Magics subclass without registration - '
493 raise ValueError('Magics subclass without registration - '
494 'did you forget to apply @magics_class?')
494 'did you forget to apply @magics_class?')
495 if shell is not None:
495 if shell is not None:
496 if hasattr(shell, 'configurables'):
496 if hasattr(shell, 'configurables'):
497 shell.configurables.append(self)
497 shell.configurables.append(self)
498 if hasattr(shell, 'config'):
498 if hasattr(shell, 'config'):
499 kwargs.setdefault('parent', shell)
499 kwargs.setdefault('parent', shell)
500
500
501 self.shell = shell
501 self.shell = shell
502 self.options_table = {}
502 self.options_table = {}
503 # The method decorators are run when the instance doesn't exist yet, so
503 # The method decorators are run when the instance doesn't exist yet, so
504 # they can only record the names of the methods they are supposed to
504 # they can only record the names of the methods they are supposed to
505 # grab. Only now, that the instance exists, can we create the proper
505 # grab. Only now, that the instance exists, can we create the proper
506 # mapping to bound methods. So we read the info off the original names
506 # mapping to bound methods. So we read the info off the original names
507 # table and replace each method name by the actual bound method.
507 # table and replace each method name by the actual bound method.
508 # But we mustn't clobber the *class* mapping, in case of multiple instances.
508 # But we mustn't clobber the *class* mapping, in case of multiple instances.
509 class_magics = self.magics
509 class_magics = self.magics
510 self.magics = {}
510 self.magics = {}
511 for mtype in magic_kinds:
511 for mtype in magic_kinds:
512 tab = self.magics[mtype] = {}
512 tab = self.magics[mtype] = {}
513 cls_tab = class_magics[mtype]
513 cls_tab = class_magics[mtype]
514 for magic_name, meth_name in cls_tab.items():
514 for magic_name, meth_name in cls_tab.items():
515 if isinstance(meth_name, str):
515 if isinstance(meth_name, str):
516 # it's a method name, grab it
516 # it's a method name, grab it
517 tab[magic_name] = getattr(self, meth_name)
517 tab[magic_name] = getattr(self, meth_name)
518 else:
518 else:
519 # it's the real thing
519 # it's the real thing
520 tab[magic_name] = meth_name
520 tab[magic_name] = meth_name
521 # Configurable **needs** to be initiated at the end or the config
521 # Configurable **needs** to be initiated at the end or the config
522 # magics get screwed up.
522 # magics get screwed up.
523 super(Magics, self).__init__(**kwargs)
523 super(Magics, self).__init__(**kwargs)
524
524
525 def arg_err(self,func):
525 def arg_err(self,func):
526 """Print docstring if incorrect arguments were passed"""
526 """Print docstring if incorrect arguments were passed"""
527 print('Error in arguments:')
527 print('Error in arguments:')
528 print(oinspect.getdoc(func))
528 print(oinspect.getdoc(func))
529
529
530 def format_latex(self, strng):
530 def format_latex(self, strng):
531 """Format a string for latex inclusion."""
531 """Format a string for latex inclusion."""
532
532
533 # Characters that need to be escaped for latex:
533 # Characters that need to be escaped for latex:
534 escape_re = re.compile(r'(%|_|\$|#|&)',re.MULTILINE)
534 escape_re = re.compile(r'(%|_|\$|#|&)',re.MULTILINE)
535 # Magic command names as headers:
535 # Magic command names as headers:
536 cmd_name_re = re.compile(r'^(%s.*?):' % ESC_MAGIC,
536 cmd_name_re = re.compile(r'^(%s.*?):' % ESC_MAGIC,
537 re.MULTILINE)
537 re.MULTILINE)
538 # Magic commands
538 # Magic commands
539 cmd_re = re.compile(r'(?P<cmd>%s.+?\b)(?!\}\}:)' % ESC_MAGIC,
539 cmd_re = re.compile(r'(?P<cmd>%s.+?\b)(?!\}\}:)' % ESC_MAGIC,
540 re.MULTILINE)
540 re.MULTILINE)
541 # Paragraph continue
541 # Paragraph continue
542 par_re = re.compile(r'\\$',re.MULTILINE)
542 par_re = re.compile(r'\\$',re.MULTILINE)
543
543
544 # The "\n" symbol
544 # The "\n" symbol
545 newline_re = re.compile(r'\\n')
545 newline_re = re.compile(r'\\n')
546
546
547 # Now build the string for output:
547 # Now build the string for output:
548 #strng = cmd_name_re.sub(r'\n\\texttt{\\textsl{\\large \1}}:',strng)
548 #strng = cmd_name_re.sub(r'\n\\texttt{\\textsl{\\large \1}}:',strng)
549 strng = cmd_name_re.sub(r'\n\\bigskip\n\\texttt{\\textbf{ \1}}:',
549 strng = cmd_name_re.sub(r'\n\\bigskip\n\\texttt{\\textbf{ \1}}:',
550 strng)
550 strng)
551 strng = cmd_re.sub(r'\\texttt{\g<cmd>}',strng)
551 strng = cmd_re.sub(r'\\texttt{\g<cmd>}',strng)
552 strng = par_re.sub(r'\\\\',strng)
552 strng = par_re.sub(r'\\\\',strng)
553 strng = escape_re.sub(r'\\\1',strng)
553 strng = escape_re.sub(r'\\\1',strng)
554 strng = newline_re.sub(r'\\textbackslash{}n',strng)
554 strng = newline_re.sub(r'\\textbackslash{}n',strng)
555 return strng
555 return strng
556
556
557 def parse_options(self, arg_str, opt_str, *long_opts, **kw):
557 def parse_options(self, arg_str, opt_str, *long_opts, **kw):
558 """Parse options passed to an argument string.
558 """Parse options passed to an argument string.
559
559
560 The interface is similar to that of :func:`getopt.getopt`, but it
560 The interface is similar to that of :func:`getopt.getopt`, but it
561 returns a :class:`~IPython.utils.struct.Struct` with the options as keys
561 returns a :class:`~IPython.utils.struct.Struct` with the options as keys
562 and the stripped argument string still as a string.
562 and the stripped argument string still as a string.
563
563
564 arg_str is quoted as a true sys.argv vector by using shlex.split.
564 arg_str is quoted as a true sys.argv vector by using shlex.split.
565 This allows us to easily expand variables, glob files, quote
565 This allows us to easily expand variables, glob files, quote
566 arguments, etc.
566 arguments, etc.
567
567
568 Parameters
568 Parameters
569 ----------
569 ----------
570
570
571 arg_str : str
571 arg_str : str
572 The arguments to parse.
572 The arguments to parse.
573
573
574 opt_str : str
574 opt_str : str
575 The options specification.
575 The options specification.
576
576
577 mode : str, default 'string'
577 mode : str, default 'string'
578 If given as 'list', the argument string is returned as a list (split
578 If given as 'list', the argument string is returned as a list (split
579 on whitespace) instead of a string.
579 on whitespace) instead of a string.
580
580
581 list_all : bool, default False
581 list_all : bool, default False
582 Put all option values in lists. Normally only options
582 Put all option values in lists. Normally only options
583 appearing more than once are put in a list.
583 appearing more than once are put in a list.
584
584
585 posix : bool, default True
585 posix : bool, default True
586 Whether to split the input line in POSIX mode or not, as per the
586 Whether to split the input line in POSIX mode or not, as per the
587 conventions outlined in the :mod:`shlex` module from the standard
587 conventions outlined in the :mod:`shlex` module from the standard
588 library.
588 library.
589 """
589 """
590
590
591 # inject default options at the beginning of the input line
591 # inject default options at the beginning of the input line
592 caller = sys._getframe(1).f_code.co_name
592 caller = sys._getframe(1).f_code.co_name
593 arg_str = '%s %s' % (self.options_table.get(caller,''),arg_str)
593 arg_str = '%s %s' % (self.options_table.get(caller,''),arg_str)
594
594
595 mode = kw.get('mode','string')
595 mode = kw.get('mode','string')
596 if mode not in ['string','list']:
596 if mode not in ['string','list']:
597 raise ValueError('incorrect mode given: %s' % mode)
597 raise ValueError('incorrect mode given: %s' % mode)
598 # Get options
598 # Get options
599 list_all = kw.get('list_all',0)
599 list_all = kw.get('list_all',0)
600 posix = kw.get('posix', os.name == 'posix')
600 posix = kw.get('posix', os.name == 'posix')
601 strict = kw.get('strict', True)
601 strict = kw.get('strict', True)
602
602
603 # Check if we have more than one argument to warrant extra processing:
603 # Check if we have more than one argument to warrant extra processing:
604 odict = {} # Dictionary with options
604 odict = {} # Dictionary with options
605 args = arg_str.split()
605 args = arg_str.split()
606 if len(args) >= 1:
606 if len(args) >= 1:
607 # If the list of inputs only has 0 or 1 thing in it, there's no
607 # If the list of inputs only has 0 or 1 thing in it, there's no
608 # need to look for options
608 # need to look for options
609 argv = arg_split(arg_str, posix, strict)
609 argv = arg_split(arg_str, posix, strict)
610 # Do regular option processing
610 # Do regular option processing
611 try:
611 try:
612 opts,args = getopt(argv, opt_str, long_opts)
612 opts,args = getopt(argv, opt_str, long_opts)
613 except GetoptError as e:
613 except GetoptError as e:
614 raise UsageError('%s ( allowed: "%s" %s)' % (e.msg,opt_str,
614 raise UsageError('%s ( allowed: "%s" %s)' % (e.msg,opt_str,
615 " ".join(long_opts)))
615 " ".join(long_opts)))
616 for o,a in opts:
616 for o,a in opts:
617 if o.startswith('--'):
617 if o.startswith('--'):
618 o = o[2:]
618 o = o[2:]
619 else:
619 else:
620 o = o[1:]
620 o = o[1:]
621 try:
621 try:
622 odict[o].append(a)
622 odict[o].append(a)
623 except AttributeError:
623 except AttributeError:
624 odict[o] = [odict[o],a]
624 odict[o] = [odict[o],a]
625 except KeyError:
625 except KeyError:
626 if list_all:
626 if list_all:
627 odict[o] = [a]
627 odict[o] = [a]
628 else:
628 else:
629 odict[o] = a
629 odict[o] = a
630
630
631 # Prepare opts,args for return
631 # Prepare opts,args for return
632 opts = Struct(odict)
632 opts = Struct(odict)
633 if mode == 'string':
633 if mode == 'string':
634 args = ' '.join(args)
634 args = ' '.join(args)
635
635
636 return opts,args
636 return opts,args
637
637
638 def default_option(self, fn, optstr):
638 def default_option(self, fn, optstr):
639 """Make an entry in the options_table for fn, with value optstr"""
639 """Make an entry in the options_table for fn, with value optstr"""
640
640
641 if fn not in self.lsmagic():
641 if fn not in self.lsmagic():
642 error("%s is not a magic function" % fn)
642 error("%s is not a magic function" % fn)
643 self.options_table[fn] = optstr
643 self.options_table[fn] = optstr
644
644
645
645
646 class MagicAlias(object):
646 class MagicAlias(object):
647 """An alias to another magic function.
647 """An alias to another magic function.
648
648
649 An alias is determined by its magic name and magic kind. Lookup
649 An alias is determined by its magic name and magic kind. Lookup
650 is done at call time, so if the underlying magic changes the alias
650 is done at call time, so if the underlying magic changes the alias
651 will call the new function.
651 will call the new function.
652
652
653 Use the :meth:`MagicsManager.register_alias` method or the
653 Use the :meth:`MagicsManager.register_alias` method or the
654 `%alias_magic` magic function to create and register a new alias.
654 `%alias_magic` magic function to create and register a new alias.
655 """
655 """
656 def __init__(self, shell, magic_name, magic_kind):
656 def __init__(self, shell, magic_name, magic_kind, magic_params=None):
657 self.shell = shell
657 self.shell = shell
658 self.magic_name = magic_name
658 self.magic_name = magic_name
659 self.magic_params = magic_params
659 self.magic_kind = magic_kind
660 self.magic_kind = magic_kind
660
661
661 self.pretty_target = '%s%s' % (magic_escapes[self.magic_kind], self.magic_name)
662 self.pretty_target = '%s%s' % (magic_escapes[self.magic_kind], self.magic_name)
662 self.__doc__ = "Alias for `%s`." % self.pretty_target
663 self.__doc__ = "Alias for `%s`." % self.pretty_target
663
664
664 self._in_call = False
665 self._in_call = False
665
666
666 def __call__(self, *args, **kwargs):
667 def __call__(self, *args, **kwargs):
667 """Call the magic alias."""
668 """Call the magic alias."""
668 fn = self.shell.find_magic(self.magic_name, self.magic_kind)
669 fn = self.shell.find_magic(self.magic_name, self.magic_kind)
669 if fn is None:
670 if fn is None:
670 raise UsageError("Magic `%s` not found." % self.pretty_target)
671 raise UsageError("Magic `%s` not found." % self.pretty_target)
671
672
672 # Protect against infinite recursion.
673 # Protect against infinite recursion.
673 if self._in_call:
674 if self._in_call:
674 raise UsageError("Infinite recursion detected; "
675 raise UsageError("Infinite recursion detected; "
675 "magic aliases cannot call themselves.")
676 "magic aliases cannot call themselves.")
676 self._in_call = True
677 self._in_call = True
677 try:
678 try:
679 if self.magic_params:
680 args_list = list(args)
681 args_list[0] = self.magic_params + " " + args[0]
682 args = tuple(args_list)
678 return fn(*args, **kwargs)
683 return fn(*args, **kwargs)
679 finally:
684 finally:
680 self._in_call = False
685 self._in_call = False
@@ -1,596 +1,612 b''
1 """Implementation of basic magic functions."""
1 """Implementation of basic magic functions."""
2
2
3
3
4 import argparse
4 import argparse
5 import textwrap
5 import textwrap
6 import io
6 import io
7 import sys
7 import sys
8 from pprint import pformat
8 from pprint import pformat
9
9
10 from IPython.core import magic_arguments, page
10 from IPython.core import magic_arguments, page
11 from IPython.core.error import UsageError
11 from IPython.core.error import UsageError
12 from IPython.core.magic import Magics, magics_class, line_magic, magic_escapes
12 from IPython.core.magic import Magics, magics_class, line_magic, magic_escapes
13 from IPython.utils.text import format_screen, dedent, indent
13 from IPython.utils.text import format_screen, dedent, indent
14 from IPython.testing.skipdoctest import skip_doctest
14 from IPython.testing.skipdoctest import skip_doctest
15 from IPython.utils.ipstruct import Struct
15 from IPython.utils.ipstruct import Struct
16 from warnings import warn
16 from warnings import warn
17 from logging import error
17 from logging import error
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 @magic_arguments.magic_arguments()
77 @magic_arguments.magic_arguments()
78 @magic_arguments.argument(
78 @magic_arguments.argument(
79 '-l', '--line', action='store_true',
79 '-l', '--line', action='store_true',
80 help="""Create a line magic alias."""
80 help="""Create a line magic alias."""
81 )
81 )
82 @magic_arguments.argument(
82 @magic_arguments.argument(
83 '-c', '--cell', action='store_true',
83 '-c', '--cell', action='store_true',
84 help="""Create a cell magic alias."""
84 help="""Create a cell magic alias."""
85 )
85 )
86 @magic_arguments.argument(
86 @magic_arguments.argument(
87 'name',
87 'name',
88 help="""Name of the magic to be created."""
88 help="""Name of the magic to be created."""
89 )
89 )
90 @magic_arguments.argument(
90 @magic_arguments.argument(
91 'target',
91 'target',
92 help="""Name of the existing line or cell magic."""
92 help="""Name of the existing line or cell magic."""
93 )
93 )
94 @magic_arguments.argument(
95 '-p', '--params', default=None,
96 help="""Parameters passed to the magic function."""
97 )
94 @line_magic
98 @line_magic
95 def alias_magic(self, line=''):
99 def alias_magic(self, line=''):
96 """Create an alias for an existing line or cell magic.
100 """Create an alias for an existing line or cell magic.
97
101
98 Examples
102 Examples
99 --------
103 --------
100 ::
104 ::
101
105
102 In [1]: %alias_magic t timeit
106 In [1]: %alias_magic t timeit
103 Created `%t` as an alias for `%timeit`.
107 Created `%t` as an alias for `%timeit`.
104 Created `%%t` as an alias for `%%timeit`.
108 Created `%%t` as an alias for `%%timeit`.
105
109
106 In [2]: %t -n1 pass
110 In [2]: %t -n1 pass
107 1 loops, best of 3: 954 ns per loop
111 1 loops, best of 3: 954 ns per loop
108
112
109 In [3]: %%t -n1
113 In [3]: %%t -n1
110 ...: pass
114 ...: pass
111 ...:
115 ...:
112 1 loops, best of 3: 954 ns per loop
116 1 loops, best of 3: 954 ns per loop
113
117
114 In [4]: %alias_magic --cell whereami pwd
118 In [4]: %alias_magic --cell whereami pwd
115 UsageError: Cell magic function `%%pwd` not found.
119 UsageError: Cell magic function `%%pwd` not found.
116 In [5]: %alias_magic --line whereami pwd
120 In [5]: %alias_magic --line whereami pwd
117 Created `%whereami` as an alias for `%pwd`.
121 Created `%whereami` as an alias for `%pwd`.
118
122
119 In [6]: %whereami
123 In [6]: %whereami
120 Out[6]: u'/home/testuser'
124 Out[6]: u'/home/testuser'
125
126 In [7]: %alias_magic h history -p "-l 30" --line
127 Created `%h` as an alias for `%history -l 30`.
121 """
128 """
129
122 args = magic_arguments.parse_argstring(self.alias_magic, line)
130 args = magic_arguments.parse_argstring(self.alias_magic, line)
123 shell = self.shell
131 shell = self.shell
124 mman = self.shell.magics_manager
132 mman = self.shell.magics_manager
125 escs = ''.join(magic_escapes.values())
133 escs = ''.join(magic_escapes.values())
126
134
127 target = args.target.lstrip(escs)
135 target = args.target.lstrip(escs)
128 name = args.name.lstrip(escs)
136 name = args.name.lstrip(escs)
129
137
138 params = args.params
139 if (params and
140 ((params.startswith('"') and params.endswith('"'))
141 or (params.startswith("'") and params.endswith("'")))):
142 params = params[1:-1]
143
130 # Find the requested magics.
144 # Find the requested magics.
131 m_line = shell.find_magic(target, 'line')
145 m_line = shell.find_magic(target, 'line')
132 m_cell = shell.find_magic(target, 'cell')
146 m_cell = shell.find_magic(target, 'cell')
133 if args.line and m_line is None:
147 if args.line and m_line is None:
134 raise UsageError('Line magic function `%s%s` not found.' %
148 raise UsageError('Line magic function `%s%s` not found.' %
135 (magic_escapes['line'], target))
149 (magic_escapes['line'], target))
136 if args.cell and m_cell is None:
150 if args.cell and m_cell is None:
137 raise UsageError('Cell magic function `%s%s` not found.' %
151 raise UsageError('Cell magic function `%s%s` not found.' %
138 (magic_escapes['cell'], target))
152 (magic_escapes['cell'], target))
139
153
140 # If --line and --cell are not specified, default to the ones
154 # If --line and --cell are not specified, default to the ones
141 # that are available.
155 # that are available.
142 if not args.line and not args.cell:
156 if not args.line and not args.cell:
143 if not m_line and not m_cell:
157 if not m_line and not m_cell:
144 raise UsageError(
158 raise UsageError(
145 'No line or cell magic with name `%s` found.' % target
159 'No line or cell magic with name `%s` found.' % target
146 )
160 )
147 args.line = bool(m_line)
161 args.line = bool(m_line)
148 args.cell = bool(m_cell)
162 args.cell = bool(m_cell)
149
163
164 params_str = "" if params is None else " " + params
165
150 if args.line:
166 if args.line:
151 mman.register_alias(name, target, 'line')
167 mman.register_alias(name, target, 'line', params)
152 print('Created `%s%s` as an alias for `%s%s`.' % (
168 print('Created `%s%s` as an alias for `%s%s%s`.' % (
153 magic_escapes['line'], name,
169 magic_escapes['line'], name,
154 magic_escapes['line'], target))
170 magic_escapes['line'], target, params_str))
155
171
156 if args.cell:
172 if args.cell:
157 mman.register_alias(name, target, 'cell')
173 mman.register_alias(name, target, 'cell', params)
158 print('Created `%s%s` as an alias for `%s%s`.' % (
174 print('Created `%s%s` as an alias for `%s%s%s`.' % (
159 magic_escapes['cell'], name,
175 magic_escapes['cell'], name,
160 magic_escapes['cell'], target))
176 magic_escapes['cell'], target, params_str))
161
177
162 @line_magic
178 @line_magic
163 def lsmagic(self, parameter_s=''):
179 def lsmagic(self, parameter_s=''):
164 """List currently available magic functions."""
180 """List currently available magic functions."""
165 return MagicsDisplay(self.shell.magics_manager, ignore=[self.pip])
181 return MagicsDisplay(self.shell.magics_manager, ignore=[self.pip])
166
182
167 def _magic_docs(self, brief=False, rest=False):
183 def _magic_docs(self, brief=False, rest=False):
168 """Return docstrings from magic functions."""
184 """Return docstrings from magic functions."""
169 mman = self.shell.magics_manager
185 mman = self.shell.magics_manager
170 docs = mman.lsmagic_docs(brief, missing='No documentation')
186 docs = mman.lsmagic_docs(brief, missing='No documentation')
171
187
172 if rest:
188 if rest:
173 format_string = '**%s%s**::\n\n%s\n\n'
189 format_string = '**%s%s**::\n\n%s\n\n'
174 else:
190 else:
175 format_string = '%s%s:\n%s\n'
191 format_string = '%s%s:\n%s\n'
176
192
177 return ''.join(
193 return ''.join(
178 [format_string % (magic_escapes['line'], fname,
194 [format_string % (magic_escapes['line'], fname,
179 indent(dedent(fndoc)))
195 indent(dedent(fndoc)))
180 for fname, fndoc in sorted(docs['line'].items())]
196 for fname, fndoc in sorted(docs['line'].items())]
181 +
197 +
182 [format_string % (magic_escapes['cell'], fname,
198 [format_string % (magic_escapes['cell'], fname,
183 indent(dedent(fndoc)))
199 indent(dedent(fndoc)))
184 for fname, fndoc in sorted(docs['cell'].items())]
200 for fname, fndoc in sorted(docs['cell'].items())]
185 )
201 )
186
202
187 @line_magic
203 @line_magic
188 def magic(self, parameter_s=''):
204 def magic(self, parameter_s=''):
189 """Print information about the magic function system.
205 """Print information about the magic function system.
190
206
191 Supported formats: -latex, -brief, -rest
207 Supported formats: -latex, -brief, -rest
192 """
208 """
193
209
194 mode = ''
210 mode = ''
195 try:
211 try:
196 mode = parameter_s.split()[0][1:]
212 mode = parameter_s.split()[0][1:]
197 except IndexError:
213 except IndexError:
198 pass
214 pass
199
215
200 brief = (mode == 'brief')
216 brief = (mode == 'brief')
201 rest = (mode == 'rest')
217 rest = (mode == 'rest')
202 magic_docs = self._magic_docs(brief, rest)
218 magic_docs = self._magic_docs(brief, rest)
203
219
204 if mode == 'latex':
220 if mode == 'latex':
205 print(self.format_latex(magic_docs))
221 print(self.format_latex(magic_docs))
206 return
222 return
207 else:
223 else:
208 magic_docs = format_screen(magic_docs)
224 magic_docs = format_screen(magic_docs)
209
225
210 out = ["""
226 out = ["""
211 IPython's 'magic' functions
227 IPython's 'magic' functions
212 ===========================
228 ===========================
213
229
214 The magic function system provides a series of functions which allow you to
230 The magic function system provides a series of functions which allow you to
215 control the behavior of IPython itself, plus a lot of system-type
231 control the behavior of IPython itself, plus a lot of system-type
216 features. There are two kinds of magics, line-oriented and cell-oriented.
232 features. There are two kinds of magics, line-oriented and cell-oriented.
217
233
218 Line magics are prefixed with the % character and work much like OS
234 Line magics are prefixed with the % character and work much like OS
219 command-line calls: they get as an argument the rest of the line, where
235 command-line calls: they get as an argument the rest of the line, where
220 arguments are passed without parentheses or quotes. For example, this will
236 arguments are passed without parentheses or quotes. For example, this will
221 time the given statement::
237 time the given statement::
222
238
223 %timeit range(1000)
239 %timeit range(1000)
224
240
225 Cell magics are prefixed with a double %%, and they are functions that get as
241 Cell magics are prefixed with a double %%, and they are functions that get as
226 an argument not only the rest of the line, but also the lines below it in a
242 an argument not only the rest of the line, but also the lines below it in a
227 separate argument. These magics are called with two arguments: the rest of the
243 separate argument. These magics are called with two arguments: the rest of the
228 call line and the body of the cell, consisting of the lines below the first.
244 call line and the body of the cell, consisting of the lines below the first.
229 For example::
245 For example::
230
246
231 %%timeit x = numpy.random.randn((100, 100))
247 %%timeit x = numpy.random.randn((100, 100))
232 numpy.linalg.svd(x)
248 numpy.linalg.svd(x)
233
249
234 will time the execution of the numpy svd routine, running the assignment of x
250 will time the execution of the numpy svd routine, running the assignment of x
235 as part of the setup phase, which is not timed.
251 as part of the setup phase, which is not timed.
236
252
237 In a line-oriented client (the terminal or Qt console IPython), starting a new
253 In a line-oriented client (the terminal or Qt console IPython), starting a new
238 input with %% will automatically enter cell mode, and IPython will continue
254 input with %% will automatically enter cell mode, and IPython will continue
239 reading input until a blank line is given. In the notebook, simply type the
255 reading input until a blank line is given. In the notebook, simply type the
240 whole cell as one entity, but keep in mind that the %% escape can only be at
256 whole cell as one entity, but keep in mind that the %% escape can only be at
241 the very start of the cell.
257 the very start of the cell.
242
258
243 NOTE: If you have 'automagic' enabled (via the command line option or with the
259 NOTE: If you have 'automagic' enabled (via the command line option or with the
244 %automagic function), you don't need to type in the % explicitly for line
260 %automagic function), you don't need to type in the % explicitly for line
245 magics; cell magics always require an explicit '%%' escape. By default,
261 magics; cell magics always require an explicit '%%' escape. By default,
246 IPython ships with automagic on, so you should only rarely need the % escape.
262 IPython ships with automagic on, so you should only rarely need the % escape.
247
263
248 Example: typing '%cd mydir' (without the quotes) changes your working directory
264 Example: typing '%cd mydir' (without the quotes) changes your working directory
249 to 'mydir', if it exists.
265 to 'mydir', if it exists.
250
266
251 For a list of the available magic functions, use %lsmagic. For a description
267 For a list of the available magic functions, use %lsmagic. For a description
252 of any of them, type %magic_name?, e.g. '%cd?'.
268 of any of them, type %magic_name?, e.g. '%cd?'.
253
269
254 Currently the magic system has the following functions:""",
270 Currently the magic system has the following functions:""",
255 magic_docs,
271 magic_docs,
256 "Summary of magic functions (from %slsmagic):" % magic_escapes['line'],
272 "Summary of magic functions (from %slsmagic):" % magic_escapes['line'],
257 str(self.lsmagic()),
273 str(self.lsmagic()),
258 ]
274 ]
259 page.page('\n'.join(out))
275 page.page('\n'.join(out))
260
276
261
277
262 @line_magic
278 @line_magic
263 def page(self, parameter_s=''):
279 def page(self, parameter_s=''):
264 """Pretty print the object and display it through a pager.
280 """Pretty print the object and display it through a pager.
265
281
266 %page [options] OBJECT
282 %page [options] OBJECT
267
283
268 If no object is given, use _ (last output).
284 If no object is given, use _ (last output).
269
285
270 Options:
286 Options:
271
287
272 -r: page str(object), don't pretty-print it."""
288 -r: page str(object), don't pretty-print it."""
273
289
274 # After a function contributed by Olivier Aubert, slightly modified.
290 # After a function contributed by Olivier Aubert, slightly modified.
275
291
276 # Process options/args
292 # Process options/args
277 opts, args = self.parse_options(parameter_s, 'r')
293 opts, args = self.parse_options(parameter_s, 'r')
278 raw = 'r' in opts
294 raw = 'r' in opts
279
295
280 oname = args and args or '_'
296 oname = args and args or '_'
281 info = self.shell._ofind(oname)
297 info = self.shell._ofind(oname)
282 if info['found']:
298 if info['found']:
283 txt = (raw and str or pformat)( info['obj'] )
299 txt = (raw and str or pformat)( info['obj'] )
284 page.page(txt)
300 page.page(txt)
285 else:
301 else:
286 print('Object `%s` not found' % oname)
302 print('Object `%s` not found' % oname)
287
303
288 @line_magic
304 @line_magic
289 def profile(self, parameter_s=''):
305 def profile(self, parameter_s=''):
290 """Print your currently active IPython profile.
306 """Print your currently active IPython profile.
291
307
292 See Also
308 See Also
293 --------
309 --------
294 prun : run code using the Python profiler
310 prun : run code using the Python profiler
295 (:meth:`~IPython.core.magics.execution.ExecutionMagics.prun`)
311 (:meth:`~IPython.core.magics.execution.ExecutionMagics.prun`)
296 """
312 """
297 raise UsageError("The `%profile` magic has been deprecated since IPython 2.0. "
313 raise UsageError("The `%profile` magic has been deprecated since IPython 2.0. "
298 "and removed in IPython 6.0. Please use the value of `get_ipython().profile` instead "
314 "and removed in IPython 6.0. Please use the value of `get_ipython().profile` instead "
299 "to see current profile in use. Perhaps you meant to use `%prun` to profile code?")
315 "to see current profile in use. Perhaps you meant to use `%prun` to profile code?")
300
316
301 @line_magic
317 @line_magic
302 def pprint(self, parameter_s=''):
318 def pprint(self, parameter_s=''):
303 """Toggle pretty printing on/off."""
319 """Toggle pretty printing on/off."""
304 ptformatter = self.shell.display_formatter.formatters['text/plain']
320 ptformatter = self.shell.display_formatter.formatters['text/plain']
305 ptformatter.pprint = bool(1 - ptformatter.pprint)
321 ptformatter.pprint = bool(1 - ptformatter.pprint)
306 print('Pretty printing has been turned',
322 print('Pretty printing has been turned',
307 ['OFF','ON'][ptformatter.pprint])
323 ['OFF','ON'][ptformatter.pprint])
308
324
309 @line_magic
325 @line_magic
310 def colors(self, parameter_s=''):
326 def colors(self, parameter_s=''):
311 """Switch color scheme for prompts, info system and exception handlers.
327 """Switch color scheme for prompts, info system and exception handlers.
312
328
313 Currently implemented schemes: NoColor, Linux, LightBG.
329 Currently implemented schemes: NoColor, Linux, LightBG.
314
330
315 Color scheme names are not case-sensitive.
331 Color scheme names are not case-sensitive.
316
332
317 Examples
333 Examples
318 --------
334 --------
319 To get a plain black and white terminal::
335 To get a plain black and white terminal::
320
336
321 %colors nocolor
337 %colors nocolor
322 """
338 """
323 def color_switch_err(name):
339 def color_switch_err(name):
324 warn('Error changing %s color schemes.\n%s' %
340 warn('Error changing %s color schemes.\n%s' %
325 (name, sys.exc_info()[1]), stacklevel=2)
341 (name, sys.exc_info()[1]), stacklevel=2)
326
342
327
343
328 new_scheme = parameter_s.strip()
344 new_scheme = parameter_s.strip()
329 if not new_scheme:
345 if not new_scheme:
330 raise UsageError(
346 raise UsageError(
331 "%colors: you must specify a color scheme. See '%colors?'")
347 "%colors: you must specify a color scheme. See '%colors?'")
332 # local shortcut
348 # local shortcut
333 shell = self.shell
349 shell = self.shell
334
350
335 # Set shell colour scheme
351 # Set shell colour scheme
336 try:
352 try:
337 shell.colors = new_scheme
353 shell.colors = new_scheme
338 shell.refresh_style()
354 shell.refresh_style()
339 except:
355 except:
340 color_switch_err('shell')
356 color_switch_err('shell')
341
357
342 # Set exception colors
358 # Set exception colors
343 try:
359 try:
344 shell.InteractiveTB.set_colors(scheme = new_scheme)
360 shell.InteractiveTB.set_colors(scheme = new_scheme)
345 shell.SyntaxTB.set_colors(scheme = new_scheme)
361 shell.SyntaxTB.set_colors(scheme = new_scheme)
346 except:
362 except:
347 color_switch_err('exception')
363 color_switch_err('exception')
348
364
349 # Set info (for 'object?') colors
365 # Set info (for 'object?') colors
350 if shell.color_info:
366 if shell.color_info:
351 try:
367 try:
352 shell.inspector.set_active_scheme(new_scheme)
368 shell.inspector.set_active_scheme(new_scheme)
353 except:
369 except:
354 color_switch_err('object inspector')
370 color_switch_err('object inspector')
355 else:
371 else:
356 shell.inspector.set_active_scheme('NoColor')
372 shell.inspector.set_active_scheme('NoColor')
357
373
358 @line_magic
374 @line_magic
359 def xmode(self, parameter_s=''):
375 def xmode(self, parameter_s=''):
360 """Switch modes for the exception handlers.
376 """Switch modes for the exception handlers.
361
377
362 Valid modes: Plain, Context and Verbose.
378 Valid modes: Plain, Context and Verbose.
363
379
364 If called without arguments, acts as a toggle."""
380 If called without arguments, acts as a toggle."""
365
381
366 def xmode_switch_err(name):
382 def xmode_switch_err(name):
367 warn('Error changing %s exception modes.\n%s' %
383 warn('Error changing %s exception modes.\n%s' %
368 (name,sys.exc_info()[1]))
384 (name,sys.exc_info()[1]))
369
385
370 shell = self.shell
386 shell = self.shell
371 new_mode = parameter_s.strip().capitalize()
387 new_mode = parameter_s.strip().capitalize()
372 try:
388 try:
373 shell.InteractiveTB.set_mode(mode=new_mode)
389 shell.InteractiveTB.set_mode(mode=new_mode)
374 print('Exception reporting mode:',shell.InteractiveTB.mode)
390 print('Exception reporting mode:',shell.InteractiveTB.mode)
375 except:
391 except:
376 xmode_switch_err('user')
392 xmode_switch_err('user')
377
393
378 @line_magic
394 @line_magic
379 def pip(self, args=''):
395 def pip(self, args=''):
380 """
396 """
381 Intercept usage of ``pip`` in IPython and direct user to run command outside of IPython.
397 Intercept usage of ``pip`` in IPython and direct user to run command outside of IPython.
382 """
398 """
383 print(textwrap.dedent('''
399 print(textwrap.dedent('''
384 The following command must be run outside of the IPython shell:
400 The following command must be run outside of the IPython shell:
385
401
386 $ pip {args}
402 $ pip {args}
387
403
388 The Python package manager (pip) can only be used from outside of IPython.
404 The Python package manager (pip) can only be used from outside of IPython.
389 Please reissue the `pip` command in a separate terminal or command prompt.
405 Please reissue the `pip` command in a separate terminal or command prompt.
390
406
391 See the Python documentation for more informations on how to install packages:
407 See the Python documentation for more informations on how to install packages:
392
408
393 https://docs.python.org/3/installing/'''.format(args=args)))
409 https://docs.python.org/3/installing/'''.format(args=args)))
394
410
395 @line_magic
411 @line_magic
396 def quickref(self, arg):
412 def quickref(self, arg):
397 """ Show a quick reference sheet """
413 """ Show a quick reference sheet """
398 from IPython.core.usage import quick_reference
414 from IPython.core.usage import quick_reference
399 qr = quick_reference + self._magic_docs(brief=True)
415 qr = quick_reference + self._magic_docs(brief=True)
400 page.page(qr)
416 page.page(qr)
401
417
402 @line_magic
418 @line_magic
403 def doctest_mode(self, parameter_s=''):
419 def doctest_mode(self, parameter_s=''):
404 """Toggle doctest mode on and off.
420 """Toggle doctest mode on and off.
405
421
406 This mode is intended to make IPython behave as much as possible like a
422 This mode is intended to make IPython behave as much as possible like a
407 plain Python shell, from the perspective of how its prompts, exceptions
423 plain Python shell, from the perspective of how its prompts, exceptions
408 and output look. This makes it easy to copy and paste parts of a
424 and output look. This makes it easy to copy and paste parts of a
409 session into doctests. It does so by:
425 session into doctests. It does so by:
410
426
411 - Changing the prompts to the classic ``>>>`` ones.
427 - Changing the prompts to the classic ``>>>`` ones.
412 - Changing the exception reporting mode to 'Plain'.
428 - Changing the exception reporting mode to 'Plain'.
413 - Disabling pretty-printing of output.
429 - Disabling pretty-printing of output.
414
430
415 Note that IPython also supports the pasting of code snippets that have
431 Note that IPython also supports the pasting of code snippets that have
416 leading '>>>' and '...' prompts in them. This means that you can paste
432 leading '>>>' and '...' prompts in them. This means that you can paste
417 doctests from files or docstrings (even if they have leading
433 doctests from files or docstrings (even if they have leading
418 whitespace), and the code will execute correctly. You can then use
434 whitespace), and the code will execute correctly. You can then use
419 '%history -t' to see the translated history; this will give you the
435 '%history -t' to see the translated history; this will give you the
420 input after removal of all the leading prompts and whitespace, which
436 input after removal of all the leading prompts and whitespace, which
421 can be pasted back into an editor.
437 can be pasted back into an editor.
422
438
423 With these features, you can switch into this mode easily whenever you
439 With these features, you can switch into this mode easily whenever you
424 need to do testing and changes to doctests, without having to leave
440 need to do testing and changes to doctests, without having to leave
425 your existing IPython session.
441 your existing IPython session.
426 """
442 """
427
443
428 # Shorthands
444 # Shorthands
429 shell = self.shell
445 shell = self.shell
430 meta = shell.meta
446 meta = shell.meta
431 disp_formatter = self.shell.display_formatter
447 disp_formatter = self.shell.display_formatter
432 ptformatter = disp_formatter.formatters['text/plain']
448 ptformatter = disp_formatter.formatters['text/plain']
433 # dstore is a data store kept in the instance metadata bag to track any
449 # dstore is a data store kept in the instance metadata bag to track any
434 # changes we make, so we can undo them later.
450 # changes we make, so we can undo them later.
435 dstore = meta.setdefault('doctest_mode',Struct())
451 dstore = meta.setdefault('doctest_mode',Struct())
436 save_dstore = dstore.setdefault
452 save_dstore = dstore.setdefault
437
453
438 # save a few values we'll need to recover later
454 # save a few values we'll need to recover later
439 mode = save_dstore('mode',False)
455 mode = save_dstore('mode',False)
440 save_dstore('rc_pprint',ptformatter.pprint)
456 save_dstore('rc_pprint',ptformatter.pprint)
441 save_dstore('xmode',shell.InteractiveTB.mode)
457 save_dstore('xmode',shell.InteractiveTB.mode)
442 save_dstore('rc_separate_out',shell.separate_out)
458 save_dstore('rc_separate_out',shell.separate_out)
443 save_dstore('rc_separate_out2',shell.separate_out2)
459 save_dstore('rc_separate_out2',shell.separate_out2)
444 save_dstore('rc_separate_in',shell.separate_in)
460 save_dstore('rc_separate_in',shell.separate_in)
445 save_dstore('rc_active_types',disp_formatter.active_types)
461 save_dstore('rc_active_types',disp_formatter.active_types)
446
462
447 if not mode:
463 if not mode:
448 # turn on
464 # turn on
449
465
450 # Prompt separators like plain python
466 # Prompt separators like plain python
451 shell.separate_in = ''
467 shell.separate_in = ''
452 shell.separate_out = ''
468 shell.separate_out = ''
453 shell.separate_out2 = ''
469 shell.separate_out2 = ''
454
470
455
471
456 ptformatter.pprint = False
472 ptformatter.pprint = False
457 disp_formatter.active_types = ['text/plain']
473 disp_formatter.active_types = ['text/plain']
458
474
459 shell.magic('xmode Plain')
475 shell.magic('xmode Plain')
460 else:
476 else:
461 # turn off
477 # turn off
462 shell.separate_in = dstore.rc_separate_in
478 shell.separate_in = dstore.rc_separate_in
463
479
464 shell.separate_out = dstore.rc_separate_out
480 shell.separate_out = dstore.rc_separate_out
465 shell.separate_out2 = dstore.rc_separate_out2
481 shell.separate_out2 = dstore.rc_separate_out2
466
482
467 ptformatter.pprint = dstore.rc_pprint
483 ptformatter.pprint = dstore.rc_pprint
468 disp_formatter.active_types = dstore.rc_active_types
484 disp_formatter.active_types = dstore.rc_active_types
469
485
470 shell.magic('xmode ' + dstore.xmode)
486 shell.magic('xmode ' + dstore.xmode)
471
487
472 # mode here is the state before we switch; switch_doctest_mode takes
488 # mode here is the state before we switch; switch_doctest_mode takes
473 # the mode we're switching to.
489 # the mode we're switching to.
474 shell.switch_doctest_mode(not mode)
490 shell.switch_doctest_mode(not mode)
475
491
476 # Store new mode and inform
492 # Store new mode and inform
477 dstore.mode = bool(not mode)
493 dstore.mode = bool(not mode)
478 mode_label = ['OFF','ON'][dstore.mode]
494 mode_label = ['OFF','ON'][dstore.mode]
479 print('Doctest mode is:', mode_label)
495 print('Doctest mode is:', mode_label)
480
496
481 @line_magic
497 @line_magic
482 def gui(self, parameter_s=''):
498 def gui(self, parameter_s=''):
483 """Enable or disable IPython GUI event loop integration.
499 """Enable or disable IPython GUI event loop integration.
484
500
485 %gui [GUINAME]
501 %gui [GUINAME]
486
502
487 This magic replaces IPython's threaded shells that were activated
503 This magic replaces IPython's threaded shells that were activated
488 using the (pylab/wthread/etc.) command line flags. GUI toolkits
504 using the (pylab/wthread/etc.) command line flags. GUI toolkits
489 can now be enabled at runtime and keyboard
505 can now be enabled at runtime and keyboard
490 interrupts should work without any problems. The following toolkits
506 interrupts should work without any problems. The following toolkits
491 are supported: wxPython, PyQt4, PyGTK, Tk and Cocoa (OSX)::
507 are supported: wxPython, PyQt4, PyGTK, Tk and Cocoa (OSX)::
492
508
493 %gui wx # enable wxPython event loop integration
509 %gui wx # enable wxPython event loop integration
494 %gui qt4|qt # enable PyQt4 event loop integration
510 %gui qt4|qt # enable PyQt4 event loop integration
495 %gui qt5 # enable PyQt5 event loop integration
511 %gui qt5 # enable PyQt5 event loop integration
496 %gui gtk # enable PyGTK event loop integration
512 %gui gtk # enable PyGTK event loop integration
497 %gui gtk3 # enable Gtk3 event loop integration
513 %gui gtk3 # enable Gtk3 event loop integration
498 %gui tk # enable Tk event loop integration
514 %gui tk # enable Tk event loop integration
499 %gui osx # enable Cocoa event loop integration
515 %gui osx # enable Cocoa event loop integration
500 # (requires %matplotlib 1.1)
516 # (requires %matplotlib 1.1)
501 %gui # disable all event loop integration
517 %gui # disable all event loop integration
502
518
503 WARNING: after any of these has been called you can simply create
519 WARNING: after any of these has been called you can simply create
504 an application object, but DO NOT start the event loop yourself, as
520 an application object, but DO NOT start the event loop yourself, as
505 we have already handled that.
521 we have already handled that.
506 """
522 """
507 opts, arg = self.parse_options(parameter_s, '')
523 opts, arg = self.parse_options(parameter_s, '')
508 if arg=='': arg = None
524 if arg=='': arg = None
509 try:
525 try:
510 return self.shell.enable_gui(arg)
526 return self.shell.enable_gui(arg)
511 except Exception as e:
527 except Exception as e:
512 # print simple error message, rather than traceback if we can't
528 # print simple error message, rather than traceback if we can't
513 # hook up the GUI
529 # hook up the GUI
514 error(str(e))
530 error(str(e))
515
531
516 @skip_doctest
532 @skip_doctest
517 @line_magic
533 @line_magic
518 def precision(self, s=''):
534 def precision(self, s=''):
519 """Set floating point precision for pretty printing.
535 """Set floating point precision for pretty printing.
520
536
521 Can set either integer precision or a format string.
537 Can set either integer precision or a format string.
522
538
523 If numpy has been imported and precision is an int,
539 If numpy has been imported and precision is an int,
524 numpy display precision will also be set, via ``numpy.set_printoptions``.
540 numpy display precision will also be set, via ``numpy.set_printoptions``.
525
541
526 If no argument is given, defaults will be restored.
542 If no argument is given, defaults will be restored.
527
543
528 Examples
544 Examples
529 --------
545 --------
530 ::
546 ::
531
547
532 In [1]: from math import pi
548 In [1]: from math import pi
533
549
534 In [2]: %precision 3
550 In [2]: %precision 3
535 Out[2]: u'%.3f'
551 Out[2]: u'%.3f'
536
552
537 In [3]: pi
553 In [3]: pi
538 Out[3]: 3.142
554 Out[3]: 3.142
539
555
540 In [4]: %precision %i
556 In [4]: %precision %i
541 Out[4]: u'%i'
557 Out[4]: u'%i'
542
558
543 In [5]: pi
559 In [5]: pi
544 Out[5]: 3
560 Out[5]: 3
545
561
546 In [6]: %precision %e
562 In [6]: %precision %e
547 Out[6]: u'%e'
563 Out[6]: u'%e'
548
564
549 In [7]: pi**10
565 In [7]: pi**10
550 Out[7]: 9.364805e+04
566 Out[7]: 9.364805e+04
551
567
552 In [8]: %precision
568 In [8]: %precision
553 Out[8]: u'%r'
569 Out[8]: u'%r'
554
570
555 In [9]: pi**10
571 In [9]: pi**10
556 Out[9]: 93648.047476082982
572 Out[9]: 93648.047476082982
557 """
573 """
558 ptformatter = self.shell.display_formatter.formatters['text/plain']
574 ptformatter = self.shell.display_formatter.formatters['text/plain']
559 ptformatter.float_precision = s
575 ptformatter.float_precision = s
560 return ptformatter.float_format
576 return ptformatter.float_format
561
577
562 @magic_arguments.magic_arguments()
578 @magic_arguments.magic_arguments()
563 @magic_arguments.argument(
579 @magic_arguments.argument(
564 '-e', '--export', action='store_true', default=False,
580 '-e', '--export', action='store_true', default=False,
565 help=argparse.SUPPRESS
581 help=argparse.SUPPRESS
566 )
582 )
567 @magic_arguments.argument(
583 @magic_arguments.argument(
568 'filename', type=str,
584 'filename', type=str,
569 help='Notebook name or filename'
585 help='Notebook name or filename'
570 )
586 )
571 @line_magic
587 @line_magic
572 def notebook(self, s):
588 def notebook(self, s):
573 """Export and convert IPython notebooks.
589 """Export and convert IPython notebooks.
574
590
575 This function can export the current IPython history to a notebook file.
591 This function can export the current IPython history to a notebook file.
576 For example, to export the history to "foo.ipynb" do "%notebook foo.ipynb".
592 For example, to export the history to "foo.ipynb" do "%notebook foo.ipynb".
577
593
578 The -e or --export flag is deprecated in IPython 5.2, and will be
594 The -e or --export flag is deprecated in IPython 5.2, and will be
579 removed in the future.
595 removed in the future.
580 """
596 """
581 args = magic_arguments.parse_argstring(self.notebook, s)
597 args = magic_arguments.parse_argstring(self.notebook, s)
582
598
583 from nbformat import write, v4
599 from nbformat import write, v4
584
600
585 cells = []
601 cells = []
586 hist = list(self.shell.history_manager.get_range())
602 hist = list(self.shell.history_manager.get_range())
587 if(len(hist)<=1):
603 if(len(hist)<=1):
588 raise ValueError('History is empty, cannot export')
604 raise ValueError('History is empty, cannot export')
589 for session, execution_count, source in hist[:-1]:
605 for session, execution_count, source in hist[:-1]:
590 cells.append(v4.new_code_cell(
606 cells.append(v4.new_code_cell(
591 execution_count=execution_count,
607 execution_count=execution_count,
592 source=source
608 source=source
593 ))
609 ))
594 nb = v4.new_notebook(cells=cells)
610 nb = v4.new_notebook(cells=cells)
595 with io.open(args.filename, 'w', encoding='utf-8') as f:
611 with io.open(args.filename, 'w', encoding='utf-8') as f:
596 write(nb, f, version=4)
612 write(nb, f, version=4)
@@ -1,979 +1,987 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Tests for various magic functions.
2 """Tests for various magic functions.
3
3
4 Needs to be run by nose (to make ipython session available).
4 Needs to be run by nose (to make ipython session available).
5 """
5 """
6
6
7 import io
7 import io
8 import os
8 import os
9 import re
9 import sys
10 import sys
10 import warnings
11 import warnings
11 from unittest import TestCase
12 from unittest import TestCase
12 from importlib import invalidate_caches
13 from importlib import invalidate_caches
13 from io import StringIO
14 from io import StringIO
14
15
15 import nose.tools as nt
16 import nose.tools as nt
16
17
18 import shlex
19
17 from IPython import get_ipython
20 from IPython import get_ipython
18 from IPython.core import magic
21 from IPython.core import magic
19 from IPython.core.error import UsageError
22 from IPython.core.error import UsageError
20 from IPython.core.magic import (Magics, magics_class, line_magic,
23 from IPython.core.magic import (Magics, magics_class, line_magic,
21 cell_magic,
24 cell_magic,
22 register_line_magic, register_cell_magic)
25 register_line_magic, register_cell_magic)
23 from IPython.core.magics import execution, script, code
26 from IPython.core.magics import execution, script, code
24 from IPython.testing import decorators as dec
27 from IPython.testing import decorators as dec
25 from IPython.testing import tools as tt
28 from IPython.testing import tools as tt
26 from IPython.utils import py3compat
29 from IPython.utils import py3compat
27 from IPython.utils.io import capture_output
30 from IPython.utils.io import capture_output
28 from IPython.utils.tempdir import TemporaryDirectory
31 from IPython.utils.tempdir import TemporaryDirectory
29 from IPython.utils.process import find_cmd
32 from IPython.utils.process import find_cmd
30
33
31
34
32
35
33 _ip = get_ipython()
36 _ip = get_ipython()
34
37
35 @magic.magics_class
38 @magic.magics_class
36 class DummyMagics(magic.Magics): pass
39 class DummyMagics(magic.Magics): pass
37
40
38 def test_extract_code_ranges():
41 def test_extract_code_ranges():
39 instr = "1 3 5-6 7-9 10:15 17: :10 10- -13 :"
42 instr = "1 3 5-6 7-9 10:15 17: :10 10- -13 :"
40 expected = [(0, 1),
43 expected = [(0, 1),
41 (2, 3),
44 (2, 3),
42 (4, 6),
45 (4, 6),
43 (6, 9),
46 (6, 9),
44 (9, 14),
47 (9, 14),
45 (16, None),
48 (16, None),
46 (None, 9),
49 (None, 9),
47 (9, None),
50 (9, None),
48 (None, 13),
51 (None, 13),
49 (None, None)]
52 (None, None)]
50 actual = list(code.extract_code_ranges(instr))
53 actual = list(code.extract_code_ranges(instr))
51 nt.assert_equal(actual, expected)
54 nt.assert_equal(actual, expected)
52
55
53 def test_extract_symbols():
56 def test_extract_symbols():
54 source = """import foo\na = 10\ndef b():\n return 42\n\n\nclass A: pass\n\n\n"""
57 source = """import foo\na = 10\ndef b():\n return 42\n\n\nclass A: pass\n\n\n"""
55 symbols_args = ["a", "b", "A", "A,b", "A,a", "z"]
58 symbols_args = ["a", "b", "A", "A,b", "A,a", "z"]
56 expected = [([], ['a']),
59 expected = [([], ['a']),
57 (["def b():\n return 42\n"], []),
60 (["def b():\n return 42\n"], []),
58 (["class A: pass\n"], []),
61 (["class A: pass\n"], []),
59 (["class A: pass\n", "def b():\n return 42\n"], []),
62 (["class A: pass\n", "def b():\n return 42\n"], []),
60 (["class A: pass\n"], ['a']),
63 (["class A: pass\n"], ['a']),
61 ([], ['z'])]
64 ([], ['z'])]
62 for symbols, exp in zip(symbols_args, expected):
65 for symbols, exp in zip(symbols_args, expected):
63 nt.assert_equal(code.extract_symbols(source, symbols), exp)
66 nt.assert_equal(code.extract_symbols(source, symbols), exp)
64
67
65
68
66 def test_extract_symbols_raises_exception_with_non_python_code():
69 def test_extract_symbols_raises_exception_with_non_python_code():
67 source = ("=begin A Ruby program :)=end\n"
70 source = ("=begin A Ruby program :)=end\n"
68 "def hello\n"
71 "def hello\n"
69 "puts 'Hello world'\n"
72 "puts 'Hello world'\n"
70 "end")
73 "end")
71 with nt.assert_raises(SyntaxError):
74 with nt.assert_raises(SyntaxError):
72 code.extract_symbols(source, "hello")
75 code.extract_symbols(source, "hello")
73
76
74 def test_config():
77 def test_config():
75 """ test that config magic does not raise
78 """ test that config magic does not raise
76 can happen if Configurable init is moved too early into
79 can happen if Configurable init is moved too early into
77 Magics.__init__ as then a Config object will be registerd as a
80 Magics.__init__ as then a Config object will be registerd as a
78 magic.
81 magic.
79 """
82 """
80 ## should not raise.
83 ## should not raise.
81 _ip.magic('config')
84 _ip.magic('config')
82
85
83 def test_rehashx():
86 def test_rehashx():
84 # clear up everything
87 # clear up everything
85 _ip.alias_manager.clear_aliases()
88 _ip.alias_manager.clear_aliases()
86 del _ip.db['syscmdlist']
89 del _ip.db['syscmdlist']
87
90
88 _ip.magic('rehashx')
91 _ip.magic('rehashx')
89 # Practically ALL ipython development systems will have more than 10 aliases
92 # Practically ALL ipython development systems will have more than 10 aliases
90
93
91 nt.assert_true(len(_ip.alias_manager.aliases) > 10)
94 nt.assert_true(len(_ip.alias_manager.aliases) > 10)
92 for name, cmd in _ip.alias_manager.aliases:
95 for name, cmd in _ip.alias_manager.aliases:
93 # we must strip dots from alias names
96 # we must strip dots from alias names
94 nt.assert_not_in('.', name)
97 nt.assert_not_in('.', name)
95
98
96 # rehashx must fill up syscmdlist
99 # rehashx must fill up syscmdlist
97 scoms = _ip.db['syscmdlist']
100 scoms = _ip.db['syscmdlist']
98 nt.assert_true(len(scoms) > 10)
101 nt.assert_true(len(scoms) > 10)
99
102
100
103
101 def test_magic_parse_options():
104 def test_magic_parse_options():
102 """Test that we don't mangle paths when parsing magic options."""
105 """Test that we don't mangle paths when parsing magic options."""
103 ip = get_ipython()
106 ip = get_ipython()
104 path = 'c:\\x'
107 path = 'c:\\x'
105 m = DummyMagics(ip)
108 m = DummyMagics(ip)
106 opts = m.parse_options('-f %s' % path,'f:')[0]
109 opts = m.parse_options('-f %s' % path,'f:')[0]
107 # argv splitting is os-dependent
110 # argv splitting is os-dependent
108 if os.name == 'posix':
111 if os.name == 'posix':
109 expected = 'c:x'
112 expected = 'c:x'
110 else:
113 else:
111 expected = path
114 expected = path
112 nt.assert_equal(opts['f'], expected)
115 nt.assert_equal(opts['f'], expected)
113
116
114 def test_magic_parse_long_options():
117 def test_magic_parse_long_options():
115 """Magic.parse_options can handle --foo=bar long options"""
118 """Magic.parse_options can handle --foo=bar long options"""
116 ip = get_ipython()
119 ip = get_ipython()
117 m = DummyMagics(ip)
120 m = DummyMagics(ip)
118 opts, _ = m.parse_options('--foo --bar=bubble', 'a', 'foo', 'bar=')
121 opts, _ = m.parse_options('--foo --bar=bubble', 'a', 'foo', 'bar=')
119 nt.assert_in('foo', opts)
122 nt.assert_in('foo', opts)
120 nt.assert_in('bar', opts)
123 nt.assert_in('bar', opts)
121 nt.assert_equal(opts['bar'], "bubble")
124 nt.assert_equal(opts['bar'], "bubble")
122
125
123
126
124 @dec.skip_without('sqlite3')
127 @dec.skip_without('sqlite3')
125 def doctest_hist_f():
128 def doctest_hist_f():
126 """Test %hist -f with temporary filename.
129 """Test %hist -f with temporary filename.
127
130
128 In [9]: import tempfile
131 In [9]: import tempfile
129
132
130 In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-')
133 In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-')
131
134
132 In [11]: %hist -nl -f $tfile 3
135 In [11]: %hist -nl -f $tfile 3
133
136
134 In [13]: import os; os.unlink(tfile)
137 In [13]: import os; os.unlink(tfile)
135 """
138 """
136
139
137
140
138 @dec.skip_without('sqlite3')
141 @dec.skip_without('sqlite3')
139 def doctest_hist_r():
142 def doctest_hist_r():
140 """Test %hist -r
143 """Test %hist -r
141
144
142 XXX - This test is not recording the output correctly. For some reason, in
145 XXX - This test is not recording the output correctly. For some reason, in
143 testing mode the raw history isn't getting populated. No idea why.
146 testing mode the raw history isn't getting populated. No idea why.
144 Disabling the output checking for now, though at least we do run it.
147 Disabling the output checking for now, though at least we do run it.
145
148
146 In [1]: 'hist' in _ip.lsmagic()
149 In [1]: 'hist' in _ip.lsmagic()
147 Out[1]: True
150 Out[1]: True
148
151
149 In [2]: x=1
152 In [2]: x=1
150
153
151 In [3]: %hist -rl 2
154 In [3]: %hist -rl 2
152 x=1 # random
155 x=1 # random
153 %hist -r 2
156 %hist -r 2
154 """
157 """
155
158
156
159
157 @dec.skip_without('sqlite3')
160 @dec.skip_without('sqlite3')
158 def doctest_hist_op():
161 def doctest_hist_op():
159 """Test %hist -op
162 """Test %hist -op
160
163
161 In [1]: class b(float):
164 In [1]: class b(float):
162 ...: pass
165 ...: pass
163 ...:
166 ...:
164
167
165 In [2]: class s(object):
168 In [2]: class s(object):
166 ...: def __str__(self):
169 ...: def __str__(self):
167 ...: return 's'
170 ...: return 's'
168 ...:
171 ...:
169
172
170 In [3]:
173 In [3]:
171
174
172 In [4]: class r(b):
175 In [4]: class r(b):
173 ...: def __repr__(self):
176 ...: def __repr__(self):
174 ...: return 'r'
177 ...: return 'r'
175 ...:
178 ...:
176
179
177 In [5]: class sr(s,r): pass
180 In [5]: class sr(s,r): pass
178 ...:
181 ...:
179
182
180 In [6]:
183 In [6]:
181
184
182 In [7]: bb=b()
185 In [7]: bb=b()
183
186
184 In [8]: ss=s()
187 In [8]: ss=s()
185
188
186 In [9]: rr=r()
189 In [9]: rr=r()
187
190
188 In [10]: ssrr=sr()
191 In [10]: ssrr=sr()
189
192
190 In [11]: 4.5
193 In [11]: 4.5
191 Out[11]: 4.5
194 Out[11]: 4.5
192
195
193 In [12]: str(ss)
196 In [12]: str(ss)
194 Out[12]: 's'
197 Out[12]: 's'
195
198
196 In [13]:
199 In [13]:
197
200
198 In [14]: %hist -op
201 In [14]: %hist -op
199 >>> class b:
202 >>> class b:
200 ... pass
203 ... pass
201 ...
204 ...
202 >>> class s(b):
205 >>> class s(b):
203 ... def __str__(self):
206 ... def __str__(self):
204 ... return 's'
207 ... return 's'
205 ...
208 ...
206 >>>
209 >>>
207 >>> class r(b):
210 >>> class r(b):
208 ... def __repr__(self):
211 ... def __repr__(self):
209 ... return 'r'
212 ... return 'r'
210 ...
213 ...
211 >>> class sr(s,r): pass
214 >>> class sr(s,r): pass
212 >>>
215 >>>
213 >>> bb=b()
216 >>> bb=b()
214 >>> ss=s()
217 >>> ss=s()
215 >>> rr=r()
218 >>> rr=r()
216 >>> ssrr=sr()
219 >>> ssrr=sr()
217 >>> 4.5
220 >>> 4.5
218 4.5
221 4.5
219 >>> str(ss)
222 >>> str(ss)
220 's'
223 's'
221 >>>
224 >>>
222 """
225 """
223
226
224 def test_hist_pof():
227 def test_hist_pof():
225 ip = get_ipython()
228 ip = get_ipython()
226 ip.run_cell(u"1+2", store_history=True)
229 ip.run_cell(u"1+2", store_history=True)
227 #raise Exception(ip.history_manager.session_number)
230 #raise Exception(ip.history_manager.session_number)
228 #raise Exception(list(ip.history_manager._get_range_session()))
231 #raise Exception(list(ip.history_manager._get_range_session()))
229 with TemporaryDirectory() as td:
232 with TemporaryDirectory() as td:
230 tf = os.path.join(td, 'hist.py')
233 tf = os.path.join(td, 'hist.py')
231 ip.run_line_magic('history', '-pof %s' % tf)
234 ip.run_line_magic('history', '-pof %s' % tf)
232 assert os.path.isfile(tf)
235 assert os.path.isfile(tf)
233
236
234
237
235 @dec.skip_without('sqlite3')
238 @dec.skip_without('sqlite3')
236 def test_macro():
239 def test_macro():
237 ip = get_ipython()
240 ip = get_ipython()
238 ip.history_manager.reset() # Clear any existing history.
241 ip.history_manager.reset() # Clear any existing history.
239 cmds = ["a=1", "def b():\n return a**2", "print(a,b())"]
242 cmds = ["a=1", "def b():\n return a**2", "print(a,b())"]
240 for i, cmd in enumerate(cmds, start=1):
243 for i, cmd in enumerate(cmds, start=1):
241 ip.history_manager.store_inputs(i, cmd)
244 ip.history_manager.store_inputs(i, cmd)
242 ip.magic("macro test 1-3")
245 ip.magic("macro test 1-3")
243 nt.assert_equal(ip.user_ns["test"].value, "\n".join(cmds)+"\n")
246 nt.assert_equal(ip.user_ns["test"].value, "\n".join(cmds)+"\n")
244
247
245 # List macros
248 # List macros
246 nt.assert_in("test", ip.magic("macro"))
249 nt.assert_in("test", ip.magic("macro"))
247
250
248
251
249 @dec.skip_without('sqlite3')
252 @dec.skip_without('sqlite3')
250 def test_macro_run():
253 def test_macro_run():
251 """Test that we can run a multi-line macro successfully."""
254 """Test that we can run a multi-line macro successfully."""
252 ip = get_ipython()
255 ip = get_ipython()
253 ip.history_manager.reset()
256 ip.history_manager.reset()
254 cmds = ["a=10", "a+=1", py3compat.doctest_refactor_print("print a"),
257 cmds = ["a=10", "a+=1", py3compat.doctest_refactor_print("print a"),
255 "%macro test 2-3"]
258 "%macro test 2-3"]
256 for cmd in cmds:
259 for cmd in cmds:
257 ip.run_cell(cmd, store_history=True)
260 ip.run_cell(cmd, store_history=True)
258 nt.assert_equal(ip.user_ns["test"].value,
261 nt.assert_equal(ip.user_ns["test"].value,
259 py3compat.doctest_refactor_print("a+=1\nprint a\n"))
262 py3compat.doctest_refactor_print("a+=1\nprint a\n"))
260 with tt.AssertPrints("12"):
263 with tt.AssertPrints("12"):
261 ip.run_cell("test")
264 ip.run_cell("test")
262 with tt.AssertPrints("13"):
265 with tt.AssertPrints("13"):
263 ip.run_cell("test")
266 ip.run_cell("test")
264
267
265
268
266 def test_magic_magic():
269 def test_magic_magic():
267 """Test %magic"""
270 """Test %magic"""
268 ip = get_ipython()
271 ip = get_ipython()
269 with capture_output() as captured:
272 with capture_output() as captured:
270 ip.magic("magic")
273 ip.magic("magic")
271
274
272 stdout = captured.stdout
275 stdout = captured.stdout
273 nt.assert_in('%magic', stdout)
276 nt.assert_in('%magic', stdout)
274 nt.assert_in('IPython', stdout)
277 nt.assert_in('IPython', stdout)
275 nt.assert_in('Available', stdout)
278 nt.assert_in('Available', stdout)
276
279
277
280
278 @dec.skipif_not_numpy
281 @dec.skipif_not_numpy
279 def test_numpy_reset_array_undec():
282 def test_numpy_reset_array_undec():
280 "Test '%reset array' functionality"
283 "Test '%reset array' functionality"
281 _ip.ex('import numpy as np')
284 _ip.ex('import numpy as np')
282 _ip.ex('a = np.empty(2)')
285 _ip.ex('a = np.empty(2)')
283 nt.assert_in('a', _ip.user_ns)
286 nt.assert_in('a', _ip.user_ns)
284 _ip.magic('reset -f array')
287 _ip.magic('reset -f array')
285 nt.assert_not_in('a', _ip.user_ns)
288 nt.assert_not_in('a', _ip.user_ns)
286
289
287 def test_reset_out():
290 def test_reset_out():
288 "Test '%reset out' magic"
291 "Test '%reset out' magic"
289 _ip.run_cell("parrot = 'dead'", store_history=True)
292 _ip.run_cell("parrot = 'dead'", store_history=True)
290 # test '%reset -f out', make an Out prompt
293 # test '%reset -f out', make an Out prompt
291 _ip.run_cell("parrot", store_history=True)
294 _ip.run_cell("parrot", store_history=True)
292 nt.assert_true('dead' in [_ip.user_ns[x] for x in ('_','__','___')])
295 nt.assert_true('dead' in [_ip.user_ns[x] for x in ('_','__','___')])
293 _ip.magic('reset -f out')
296 _ip.magic('reset -f out')
294 nt.assert_false('dead' in [_ip.user_ns[x] for x in ('_','__','___')])
297 nt.assert_false('dead' in [_ip.user_ns[x] for x in ('_','__','___')])
295 nt.assert_equal(len(_ip.user_ns['Out']), 0)
298 nt.assert_equal(len(_ip.user_ns['Out']), 0)
296
299
297 def test_reset_in():
300 def test_reset_in():
298 "Test '%reset in' magic"
301 "Test '%reset in' magic"
299 # test '%reset -f in'
302 # test '%reset -f in'
300 _ip.run_cell("parrot", store_history=True)
303 _ip.run_cell("parrot", store_history=True)
301 nt.assert_true('parrot' in [_ip.user_ns[x] for x in ('_i','_ii','_iii')])
304 nt.assert_true('parrot' in [_ip.user_ns[x] for x in ('_i','_ii','_iii')])
302 _ip.magic('%reset -f in')
305 _ip.magic('%reset -f in')
303 nt.assert_false('parrot' in [_ip.user_ns[x] for x in ('_i','_ii','_iii')])
306 nt.assert_false('parrot' in [_ip.user_ns[x] for x in ('_i','_ii','_iii')])
304 nt.assert_equal(len(set(_ip.user_ns['In'])), 1)
307 nt.assert_equal(len(set(_ip.user_ns['In'])), 1)
305
308
306 def test_reset_dhist():
309 def test_reset_dhist():
307 "Test '%reset dhist' magic"
310 "Test '%reset dhist' magic"
308 _ip.run_cell("tmp = [d for d in _dh]") # copy before clearing
311 _ip.run_cell("tmp = [d for d in _dh]") # copy before clearing
309 _ip.magic('cd ' + os.path.dirname(nt.__file__))
312 _ip.magic('cd ' + os.path.dirname(nt.__file__))
310 _ip.magic('cd -')
313 _ip.magic('cd -')
311 nt.assert_true(len(_ip.user_ns['_dh']) > 0)
314 nt.assert_true(len(_ip.user_ns['_dh']) > 0)
312 _ip.magic('reset -f dhist')
315 _ip.magic('reset -f dhist')
313 nt.assert_equal(len(_ip.user_ns['_dh']), 0)
316 nt.assert_equal(len(_ip.user_ns['_dh']), 0)
314 _ip.run_cell("_dh = [d for d in tmp]") #restore
317 _ip.run_cell("_dh = [d for d in tmp]") #restore
315
318
316 def test_reset_in_length():
319 def test_reset_in_length():
317 "Test that '%reset in' preserves In[] length"
320 "Test that '%reset in' preserves In[] length"
318 _ip.run_cell("print 'foo'")
321 _ip.run_cell("print 'foo'")
319 _ip.run_cell("reset -f in")
322 _ip.run_cell("reset -f in")
320 nt.assert_equal(len(_ip.user_ns['In']), _ip.displayhook.prompt_count+1)
323 nt.assert_equal(len(_ip.user_ns['In']), _ip.displayhook.prompt_count+1)
321
324
322 def test_tb_syntaxerror():
325 def test_tb_syntaxerror():
323 """test %tb after a SyntaxError"""
326 """test %tb after a SyntaxError"""
324 ip = get_ipython()
327 ip = get_ipython()
325 ip.run_cell("for")
328 ip.run_cell("for")
326
329
327 # trap and validate stdout
330 # trap and validate stdout
328 save_stdout = sys.stdout
331 save_stdout = sys.stdout
329 try:
332 try:
330 sys.stdout = StringIO()
333 sys.stdout = StringIO()
331 ip.run_cell("%tb")
334 ip.run_cell("%tb")
332 out = sys.stdout.getvalue()
335 out = sys.stdout.getvalue()
333 finally:
336 finally:
334 sys.stdout = save_stdout
337 sys.stdout = save_stdout
335 # trim output, and only check the last line
338 # trim output, and only check the last line
336 last_line = out.rstrip().splitlines()[-1].strip()
339 last_line = out.rstrip().splitlines()[-1].strip()
337 nt.assert_equal(last_line, "SyntaxError: invalid syntax")
340 nt.assert_equal(last_line, "SyntaxError: invalid syntax")
338
341
339
342
340 def test_time():
343 def test_time():
341 ip = get_ipython()
344 ip = get_ipython()
342
345
343 with tt.AssertPrints("Wall time: "):
346 with tt.AssertPrints("Wall time: "):
344 ip.run_cell("%time None")
347 ip.run_cell("%time None")
345
348
346 ip.run_cell("def f(kmjy):\n"
349 ip.run_cell("def f(kmjy):\n"
347 " %time print (2*kmjy)")
350 " %time print (2*kmjy)")
348
351
349 with tt.AssertPrints("Wall time: "):
352 with tt.AssertPrints("Wall time: "):
350 with tt.AssertPrints("hihi", suppress=False):
353 with tt.AssertPrints("hihi", suppress=False):
351 ip.run_cell("f('hi')")
354 ip.run_cell("f('hi')")
352
355
353
356
354 @dec.skip_win32
357 @dec.skip_win32
355 def test_time2():
358 def test_time2():
356 ip = get_ipython()
359 ip = get_ipython()
357
360
358 with tt.AssertPrints("CPU times: user "):
361 with tt.AssertPrints("CPU times: user "):
359 ip.run_cell("%time None")
362 ip.run_cell("%time None")
360
363
361 def test_time3():
364 def test_time3():
362 """Erroneous magic function calls, issue gh-3334"""
365 """Erroneous magic function calls, issue gh-3334"""
363 ip = get_ipython()
366 ip = get_ipython()
364 ip.user_ns.pop('run', None)
367 ip.user_ns.pop('run', None)
365
368
366 with tt.AssertNotPrints("not found", channel='stderr'):
369 with tt.AssertNotPrints("not found", channel='stderr'):
367 ip.run_cell("%%time\n"
370 ip.run_cell("%%time\n"
368 "run = 0\n"
371 "run = 0\n"
369 "run += 1")
372 "run += 1")
370
373
371 def test_doctest_mode():
374 def test_doctest_mode():
372 "Toggle doctest_mode twice, it should be a no-op and run without error"
375 "Toggle doctest_mode twice, it should be a no-op and run without error"
373 _ip.magic('doctest_mode')
376 _ip.magic('doctest_mode')
374 _ip.magic('doctest_mode')
377 _ip.magic('doctest_mode')
375
378
376
379
377 def test_parse_options():
380 def test_parse_options():
378 """Tests for basic options parsing in magics."""
381 """Tests for basic options parsing in magics."""
379 # These are only the most minimal of tests, more should be added later. At
382 # These are only the most minimal of tests, more should be added later. At
380 # the very least we check that basic text/unicode calls work OK.
383 # the very least we check that basic text/unicode calls work OK.
381 m = DummyMagics(_ip)
384 m = DummyMagics(_ip)
382 nt.assert_equal(m.parse_options('foo', '')[1], 'foo')
385 nt.assert_equal(m.parse_options('foo', '')[1], 'foo')
383 nt.assert_equal(m.parse_options(u'foo', '')[1], u'foo')
386 nt.assert_equal(m.parse_options(u'foo', '')[1], u'foo')
384
387
385
388
386 def test_dirops():
389 def test_dirops():
387 """Test various directory handling operations."""
390 """Test various directory handling operations."""
388 # curpath = lambda :os.path.splitdrive(os.getcwd())[1].replace('\\','/')
391 # curpath = lambda :os.path.splitdrive(os.getcwd())[1].replace('\\','/')
389 curpath = os.getcwd
392 curpath = os.getcwd
390 startdir = os.getcwd()
393 startdir = os.getcwd()
391 ipdir = os.path.realpath(_ip.ipython_dir)
394 ipdir = os.path.realpath(_ip.ipython_dir)
392 try:
395 try:
393 _ip.magic('cd "%s"' % ipdir)
396 _ip.magic('cd "%s"' % ipdir)
394 nt.assert_equal(curpath(), ipdir)
397 nt.assert_equal(curpath(), ipdir)
395 _ip.magic('cd -')
398 _ip.magic('cd -')
396 nt.assert_equal(curpath(), startdir)
399 nt.assert_equal(curpath(), startdir)
397 _ip.magic('pushd "%s"' % ipdir)
400 _ip.magic('pushd "%s"' % ipdir)
398 nt.assert_equal(curpath(), ipdir)
401 nt.assert_equal(curpath(), ipdir)
399 _ip.magic('popd')
402 _ip.magic('popd')
400 nt.assert_equal(curpath(), startdir)
403 nt.assert_equal(curpath(), startdir)
401 finally:
404 finally:
402 os.chdir(startdir)
405 os.chdir(startdir)
403
406
404
407
405 def test_xmode():
408 def test_xmode():
406 # Calling xmode three times should be a no-op
409 # Calling xmode three times should be a no-op
407 xmode = _ip.InteractiveTB.mode
410 xmode = _ip.InteractiveTB.mode
408 for i in range(3):
411 for i in range(3):
409 _ip.magic("xmode")
412 _ip.magic("xmode")
410 nt.assert_equal(_ip.InteractiveTB.mode, xmode)
413 nt.assert_equal(_ip.InteractiveTB.mode, xmode)
411
414
412 def test_reset_hard():
415 def test_reset_hard():
413 monitor = []
416 monitor = []
414 class A(object):
417 class A(object):
415 def __del__(self):
418 def __del__(self):
416 monitor.append(1)
419 monitor.append(1)
417 def __repr__(self):
420 def __repr__(self):
418 return "<A instance>"
421 return "<A instance>"
419
422
420 _ip.user_ns["a"] = A()
423 _ip.user_ns["a"] = A()
421 _ip.run_cell("a")
424 _ip.run_cell("a")
422
425
423 nt.assert_equal(monitor, [])
426 nt.assert_equal(monitor, [])
424 _ip.magic("reset -f")
427 _ip.magic("reset -f")
425 nt.assert_equal(monitor, [1])
428 nt.assert_equal(monitor, [1])
426
429
427 class TestXdel(tt.TempFileMixin):
430 class TestXdel(tt.TempFileMixin):
428 def test_xdel(self):
431 def test_xdel(self):
429 """Test that references from %run are cleared by xdel."""
432 """Test that references from %run are cleared by xdel."""
430 src = ("class A(object):\n"
433 src = ("class A(object):\n"
431 " monitor = []\n"
434 " monitor = []\n"
432 " def __del__(self):\n"
435 " def __del__(self):\n"
433 " self.monitor.append(1)\n"
436 " self.monitor.append(1)\n"
434 "a = A()\n")
437 "a = A()\n")
435 self.mktmp(src)
438 self.mktmp(src)
436 # %run creates some hidden references...
439 # %run creates some hidden references...
437 _ip.magic("run %s" % self.fname)
440 _ip.magic("run %s" % self.fname)
438 # ... as does the displayhook.
441 # ... as does the displayhook.
439 _ip.run_cell("a")
442 _ip.run_cell("a")
440
443
441 monitor = _ip.user_ns["A"].monitor
444 monitor = _ip.user_ns["A"].monitor
442 nt.assert_equal(monitor, [])
445 nt.assert_equal(monitor, [])
443
446
444 _ip.magic("xdel a")
447 _ip.magic("xdel a")
445
448
446 # Check that a's __del__ method has been called.
449 # Check that a's __del__ method has been called.
447 nt.assert_equal(monitor, [1])
450 nt.assert_equal(monitor, [1])
448
451
449 def doctest_who():
452 def doctest_who():
450 """doctest for %who
453 """doctest for %who
451
454
452 In [1]: %reset -f
455 In [1]: %reset -f
453
456
454 In [2]: alpha = 123
457 In [2]: alpha = 123
455
458
456 In [3]: beta = 'beta'
459 In [3]: beta = 'beta'
457
460
458 In [4]: %who int
461 In [4]: %who int
459 alpha
462 alpha
460
463
461 In [5]: %who str
464 In [5]: %who str
462 beta
465 beta
463
466
464 In [6]: %whos
467 In [6]: %whos
465 Variable Type Data/Info
468 Variable Type Data/Info
466 ----------------------------
469 ----------------------------
467 alpha int 123
470 alpha int 123
468 beta str beta
471 beta str beta
469
472
470 In [7]: %who_ls
473 In [7]: %who_ls
471 Out[7]: ['alpha', 'beta']
474 Out[7]: ['alpha', 'beta']
472 """
475 """
473
476
474 def test_whos():
477 def test_whos():
475 """Check that whos is protected against objects where repr() fails."""
478 """Check that whos is protected against objects where repr() fails."""
476 class A(object):
479 class A(object):
477 def __repr__(self):
480 def __repr__(self):
478 raise Exception()
481 raise Exception()
479 _ip.user_ns['a'] = A()
482 _ip.user_ns['a'] = A()
480 _ip.magic("whos")
483 _ip.magic("whos")
481
484
482 @py3compat.u_format
485 @py3compat.u_format
483 def doctest_precision():
486 def doctest_precision():
484 """doctest for %precision
487 """doctest for %precision
485
488
486 In [1]: f = get_ipython().display_formatter.formatters['text/plain']
489 In [1]: f = get_ipython().display_formatter.formatters['text/plain']
487
490
488 In [2]: %precision 5
491 In [2]: %precision 5
489 Out[2]: {u}'%.5f'
492 Out[2]: {u}'%.5f'
490
493
491 In [3]: f.float_format
494 In [3]: f.float_format
492 Out[3]: {u}'%.5f'
495 Out[3]: {u}'%.5f'
493
496
494 In [4]: %precision %e
497 In [4]: %precision %e
495 Out[4]: {u}'%e'
498 Out[4]: {u}'%e'
496
499
497 In [5]: f(3.1415927)
500 In [5]: f(3.1415927)
498 Out[5]: {u}'3.141593e+00'
501 Out[5]: {u}'3.141593e+00'
499 """
502 """
500
503
501 def test_psearch():
504 def test_psearch():
502 with tt.AssertPrints("dict.fromkeys"):
505 with tt.AssertPrints("dict.fromkeys"):
503 _ip.run_cell("dict.fr*?")
506 _ip.run_cell("dict.fr*?")
504
507
505 def test_timeit_shlex():
508 def test_timeit_shlex():
506 """test shlex issues with timeit (#1109)"""
509 """test shlex issues with timeit (#1109)"""
507 _ip.ex("def f(*a,**kw): pass")
510 _ip.ex("def f(*a,**kw): pass")
508 _ip.magic('timeit -n1 "this is a bug".count(" ")')
511 _ip.magic('timeit -n1 "this is a bug".count(" ")')
509 _ip.magic('timeit -r1 -n1 f(" ", 1)')
512 _ip.magic('timeit -r1 -n1 f(" ", 1)')
510 _ip.magic('timeit -r1 -n1 f(" ", 1, " ", 2, " ")')
513 _ip.magic('timeit -r1 -n1 f(" ", 1, " ", 2, " ")')
511 _ip.magic('timeit -r1 -n1 ("a " + "b")')
514 _ip.magic('timeit -r1 -n1 ("a " + "b")')
512 _ip.magic('timeit -r1 -n1 f("a " + "b")')
515 _ip.magic('timeit -r1 -n1 f("a " + "b")')
513 _ip.magic('timeit -r1 -n1 f("a " + "b ")')
516 _ip.magic('timeit -r1 -n1 f("a " + "b ")')
514
517
515
518
516 def test_timeit_arguments():
519 def test_timeit_arguments():
517 "Test valid timeit arguments, should not cause SyntaxError (GH #1269)"
520 "Test valid timeit arguments, should not cause SyntaxError (GH #1269)"
518 _ip.magic("timeit ('#')")
521 _ip.magic("timeit ('#')")
519
522
520
523
521 def test_timeit_special_syntax():
524 def test_timeit_special_syntax():
522 "Test %%timeit with IPython special syntax"
525 "Test %%timeit with IPython special syntax"
523 @register_line_magic
526 @register_line_magic
524 def lmagic(line):
527 def lmagic(line):
525 ip = get_ipython()
528 ip = get_ipython()
526 ip.user_ns['lmagic_out'] = line
529 ip.user_ns['lmagic_out'] = line
527
530
528 # line mode test
531 # line mode test
529 _ip.run_line_magic('timeit', '-n1 -r1 %lmagic my line')
532 _ip.run_line_magic('timeit', '-n1 -r1 %lmagic my line')
530 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
533 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
531 # cell mode test
534 # cell mode test
532 _ip.run_cell_magic('timeit', '-n1 -r1', '%lmagic my line2')
535 _ip.run_cell_magic('timeit', '-n1 -r1', '%lmagic my line2')
533 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
536 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
534
537
535 def test_timeit_return():
538 def test_timeit_return():
536 """
539 """
537 test wether timeit -o return object
540 test wether timeit -o return object
538 """
541 """
539
542
540 res = _ip.run_line_magic('timeit','-n10 -r10 -o 1')
543 res = _ip.run_line_magic('timeit','-n10 -r10 -o 1')
541 assert(res is not None)
544 assert(res is not None)
542
545
543 def test_timeit_quiet():
546 def test_timeit_quiet():
544 """
547 """
545 test quiet option of timeit magic
548 test quiet option of timeit magic
546 """
549 """
547 with tt.AssertNotPrints("loops"):
550 with tt.AssertNotPrints("loops"):
548 _ip.run_cell("%timeit -n1 -r1 -q 1")
551 _ip.run_cell("%timeit -n1 -r1 -q 1")
549
552
550 def test_timeit_return_quiet():
553 def test_timeit_return_quiet():
551 with tt.AssertNotPrints("loops"):
554 with tt.AssertNotPrints("loops"):
552 res = _ip.run_line_magic('timeit', '-n1 -r1 -q -o 1')
555 res = _ip.run_line_magic('timeit', '-n1 -r1 -q -o 1')
553 assert (res is not None)
556 assert (res is not None)
554
557
555 @dec.skipif(execution.profile is None)
558 @dec.skipif(execution.profile is None)
556 def test_prun_special_syntax():
559 def test_prun_special_syntax():
557 "Test %%prun with IPython special syntax"
560 "Test %%prun with IPython special syntax"
558 @register_line_magic
561 @register_line_magic
559 def lmagic(line):
562 def lmagic(line):
560 ip = get_ipython()
563 ip = get_ipython()
561 ip.user_ns['lmagic_out'] = line
564 ip.user_ns['lmagic_out'] = line
562
565
563 # line mode test
566 # line mode test
564 _ip.run_line_magic('prun', '-q %lmagic my line')
567 _ip.run_line_magic('prun', '-q %lmagic my line')
565 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
568 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
566 # cell mode test
569 # cell mode test
567 _ip.run_cell_magic('prun', '-q', '%lmagic my line2')
570 _ip.run_cell_magic('prun', '-q', '%lmagic my line2')
568 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
571 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
569
572
570 @dec.skipif(execution.profile is None)
573 @dec.skipif(execution.profile is None)
571 def test_prun_quotes():
574 def test_prun_quotes():
572 "Test that prun does not clobber string escapes (GH #1302)"
575 "Test that prun does not clobber string escapes (GH #1302)"
573 _ip.magic(r"prun -q x = '\t'")
576 _ip.magic(r"prun -q x = '\t'")
574 nt.assert_equal(_ip.user_ns['x'], '\t')
577 nt.assert_equal(_ip.user_ns['x'], '\t')
575
578
576 def test_extension():
579 def test_extension():
577 # Debugging information for failures of this test
580 # Debugging information for failures of this test
578 print('sys.path:')
581 print('sys.path:')
579 for p in sys.path:
582 for p in sys.path:
580 print(' ', p)
583 print(' ', p)
581 print('CWD', os.getcwd())
584 print('CWD', os.getcwd())
582
585
583 nt.assert_raises(ImportError, _ip.magic, "load_ext daft_extension")
586 nt.assert_raises(ImportError, _ip.magic, "load_ext daft_extension")
584 daft_path = os.path.join(os.path.dirname(__file__), "daft_extension")
587 daft_path = os.path.join(os.path.dirname(__file__), "daft_extension")
585 sys.path.insert(0, daft_path)
588 sys.path.insert(0, daft_path)
586 try:
589 try:
587 _ip.user_ns.pop('arq', None)
590 _ip.user_ns.pop('arq', None)
588 invalidate_caches() # Clear import caches
591 invalidate_caches() # Clear import caches
589 _ip.magic("load_ext daft_extension")
592 _ip.magic("load_ext daft_extension")
590 nt.assert_equal(_ip.user_ns['arq'], 185)
593 nt.assert_equal(_ip.user_ns['arq'], 185)
591 _ip.magic("unload_ext daft_extension")
594 _ip.magic("unload_ext daft_extension")
592 assert 'arq' not in _ip.user_ns
595 assert 'arq' not in _ip.user_ns
593 finally:
596 finally:
594 sys.path.remove(daft_path)
597 sys.path.remove(daft_path)
595
598
596
599
597 def test_notebook_export_json():
600 def test_notebook_export_json():
598 _ip = get_ipython()
601 _ip = get_ipython()
599 _ip.history_manager.reset() # Clear any existing history.
602 _ip.history_manager.reset() # Clear any existing history.
600 cmds = [u"a=1", u"def b():\n return a**2", u"print('noΓ«l, Γ©tΓ©', b())"]
603 cmds = [u"a=1", u"def b():\n return a**2", u"print('noΓ«l, Γ©tΓ©', b())"]
601 for i, cmd in enumerate(cmds, start=1):
604 for i, cmd in enumerate(cmds, start=1):
602 _ip.history_manager.store_inputs(i, cmd)
605 _ip.history_manager.store_inputs(i, cmd)
603 with TemporaryDirectory() as td:
606 with TemporaryDirectory() as td:
604 outfile = os.path.join(td, "nb.ipynb")
607 outfile = os.path.join(td, "nb.ipynb")
605 _ip.magic("notebook -e %s" % outfile)
608 _ip.magic("notebook -e %s" % outfile)
606
609
607
610
608 class TestEnv(TestCase):
611 class TestEnv(TestCase):
609
612
610 def test_env(self):
613 def test_env(self):
611 env = _ip.magic("env")
614 env = _ip.magic("env")
612 self.assertTrue(isinstance(env, dict))
615 self.assertTrue(isinstance(env, dict))
613
616
614 def test_env_get_set_simple(self):
617 def test_env_get_set_simple(self):
615 env = _ip.magic("env var val1")
618 env = _ip.magic("env var val1")
616 self.assertEqual(env, None)
619 self.assertEqual(env, None)
617 self.assertEqual(os.environ['var'], 'val1')
620 self.assertEqual(os.environ['var'], 'val1')
618 self.assertEqual(_ip.magic("env var"), 'val1')
621 self.assertEqual(_ip.magic("env var"), 'val1')
619 env = _ip.magic("env var=val2")
622 env = _ip.magic("env var=val2")
620 self.assertEqual(env, None)
623 self.assertEqual(env, None)
621 self.assertEqual(os.environ['var'], 'val2')
624 self.assertEqual(os.environ['var'], 'val2')
622
625
623 def test_env_get_set_complex(self):
626 def test_env_get_set_complex(self):
624 env = _ip.magic("env var 'val1 '' 'val2")
627 env = _ip.magic("env var 'val1 '' 'val2")
625 self.assertEqual(env, None)
628 self.assertEqual(env, None)
626 self.assertEqual(os.environ['var'], "'val1 '' 'val2")
629 self.assertEqual(os.environ['var'], "'val1 '' 'val2")
627 self.assertEqual(_ip.magic("env var"), "'val1 '' 'val2")
630 self.assertEqual(_ip.magic("env var"), "'val1 '' 'val2")
628 env = _ip.magic('env var=val2 val3="val4')
631 env = _ip.magic('env var=val2 val3="val4')
629 self.assertEqual(env, None)
632 self.assertEqual(env, None)
630 self.assertEqual(os.environ['var'], 'val2 val3="val4')
633 self.assertEqual(os.environ['var'], 'val2 val3="val4')
631
634
632 def test_env_set_bad_input(self):
635 def test_env_set_bad_input(self):
633 self.assertRaises(UsageError, lambda: _ip.magic("set_env var"))
636 self.assertRaises(UsageError, lambda: _ip.magic("set_env var"))
634
637
635 def test_env_set_whitespace(self):
638 def test_env_set_whitespace(self):
636 self.assertRaises(UsageError, lambda: _ip.magic("env var A=B"))
639 self.assertRaises(UsageError, lambda: _ip.magic("env var A=B"))
637
640
638
641
639 class CellMagicTestCase(TestCase):
642 class CellMagicTestCase(TestCase):
640
643
641 def check_ident(self, magic):
644 def check_ident(self, magic):
642 # Manually called, we get the result
645 # Manually called, we get the result
643 out = _ip.run_cell_magic(magic, 'a', 'b')
646 out = _ip.run_cell_magic(magic, 'a', 'b')
644 nt.assert_equal(out, ('a','b'))
647 nt.assert_equal(out, ('a','b'))
645 # Via run_cell, it goes into the user's namespace via displayhook
648 # Via run_cell, it goes into the user's namespace via displayhook
646 _ip.run_cell('%%' + magic +' c\nd')
649 _ip.run_cell('%%' + magic +' c\nd')
647 nt.assert_equal(_ip.user_ns['_'], ('c','d'))
650 nt.assert_equal(_ip.user_ns['_'], ('c','d'))
648
651
649 def test_cell_magic_func_deco(self):
652 def test_cell_magic_func_deco(self):
650 "Cell magic using simple decorator"
653 "Cell magic using simple decorator"
651 @register_cell_magic
654 @register_cell_magic
652 def cellm(line, cell):
655 def cellm(line, cell):
653 return line, cell
656 return line, cell
654
657
655 self.check_ident('cellm')
658 self.check_ident('cellm')
656
659
657 def test_cell_magic_reg(self):
660 def test_cell_magic_reg(self):
658 "Cell magic manually registered"
661 "Cell magic manually registered"
659 def cellm(line, cell):
662 def cellm(line, cell):
660 return line, cell
663 return line, cell
661
664
662 _ip.register_magic_function(cellm, 'cell', 'cellm2')
665 _ip.register_magic_function(cellm, 'cell', 'cellm2')
663 self.check_ident('cellm2')
666 self.check_ident('cellm2')
664
667
665 def test_cell_magic_class(self):
668 def test_cell_magic_class(self):
666 "Cell magics declared via a class"
669 "Cell magics declared via a class"
667 @magics_class
670 @magics_class
668 class MyMagics(Magics):
671 class MyMagics(Magics):
669
672
670 @cell_magic
673 @cell_magic
671 def cellm3(self, line, cell):
674 def cellm3(self, line, cell):
672 return line, cell
675 return line, cell
673
676
674 _ip.register_magics(MyMagics)
677 _ip.register_magics(MyMagics)
675 self.check_ident('cellm3')
678 self.check_ident('cellm3')
676
679
677 def test_cell_magic_class2(self):
680 def test_cell_magic_class2(self):
678 "Cell magics declared via a class, #2"
681 "Cell magics declared via a class, #2"
679 @magics_class
682 @magics_class
680 class MyMagics2(Magics):
683 class MyMagics2(Magics):
681
684
682 @cell_magic('cellm4')
685 @cell_magic('cellm4')
683 def cellm33(self, line, cell):
686 def cellm33(self, line, cell):
684 return line, cell
687 return line, cell
685
688
686 _ip.register_magics(MyMagics2)
689 _ip.register_magics(MyMagics2)
687 self.check_ident('cellm4')
690 self.check_ident('cellm4')
688 # Check that nothing is registered as 'cellm33'
691 # Check that nothing is registered as 'cellm33'
689 c33 = _ip.find_cell_magic('cellm33')
692 c33 = _ip.find_cell_magic('cellm33')
690 nt.assert_equal(c33, None)
693 nt.assert_equal(c33, None)
691
694
692 def test_file():
695 def test_file():
693 """Basic %%file"""
696 """Basic %%file"""
694 ip = get_ipython()
697 ip = get_ipython()
695 with TemporaryDirectory() as td:
698 with TemporaryDirectory() as td:
696 fname = os.path.join(td, 'file1')
699 fname = os.path.join(td, 'file1')
697 ip.run_cell_magic("file", fname, u'\n'.join([
700 ip.run_cell_magic("file", fname, u'\n'.join([
698 'line1',
701 'line1',
699 'line2',
702 'line2',
700 ]))
703 ]))
701 with open(fname) as f:
704 with open(fname) as f:
702 s = f.read()
705 s = f.read()
703 nt.assert_in('line1\n', s)
706 nt.assert_in('line1\n', s)
704 nt.assert_in('line2', s)
707 nt.assert_in('line2', s)
705
708
706 def test_file_var_expand():
709 def test_file_var_expand():
707 """%%file $filename"""
710 """%%file $filename"""
708 ip = get_ipython()
711 ip = get_ipython()
709 with TemporaryDirectory() as td:
712 with TemporaryDirectory() as td:
710 fname = os.path.join(td, 'file1')
713 fname = os.path.join(td, 'file1')
711 ip.user_ns['filename'] = fname
714 ip.user_ns['filename'] = fname
712 ip.run_cell_magic("file", '$filename', u'\n'.join([
715 ip.run_cell_magic("file", '$filename', u'\n'.join([
713 'line1',
716 'line1',
714 'line2',
717 'line2',
715 ]))
718 ]))
716 with open(fname) as f:
719 with open(fname) as f:
717 s = f.read()
720 s = f.read()
718 nt.assert_in('line1\n', s)
721 nt.assert_in('line1\n', s)
719 nt.assert_in('line2', s)
722 nt.assert_in('line2', s)
720
723
721 def test_file_unicode():
724 def test_file_unicode():
722 """%%file with unicode cell"""
725 """%%file with unicode cell"""
723 ip = get_ipython()
726 ip = get_ipython()
724 with TemporaryDirectory() as td:
727 with TemporaryDirectory() as td:
725 fname = os.path.join(td, 'file1')
728 fname = os.path.join(td, 'file1')
726 ip.run_cell_magic("file", fname, u'\n'.join([
729 ip.run_cell_magic("file", fname, u'\n'.join([
727 u'linΓ©1',
730 u'linΓ©1',
728 u'linΓ©2',
731 u'linΓ©2',
729 ]))
732 ]))
730 with io.open(fname, encoding='utf-8') as f:
733 with io.open(fname, encoding='utf-8') as f:
731 s = f.read()
734 s = f.read()
732 nt.assert_in(u'linΓ©1\n', s)
735 nt.assert_in(u'linΓ©1\n', s)
733 nt.assert_in(u'linΓ©2', s)
736 nt.assert_in(u'linΓ©2', s)
734
737
735 def test_file_amend():
738 def test_file_amend():
736 """%%file -a amends files"""
739 """%%file -a amends files"""
737 ip = get_ipython()
740 ip = get_ipython()
738 with TemporaryDirectory() as td:
741 with TemporaryDirectory() as td:
739 fname = os.path.join(td, 'file2')
742 fname = os.path.join(td, 'file2')
740 ip.run_cell_magic("file", fname, u'\n'.join([
743 ip.run_cell_magic("file", fname, u'\n'.join([
741 'line1',
744 'line1',
742 'line2',
745 'line2',
743 ]))
746 ]))
744 ip.run_cell_magic("file", "-a %s" % fname, u'\n'.join([
747 ip.run_cell_magic("file", "-a %s" % fname, u'\n'.join([
745 'line3',
748 'line3',
746 'line4',
749 'line4',
747 ]))
750 ]))
748 with open(fname) as f:
751 with open(fname) as f:
749 s = f.read()
752 s = f.read()
750 nt.assert_in('line1\n', s)
753 nt.assert_in('line1\n', s)
751 nt.assert_in('line3\n', s)
754 nt.assert_in('line3\n', s)
752
755
753
756
754 def test_script_config():
757 def test_script_config():
755 ip = get_ipython()
758 ip = get_ipython()
756 ip.config.ScriptMagics.script_magics = ['whoda']
759 ip.config.ScriptMagics.script_magics = ['whoda']
757 sm = script.ScriptMagics(shell=ip)
760 sm = script.ScriptMagics(shell=ip)
758 nt.assert_in('whoda', sm.magics['cell'])
761 nt.assert_in('whoda', sm.magics['cell'])
759
762
760 @dec.skip_win32
763 @dec.skip_win32
761 def test_script_out():
764 def test_script_out():
762 ip = get_ipython()
765 ip = get_ipython()
763 ip.run_cell_magic("script", "--out output sh", "echo 'hi'")
766 ip.run_cell_magic("script", "--out output sh", "echo 'hi'")
764 nt.assert_equal(ip.user_ns['output'], 'hi\n')
767 nt.assert_equal(ip.user_ns['output'], 'hi\n')
765
768
766 @dec.skip_win32
769 @dec.skip_win32
767 def test_script_err():
770 def test_script_err():
768 ip = get_ipython()
771 ip = get_ipython()
769 ip.run_cell_magic("script", "--err error sh", "echo 'hello' >&2")
772 ip.run_cell_magic("script", "--err error sh", "echo 'hello' >&2")
770 nt.assert_equal(ip.user_ns['error'], 'hello\n')
773 nt.assert_equal(ip.user_ns['error'], 'hello\n')
771
774
772 @dec.skip_win32
775 @dec.skip_win32
773 def test_script_out_err():
776 def test_script_out_err():
774 ip = get_ipython()
777 ip = get_ipython()
775 ip.run_cell_magic("script", "--out output --err error sh", "echo 'hi'\necho 'hello' >&2")
778 ip.run_cell_magic("script", "--out output --err error sh", "echo 'hi'\necho 'hello' >&2")
776 nt.assert_equal(ip.user_ns['output'], 'hi\n')
779 nt.assert_equal(ip.user_ns['output'], 'hi\n')
777 nt.assert_equal(ip.user_ns['error'], 'hello\n')
780 nt.assert_equal(ip.user_ns['error'], 'hello\n')
778
781
779 @dec.skip_win32
782 @dec.skip_win32
780 def test_script_bg_out():
783 def test_script_bg_out():
781 ip = get_ipython()
784 ip = get_ipython()
782 ip.run_cell_magic("script", "--bg --out output sh", "echo 'hi'")
785 ip.run_cell_magic("script", "--bg --out output sh", "echo 'hi'")
783 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
786 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
784
787
785 @dec.skip_win32
788 @dec.skip_win32
786 def test_script_bg_err():
789 def test_script_bg_err():
787 ip = get_ipython()
790 ip = get_ipython()
788 ip.run_cell_magic("script", "--bg --err error sh", "echo 'hello' >&2")
791 ip.run_cell_magic("script", "--bg --err error sh", "echo 'hello' >&2")
789 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
792 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
790
793
791 @dec.skip_win32
794 @dec.skip_win32
792 def test_script_bg_out_err():
795 def test_script_bg_out_err():
793 ip = get_ipython()
796 ip = get_ipython()
794 ip.run_cell_magic("script", "--bg --out output --err error sh", "echo 'hi'\necho 'hello' >&2")
797 ip.run_cell_magic("script", "--bg --out output --err error sh", "echo 'hi'\necho 'hello' >&2")
795 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
798 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
796 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
799 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
797
800
798 def test_script_defaults():
801 def test_script_defaults():
799 ip = get_ipython()
802 ip = get_ipython()
800 for cmd in ['sh', 'bash', 'perl', 'ruby']:
803 for cmd in ['sh', 'bash', 'perl', 'ruby']:
801 try:
804 try:
802 find_cmd(cmd)
805 find_cmd(cmd)
803 except Exception:
806 except Exception:
804 pass
807 pass
805 else:
808 else:
806 nt.assert_in(cmd, ip.magics_manager.magics['cell'])
809 nt.assert_in(cmd, ip.magics_manager.magics['cell'])
807
810
808
811
809 @magics_class
812 @magics_class
810 class FooFoo(Magics):
813 class FooFoo(Magics):
811 """class with both %foo and %%foo magics"""
814 """class with both %foo and %%foo magics"""
812 @line_magic('foo')
815 @line_magic('foo')
813 def line_foo(self, line):
816 def line_foo(self, line):
814 "I am line foo"
817 "I am line foo"
815 pass
818 pass
816
819
817 @cell_magic("foo")
820 @cell_magic("foo")
818 def cell_foo(self, line, cell):
821 def cell_foo(self, line, cell):
819 "I am cell foo, not line foo"
822 "I am cell foo, not line foo"
820 pass
823 pass
821
824
822 def test_line_cell_info():
825 def test_line_cell_info():
823 """%%foo and %foo magics are distinguishable to inspect"""
826 """%%foo and %foo magics are distinguishable to inspect"""
824 ip = get_ipython()
827 ip = get_ipython()
825 ip.magics_manager.register(FooFoo)
828 ip.magics_manager.register(FooFoo)
826 oinfo = ip.object_inspect('foo')
829 oinfo = ip.object_inspect('foo')
827 nt.assert_true(oinfo['found'])
830 nt.assert_true(oinfo['found'])
828 nt.assert_true(oinfo['ismagic'])
831 nt.assert_true(oinfo['ismagic'])
829
832
830 oinfo = ip.object_inspect('%%foo')
833 oinfo = ip.object_inspect('%%foo')
831 nt.assert_true(oinfo['found'])
834 nt.assert_true(oinfo['found'])
832 nt.assert_true(oinfo['ismagic'])
835 nt.assert_true(oinfo['ismagic'])
833 nt.assert_equal(oinfo['docstring'], FooFoo.cell_foo.__doc__)
836 nt.assert_equal(oinfo['docstring'], FooFoo.cell_foo.__doc__)
834
837
835 oinfo = ip.object_inspect('%foo')
838 oinfo = ip.object_inspect('%foo')
836 nt.assert_true(oinfo['found'])
839 nt.assert_true(oinfo['found'])
837 nt.assert_true(oinfo['ismagic'])
840 nt.assert_true(oinfo['ismagic'])
838 nt.assert_equal(oinfo['docstring'], FooFoo.line_foo.__doc__)
841 nt.assert_equal(oinfo['docstring'], FooFoo.line_foo.__doc__)
839
842
840 def test_multiple_magics():
843 def test_multiple_magics():
841 ip = get_ipython()
844 ip = get_ipython()
842 foo1 = FooFoo(ip)
845 foo1 = FooFoo(ip)
843 foo2 = FooFoo(ip)
846 foo2 = FooFoo(ip)
844 mm = ip.magics_manager
847 mm = ip.magics_manager
845 mm.register(foo1)
848 mm.register(foo1)
846 nt.assert_true(mm.magics['line']['foo'].__self__ is foo1)
849 nt.assert_true(mm.magics['line']['foo'].__self__ is foo1)
847 mm.register(foo2)
850 mm.register(foo2)
848 nt.assert_true(mm.magics['line']['foo'].__self__ is foo2)
851 nt.assert_true(mm.magics['line']['foo'].__self__ is foo2)
849
852
850 def test_alias_magic():
853 def test_alias_magic():
851 """Test %alias_magic."""
854 """Test %alias_magic."""
852 ip = get_ipython()
855 ip = get_ipython()
853 mm = ip.magics_manager
856 mm = ip.magics_manager
854
857
855 # Basic operation: both cell and line magics are created, if possible.
858 # Basic operation: both cell and line magics are created, if possible.
856 ip.run_line_magic('alias_magic', 'timeit_alias timeit')
859 ip.run_line_magic('alias_magic', 'timeit_alias timeit')
857 nt.assert_in('timeit_alias', mm.magics['line'])
860 nt.assert_in('timeit_alias', mm.magics['line'])
858 nt.assert_in('timeit_alias', mm.magics['cell'])
861 nt.assert_in('timeit_alias', mm.magics['cell'])
859
862
860 # --cell is specified, line magic not created.
863 # --cell is specified, line magic not created.
861 ip.run_line_magic('alias_magic', '--cell timeit_cell_alias timeit')
864 ip.run_line_magic('alias_magic', '--cell timeit_cell_alias timeit')
862 nt.assert_not_in('timeit_cell_alias', mm.magics['line'])
865 nt.assert_not_in('timeit_cell_alias', mm.magics['line'])
863 nt.assert_in('timeit_cell_alias', mm.magics['cell'])
866 nt.assert_in('timeit_cell_alias', mm.magics['cell'])
864
867
865 # Test that line alias is created successfully.
868 # Test that line alias is created successfully.
866 ip.run_line_magic('alias_magic', '--line env_alias env')
869 ip.run_line_magic('alias_magic', '--line env_alias env')
867 nt.assert_equal(ip.run_line_magic('env', ''),
870 nt.assert_equal(ip.run_line_magic('env', ''),
868 ip.run_line_magic('env_alias', ''))
871 ip.run_line_magic('env_alias', ''))
869
872
873 # Test that line alias with parameters passed in is created successfully.
874 ip.run_line_magic('alias_magic', '--line history_alias history --params ' + shlex.quote('3'))
875 nt.assert_in('history_alias', mm.magics['line'])
876
877
870 def test_save():
878 def test_save():
871 """Test %save."""
879 """Test %save."""
872 ip = get_ipython()
880 ip = get_ipython()
873 ip.history_manager.reset() # Clear any existing history.
881 ip.history_manager.reset() # Clear any existing history.
874 cmds = [u"a=1", u"def b():\n return a**2", u"print(a, b())"]
882 cmds = [u"a=1", u"def b():\n return a**2", u"print(a, b())"]
875 for i, cmd in enumerate(cmds, start=1):
883 for i, cmd in enumerate(cmds, start=1):
876 ip.history_manager.store_inputs(i, cmd)
884 ip.history_manager.store_inputs(i, cmd)
877 with TemporaryDirectory() as tmpdir:
885 with TemporaryDirectory() as tmpdir:
878 file = os.path.join(tmpdir, "testsave.py")
886 file = os.path.join(tmpdir, "testsave.py")
879 ip.run_line_magic("save", "%s 1-10" % file)
887 ip.run_line_magic("save", "%s 1-10" % file)
880 with open(file) as f:
888 with open(file) as f:
881 content = f.read()
889 content = f.read()
882 nt.assert_equal(content.count(cmds[0]), 1)
890 nt.assert_equal(content.count(cmds[0]), 1)
883 nt.assert_in('coding: utf-8', content)
891 nt.assert_in('coding: utf-8', content)
884 ip.run_line_magic("save", "-a %s 1-10" % file)
892 ip.run_line_magic("save", "-a %s 1-10" % file)
885 with open(file) as f:
893 with open(file) as f:
886 content = f.read()
894 content = f.read()
887 nt.assert_equal(content.count(cmds[0]), 2)
895 nt.assert_equal(content.count(cmds[0]), 2)
888 nt.assert_in('coding: utf-8', content)
896 nt.assert_in('coding: utf-8', content)
889
897
890
898
891 def test_store():
899 def test_store():
892 """Test %store."""
900 """Test %store."""
893 ip = get_ipython()
901 ip = get_ipython()
894 ip.run_line_magic('load_ext', 'storemagic')
902 ip.run_line_magic('load_ext', 'storemagic')
895
903
896 # make sure the storage is empty
904 # make sure the storage is empty
897 ip.run_line_magic('store', '-z')
905 ip.run_line_magic('store', '-z')
898 ip.user_ns['var'] = 42
906 ip.user_ns['var'] = 42
899 ip.run_line_magic('store', 'var')
907 ip.run_line_magic('store', 'var')
900 ip.user_ns['var'] = 39
908 ip.user_ns['var'] = 39
901 ip.run_line_magic('store', '-r')
909 ip.run_line_magic('store', '-r')
902 nt.assert_equal(ip.user_ns['var'], 42)
910 nt.assert_equal(ip.user_ns['var'], 42)
903
911
904 ip.run_line_magic('store', '-d var')
912 ip.run_line_magic('store', '-d var')
905 ip.user_ns['var'] = 39
913 ip.user_ns['var'] = 39
906 ip.run_line_magic('store' , '-r')
914 ip.run_line_magic('store' , '-r')
907 nt.assert_equal(ip.user_ns['var'], 39)
915 nt.assert_equal(ip.user_ns['var'], 39)
908
916
909
917
910 def _run_edit_test(arg_s, exp_filename=None,
918 def _run_edit_test(arg_s, exp_filename=None,
911 exp_lineno=-1,
919 exp_lineno=-1,
912 exp_contents=None,
920 exp_contents=None,
913 exp_is_temp=None):
921 exp_is_temp=None):
914 ip = get_ipython()
922 ip = get_ipython()
915 M = code.CodeMagics(ip)
923 M = code.CodeMagics(ip)
916 last_call = ['','']
924 last_call = ['','']
917 opts,args = M.parse_options(arg_s,'prxn:')
925 opts,args = M.parse_options(arg_s,'prxn:')
918 filename, lineno, is_temp = M._find_edit_target(ip, args, opts, last_call)
926 filename, lineno, is_temp = M._find_edit_target(ip, args, opts, last_call)
919
927
920 if exp_filename is not None:
928 if exp_filename is not None:
921 nt.assert_equal(exp_filename, filename)
929 nt.assert_equal(exp_filename, filename)
922 if exp_contents is not None:
930 if exp_contents is not None:
923 with io.open(filename, 'r', encoding='utf-8') as f:
931 with io.open(filename, 'r', encoding='utf-8') as f:
924 contents = f.read()
932 contents = f.read()
925 nt.assert_equal(exp_contents, contents)
933 nt.assert_equal(exp_contents, contents)
926 if exp_lineno != -1:
934 if exp_lineno != -1:
927 nt.assert_equal(exp_lineno, lineno)
935 nt.assert_equal(exp_lineno, lineno)
928 if exp_is_temp is not None:
936 if exp_is_temp is not None:
929 nt.assert_equal(exp_is_temp, is_temp)
937 nt.assert_equal(exp_is_temp, is_temp)
930
938
931
939
932 def test_edit_interactive():
940 def test_edit_interactive():
933 """%edit on interactively defined objects"""
941 """%edit on interactively defined objects"""
934 ip = get_ipython()
942 ip = get_ipython()
935 n = ip.execution_count
943 n = ip.execution_count
936 ip.run_cell(u"def foo(): return 1", store_history=True)
944 ip.run_cell(u"def foo(): return 1", store_history=True)
937
945
938 try:
946 try:
939 _run_edit_test("foo")
947 _run_edit_test("foo")
940 except code.InteractivelyDefined as e:
948 except code.InteractivelyDefined as e:
941 nt.assert_equal(e.index, n)
949 nt.assert_equal(e.index, n)
942 else:
950 else:
943 raise AssertionError("Should have raised InteractivelyDefined")
951 raise AssertionError("Should have raised InteractivelyDefined")
944
952
945
953
946 def test_edit_cell():
954 def test_edit_cell():
947 """%edit [cell id]"""
955 """%edit [cell id]"""
948 ip = get_ipython()
956 ip = get_ipython()
949
957
950 ip.run_cell(u"def foo(): return 1", store_history=True)
958 ip.run_cell(u"def foo(): return 1", store_history=True)
951
959
952 # test
960 # test
953 _run_edit_test("1", exp_contents=ip.user_ns['In'][1], exp_is_temp=True)
961 _run_edit_test("1", exp_contents=ip.user_ns['In'][1], exp_is_temp=True)
954
962
955 def test_bookmark():
963 def test_bookmark():
956 ip = get_ipython()
964 ip = get_ipython()
957 ip.run_line_magic('bookmark', 'bmname')
965 ip.run_line_magic('bookmark', 'bmname')
958 with tt.AssertPrints('bmname'):
966 with tt.AssertPrints('bmname'):
959 ip.run_line_magic('bookmark', '-l')
967 ip.run_line_magic('bookmark', '-l')
960 ip.run_line_magic('bookmark', '-d bmname')
968 ip.run_line_magic('bookmark', '-d bmname')
961
969
962 def test_ls_magic():
970 def test_ls_magic():
963 ip = get_ipython()
971 ip = get_ipython()
964 json_formatter = ip.display_formatter.formatters['application/json']
972 json_formatter = ip.display_formatter.formatters['application/json']
965 json_formatter.enabled = True
973 json_formatter.enabled = True
966 lsmagic = ip.magic('lsmagic')
974 lsmagic = ip.magic('lsmagic')
967 with warnings.catch_warnings(record=True) as w:
975 with warnings.catch_warnings(record=True) as w:
968 j = json_formatter(lsmagic)
976 j = json_formatter(lsmagic)
969 nt.assert_equal(sorted(j), ['cell', 'line'])
977 nt.assert_equal(sorted(j), ['cell', 'line'])
970 nt.assert_equal(w, []) # no warnings
978 nt.assert_equal(w, []) # no warnings
971
979
972 def test_strip_initial_indent():
980 def test_strip_initial_indent():
973 def sii(s):
981 def sii(s):
974 lines = s.splitlines()
982 lines = s.splitlines()
975 return '\n'.join(code.strip_initial_indent(lines))
983 return '\n'.join(code.strip_initial_indent(lines))
976
984
977 nt.assert_equal(sii(" a = 1\nb = 2"), "a = 1\nb = 2")
985 nt.assert_equal(sii(" a = 1\nb = 2"), "a = 1\nb = 2")
978 nt.assert_equal(sii(" a\n b\nc"), "a\n b\nc")
986 nt.assert_equal(sii(" a\n b\nc"), "a\n b\nc")
979 nt.assert_equal(sii("a\n b"), "a\n b")
987 nt.assert_equal(sii("a\n b"), "a\n b")
General Comments 0
You need to be logged in to leave comments. Login now