##// END OF EJS Templates
test Magic.parse_options with long options
MinRK -
Show More
@@ -1,575 +1,575 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 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15 # Imports
15 # Imports
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17 # Stdlib
17 # Stdlib
18 import os
18 import os
19 import re
19 import re
20 import sys
20 import sys
21 import types
21 import types
22 from getopt import getopt, GetoptError
22 from getopt import getopt, GetoptError
23
23
24 # Our own
24 # Our own
25 from IPython.config.configurable import Configurable
25 from IPython.config.configurable import Configurable
26 from IPython.core import oinspect
26 from IPython.core import oinspect
27 from IPython.core.error import UsageError
27 from IPython.core.error import UsageError
28 from IPython.core.prefilter import ESC_MAGIC
28 from IPython.core.prefilter import ESC_MAGIC
29 from IPython.external.decorator import decorator
29 from IPython.external.decorator import decorator
30 from IPython.utils.ipstruct import Struct
30 from IPython.utils.ipstruct import Struct
31 from IPython.utils.process import arg_split
31 from IPython.utils.process import arg_split
32 from IPython.utils.text import dedent
32 from IPython.utils.text import dedent
33 from IPython.utils.traitlets import Bool, Dict, Instance
33 from IPython.utils.traitlets import Bool, Dict, Instance
34 from IPython.utils.warn import error, warn
34 from IPython.utils.warn import error, warn
35
35
36 #-----------------------------------------------------------------------------
36 #-----------------------------------------------------------------------------
37 # Globals
37 # Globals
38 #-----------------------------------------------------------------------------
38 #-----------------------------------------------------------------------------
39
39
40 # A dict we'll use for each class that has magics, used as temporary storage to
40 # A dict we'll use for each class that has magics, used as temporary storage to
41 # pass information between the @line/cell_magic method decorators and the
41 # pass information between the @line/cell_magic method decorators and the
42 # @magics_class class decorator, because the method decorators have no
42 # @magics_class class decorator, because the method decorators have no
43 # access to the class when they run. See for more details:
43 # access to the class when they run. See for more details:
44 # http://stackoverflow.com/questions/2366713/can-a-python-decorator-of-an-instance-method-access-the-class
44 # http://stackoverflow.com/questions/2366713/can-a-python-decorator-of-an-instance-method-access-the-class
45
45
46 magics = dict(line={}, cell={})
46 magics = dict(line={}, cell={})
47
47
48 magic_kinds = ('line', 'cell')
48 magic_kinds = ('line', 'cell')
49 magic_spec = ('line', 'cell', 'line_cell')
49 magic_spec = ('line', 'cell', 'line_cell')
50
50
51 #-----------------------------------------------------------------------------
51 #-----------------------------------------------------------------------------
52 # Utility classes and functions
52 # Utility classes and functions
53 #-----------------------------------------------------------------------------
53 #-----------------------------------------------------------------------------
54
54
55 class Bunch: pass
55 class Bunch: pass
56
56
57
57
58 def on_off(tag):
58 def on_off(tag):
59 """Return an ON/OFF string for a 1/0 input. Simple utility function."""
59 """Return an ON/OFF string for a 1/0 input. Simple utility function."""
60 return ['OFF','ON'][tag]
60 return ['OFF','ON'][tag]
61
61
62
62
63 def compress_dhist(dh):
63 def compress_dhist(dh):
64 """Compress a directory history into a new one with at most 20 entries.
64 """Compress a directory history into a new one with at most 20 entries.
65
65
66 Return a new list made from the first and last 10 elements of dhist after
66 Return a new list made from the first and last 10 elements of dhist after
67 removal of duplicates.
67 removal of duplicates.
68 """
68 """
69 head, tail = dh[:-10], dh[-10:]
69 head, tail = dh[:-10], dh[-10:]
70
70
71 newhead = []
71 newhead = []
72 done = set()
72 done = set()
73 for h in head:
73 for h in head:
74 if h in done:
74 if h in done:
75 continue
75 continue
76 newhead.append(h)
76 newhead.append(h)
77 done.add(h)
77 done.add(h)
78
78
79 return newhead + tail
79 return newhead + tail
80
80
81
81
82 def needs_local_scope(func):
82 def needs_local_scope(func):
83 """Decorator to mark magic functions which need to local scope to run."""
83 """Decorator to mark magic functions which need to local scope to run."""
84 func.needs_local_scope = True
84 func.needs_local_scope = True
85 return func
85 return func
86
86
87 #-----------------------------------------------------------------------------
87 #-----------------------------------------------------------------------------
88 # Class and method decorators for registering magics
88 # Class and method decorators for registering magics
89 #-----------------------------------------------------------------------------
89 #-----------------------------------------------------------------------------
90
90
91 def magics_class(cls):
91 def magics_class(cls):
92 """Class decorator for all subclasses of the main Magics class.
92 """Class decorator for all subclasses of the main Magics class.
93
93
94 Any class that subclasses Magics *must* also apply this decorator, to
94 Any class that subclasses Magics *must* also apply this decorator, to
95 ensure that all the methods that have been decorated as line/cell magics
95 ensure that all the methods that have been decorated as line/cell magics
96 get correctly registered in the class instance. This is necessary because
96 get correctly registered in the class instance. This is necessary because
97 when method decorators run, the class does not exist yet, so they
97 when method decorators run, the class does not exist yet, so they
98 temporarily store their information into a module global. Application of
98 temporarily store their information into a module global. Application of
99 this class decorator copies that global data to the class instance and
99 this class decorator copies that global data to the class instance and
100 clears the global.
100 clears the global.
101
101
102 Obviously, this mechanism is not thread-safe, which means that the
102 Obviously, this mechanism is not thread-safe, which means that the
103 *creation* of subclasses of Magic should only be done in a single-thread
103 *creation* of subclasses of Magic should only be done in a single-thread
104 context. Instantiation of the classes has no restrictions. Given that
104 context. Instantiation of the classes has no restrictions. Given that
105 these classes are typically created at IPython startup time and before user
105 these classes are typically created at IPython startup time and before user
106 application code becomes active, in practice this should not pose any
106 application code becomes active, in practice this should not pose any
107 problems.
107 problems.
108 """
108 """
109 cls.registered = True
109 cls.registered = True
110 cls.magics = dict(line = magics['line'],
110 cls.magics = dict(line = magics['line'],
111 cell = magics['cell'])
111 cell = magics['cell'])
112 magics['line'] = {}
112 magics['line'] = {}
113 magics['cell'] = {}
113 magics['cell'] = {}
114 return cls
114 return cls
115
115
116
116
117 def record_magic(dct, magic_kind, magic_name, func):
117 def record_magic(dct, magic_kind, magic_name, func):
118 """Utility function to store a function as a magic of a specific kind.
118 """Utility function to store a function as a magic of a specific kind.
119
119
120 Parameters
120 Parameters
121 ----------
121 ----------
122 dct : dict
122 dct : dict
123 A dictionary with 'line' and 'cell' subdicts.
123 A dictionary with 'line' and 'cell' subdicts.
124
124
125 magic_kind : str
125 magic_kind : str
126 Kind of magic to be stored.
126 Kind of magic to be stored.
127
127
128 magic_name : str
128 magic_name : str
129 Key to store the magic as.
129 Key to store the magic as.
130
130
131 func : function
131 func : function
132 Callable object to store.
132 Callable object to store.
133 """
133 """
134 if magic_kind == 'line_cell':
134 if magic_kind == 'line_cell':
135 dct['line'][magic_name] = dct['cell'][magic_name] = func
135 dct['line'][magic_name] = dct['cell'][magic_name] = func
136 else:
136 else:
137 dct[magic_kind][magic_name] = func
137 dct[magic_kind][magic_name] = func
138
138
139
139
140 def validate_type(magic_kind):
140 def validate_type(magic_kind):
141 """Ensure that the given magic_kind is valid.
141 """Ensure that the given magic_kind is valid.
142
142
143 Check that the given magic_kind is one of the accepted spec types (stored
143 Check that the given magic_kind is one of the accepted spec types (stored
144 in the global `magic_spec`), raise ValueError otherwise.
144 in the global `magic_spec`), raise ValueError otherwise.
145 """
145 """
146 if magic_kind not in magic_spec:
146 if magic_kind not in magic_spec:
147 raise ValueError('magic_kind must be one of %s, %s given' %
147 raise ValueError('magic_kind must be one of %s, %s given' %
148 magic_kinds, magic_kind)
148 magic_kinds, magic_kind)
149
149
150
150
151 # The docstrings for the decorator below will be fairly similar for the two
151 # The docstrings for the decorator below will be fairly similar for the two
152 # types (method and function), so we generate them here once and reuse the
152 # types (method and function), so we generate them here once and reuse the
153 # templates below.
153 # templates below.
154 _docstring_template = \
154 _docstring_template = \
155 """Decorate the given {0} as {1} magic.
155 """Decorate the given {0} as {1} magic.
156
156
157 The decorator can be used with or without arguments, as follows.
157 The decorator can be used with or without arguments, as follows.
158
158
159 i) without arguments: it will create a {1} magic named as the {0} being
159 i) without arguments: it will create a {1} magic named as the {0} being
160 decorated::
160 decorated::
161
161
162 @deco
162 @deco
163 def foo(...)
163 def foo(...)
164
164
165 will create a {1} magic named `foo`.
165 will create a {1} magic named `foo`.
166
166
167 ii) with one string argument: which will be used as the actual name of the
167 ii) with one string argument: which will be used as the actual name of the
168 resulting magic::
168 resulting magic::
169
169
170 @deco('bar')
170 @deco('bar')
171 def foo(...)
171 def foo(...)
172
172
173 will create a {1} magic named `bar`.
173 will create a {1} magic named `bar`.
174 """
174 """
175
175
176 # These two are decorator factories. While they are conceptually very similar,
176 # These two are decorator factories. While they are conceptually very similar,
177 # there are enough differences in the details that it's simpler to have them
177 # there are enough differences in the details that it's simpler to have them
178 # written as completely standalone functions rather than trying to share code
178 # written as completely standalone functions rather than trying to share code
179 # and make a single one with convoluted logic.
179 # and make a single one with convoluted logic.
180
180
181 def _method_magic_marker(magic_kind):
181 def _method_magic_marker(magic_kind):
182 """Decorator factory for methods in Magics subclasses.
182 """Decorator factory for methods in Magics subclasses.
183 """
183 """
184
184
185 validate_type(magic_kind)
185 validate_type(magic_kind)
186
186
187 # This is a closure to capture the magic_kind. We could also use a class,
187 # This is a closure to capture the magic_kind. We could also use a class,
188 # but it's overkill for just that one bit of state.
188 # but it's overkill for just that one bit of state.
189 def magic_deco(arg):
189 def magic_deco(arg):
190 call = lambda f, *a, **k: f(*a, **k)
190 call = lambda f, *a, **k: f(*a, **k)
191
191
192 if callable(arg):
192 if callable(arg):
193 # "Naked" decorator call (just @foo, no args)
193 # "Naked" decorator call (just @foo, no args)
194 func = arg
194 func = arg
195 name = func.func_name
195 name = func.func_name
196 retval = decorator(call, func)
196 retval = decorator(call, func)
197 record_magic(magics, magic_kind, name, name)
197 record_magic(magics, magic_kind, name, name)
198 elif isinstance(arg, basestring):
198 elif isinstance(arg, basestring):
199 # Decorator called with arguments (@foo('bar'))
199 # Decorator called with arguments (@foo('bar'))
200 name = arg
200 name = arg
201 def mark(func, *a, **kw):
201 def mark(func, *a, **kw):
202 record_magic(magics, magic_kind, name, func.func_name)
202 record_magic(magics, magic_kind, name, func.func_name)
203 return decorator(call, func)
203 return decorator(call, func)
204 retval = mark
204 retval = mark
205 else:
205 else:
206 raise ValueError("Decorator can only be called with "
206 raise ValueError("Decorator can only be called with "
207 "string or function")
207 "string or function")
208 return retval
208 return retval
209
209
210 # Ensure the resulting decorator has a usable docstring
210 # Ensure the resulting decorator has a usable docstring
211 magic_deco.__doc__ = _docstring_template.format('method', magic_kind)
211 magic_deco.__doc__ = _docstring_template.format('method', magic_kind)
212 return magic_deco
212 return magic_deco
213
213
214
214
215 def _function_magic_marker(magic_kind):
215 def _function_magic_marker(magic_kind):
216 """Decorator factory for standalone functions.
216 """Decorator factory for standalone functions.
217 """
217 """
218 validate_type(magic_kind)
218 validate_type(magic_kind)
219
219
220 # This is a closure to capture the magic_kind. We could also use a class,
220 # This is a closure to capture the magic_kind. We could also use a class,
221 # but it's overkill for just that one bit of state.
221 # but it's overkill for just that one bit of state.
222 def magic_deco(arg):
222 def magic_deco(arg):
223 call = lambda f, *a, **k: f(*a, **k)
223 call = lambda f, *a, **k: f(*a, **k)
224
224
225 # Find get_ipython() in the caller's namespace
225 # Find get_ipython() in the caller's namespace
226 caller = sys._getframe(1)
226 caller = sys._getframe(1)
227 for ns in ['f_locals', 'f_globals', 'f_builtins']:
227 for ns in ['f_locals', 'f_globals', 'f_builtins']:
228 get_ipython = getattr(caller, ns).get('get_ipython')
228 get_ipython = getattr(caller, ns).get('get_ipython')
229 if get_ipython is not None:
229 if get_ipython is not None:
230 break
230 break
231 else:
231 else:
232 raise('Decorator can only run in context where `get_ipython` exists')
232 raise('Decorator can only run in context where `get_ipython` exists')
233
233
234 ip = get_ipython()
234 ip = get_ipython()
235
235
236 if callable(arg):
236 if callable(arg):
237 # "Naked" decorator call (just @foo, no args)
237 # "Naked" decorator call (just @foo, no args)
238 func = arg
238 func = arg
239 name = func.func_name
239 name = func.func_name
240 ip.register_magic_function(func, magic_kind, name)
240 ip.register_magic_function(func, magic_kind, name)
241 retval = decorator(call, func)
241 retval = decorator(call, func)
242 elif isinstance(arg, basestring):
242 elif isinstance(arg, basestring):
243 # Decorator called with arguments (@foo('bar'))
243 # Decorator called with arguments (@foo('bar'))
244 name = arg
244 name = arg
245 def mark(func, *a, **kw):
245 def mark(func, *a, **kw):
246 ip.register_magic_function(func, magic_kind, name)
246 ip.register_magic_function(func, magic_kind, name)
247 return decorator(call, func)
247 return decorator(call, func)
248 retval = mark
248 retval = mark
249 else:
249 else:
250 raise ValueError("Decorator can only be called with "
250 raise ValueError("Decorator can only be called with "
251 "string or function")
251 "string or function")
252 return retval
252 return retval
253
253
254 # Ensure the resulting decorator has a usable docstring
254 # Ensure the resulting decorator has a usable docstring
255 ds = _docstring_template.format('function', magic_kind)
255 ds = _docstring_template.format('function', magic_kind)
256
256
257 ds += dedent("""
257 ds += dedent("""
258 Note: this decorator can only be used in a context where IPython is already
258 Note: this decorator can only be used in a context where IPython is already
259 active, so that the `get_ipython()` call succeeds. You can therefore use
259 active, so that the `get_ipython()` call succeeds. You can therefore use
260 it in your startup files loaded after IPython initializes, but *not* in the
260 it in your startup files loaded after IPython initializes, but *not* in the
261 IPython configuration file itself, which is executed before IPython is
261 IPython configuration file itself, which is executed before IPython is
262 fully up and running. Any file located in the `startup` subdirectory of
262 fully up and running. Any file located in the `startup` subdirectory of
263 your configuration profile will be OK in this sense.
263 your configuration profile will be OK in this sense.
264 """)
264 """)
265
265
266 magic_deco.__doc__ = ds
266 magic_deco.__doc__ = ds
267 return magic_deco
267 return magic_deco
268
268
269
269
270 # Create the actual decorators for public use
270 # Create the actual decorators for public use
271
271
272 # These three are used to decorate methods in class definitions
272 # These three are used to decorate methods in class definitions
273 line_magic = _method_magic_marker('line')
273 line_magic = _method_magic_marker('line')
274 cell_magic = _method_magic_marker('cell')
274 cell_magic = _method_magic_marker('cell')
275 line_cell_magic = _method_magic_marker('line_cell')
275 line_cell_magic = _method_magic_marker('line_cell')
276
276
277 # These three decorate standalone functions and perform the decoration
277 # These three decorate standalone functions and perform the decoration
278 # immediately. They can only run where get_ipython() works
278 # immediately. They can only run where get_ipython() works
279 register_line_magic = _function_magic_marker('line')
279 register_line_magic = _function_magic_marker('line')
280 register_cell_magic = _function_magic_marker('cell')
280 register_cell_magic = _function_magic_marker('cell')
281 register_line_cell_magic = _function_magic_marker('line_cell')
281 register_line_cell_magic = _function_magic_marker('line_cell')
282
282
283 #-----------------------------------------------------------------------------
283 #-----------------------------------------------------------------------------
284 # Core Magic classes
284 # Core Magic classes
285 #-----------------------------------------------------------------------------
285 #-----------------------------------------------------------------------------
286
286
287 class MagicsManager(Configurable):
287 class MagicsManager(Configurable):
288 """Object that handles all magic-related functionality for IPython.
288 """Object that handles all magic-related functionality for IPython.
289 """
289 """
290 # Non-configurable class attributes
290 # Non-configurable class attributes
291
291
292 # A two-level dict, first keyed by magic type, then by magic function, and
292 # A two-level dict, first keyed by magic type, then by magic function, and
293 # holding the actual callable object as value. This is the dict used for
293 # holding the actual callable object as value. This is the dict used for
294 # magic function dispatch
294 # magic function dispatch
295 magics = Dict
295 magics = Dict
296
296
297 # A registry of the original objects that we've been given holding magics.
297 # A registry of the original objects that we've been given holding magics.
298 registry = Dict
298 registry = Dict
299
299
300 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
300 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
301
301
302 auto_magic = Bool(True, config=True, help=
302 auto_magic = Bool(True, config=True, help=
303 "Automatically call line magics without requiring explicit % prefix")
303 "Automatically call line magics without requiring explicit % prefix")
304
304
305 _auto_status = [
305 _auto_status = [
306 'Automagic is OFF, % prefix IS needed for line magics.',
306 'Automagic is OFF, % prefix IS needed for line magics.',
307 'Automagic is ON, % prefix IS NOT needed for line magics.']
307 'Automagic is ON, % prefix IS NOT needed for line magics.']
308
308
309 user_magics = Instance('IPython.core.magics.UserMagics')
309 user_magics = Instance('IPython.core.magics.UserMagics')
310
310
311 def __init__(self, shell=None, config=None, user_magics=None, **traits):
311 def __init__(self, shell=None, config=None, user_magics=None, **traits):
312
312
313 super(MagicsManager, self).__init__(shell=shell, config=config,
313 super(MagicsManager, self).__init__(shell=shell, config=config,
314 user_magics=user_magics, **traits)
314 user_magics=user_magics, **traits)
315 self.magics = dict(line={}, cell={})
315 self.magics = dict(line={}, cell={})
316 # Let's add the user_magics to the registry for uniformity, so *all*
316 # Let's add the user_magics to the registry for uniformity, so *all*
317 # registered magic containers can be found there.
317 # registered magic containers can be found there.
318 self.registry[user_magics.__class__.__name__] = user_magics
318 self.registry[user_magics.__class__.__name__] = user_magics
319
319
320 def auto_status(self):
320 def auto_status(self):
321 """Return descriptive string with automagic status."""
321 """Return descriptive string with automagic status."""
322 return self._auto_status[self.auto_magic]
322 return self._auto_status[self.auto_magic]
323
323
324 def lsmagic(self):
324 def lsmagic(self):
325 """Return a dict of currently available magic functions.
325 """Return a dict of currently available magic functions.
326
326
327 The return dict has the keys 'line' and 'cell', corresponding to the
327 The return dict has the keys 'line' and 'cell', corresponding to the
328 two types of magics we support. Each value is a list of names.
328 two types of magics we support. Each value is a list of names.
329 """
329 """
330 return self.magics
330 return self.magics
331
331
332 def register(self, *magic_objects):
332 def register(self, *magic_objects):
333 """Register one or more instances of Magics.
333 """Register one or more instances of Magics.
334
334
335 Take one or more classes or instances of classes that subclass the main
335 Take one or more classes or instances of classes that subclass the main
336 `core.Magic` class, and register them with IPython to use the magic
336 `core.Magic` class, and register them with IPython to use the magic
337 functions they provide. The registration process will then ensure that
337 functions they provide. The registration process will then ensure that
338 any methods that have decorated to provide line and/or cell magics will
338 any methods that have decorated to provide line and/or cell magics will
339 be recognized with the `%x`/`%%x` syntax as a line/cell magic
339 be recognized with the `%x`/`%%x` syntax as a line/cell magic
340 respectively.
340 respectively.
341
341
342 If classes are given, they will be instantiated with the default
342 If classes are given, they will be instantiated with the default
343 constructor. If your classes need a custom constructor, you should
343 constructor. If your classes need a custom constructor, you should
344 instanitate them first and pass the instance.
344 instanitate them first and pass the instance.
345
345
346 The provided arguments can be an arbitrary mix of classes and instances.
346 The provided arguments can be an arbitrary mix of classes and instances.
347
347
348 Parameters
348 Parameters
349 ----------
349 ----------
350 magic_objects : one or more classes or instances
350 magic_objects : one or more classes or instances
351 """
351 """
352 # Start by validating them to ensure they have all had their magic
352 # Start by validating them to ensure they have all had their magic
353 # methods registered at the instance level
353 # methods registered at the instance level
354 for m in magic_objects:
354 for m in magic_objects:
355 if not m.registered:
355 if not m.registered:
356 raise ValueError("Class of magics %r was constructed without "
356 raise ValueError("Class of magics %r was constructed without "
357 "the @register_macics class decorator")
357 "the @register_macics class decorator")
358 if type(m) is type:
358 if type(m) is type:
359 # If we're given an uninstantiated class
359 # If we're given an uninstantiated class
360 m = m(self.shell)
360 m = m(self.shell)
361
361
362 # Now that we have an instance, we can register it and update the
362 # Now that we have an instance, we can register it and update the
363 # table of callables
363 # table of callables
364 self.registry[m.__class__.__name__] = m
364 self.registry[m.__class__.__name__] = m
365 for mtype in magic_kinds:
365 for mtype in magic_kinds:
366 self.magics[mtype].update(m.magics[mtype])
366 self.magics[mtype].update(m.magics[mtype])
367
367
368 def register_function(self, func, magic_kind='line', magic_name=None):
368 def register_function(self, func, magic_kind='line', magic_name=None):
369 """Expose a standalone function as magic function for IPython.
369 """Expose a standalone function as magic function for IPython.
370
370
371 This will create an IPython magic (line, cell or both) from a
371 This will create an IPython magic (line, cell or both) from a
372 standalone function. The functions should have the following
372 standalone function. The functions should have the following
373 signatures:
373 signatures:
374
374
375 * For line magics: `def f(line)`
375 * For line magics: `def f(line)`
376 * For cell magics: `def f(line, cell)`
376 * For cell magics: `def f(line, cell)`
377 * For a function that does both: `def f(line, cell=None)`
377 * For a function that does both: `def f(line, cell=None)`
378
378
379 In the latter case, the function will be called with `cell==None` when
379 In the latter case, the function will be called with `cell==None` when
380 invoked as `%f`, and with cell as a string when invoked as `%%f`.
380 invoked as `%f`, and with cell as a string when invoked as `%%f`.
381
381
382 Parameters
382 Parameters
383 ----------
383 ----------
384 func : callable
384 func : callable
385 Function to be registered as a magic.
385 Function to be registered as a magic.
386
386
387 magic_kind : str
387 magic_kind : str
388 Kind of magic, one of 'line', 'cell' or 'line_cell'
388 Kind of magic, one of 'line', 'cell' or 'line_cell'
389
389
390 magic_name : optional str
390 magic_name : optional str
391 If given, the name the magic will have in the IPython namespace. By
391 If given, the name the magic will have in the IPython namespace. By
392 default, the name of the function itself is used.
392 default, the name of the function itself is used.
393 """
393 """
394
394
395 # Create the new method in the user_magics and register it in the
395 # Create the new method in the user_magics and register it in the
396 # global table
396 # global table
397 validate_type(magic_kind)
397 validate_type(magic_kind)
398 magic_name = func.func_name if magic_name is None else magic_name
398 magic_name = func.func_name if magic_name is None else magic_name
399 setattr(self.user_magics, magic_name, func)
399 setattr(self.user_magics, magic_name, func)
400 record_magic(self.magics, magic_kind, magic_name, func)
400 record_magic(self.magics, magic_kind, magic_name, func)
401
401
402 def define_magic(self, name, func):
402 def define_magic(self, name, func):
403 """[Deprecated] Expose own function as magic function for IPython.
403 """[Deprecated] Expose own function as magic function for IPython.
404
404
405 Example::
405 Example::
406
406
407 def foo_impl(self, parameter_s=''):
407 def foo_impl(self, parameter_s=''):
408 'My very own magic!. (Use docstrings, IPython reads them).'
408 'My very own magic!. (Use docstrings, IPython reads them).'
409 print 'Magic function. Passed parameter is between < >:'
409 print 'Magic function. Passed parameter is between < >:'
410 print '<%s>' % parameter_s
410 print '<%s>' % parameter_s
411 print 'The self object is:', self
411 print 'The self object is:', self
412
412
413 ip.define_magic('foo',foo_impl)
413 ip.define_magic('foo',foo_impl)
414 """
414 """
415 meth = types.MethodType(func, self.user_magics)
415 meth = types.MethodType(func, self.user_magics)
416 setattr(self.user_magics, name, meth)
416 setattr(self.user_magics, name, meth)
417 record_magic(self.magics, 'line', name, meth)
417 record_magic(self.magics, 'line', name, meth)
418
418
419 # Key base class that provides the central functionality for magics.
419 # Key base class that provides the central functionality for magics.
420
420
421 class Magics(object):
421 class Magics(object):
422 """Base class for implementing magic functions.
422 """Base class for implementing magic functions.
423
423
424 Shell functions which can be reached as %function_name. All magic
424 Shell functions which can be reached as %function_name. All magic
425 functions should accept a string, which they can parse for their own
425 functions should accept a string, which they can parse for their own
426 needs. This can make some functions easier to type, eg `%cd ../`
426 needs. This can make some functions easier to type, eg `%cd ../`
427 vs. `%cd("../")`
427 vs. `%cd("../")`
428
428
429 Classes providing magic functions need to subclass this class, and they
429 Classes providing magic functions need to subclass this class, and they
430 MUST:
430 MUST:
431
431
432 - Use the method decorators `@line_magic` and `@cell_magic` to decorate
432 - Use the method decorators `@line_magic` and `@cell_magic` to decorate
433 individual methods as magic functions, AND
433 individual methods as magic functions, AND
434
434
435 - Use the class decorator `@magics_class` to ensure that the magic
435 - Use the class decorator `@magics_class` to ensure that the magic
436 methods are properly registered at the instance level upon instance
436 methods are properly registered at the instance level upon instance
437 initialization.
437 initialization.
438
438
439 See :mod:`magic_functions` for examples of actual implementation classes.
439 See :mod:`magic_functions` for examples of actual implementation classes.
440 """
440 """
441 # Dict holding all command-line options for each magic.
441 # Dict holding all command-line options for each magic.
442 options_table = None
442 options_table = None
443 # Dict for the mapping of magic names to methods, set by class decorator
443 # Dict for the mapping of magic names to methods, set by class decorator
444 magics = None
444 magics = None
445 # Flag to check that the class decorator was properly applied
445 # Flag to check that the class decorator was properly applied
446 registered = False
446 registered = False
447 # Instance of IPython shell
447 # Instance of IPython shell
448 shell = None
448 shell = None
449
449
450 def __init__(self, shell):
450 def __init__(self, shell):
451 if not(self.__class__.registered):
451 if not(self.__class__.registered):
452 raise ValueError('Magics subclass without registration - '
452 raise ValueError('Magics subclass without registration - '
453 'did you forget to apply @magics_class?')
453 'did you forget to apply @magics_class?')
454 self.shell = shell
454 self.shell = shell
455 self.options_table = {}
455 self.options_table = {}
456 # The method decorators are run when the instance doesn't exist yet, so
456 # The method decorators are run when the instance doesn't exist yet, so
457 # they can only record the names of the methods they are supposed to
457 # they can only record the names of the methods they are supposed to
458 # grab. Only now, that the instance exists, can we create the proper
458 # grab. Only now, that the instance exists, can we create the proper
459 # mapping to bound methods. So we read the info off the original names
459 # mapping to bound methods. So we read the info off the original names
460 # table and replace each method name by the actual bound method.
460 # table and replace each method name by the actual bound method.
461 for mtype in magic_kinds:
461 for mtype in magic_kinds:
462 tab = self.magics[mtype]
462 tab = self.magics[mtype]
463 # must explicitly use keys, as we're mutating this puppy
463 # must explicitly use keys, as we're mutating this puppy
464 for magic_name in tab.keys():
464 for magic_name in tab.keys():
465 meth_name = tab[magic_name]
465 meth_name = tab[magic_name]
466 if isinstance(meth_name, basestring):
466 if isinstance(meth_name, basestring):
467 tab[magic_name] = getattr(self, meth_name)
467 tab[magic_name] = getattr(self, meth_name)
468
468
469 def arg_err(self,func):
469 def arg_err(self,func):
470 """Print docstring if incorrect arguments were passed"""
470 """Print docstring if incorrect arguments were passed"""
471 print 'Error in arguments:'
471 print 'Error in arguments:'
472 print oinspect.getdoc(func)
472 print oinspect.getdoc(func)
473
473
474 def format_latex(self, strng):
474 def format_latex(self, strng):
475 """Format a string for latex inclusion."""
475 """Format a string for latex inclusion."""
476
476
477 # Characters that need to be escaped for latex:
477 # Characters that need to be escaped for latex:
478 escape_re = re.compile(r'(%|_|\$|#|&)',re.MULTILINE)
478 escape_re = re.compile(r'(%|_|\$|#|&)',re.MULTILINE)
479 # Magic command names as headers:
479 # Magic command names as headers:
480 cmd_name_re = re.compile(r'^(%s.*?):' % ESC_MAGIC,
480 cmd_name_re = re.compile(r'^(%s.*?):' % ESC_MAGIC,
481 re.MULTILINE)
481 re.MULTILINE)
482 # Magic commands
482 # Magic commands
483 cmd_re = re.compile(r'(?P<cmd>%s.+?\b)(?!\}\}:)' % ESC_MAGIC,
483 cmd_re = re.compile(r'(?P<cmd>%s.+?\b)(?!\}\}:)' % ESC_MAGIC,
484 re.MULTILINE)
484 re.MULTILINE)
485 # Paragraph continue
485 # Paragraph continue
486 par_re = re.compile(r'\\$',re.MULTILINE)
486 par_re = re.compile(r'\\$',re.MULTILINE)
487
487
488 # The "\n" symbol
488 # The "\n" symbol
489 newline_re = re.compile(r'\\n')
489 newline_re = re.compile(r'\\n')
490
490
491 # Now build the string for output:
491 # Now build the string for output:
492 #strng = cmd_name_re.sub(r'\n\\texttt{\\textsl{\\large \1}}:',strng)
492 #strng = cmd_name_re.sub(r'\n\\texttt{\\textsl{\\large \1}}:',strng)
493 strng = cmd_name_re.sub(r'\n\\bigskip\n\\texttt{\\textbf{ \1}}:',
493 strng = cmd_name_re.sub(r'\n\\bigskip\n\\texttt{\\textbf{ \1}}:',
494 strng)
494 strng)
495 strng = cmd_re.sub(r'\\texttt{\g<cmd>}',strng)
495 strng = cmd_re.sub(r'\\texttt{\g<cmd>}',strng)
496 strng = par_re.sub(r'\\\\',strng)
496 strng = par_re.sub(r'\\\\',strng)
497 strng = escape_re.sub(r'\\\1',strng)
497 strng = escape_re.sub(r'\\\1',strng)
498 strng = newline_re.sub(r'\\textbackslash{}n',strng)
498 strng = newline_re.sub(r'\\textbackslash{}n',strng)
499 return strng
499 return strng
500
500
501 def parse_options(self, arg_str, opt_str, *long_opts, **kw):
501 def parse_options(self, arg_str, opt_str, *long_opts, **kw):
502 """Parse options passed to an argument string.
502 """Parse options passed to an argument string.
503
503
504 The interface is similar to that of getopt(), but it returns back a
504 The interface is similar to that of getopt(), but it returns back a
505 Struct with the options as keys and the stripped argument string still
505 Struct with the options as keys and the stripped argument string still
506 as a string.
506 as a string.
507
507
508 arg_str is quoted as a true sys.argv vector by using shlex.split.
508 arg_str is quoted as a true sys.argv vector by using shlex.split.
509 This allows us to easily expand variables, glob files, quote
509 This allows us to easily expand variables, glob files, quote
510 arguments, etc.
510 arguments, etc.
511
511
512 Options:
512 Options:
513 -mode: default 'string'. If given as 'list', the argument string is
513 -mode: default 'string'. If given as 'list', the argument string is
514 returned as a list (split on whitespace) instead of a string.
514 returned as a list (split on whitespace) instead of a string.
515
515
516 -list_all: put all option values in lists. Normally only options
516 -list_all: put all option values in lists. Normally only options
517 appearing more than once are put in a list.
517 appearing more than once are put in a list.
518
518
519 -posix (True): whether to split the input line in POSIX mode or not,
519 -posix (True): whether to split the input line in POSIX mode or not,
520 as per the conventions outlined in the shlex module from the
520 as per the conventions outlined in the shlex module from the
521 standard library."""
521 standard library."""
522
522
523 # inject default options at the beginning of the input line
523 # inject default options at the beginning of the input line
524 caller = sys._getframe(1).f_code.co_name
524 caller = sys._getframe(1).f_code.co_name
525 arg_str = '%s %s' % (self.options_table.get(caller,''),arg_str)
525 arg_str = '%s %s' % (self.options_table.get(caller,''),arg_str)
526
526
527 mode = kw.get('mode','string')
527 mode = kw.get('mode','string')
528 if mode not in ['string','list']:
528 if mode not in ['string','list']:
529 raise ValueError,'incorrect mode given: %s' % mode
529 raise ValueError,'incorrect mode given: %s' % mode
530 # Get options
530 # Get options
531 list_all = kw.get('list_all',0)
531 list_all = kw.get('list_all',0)
532 posix = kw.get('posix', os.name == 'posix')
532 posix = kw.get('posix', os.name == 'posix')
533 strict = kw.get('strict', True)
533 strict = kw.get('strict', True)
534
534
535 # Check if we have more than one argument to warrant extra processing:
535 # Check if we have more than one argument to warrant extra processing:
536 odict = {} # Dictionary with options
536 odict = {} # Dictionary with options
537 args = arg_str.split()
537 args = arg_str.split()
538 if len(args) >= 1:
538 if len(args) >= 1:
539 # If the list of inputs only has 0 or 1 thing in it, there's no
539 # If the list of inputs only has 0 or 1 thing in it, there's no
540 # need to look for options
540 # need to look for options
541 argv = arg_split(arg_str, posix, strict)
541 argv = arg_split(arg_str, posix, strict)
542 # Do regular option processing
542 # Do regular option processing
543 try:
543 try:
544 opts,args = getopt(argv,opt_str,*long_opts)
544 opts,args = getopt(argv, opt_str, long_opts)
545 except GetoptError,e:
545 except GetoptError,e:
546 raise UsageError('%s ( allowed: "%s" %s)' % (e.msg,opt_str,
546 raise UsageError('%s ( allowed: "%s" %s)' % (e.msg,opt_str,
547 " ".join(long_opts)))
547 " ".join(long_opts)))
548 for o,a in opts:
548 for o,a in opts:
549 if o.startswith('--'):
549 if o.startswith('--'):
550 o = o[2:]
550 o = o[2:]
551 else:
551 else:
552 o = o[1:]
552 o = o[1:]
553 try:
553 try:
554 odict[o].append(a)
554 odict[o].append(a)
555 except AttributeError:
555 except AttributeError:
556 odict[o] = [odict[o],a]
556 odict[o] = [odict[o],a]
557 except KeyError:
557 except KeyError:
558 if list_all:
558 if list_all:
559 odict[o] = [a]
559 odict[o] = [a]
560 else:
560 else:
561 odict[o] = a
561 odict[o] = a
562
562
563 # Prepare opts,args for return
563 # Prepare opts,args for return
564 opts = Struct(odict)
564 opts = Struct(odict)
565 if mode == 'string':
565 if mode == 'string':
566 args = ' '.join(args)
566 args = ' '.join(args)
567
567
568 return opts,args
568 return opts,args
569
569
570 def default_option(self, fn, optstr):
570 def default_option(self, fn, optstr):
571 """Make an entry in the options_table for fn, with value optstr"""
571 """Make an entry in the options_table for fn, with value optstr"""
572
572
573 if fn not in self.lsmagic():
573 if fn not in self.lsmagic():
574 error("%s is not a magic function" % fn)
574 error("%s is not a magic function" % fn)
575 self.options_table[fn] = optstr
575 self.options_table[fn] = optstr
@@ -1,547 +1,556 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 from __future__ import absolute_import
6 from __future__ import absolute_import
7
7
8 #-----------------------------------------------------------------------------
8 #-----------------------------------------------------------------------------
9 # Imports
9 # Imports
10 #-----------------------------------------------------------------------------
10 #-----------------------------------------------------------------------------
11
11
12 import io
12 import io
13 import os
13 import os
14 import sys
14 import sys
15 from StringIO import StringIO
15 from StringIO import StringIO
16 from unittest import TestCase
16 from unittest import TestCase
17
17
18 import nose.tools as nt
18 import nose.tools as nt
19
19
20 from IPython.core import magic
20 from IPython.core import magic
21 from IPython.core.magic import (Magics, magics_class, line_magic,
21 from IPython.core.magic import (Magics, magics_class, line_magic,
22 cell_magic, line_cell_magic,
22 cell_magic, line_cell_magic,
23 register_line_magic, register_cell_magic,
23 register_line_magic, register_cell_magic,
24 register_line_cell_magic)
24 register_line_cell_magic)
25 from IPython.core.magics import execution
25 from IPython.core.magics import execution
26 from IPython.nbformat.v3.tests.nbexamples import nb0
26 from IPython.nbformat.v3.tests.nbexamples import nb0
27 from IPython.nbformat import current
27 from IPython.nbformat import current
28 from IPython.testing import decorators as dec
28 from IPython.testing import decorators as dec
29 from IPython.testing import tools as tt
29 from IPython.testing import tools as tt
30 from IPython.utils import py3compat
30 from IPython.utils import py3compat
31 from IPython.utils.tempdir import TemporaryDirectory
31 from IPython.utils.tempdir import TemporaryDirectory
32
32
33 #-----------------------------------------------------------------------------
33 #-----------------------------------------------------------------------------
34 # Test functions begin
34 # Test functions begin
35 #-----------------------------------------------------------------------------
35 #-----------------------------------------------------------------------------
36
36
37 @magic.magics_class
37 @magic.magics_class
38 class DummyMagics(magic.Magics): pass
38 class DummyMagics(magic.Magics): pass
39
39
40 def test_rehashx():
40 def test_rehashx():
41 # clear up everything
41 # clear up everything
42 _ip = get_ipython()
42 _ip = get_ipython()
43 _ip.alias_manager.alias_table.clear()
43 _ip.alias_manager.alias_table.clear()
44 del _ip.db['syscmdlist']
44 del _ip.db['syscmdlist']
45
45
46 _ip.magic('rehashx')
46 _ip.magic('rehashx')
47 # Practically ALL ipython development systems will have more than 10 aliases
47 # Practically ALL ipython development systems will have more than 10 aliases
48
48
49 yield (nt.assert_true, len(_ip.alias_manager.alias_table) > 10)
49 yield (nt.assert_true, len(_ip.alias_manager.alias_table) > 10)
50 for key, val in _ip.alias_manager.alias_table.iteritems():
50 for key, val in _ip.alias_manager.alias_table.iteritems():
51 # we must strip dots from alias names
51 # we must strip dots from alias names
52 nt.assert_true('.' not in key)
52 nt.assert_true('.' not in key)
53
53
54 # rehashx must fill up syscmdlist
54 # rehashx must fill up syscmdlist
55 scoms = _ip.db['syscmdlist']
55 scoms = _ip.db['syscmdlist']
56 yield (nt.assert_true, len(scoms) > 10)
56 yield (nt.assert_true, len(scoms) > 10)
57
57
58
58
59 def test_magic_parse_options():
59 def test_magic_parse_options():
60 """Test that we don't mangle paths when parsing magic options."""
60 """Test that we don't mangle paths when parsing magic options."""
61 ip = get_ipython()
61 ip = get_ipython()
62 path = 'c:\\x'
62 path = 'c:\\x'
63 m = DummyMagics(ip)
63 m = DummyMagics(ip)
64 opts = m.parse_options('-f %s' % path,'f:')[0]
64 opts = m.parse_options('-f %s' % path,'f:')[0]
65 # argv splitting is os-dependent
65 # argv splitting is os-dependent
66 if os.name == 'posix':
66 if os.name == 'posix':
67 expected = 'c:x'
67 expected = 'c:x'
68 else:
68 else:
69 expected = path
69 expected = path
70 nt.assert_equals(opts['f'], expected)
70 nt.assert_equals(opts['f'], expected)
71
71
72 def test_magic_parse_long_options():
73 """Magic.parse_options can handle --foo=bar long options"""
74 ip = get_ipython()
75 m = DummyMagics(ip)
76 opts, _ = m.parse_options('--foo --bar=bubble', 'a', 'foo', 'bar=')
77 nt.assert_true('foo' in opts)
78 nt.assert_true('bar' in opts)
79 nt.assert_true(opts['bar'], "bubble")
80
72
81
73 @dec.skip_without('sqlite3')
82 @dec.skip_without('sqlite3')
74 def doctest_hist_f():
83 def doctest_hist_f():
75 """Test %hist -f with temporary filename.
84 """Test %hist -f with temporary filename.
76
85
77 In [9]: import tempfile
86 In [9]: import tempfile
78
87
79 In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-')
88 In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-')
80
89
81 In [11]: %hist -nl -f $tfile 3
90 In [11]: %hist -nl -f $tfile 3
82
91
83 In [13]: import os; os.unlink(tfile)
92 In [13]: import os; os.unlink(tfile)
84 """
93 """
85
94
86
95
87 @dec.skip_without('sqlite3')
96 @dec.skip_without('sqlite3')
88 def doctest_hist_r():
97 def doctest_hist_r():
89 """Test %hist -r
98 """Test %hist -r
90
99
91 XXX - This test is not recording the output correctly. For some reason, in
100 XXX - This test is not recording the output correctly. For some reason, in
92 testing mode the raw history isn't getting populated. No idea why.
101 testing mode the raw history isn't getting populated. No idea why.
93 Disabling the output checking for now, though at least we do run it.
102 Disabling the output checking for now, though at least we do run it.
94
103
95 In [1]: 'hist' in _ip.lsmagic()
104 In [1]: 'hist' in _ip.lsmagic()
96 Out[1]: True
105 Out[1]: True
97
106
98 In [2]: x=1
107 In [2]: x=1
99
108
100 In [3]: %hist -rl 2
109 In [3]: %hist -rl 2
101 x=1 # random
110 x=1 # random
102 %hist -r 2
111 %hist -r 2
103 """
112 """
104
113
105
114
106 @dec.skip_without('sqlite3')
115 @dec.skip_without('sqlite3')
107 def doctest_hist_op():
116 def doctest_hist_op():
108 """Test %hist -op
117 """Test %hist -op
109
118
110 In [1]: class b(float):
119 In [1]: class b(float):
111 ...: pass
120 ...: pass
112 ...:
121 ...:
113
122
114 In [2]: class s(object):
123 In [2]: class s(object):
115 ...: def __str__(self):
124 ...: def __str__(self):
116 ...: return 's'
125 ...: return 's'
117 ...:
126 ...:
118
127
119 In [3]:
128 In [3]:
120
129
121 In [4]: class r(b):
130 In [4]: class r(b):
122 ...: def __repr__(self):
131 ...: def __repr__(self):
123 ...: return 'r'
132 ...: return 'r'
124 ...:
133 ...:
125
134
126 In [5]: class sr(s,r): pass
135 In [5]: class sr(s,r): pass
127 ...:
136 ...:
128
137
129 In [6]:
138 In [6]:
130
139
131 In [7]: bb=b()
140 In [7]: bb=b()
132
141
133 In [8]: ss=s()
142 In [8]: ss=s()
134
143
135 In [9]: rr=r()
144 In [9]: rr=r()
136
145
137 In [10]: ssrr=sr()
146 In [10]: ssrr=sr()
138
147
139 In [11]: 4.5
148 In [11]: 4.5
140 Out[11]: 4.5
149 Out[11]: 4.5
141
150
142 In [12]: str(ss)
151 In [12]: str(ss)
143 Out[12]: 's'
152 Out[12]: 's'
144
153
145 In [13]:
154 In [13]:
146
155
147 In [14]: %hist -op
156 In [14]: %hist -op
148 >>> class b:
157 >>> class b:
149 ... pass
158 ... pass
150 ...
159 ...
151 >>> class s(b):
160 >>> class s(b):
152 ... def __str__(self):
161 ... def __str__(self):
153 ... return 's'
162 ... return 's'
154 ...
163 ...
155 >>>
164 >>>
156 >>> class r(b):
165 >>> class r(b):
157 ... def __repr__(self):
166 ... def __repr__(self):
158 ... return 'r'
167 ... return 'r'
159 ...
168 ...
160 >>> class sr(s,r): pass
169 >>> class sr(s,r): pass
161 >>>
170 >>>
162 >>> bb=b()
171 >>> bb=b()
163 >>> ss=s()
172 >>> ss=s()
164 >>> rr=r()
173 >>> rr=r()
165 >>> ssrr=sr()
174 >>> ssrr=sr()
166 >>> 4.5
175 >>> 4.5
167 4.5
176 4.5
168 >>> str(ss)
177 >>> str(ss)
169 's'
178 's'
170 >>>
179 >>>
171 """
180 """
172
181
173
182
174 @dec.skip_without('sqlite3')
183 @dec.skip_without('sqlite3')
175 def test_macro():
184 def test_macro():
176 ip = get_ipython()
185 ip = get_ipython()
177 ip.history_manager.reset() # Clear any existing history.
186 ip.history_manager.reset() # Clear any existing history.
178 cmds = ["a=1", "def b():\n return a**2", "print(a,b())"]
187 cmds = ["a=1", "def b():\n return a**2", "print(a,b())"]
179 for i, cmd in enumerate(cmds, start=1):
188 for i, cmd in enumerate(cmds, start=1):
180 ip.history_manager.store_inputs(i, cmd)
189 ip.history_manager.store_inputs(i, cmd)
181 ip.magic("macro test 1-3")
190 ip.magic("macro test 1-3")
182 nt.assert_equal(ip.user_ns["test"].value, "\n".join(cmds)+"\n")
191 nt.assert_equal(ip.user_ns["test"].value, "\n".join(cmds)+"\n")
183
192
184 # List macros.
193 # List macros.
185 assert "test" in ip.magic("macro")
194 assert "test" in ip.magic("macro")
186
195
187
196
188 @dec.skip_without('sqlite3')
197 @dec.skip_without('sqlite3')
189 def test_macro_run():
198 def test_macro_run():
190 """Test that we can run a multi-line macro successfully."""
199 """Test that we can run a multi-line macro successfully."""
191 ip = get_ipython()
200 ip = get_ipython()
192 ip.history_manager.reset()
201 ip.history_manager.reset()
193 cmds = ["a=10", "a+=1", py3compat.doctest_refactor_print("print a"),
202 cmds = ["a=10", "a+=1", py3compat.doctest_refactor_print("print a"),
194 "%macro test 2-3"]
203 "%macro test 2-3"]
195 for cmd in cmds:
204 for cmd in cmds:
196 ip.run_cell(cmd, store_history=True)
205 ip.run_cell(cmd, store_history=True)
197 nt.assert_equal(ip.user_ns["test"].value,
206 nt.assert_equal(ip.user_ns["test"].value,
198 py3compat.doctest_refactor_print("a+=1\nprint a\n"))
207 py3compat.doctest_refactor_print("a+=1\nprint a\n"))
199 with tt.AssertPrints("12"):
208 with tt.AssertPrints("12"):
200 ip.run_cell("test")
209 ip.run_cell("test")
201 with tt.AssertPrints("13"):
210 with tt.AssertPrints("13"):
202 ip.run_cell("test")
211 ip.run_cell("test")
203
212
204
213
205 @dec.skipif_not_numpy
214 @dec.skipif_not_numpy
206 def test_numpy_reset_array_undec():
215 def test_numpy_reset_array_undec():
207 "Test '%reset array' functionality"
216 "Test '%reset array' functionality"
208 _ip.ex('import numpy as np')
217 _ip.ex('import numpy as np')
209 _ip.ex('a = np.empty(2)')
218 _ip.ex('a = np.empty(2)')
210 yield (nt.assert_true, 'a' in _ip.user_ns)
219 yield (nt.assert_true, 'a' in _ip.user_ns)
211 _ip.magic('reset -f array')
220 _ip.magic('reset -f array')
212 yield (nt.assert_false, 'a' in _ip.user_ns)
221 yield (nt.assert_false, 'a' in _ip.user_ns)
213
222
214 def test_reset_out():
223 def test_reset_out():
215 "Test '%reset out' magic"
224 "Test '%reset out' magic"
216 _ip.run_cell("parrot = 'dead'", store_history=True)
225 _ip.run_cell("parrot = 'dead'", store_history=True)
217 # test '%reset -f out', make an Out prompt
226 # test '%reset -f out', make an Out prompt
218 _ip.run_cell("parrot", store_history=True)
227 _ip.run_cell("parrot", store_history=True)
219 nt.assert_true('dead' in [_ip.user_ns[x] for x in '_','__','___'])
228 nt.assert_true('dead' in [_ip.user_ns[x] for x in '_','__','___'])
220 _ip.magic('reset -f out')
229 _ip.magic('reset -f out')
221 nt.assert_false('dead' in [_ip.user_ns[x] for x in '_','__','___'])
230 nt.assert_false('dead' in [_ip.user_ns[x] for x in '_','__','___'])
222 nt.assert_true(len(_ip.user_ns['Out']) == 0)
231 nt.assert_true(len(_ip.user_ns['Out']) == 0)
223
232
224 def test_reset_in():
233 def test_reset_in():
225 "Test '%reset in' magic"
234 "Test '%reset in' magic"
226 # test '%reset -f in'
235 # test '%reset -f in'
227 _ip.run_cell("parrot", store_history=True)
236 _ip.run_cell("parrot", store_history=True)
228 nt.assert_true('parrot' in [_ip.user_ns[x] for x in '_i','_ii','_iii'])
237 nt.assert_true('parrot' in [_ip.user_ns[x] for x in '_i','_ii','_iii'])
229 _ip.magic('%reset -f in')
238 _ip.magic('%reset -f in')
230 nt.assert_false('parrot' in [_ip.user_ns[x] for x in '_i','_ii','_iii'])
239 nt.assert_false('parrot' in [_ip.user_ns[x] for x in '_i','_ii','_iii'])
231 nt.assert_true(len(set(_ip.user_ns['In'])) == 1)
240 nt.assert_true(len(set(_ip.user_ns['In'])) == 1)
232
241
233 def test_reset_dhist():
242 def test_reset_dhist():
234 "Test '%reset dhist' magic"
243 "Test '%reset dhist' magic"
235 _ip.run_cell("tmp = [d for d in _dh]") # copy before clearing
244 _ip.run_cell("tmp = [d for d in _dh]") # copy before clearing
236 _ip.magic('cd ' + os.path.dirname(nt.__file__))
245 _ip.magic('cd ' + os.path.dirname(nt.__file__))
237 _ip.magic('cd -')
246 _ip.magic('cd -')
238 nt.assert_true(len(_ip.user_ns['_dh']) > 0)
247 nt.assert_true(len(_ip.user_ns['_dh']) > 0)
239 _ip.magic('reset -f dhist')
248 _ip.magic('reset -f dhist')
240 nt.assert_true(len(_ip.user_ns['_dh']) == 0)
249 nt.assert_true(len(_ip.user_ns['_dh']) == 0)
241 _ip.run_cell("_dh = [d for d in tmp]") #restore
250 _ip.run_cell("_dh = [d for d in tmp]") #restore
242
251
243 def test_reset_in_length():
252 def test_reset_in_length():
244 "Test that '%reset in' preserves In[] length"
253 "Test that '%reset in' preserves In[] length"
245 _ip.run_cell("print 'foo'")
254 _ip.run_cell("print 'foo'")
246 _ip.run_cell("reset -f in")
255 _ip.run_cell("reset -f in")
247 nt.assert_true(len(_ip.user_ns['In']) == _ip.displayhook.prompt_count+1)
256 nt.assert_true(len(_ip.user_ns['In']) == _ip.displayhook.prompt_count+1)
248
257
249 def test_time():
258 def test_time():
250 _ip.magic('time None')
259 _ip.magic('time None')
251
260
252 def test_tb_syntaxerror():
261 def test_tb_syntaxerror():
253 """test %tb after a SyntaxError"""
262 """test %tb after a SyntaxError"""
254 ip = get_ipython()
263 ip = get_ipython()
255 ip.run_cell("for")
264 ip.run_cell("for")
256
265
257 # trap and validate stdout
266 # trap and validate stdout
258 save_stdout = sys.stdout
267 save_stdout = sys.stdout
259 try:
268 try:
260 sys.stdout = StringIO()
269 sys.stdout = StringIO()
261 ip.run_cell("%tb")
270 ip.run_cell("%tb")
262 out = sys.stdout.getvalue()
271 out = sys.stdout.getvalue()
263 finally:
272 finally:
264 sys.stdout = save_stdout
273 sys.stdout = save_stdout
265 # trim output, and only check the last line
274 # trim output, and only check the last line
266 last_line = out.rstrip().splitlines()[-1].strip()
275 last_line = out.rstrip().splitlines()[-1].strip()
267 nt.assert_equals(last_line, "SyntaxError: invalid syntax")
276 nt.assert_equals(last_line, "SyntaxError: invalid syntax")
268
277
269
278
270 @py3compat.doctest_refactor_print
279 @py3compat.doctest_refactor_print
271 def doctest_time():
280 def doctest_time():
272 """
281 """
273 In [10]: %time None
282 In [10]: %time None
274 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
283 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
275 Wall time: 0.00 s
284 Wall time: 0.00 s
276
285
277 In [11]: def f(kmjy):
286 In [11]: def f(kmjy):
278 ....: %time print 2*kmjy
287 ....: %time print 2*kmjy
279
288
280 In [12]: f(3)
289 In [12]: f(3)
281 6
290 6
282 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
291 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
283 Wall time: 0.00 s
292 Wall time: 0.00 s
284 """
293 """
285
294
286
295
287 def test_doctest_mode():
296 def test_doctest_mode():
288 "Toggle doctest_mode twice, it should be a no-op and run without error"
297 "Toggle doctest_mode twice, it should be a no-op and run without error"
289 _ip.magic('doctest_mode')
298 _ip.magic('doctest_mode')
290 _ip.magic('doctest_mode')
299 _ip.magic('doctest_mode')
291
300
292
301
293 def test_parse_options():
302 def test_parse_options():
294 """Tests for basic options parsing in magics."""
303 """Tests for basic options parsing in magics."""
295 # These are only the most minimal of tests, more should be added later. At
304 # These are only the most minimal of tests, more should be added later. At
296 # the very least we check that basic text/unicode calls work OK.
305 # the very least we check that basic text/unicode calls work OK.
297 m = DummyMagics(_ip)
306 m = DummyMagics(_ip)
298 nt.assert_equal(m.parse_options('foo', '')[1], 'foo')
307 nt.assert_equal(m.parse_options('foo', '')[1], 'foo')
299 nt.assert_equal(m.parse_options(u'foo', '')[1], u'foo')
308 nt.assert_equal(m.parse_options(u'foo', '')[1], u'foo')
300
309
301
310
302 def test_dirops():
311 def test_dirops():
303 """Test various directory handling operations."""
312 """Test various directory handling operations."""
304 # curpath = lambda :os.path.splitdrive(os.getcwdu())[1].replace('\\','/')
313 # curpath = lambda :os.path.splitdrive(os.getcwdu())[1].replace('\\','/')
305 curpath = os.getcwdu
314 curpath = os.getcwdu
306 startdir = os.getcwdu()
315 startdir = os.getcwdu()
307 ipdir = os.path.realpath(_ip.ipython_dir)
316 ipdir = os.path.realpath(_ip.ipython_dir)
308 try:
317 try:
309 _ip.magic('cd "%s"' % ipdir)
318 _ip.magic('cd "%s"' % ipdir)
310 nt.assert_equal(curpath(), ipdir)
319 nt.assert_equal(curpath(), ipdir)
311 _ip.magic('cd -')
320 _ip.magic('cd -')
312 nt.assert_equal(curpath(), startdir)
321 nt.assert_equal(curpath(), startdir)
313 _ip.magic('pushd "%s"' % ipdir)
322 _ip.magic('pushd "%s"' % ipdir)
314 nt.assert_equal(curpath(), ipdir)
323 nt.assert_equal(curpath(), ipdir)
315 _ip.magic('popd')
324 _ip.magic('popd')
316 nt.assert_equal(curpath(), startdir)
325 nt.assert_equal(curpath(), startdir)
317 finally:
326 finally:
318 os.chdir(startdir)
327 os.chdir(startdir)
319
328
320
329
321 def test_xmode():
330 def test_xmode():
322 # Calling xmode three times should be a no-op
331 # Calling xmode three times should be a no-op
323 xmode = _ip.InteractiveTB.mode
332 xmode = _ip.InteractiveTB.mode
324 for i in range(3):
333 for i in range(3):
325 _ip.magic("xmode")
334 _ip.magic("xmode")
326 nt.assert_equal(_ip.InteractiveTB.mode, xmode)
335 nt.assert_equal(_ip.InteractiveTB.mode, xmode)
327
336
328 def test_reset_hard():
337 def test_reset_hard():
329 monitor = []
338 monitor = []
330 class A(object):
339 class A(object):
331 def __del__(self):
340 def __del__(self):
332 monitor.append(1)
341 monitor.append(1)
333 def __repr__(self):
342 def __repr__(self):
334 return "<A instance>"
343 return "<A instance>"
335
344
336 _ip.user_ns["a"] = A()
345 _ip.user_ns["a"] = A()
337 _ip.run_cell("a")
346 _ip.run_cell("a")
338
347
339 nt.assert_equal(monitor, [])
348 nt.assert_equal(monitor, [])
340 _ip.magic("reset -f")
349 _ip.magic("reset -f")
341 nt.assert_equal(monitor, [1])
350 nt.assert_equal(monitor, [1])
342
351
343 class TestXdel(tt.TempFileMixin):
352 class TestXdel(tt.TempFileMixin):
344 def test_xdel(self):
353 def test_xdel(self):
345 """Test that references from %run are cleared by xdel."""
354 """Test that references from %run are cleared by xdel."""
346 src = ("class A(object):\n"
355 src = ("class A(object):\n"
347 " monitor = []\n"
356 " monitor = []\n"
348 " def __del__(self):\n"
357 " def __del__(self):\n"
349 " self.monitor.append(1)\n"
358 " self.monitor.append(1)\n"
350 "a = A()\n")
359 "a = A()\n")
351 self.mktmp(src)
360 self.mktmp(src)
352 # %run creates some hidden references...
361 # %run creates some hidden references...
353 _ip.magic("run %s" % self.fname)
362 _ip.magic("run %s" % self.fname)
354 # ... as does the displayhook.
363 # ... as does the displayhook.
355 _ip.run_cell("a")
364 _ip.run_cell("a")
356
365
357 monitor = _ip.user_ns["A"].monitor
366 monitor = _ip.user_ns["A"].monitor
358 nt.assert_equal(monitor, [])
367 nt.assert_equal(monitor, [])
359
368
360 _ip.magic("xdel a")
369 _ip.magic("xdel a")
361
370
362 # Check that a's __del__ method has been called.
371 # Check that a's __del__ method has been called.
363 nt.assert_equal(monitor, [1])
372 nt.assert_equal(monitor, [1])
364
373
365 def doctest_who():
374 def doctest_who():
366 """doctest for %who
375 """doctest for %who
367
376
368 In [1]: %reset -f
377 In [1]: %reset -f
369
378
370 In [2]: alpha = 123
379 In [2]: alpha = 123
371
380
372 In [3]: beta = 'beta'
381 In [3]: beta = 'beta'
373
382
374 In [4]: %who int
383 In [4]: %who int
375 alpha
384 alpha
376
385
377 In [5]: %who str
386 In [5]: %who str
378 beta
387 beta
379
388
380 In [6]: %whos
389 In [6]: %whos
381 Variable Type Data/Info
390 Variable Type Data/Info
382 ----------------------------
391 ----------------------------
383 alpha int 123
392 alpha int 123
384 beta str beta
393 beta str beta
385
394
386 In [7]: %who_ls
395 In [7]: %who_ls
387 Out[7]: ['alpha', 'beta']
396 Out[7]: ['alpha', 'beta']
388 """
397 """
389
398
390 def test_whos():
399 def test_whos():
391 """Check that whos is protected against objects where repr() fails."""
400 """Check that whos is protected against objects where repr() fails."""
392 class A(object):
401 class A(object):
393 def __repr__(self):
402 def __repr__(self):
394 raise Exception()
403 raise Exception()
395 _ip.user_ns['a'] = A()
404 _ip.user_ns['a'] = A()
396 _ip.magic("whos")
405 _ip.magic("whos")
397
406
398 @py3compat.u_format
407 @py3compat.u_format
399 def doctest_precision():
408 def doctest_precision():
400 """doctest for %precision
409 """doctest for %precision
401
410
402 In [1]: f = get_ipython().display_formatter.formatters['text/plain']
411 In [1]: f = get_ipython().display_formatter.formatters['text/plain']
403
412
404 In [2]: %precision 5
413 In [2]: %precision 5
405 Out[2]: {u}'%.5f'
414 Out[2]: {u}'%.5f'
406
415
407 In [3]: f.float_format
416 In [3]: f.float_format
408 Out[3]: {u}'%.5f'
417 Out[3]: {u}'%.5f'
409
418
410 In [4]: %precision %e
419 In [4]: %precision %e
411 Out[4]: {u}'%e'
420 Out[4]: {u}'%e'
412
421
413 In [5]: f(3.1415927)
422 In [5]: f(3.1415927)
414 Out[5]: {u}'3.141593e+00'
423 Out[5]: {u}'3.141593e+00'
415 """
424 """
416
425
417 def test_psearch():
426 def test_psearch():
418 with tt.AssertPrints("dict.fromkeys"):
427 with tt.AssertPrints("dict.fromkeys"):
419 _ip.run_cell("dict.fr*?")
428 _ip.run_cell("dict.fr*?")
420
429
421 def test_timeit_shlex():
430 def test_timeit_shlex():
422 """test shlex issues with timeit (#1109)"""
431 """test shlex issues with timeit (#1109)"""
423 _ip.ex("def f(*a,**kw): pass")
432 _ip.ex("def f(*a,**kw): pass")
424 _ip.magic('timeit -n1 "this is a bug".count(" ")')
433 _ip.magic('timeit -n1 "this is a bug".count(" ")')
425 _ip.magic('timeit -r1 -n1 f(" ", 1)')
434 _ip.magic('timeit -r1 -n1 f(" ", 1)')
426 _ip.magic('timeit -r1 -n1 f(" ", 1, " ", 2, " ")')
435 _ip.magic('timeit -r1 -n1 f(" ", 1, " ", 2, " ")')
427 _ip.magic('timeit -r1 -n1 ("a " + "b")')
436 _ip.magic('timeit -r1 -n1 ("a " + "b")')
428 _ip.magic('timeit -r1 -n1 f("a " + "b")')
437 _ip.magic('timeit -r1 -n1 f("a " + "b")')
429 _ip.magic('timeit -r1 -n1 f("a " + "b ")')
438 _ip.magic('timeit -r1 -n1 f("a " + "b ")')
430
439
431
440
432 def test_timeit_arguments():
441 def test_timeit_arguments():
433 "Test valid timeit arguments, should not cause SyntaxError (GH #1269)"
442 "Test valid timeit arguments, should not cause SyntaxError (GH #1269)"
434 _ip.magic("timeit ('#')")
443 _ip.magic("timeit ('#')")
435
444
436
445
437 @dec.skipif(execution.profile is None)
446 @dec.skipif(execution.profile is None)
438 def test_prun_quotes():
447 def test_prun_quotes():
439 "Test that prun does not clobber string escapes (GH #1302)"
448 "Test that prun does not clobber string escapes (GH #1302)"
440 _ip.magic("prun -q x = '\t'")
449 _ip.magic("prun -q x = '\t'")
441 nt.assert_equal(_ip.user_ns['x'], '\t')
450 nt.assert_equal(_ip.user_ns['x'], '\t')
442
451
443 def test_extension():
452 def test_extension():
444 tmpdir = TemporaryDirectory()
453 tmpdir = TemporaryDirectory()
445 orig_ipython_dir = _ip.ipython_dir
454 orig_ipython_dir = _ip.ipython_dir
446 try:
455 try:
447 _ip.ipython_dir = tmpdir.name
456 _ip.ipython_dir = tmpdir.name
448 nt.assert_raises(ImportError, _ip.magic, "load_ext daft_extension")
457 nt.assert_raises(ImportError, _ip.magic, "load_ext daft_extension")
449 url = os.path.join(os.path.dirname(__file__), "daft_extension.py")
458 url = os.path.join(os.path.dirname(__file__), "daft_extension.py")
450 _ip.magic("install_ext %s" % url)
459 _ip.magic("install_ext %s" % url)
451 _ip.user_ns.pop('arq', None)
460 _ip.user_ns.pop('arq', None)
452 _ip.magic("load_ext daft_extension")
461 _ip.magic("load_ext daft_extension")
453 tt.assert_equal(_ip.user_ns['arq'], 185)
462 tt.assert_equal(_ip.user_ns['arq'], 185)
454 _ip.magic("unload_ext daft_extension")
463 _ip.magic("unload_ext daft_extension")
455 assert 'arq' not in _ip.user_ns
464 assert 'arq' not in _ip.user_ns
456 finally:
465 finally:
457 _ip.ipython_dir = orig_ipython_dir
466 _ip.ipython_dir = orig_ipython_dir
458
467
459 def test_notebook_export_json():
468 def test_notebook_export_json():
460 with TemporaryDirectory() as td:
469 with TemporaryDirectory() as td:
461 outfile = os.path.join(td, "nb.ipynb")
470 outfile = os.path.join(td, "nb.ipynb")
462 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
471 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
463 _ip.magic("notebook -e %s" % outfile)
472 _ip.magic("notebook -e %s" % outfile)
464
473
465 def test_notebook_export_py():
474 def test_notebook_export_py():
466 with TemporaryDirectory() as td:
475 with TemporaryDirectory() as td:
467 outfile = os.path.join(td, "nb.py")
476 outfile = os.path.join(td, "nb.py")
468 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
477 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
469 _ip.magic("notebook -e %s" % outfile)
478 _ip.magic("notebook -e %s" % outfile)
470
479
471 def test_notebook_reformat_py():
480 def test_notebook_reformat_py():
472 with TemporaryDirectory() as td:
481 with TemporaryDirectory() as td:
473 infile = os.path.join(td, "nb.ipynb")
482 infile = os.path.join(td, "nb.ipynb")
474 with io.open(infile, 'w', encoding='utf-8') as f:
483 with io.open(infile, 'w', encoding='utf-8') as f:
475 current.write(nb0, f, 'json')
484 current.write(nb0, f, 'json')
476
485
477 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
486 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
478 _ip.magic("notebook -f py %s" % infile)
487 _ip.magic("notebook -f py %s" % infile)
479
488
480 def test_notebook_reformat_json():
489 def test_notebook_reformat_json():
481 with TemporaryDirectory() as td:
490 with TemporaryDirectory() as td:
482 infile = os.path.join(td, "nb.py")
491 infile = os.path.join(td, "nb.py")
483 with io.open(infile, 'w', encoding='utf-8') as f:
492 with io.open(infile, 'w', encoding='utf-8') as f:
484 current.write(nb0, f, 'py')
493 current.write(nb0, f, 'py')
485
494
486 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
495 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
487 _ip.magic("notebook -f ipynb %s" % infile)
496 _ip.magic("notebook -f ipynb %s" % infile)
488 _ip.magic("notebook -f json %s" % infile)
497 _ip.magic("notebook -f json %s" % infile)
489
498
490 def test_env():
499 def test_env():
491 env = _ip.magic("env")
500 env = _ip.magic("env")
492 assert isinstance(env, dict), type(env)
501 assert isinstance(env, dict), type(env)
493
502
494
503
495 class CellMagicTestCase(TestCase):
504 class CellMagicTestCase(TestCase):
496
505
497 def check_ident(self, magic):
506 def check_ident(self, magic):
498 # Manually called, we get the result
507 # Manually called, we get the result
499 out = _ip.run_cell_magic(magic, 'a', 'b')
508 out = _ip.run_cell_magic(magic, 'a', 'b')
500 nt.assert_equals(out, ('a','b'))
509 nt.assert_equals(out, ('a','b'))
501 # Via run_cell, it goes into the user's namespace via displayhook
510 # Via run_cell, it goes into the user's namespace via displayhook
502 _ip.run_cell('%%' + magic +' c\nd')
511 _ip.run_cell('%%' + magic +' c\nd')
503 nt.assert_equals(_ip.user_ns['_'], ('c','d'))
512 nt.assert_equals(_ip.user_ns['_'], ('c','d'))
504
513
505 def test_cell_magic_func_deco(self):
514 def test_cell_magic_func_deco(self):
506 "Cell magic using simple decorator"
515 "Cell magic using simple decorator"
507 @register_cell_magic
516 @register_cell_magic
508 def cellm(line, cell):
517 def cellm(line, cell):
509 return line, cell
518 return line, cell
510
519
511 self.check_ident('cellm')
520 self.check_ident('cellm')
512
521
513 def test_cell_magic_reg(self):
522 def test_cell_magic_reg(self):
514 "Cell magic manually registered"
523 "Cell magic manually registered"
515 def cellm(line, cell):
524 def cellm(line, cell):
516 return line, cell
525 return line, cell
517
526
518 _ip.register_magic_function(cellm, 'cell', 'cellm2')
527 _ip.register_magic_function(cellm, 'cell', 'cellm2')
519 self.check_ident('cellm2')
528 self.check_ident('cellm2')
520
529
521 def test_cell_magic_class(self):
530 def test_cell_magic_class(self):
522 "Cell magics declared via a class"
531 "Cell magics declared via a class"
523 @magics_class
532 @magics_class
524 class MyMagics(Magics):
533 class MyMagics(Magics):
525
534
526 @cell_magic
535 @cell_magic
527 def cellm3(self, line, cell):
536 def cellm3(self, line, cell):
528 return line, cell
537 return line, cell
529
538
530 _ip.register_magics(MyMagics)
539 _ip.register_magics(MyMagics)
531 self.check_ident('cellm3')
540 self.check_ident('cellm3')
532
541
533 def test_cell_magic_class2(self):
542 def test_cell_magic_class2(self):
534 "Cell magics declared via a class, #2"
543 "Cell magics declared via a class, #2"
535 @magics_class
544 @magics_class
536 class MyMagics2(Magics):
545 class MyMagics2(Magics):
537
546
538 @cell_magic('cellm4')
547 @cell_magic('cellm4')
539 def cellm33(self, line, cell):
548 def cellm33(self, line, cell):
540 return line, cell
549 return line, cell
541
550
542 _ip.register_magics(MyMagics2)
551 _ip.register_magics(MyMagics2)
543 self.check_ident('cellm4')
552 self.check_ident('cellm4')
544 # Check that nothing is registered as 'cellm33'
553 # Check that nothing is registered as 'cellm33'
545 c33 = _ip.find_cell_magic('cellm33')
554 c33 = _ip.find_cell_magic('cellm33')
546 nt.assert_equals(c33, None)
555 nt.assert_equals(c33, None)
547
556
General Comments 0
You need to be logged in to leave comments. Login now