##// END OF EJS Templates
By default, Magics inherit from Configurable
Matthias BUSSONNIER -
Show More
@@ -1,676 +1,694 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.inputsplitter import ESC_MAGIC, ESC_MAGIC2
28 from IPython.core.inputsplitter import ESC_MAGIC, ESC_MAGIC2
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, MetaHasTraits
33 from IPython.utils.traitlets import Bool, Dict, Instance, MetaHasTraits
34 from IPython.utils.warn import error
34 from IPython.utils.warn import error
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 magic_escapes = dict(line=ESC_MAGIC, cell=ESC_MAGIC2)
50 magic_escapes = dict(line=ESC_MAGIC, cell=ESC_MAGIC2)
51
51
52 #-----------------------------------------------------------------------------
52 #-----------------------------------------------------------------------------
53 # Utility classes and functions
53 # Utility classes and functions
54 #-----------------------------------------------------------------------------
54 #-----------------------------------------------------------------------------
55
55
56 class Bunch: pass
56 class Bunch: pass
57
57
58
58
59 def on_off(tag):
59 def on_off(tag):
60 """Return an ON/OFF string for a 1/0 input. Simple utility function."""
60 """Return an ON/OFF string for a 1/0 input. Simple utility function."""
61 return ['OFF','ON'][tag]
61 return ['OFF','ON'][tag]
62
62
63
63
64 def compress_dhist(dh):
64 def compress_dhist(dh):
65 """Compress a directory history into a new one with at most 20 entries.
65 """Compress a directory history into a new one with at most 20 entries.
66
66
67 Return a new list made from the first and last 10 elements of dhist after
67 Return a new list made from the first and last 10 elements of dhist after
68 removal of duplicates.
68 removal of duplicates.
69 """
69 """
70 head, tail = dh[:-10], dh[-10:]
70 head, tail = dh[:-10], dh[-10:]
71
71
72 newhead = []
72 newhead = []
73 done = set()
73 done = set()
74 for h in head:
74 for h in head:
75 if h in done:
75 if h in done:
76 continue
76 continue
77 newhead.append(h)
77 newhead.append(h)
78 done.add(h)
78 done.add(h)
79
79
80 return newhead + tail
80 return newhead + tail
81
81
82
82
83 def needs_local_scope(func):
83 def needs_local_scope(func):
84 """Decorator to mark magic functions which need to local scope to run."""
84 """Decorator to mark magic functions which need to local scope to run."""
85 func.needs_local_scope = True
85 func.needs_local_scope = True
86 return func
86 return func
87
87
88 #-----------------------------------------------------------------------------
88 #-----------------------------------------------------------------------------
89 # Class and method decorators for registering magics
89 # Class and method decorators for registering magics
90 #-----------------------------------------------------------------------------
90 #-----------------------------------------------------------------------------
91
91
92 def magics_class(cls):
92 def magics_class(cls):
93 """Class decorator for all subclasses of the main Magics class.
93 """Class decorator for all subclasses of the main Magics class.
94
94
95 Any class that subclasses Magics *must* also apply this decorator, to
95 Any class that subclasses Magics *must* also apply this decorator, to
96 ensure that all the methods that have been decorated as line/cell magics
96 ensure that all the methods that have been decorated as line/cell magics
97 get correctly registered in the class instance. This is necessary because
97 get correctly registered in the class instance. This is necessary because
98 when method decorators run, the class does not exist yet, so they
98 when method decorators run, the class does not exist yet, so they
99 temporarily store their information into a module global. Application of
99 temporarily store their information into a module global. Application of
100 this class decorator copies that global data to the class instance and
100 this class decorator copies that global data to the class instance and
101 clears the global.
101 clears the global.
102
102
103 Obviously, this mechanism is not thread-safe, which means that the
103 Obviously, this mechanism is not thread-safe, which means that the
104 *creation* of subclasses of Magic should only be done in a single-thread
104 *creation* of subclasses of Magic should only be done in a single-thread
105 context. Instantiation of the classes has no restrictions. Given that
105 context. Instantiation of the classes has no restrictions. Given that
106 these classes are typically created at IPython startup time and before user
106 these classes are typically created at IPython startup time and before user
107 application code becomes active, in practice this should not pose any
107 application code becomes active, in practice this should not pose any
108 problems.
108 problems.
109 """
109 """
110 cls.registered = True
110 cls.registered = True
111 cls.magics = dict(line = magics['line'],
111 cls.magics = dict(line = magics['line'],
112 cell = magics['cell'])
112 cell = magics['cell'])
113 magics['line'] = {}
113 magics['line'] = {}
114 magics['cell'] = {}
114 magics['cell'] = {}
115 return cls
115 return cls
116
116
117
117
118 def record_magic(dct, magic_kind, magic_name, func):
118 def record_magic(dct, magic_kind, magic_name, func):
119 """Utility function to store a function as a magic of a specific kind.
119 """Utility function to store a function as a magic of a specific kind.
120
120
121 Parameters
121 Parameters
122 ----------
122 ----------
123 dct : dict
123 dct : dict
124 A dictionary with 'line' and 'cell' subdicts.
124 A dictionary with 'line' and 'cell' subdicts.
125
125
126 magic_kind : str
126 magic_kind : str
127 Kind of magic to be stored.
127 Kind of magic to be stored.
128
128
129 magic_name : str
129 magic_name : str
130 Key to store the magic as.
130 Key to store the magic as.
131
131
132 func : function
132 func : function
133 Callable object to store.
133 Callable object to store.
134 """
134 """
135 if magic_kind == 'line_cell':
135 if magic_kind == 'line_cell':
136 dct['line'][magic_name] = dct['cell'][magic_name] = func
136 dct['line'][magic_name] = dct['cell'][magic_name] = func
137 else:
137 else:
138 dct[magic_kind][magic_name] = func
138 dct[magic_kind][magic_name] = func
139
139
140
140
141 def validate_type(magic_kind):
141 def validate_type(magic_kind):
142 """Ensure that the given magic_kind is valid.
142 """Ensure that the given magic_kind is valid.
143
143
144 Check that the given magic_kind is one of the accepted spec types (stored
144 Check that the given magic_kind is one of the accepted spec types (stored
145 in the global `magic_spec`), raise ValueError otherwise.
145 in the global `magic_spec`), raise ValueError otherwise.
146 """
146 """
147 if magic_kind not in magic_spec:
147 if magic_kind not in magic_spec:
148 raise ValueError('magic_kind must be one of %s, %s given' %
148 raise ValueError('magic_kind must be one of %s, %s given' %
149 magic_kinds, magic_kind)
149 magic_kinds, magic_kind)
150
150
151
151
152 # The docstrings for the decorator below will be fairly similar for the two
152 # The docstrings for the decorator below will be fairly similar for the two
153 # types (method and function), so we generate them here once and reuse the
153 # types (method and function), so we generate them here once and reuse the
154 # templates below.
154 # templates below.
155 _docstring_template = \
155 _docstring_template = \
156 """Decorate the given {0} as {1} magic.
156 """Decorate the given {0} as {1} magic.
157
157
158 The decorator can be used with or without arguments, as follows.
158 The decorator can be used with or without arguments, as follows.
159
159
160 i) without arguments: it will create a {1} magic named as the {0} being
160 i) without arguments: it will create a {1} magic named as the {0} being
161 decorated::
161 decorated::
162
162
163 @deco
163 @deco
164 def foo(...)
164 def foo(...)
165
165
166 will create a {1} magic named `foo`.
166 will create a {1} magic named `foo`.
167
167
168 ii) with one string argument: which will be used as the actual name of the
168 ii) with one string argument: which will be used as the actual name of the
169 resulting magic::
169 resulting magic::
170
170
171 @deco('bar')
171 @deco('bar')
172 def foo(...)
172 def foo(...)
173
173
174 will create a {1} magic named `bar`.
174 will create a {1} magic named `bar`.
175 """
175 """
176
176
177 # These two are decorator factories. While they are conceptually very similar,
177 # These two are decorator factories. While they are conceptually very similar,
178 # there are enough differences in the details that it's simpler to have them
178 # there are enough differences in the details that it's simpler to have them
179 # written as completely standalone functions rather than trying to share code
179 # written as completely standalone functions rather than trying to share code
180 # and make a single one with convoluted logic.
180 # and make a single one with convoluted logic.
181
181
182 def _method_magic_marker(magic_kind):
182 def _method_magic_marker(magic_kind):
183 """Decorator factory for methods in Magics subclasses.
183 """Decorator factory for methods in Magics subclasses.
184 """
184 """
185
185
186 validate_type(magic_kind)
186 validate_type(magic_kind)
187
187
188 # This is a closure to capture the magic_kind. We could also use a class,
188 # This is a closure to capture the magic_kind. We could also use a class,
189 # but it's overkill for just that one bit of state.
189 # but it's overkill for just that one bit of state.
190 def magic_deco(arg):
190 def magic_deco(arg):
191 call = lambda f, *a, **k: f(*a, **k)
191 call = lambda f, *a, **k: f(*a, **k)
192
192
193 if callable(arg):
193 if callable(arg):
194 # "Naked" decorator call (just @foo, no args)
194 # "Naked" decorator call (just @foo, no args)
195 func = arg
195 func = arg
196 name = func.func_name
196 name = func.func_name
197 retval = decorator(call, func)
197 retval = decorator(call, func)
198 record_magic(magics, magic_kind, name, name)
198 record_magic(magics, magic_kind, name, name)
199 elif isinstance(arg, basestring):
199 elif isinstance(arg, basestring):
200 # Decorator called with arguments (@foo('bar'))
200 # Decorator called with arguments (@foo('bar'))
201 name = arg
201 name = arg
202 def mark(func, *a, **kw):
202 def mark(func, *a, **kw):
203 record_magic(magics, magic_kind, name, func.func_name)
203 record_magic(magics, magic_kind, name, func.func_name)
204 return decorator(call, func)
204 return decorator(call, func)
205 retval = mark
205 retval = mark
206 else:
206 else:
207 raise TypeError("Decorator can only be called with "
207 raise TypeError("Decorator can only be called with "
208 "string or function")
208 "string or function")
209 return retval
209 return retval
210
210
211 # Ensure the resulting decorator has a usable docstring
211 # Ensure the resulting decorator has a usable docstring
212 magic_deco.__doc__ = _docstring_template.format('method', magic_kind)
212 magic_deco.__doc__ = _docstring_template.format('method', magic_kind)
213 return magic_deco
213 return magic_deco
214
214
215
215
216 def _function_magic_marker(magic_kind):
216 def _function_magic_marker(magic_kind):
217 """Decorator factory for standalone functions.
217 """Decorator factory for standalone functions.
218 """
218 """
219 validate_type(magic_kind)
219 validate_type(magic_kind)
220
220
221 # This is a closure to capture the magic_kind. We could also use a class,
221 # This is a closure to capture the magic_kind. We could also use a class,
222 # but it's overkill for just that one bit of state.
222 # but it's overkill for just that one bit of state.
223 def magic_deco(arg):
223 def magic_deco(arg):
224 call = lambda f, *a, **k: f(*a, **k)
224 call = lambda f, *a, **k: f(*a, **k)
225
225
226 # Find get_ipython() in the caller's namespace
226 # Find get_ipython() in the caller's namespace
227 caller = sys._getframe(1)
227 caller = sys._getframe(1)
228 for ns in ['f_locals', 'f_globals', 'f_builtins']:
228 for ns in ['f_locals', 'f_globals', 'f_builtins']:
229 get_ipython = getattr(caller, ns).get('get_ipython')
229 get_ipython = getattr(caller, ns).get('get_ipython')
230 if get_ipython is not None:
230 if get_ipython is not None:
231 break
231 break
232 else:
232 else:
233 raise NameError('Decorator can only run in context where '
233 raise NameError('Decorator can only run in context where '
234 '`get_ipython` exists')
234 '`get_ipython` exists')
235
235
236 ip = get_ipython()
236 ip = get_ipython()
237
237
238 if callable(arg):
238 if callable(arg):
239 # "Naked" decorator call (just @foo, no args)
239 # "Naked" decorator call (just @foo, no args)
240 func = arg
240 func = arg
241 name = func.func_name
241 name = func.func_name
242 ip.register_magic_function(func, magic_kind, name)
242 ip.register_magic_function(func, magic_kind, name)
243 retval = decorator(call, func)
243 retval = decorator(call, func)
244 elif isinstance(arg, basestring):
244 elif isinstance(arg, basestring):
245 # Decorator called with arguments (@foo('bar'))
245 # Decorator called with arguments (@foo('bar'))
246 name = arg
246 name = arg
247 def mark(func, *a, **kw):
247 def mark(func, *a, **kw):
248 ip.register_magic_function(func, magic_kind, name)
248 ip.register_magic_function(func, magic_kind, name)
249 return decorator(call, func)
249 return decorator(call, func)
250 retval = mark
250 retval = mark
251 else:
251 else:
252 raise TypeError("Decorator can only be called with "
252 raise TypeError("Decorator can only be called with "
253 "string or function")
253 "string or function")
254 return retval
254 return retval
255
255
256 # Ensure the resulting decorator has a usable docstring
256 # Ensure the resulting decorator has a usable docstring
257 ds = _docstring_template.format('function', magic_kind)
257 ds = _docstring_template.format('function', magic_kind)
258
258
259 ds += dedent("""
259 ds += dedent("""
260 Note: this decorator can only be used in a context where IPython is already
260 Note: this decorator can only be used in a context where IPython is already
261 active, so that the `get_ipython()` call succeeds. You can therefore use
261 active, so that the `get_ipython()` call succeeds. You can therefore use
262 it in your startup files loaded after IPython initializes, but *not* in the
262 it in your startup files loaded after IPython initializes, but *not* in the
263 IPython configuration file itself, which is executed before IPython is
263 IPython configuration file itself, which is executed before IPython is
264 fully up and running. Any file located in the `startup` subdirectory of
264 fully up and running. Any file located in the `startup` subdirectory of
265 your configuration profile will be OK in this sense.
265 your configuration profile will be OK in this sense.
266 """)
266 """)
267
267
268 magic_deco.__doc__ = ds
268 magic_deco.__doc__ = ds
269 return magic_deco
269 return magic_deco
270
270
271
271
272 # Create the actual decorators for public use
272 # Create the actual decorators for public use
273
273
274 # These three are used to decorate methods in class definitions
274 # These three are used to decorate methods in class definitions
275 line_magic = _method_magic_marker('line')
275 line_magic = _method_magic_marker('line')
276 cell_magic = _method_magic_marker('cell')
276 cell_magic = _method_magic_marker('cell')
277 line_cell_magic = _method_magic_marker('line_cell')
277 line_cell_magic = _method_magic_marker('line_cell')
278
278
279 # These three decorate standalone functions and perform the decoration
279 # These three decorate standalone functions and perform the decoration
280 # immediately. They can only run where get_ipython() works
280 # immediately. They can only run where get_ipython() works
281 register_line_magic = _function_magic_marker('line')
281 register_line_magic = _function_magic_marker('line')
282 register_cell_magic = _function_magic_marker('cell')
282 register_cell_magic = _function_magic_marker('cell')
283 register_line_cell_magic = _function_magic_marker('line_cell')
283 register_line_cell_magic = _function_magic_marker('line_cell')
284
284
285 #-----------------------------------------------------------------------------
285 #-----------------------------------------------------------------------------
286 # Core Magic classes
286 # Core Magic classes
287 #-----------------------------------------------------------------------------
287 #-----------------------------------------------------------------------------
288
288
289 class MagicsManager(Configurable):
289 class MagicsManager(Configurable):
290 """Object that handles all magic-related functionality for IPython.
290 """Object that handles all magic-related functionality for IPython.
291 """
291 """
292 # Non-configurable class attributes
292 # Non-configurable class attributes
293
293
294 # A two-level dict, first keyed by magic type, then by magic function, and
294 # A two-level dict, first keyed by magic type, then by magic function, and
295 # holding the actual callable object as value. This is the dict used for
295 # holding the actual callable object as value. This is the dict used for
296 # magic function dispatch
296 # magic function dispatch
297 magics = Dict
297 magics = Dict
298
298
299 # A registry of the original objects that we've been given holding magics.
299 # A registry of the original objects that we've been given holding magics.
300 registry = Dict
300 registry = Dict
301
301
302 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
302 shell = Instance('IPython.core.interactiveshell.InteractiveShellABC')
303
303
304 auto_magic = Bool(True, config=True, help=
304 auto_magic = Bool(True, config=True, help=
305 "Automatically call line magics without requiring explicit % prefix")
305 "Automatically call line magics without requiring explicit % prefix")
306
306
307 def _auto_magic_changed(self, name, value):
307 def _auto_magic_changed(self, name, value):
308 self.shell.automagic = value
308 self.shell.automagic = value
309
309
310 _auto_status = [
310 _auto_status = [
311 'Automagic is OFF, % prefix IS needed for line magics.',
311 'Automagic is OFF, % prefix IS needed for line magics.',
312 'Automagic is ON, % prefix IS NOT needed for line magics.']
312 'Automagic is ON, % prefix IS NOT needed for line magics.']
313
313
314 user_magics = Instance('IPython.core.magics.UserMagics')
314 user_magics = Instance('IPython.core.magics.UserMagics')
315
315
316 def __init__(self, shell=None, config=None, user_magics=None, **traits):
316 def __init__(self, shell=None, config=None, user_magics=None, **traits):
317
317
318 super(MagicsManager, self).__init__(shell=shell, config=config,
318 super(MagicsManager, self).__init__(shell=shell, config=config,
319 user_magics=user_magics, **traits)
319 user_magics=user_magics, **traits)
320 self.magics = dict(line={}, cell={})
320 self.magics = dict(line={}, cell={})
321 # Let's add the user_magics to the registry for uniformity, so *all*
321 # Let's add the user_magics to the registry for uniformity, so *all*
322 # registered magic containers can be found there.
322 # registered magic containers can be found there.
323 self.registry[user_magics.__class__.__name__] = user_magics
323 self.registry[user_magics.__class__.__name__] = user_magics
324
324
325 def auto_status(self):
325 def auto_status(self):
326 """Return descriptive string with automagic status."""
326 """Return descriptive string with automagic status."""
327 return self._auto_status[self.auto_magic]
327 return self._auto_status[self.auto_magic]
328
328
329 def lsmagic(self):
329 def lsmagic(self):
330 """Return a dict of currently available magic functions.
330 """Return a dict of currently available magic functions.
331
331
332 The return dict has the keys 'line' and 'cell', corresponding to the
332 The return dict has the keys 'line' and 'cell', corresponding to the
333 two types of magics we support. Each value is a list of names.
333 two types of magics we support. Each value is a list of names.
334 """
334 """
335 return self.magics
335 return self.magics
336
336
337 def lsmagic_docs(self, brief=False, missing=''):
337 def lsmagic_docs(self, brief=False, missing=''):
338 """Return dict of documentation of magic functions.
338 """Return dict of documentation of magic functions.
339
339
340 The return dict has the keys 'line' and 'cell', corresponding to the
340 The return dict has the keys 'line' and 'cell', corresponding to the
341 two types of magics we support. Each value is a dict keyed by magic
341 two types of magics we support. Each value is a dict keyed by magic
342 name whose value is the function docstring. If a docstring is
342 name whose value is the function docstring. If a docstring is
343 unavailable, the value of `missing` is used instead.
343 unavailable, the value of `missing` is used instead.
344
344
345 If brief is True, only the first line of each docstring will be returned.
345 If brief is True, only the first line of each docstring will be returned.
346 """
346 """
347 docs = {}
347 docs = {}
348 for m_type in self.magics:
348 for m_type in self.magics:
349 m_docs = {}
349 m_docs = {}
350 for m_name, m_func in self.magics[m_type].iteritems():
350 for m_name, m_func in self.magics[m_type].iteritems():
351 if m_func.__doc__:
351 if m_func.__doc__:
352 if brief:
352 if brief:
353 m_docs[m_name] = m_func.__doc__.split('\n', 1)[0]
353 m_docs[m_name] = m_func.__doc__.split('\n', 1)[0]
354 else:
354 else:
355 m_docs[m_name] = m_func.__doc__.rstrip()
355 m_docs[m_name] = m_func.__doc__.rstrip()
356 else:
356 else:
357 m_docs[m_name] = missing
357 m_docs[m_name] = missing
358 docs[m_type] = m_docs
358 docs[m_type] = m_docs
359 return docs
359 return docs
360
360
361 def register(self, *magic_objects):
361 def register(self, *magic_objects):
362 """Register one or more instances of Magics.
362 """Register one or more instances of Magics.
363
363
364 Take one or more classes or instances of classes that subclass the main
364 Take one or more classes or instances of classes that subclass the main
365 `core.Magic` class, and register them with IPython to use the magic
365 `core.Magic` class, and register them with IPython to use the magic
366 functions they provide. The registration process will then ensure that
366 functions they provide. The registration process will then ensure that
367 any methods that have decorated to provide line and/or cell magics will
367 any methods that have decorated to provide line and/or cell magics will
368 be recognized with the `%x`/`%%x` syntax as a line/cell magic
368 be recognized with the `%x`/`%%x` syntax as a line/cell magic
369 respectively.
369 respectively.
370
370
371 If classes are given, they will be instantiated with the default
371 If classes are given, they will be instantiated with the default
372 constructor. If your classes need a custom constructor, you should
372 constructor. If your classes need a custom constructor, you should
373 instanitate them first and pass the instance.
373 instanitate them first and pass the instance.
374
374
375 The provided arguments can be an arbitrary mix of classes and instances.
375 The provided arguments can be an arbitrary mix of classes and instances.
376
376
377 Parameters
377 Parameters
378 ----------
378 ----------
379 magic_objects : one or more classes or instances
379 magic_objects : one or more classes or instances
380 """
380 """
381 # Start by validating them to ensure they have all had their magic
381 # Start by validating them to ensure they have all had their magic
382 # methods registered at the instance level
382 # methods registered at the instance level
383 for m in magic_objects:
383 for m in magic_objects:
384 if not m.registered:
384 if not m.registered:
385 raise ValueError("Class of magics %r was constructed without "
385 raise ValueError("Class of magics %r was constructed without "
386 "the @register_magics class decorator")
386 "the @register_magics class decorator")
387 if type(m) in (type, MetaHasTraits):
387 if type(m) in (type, MetaHasTraits):
388 # If we're given an uninstantiated class
388 # If we're given an uninstantiated class
389 m = m(shell=self.shell)
389 m = m(shell=self.shell)
390
390
391 # Now that we have an instance, we can register it and update the
391 # Now that we have an instance, we can register it and update the
392 # table of callables
392 # table of callables
393 self.registry[m.__class__.__name__] = m
393 self.registry[m.__class__.__name__] = m
394 for mtype in magic_kinds:
394 for mtype in magic_kinds:
395 self.magics[mtype].update(m.magics[mtype])
395 self.magics[mtype].update(m.magics[mtype])
396
396
397 def register_function(self, func, magic_kind='line', magic_name=None):
397 def register_function(self, func, magic_kind='line', magic_name=None):
398 """Expose a standalone function as magic function for IPython.
398 """Expose a standalone function as magic function for IPython.
399
399
400 This will create an IPython magic (line, cell or both) from a
400 This will create an IPython magic (line, cell or both) from a
401 standalone function. The functions should have the following
401 standalone function. The functions should have the following
402 signatures:
402 signatures:
403
403
404 * For line magics: `def f(line)`
404 * For line magics: `def f(line)`
405 * For cell magics: `def f(line, cell)`
405 * For cell magics: `def f(line, cell)`
406 * For a function that does both: `def f(line, cell=None)`
406 * For a function that does both: `def f(line, cell=None)`
407
407
408 In the latter case, the function will be called with `cell==None` when
408 In the latter case, the function will be called with `cell==None` when
409 invoked as `%f`, and with cell as a string when invoked as `%%f`.
409 invoked as `%f`, and with cell as a string when invoked as `%%f`.
410
410
411 Parameters
411 Parameters
412 ----------
412 ----------
413 func : callable
413 func : callable
414 Function to be registered as a magic.
414 Function to be registered as a magic.
415
415
416 magic_kind : str
416 magic_kind : str
417 Kind of magic, one of 'line', 'cell' or 'line_cell'
417 Kind of magic, one of 'line', 'cell' or 'line_cell'
418
418
419 magic_name : optional str
419 magic_name : optional str
420 If given, the name the magic will have in the IPython namespace. By
420 If given, the name the magic will have in the IPython namespace. By
421 default, the name of the function itself is used.
421 default, the name of the function itself is used.
422 """
422 """
423
423
424 # Create the new method in the user_magics and register it in the
424 # Create the new method in the user_magics and register it in the
425 # global table
425 # global table
426 validate_type(magic_kind)
426 validate_type(magic_kind)
427 magic_name = func.func_name if magic_name is None else magic_name
427 magic_name = func.func_name if magic_name is None else magic_name
428 setattr(self.user_magics, magic_name, func)
428 setattr(self.user_magics, magic_name, func)
429 record_magic(self.magics, magic_kind, magic_name, func)
429 record_magic(self.magics, magic_kind, magic_name, func)
430
430
431 def define_magic(self, name, func):
431 def define_magic(self, name, func):
432 """[Deprecated] Expose own function as magic function for IPython.
432 """[Deprecated] Expose own function as magic function for IPython.
433
433
434 Example::
434 Example::
435
435
436 def foo_impl(self, parameter_s=''):
436 def foo_impl(self, parameter_s=''):
437 'My very own magic!. (Use docstrings, IPython reads them).'
437 'My very own magic!. (Use docstrings, IPython reads them).'
438 print 'Magic function. Passed parameter is between < >:'
438 print 'Magic function. Passed parameter is between < >:'
439 print '<%s>' % parameter_s
439 print '<%s>' % parameter_s
440 print 'The self object is:', self
440 print 'The self object is:', self
441
441
442 ip.define_magic('foo',foo_impl)
442 ip.define_magic('foo',foo_impl)
443 """
443 """
444 meth = types.MethodType(func, self.user_magics)
444 meth = types.MethodType(func, self.user_magics)
445 setattr(self.user_magics, name, meth)
445 setattr(self.user_magics, name, meth)
446 record_magic(self.magics, 'line', name, meth)
446 record_magic(self.magics, 'line', name, meth)
447
447
448 def register_alias(self, alias_name, magic_name, magic_kind='line'):
448 def register_alias(self, alias_name, magic_name, magic_kind='line'):
449 """Register an alias to a magic function.
449 """Register an alias to a magic function.
450
450
451 The alias is an instance of :class:`MagicAlias`, which holds the
451 The alias is an instance of :class:`MagicAlias`, which holds the
452 name and kind of the magic it should call. Binding is done at
452 name and kind of the magic it should call. Binding is done at
453 call time, so if the underlying magic function is changed the alias
453 call time, so if the underlying magic function is changed the alias
454 will call the new function.
454 will call the new function.
455
455
456 Parameters
456 Parameters
457 ----------
457 ----------
458 alias_name : str
458 alias_name : str
459 The name of the magic to be registered.
459 The name of the magic to be registered.
460
460
461 magic_name : str
461 magic_name : str
462 The name of an existing magic.
462 The name of an existing magic.
463
463
464 magic_kind : str
464 magic_kind : str
465 Kind of magic, one of 'line' or 'cell'
465 Kind of magic, one of 'line' or 'cell'
466 """
466 """
467
467
468 # `validate_type` is too permissive, as it allows 'line_cell'
468 # `validate_type` is too permissive, as it allows 'line_cell'
469 # which we do not handle.
469 # which we do not handle.
470 if magic_kind not in magic_kinds:
470 if magic_kind not in magic_kinds:
471 raise ValueError('magic_kind must be one of %s, %s given' %
471 raise ValueError('magic_kind must be one of %s, %s given' %
472 magic_kinds, magic_kind)
472 magic_kinds, magic_kind)
473
473
474 alias = MagicAlias(self.shell, magic_name, magic_kind)
474 alias = MagicAlias(self.shell, magic_name, magic_kind)
475 setattr(self.user_magics, alias_name, alias)
475 setattr(self.user_magics, alias_name, alias)
476 record_magic(self.magics, magic_kind, alias_name, alias)
476 record_magic(self.magics, magic_kind, alias_name, alias)
477
477
478 # Key base class that provides the central functionality for magics.
478 # Key base class that provides the central functionality for magics.
479
479
480 class Magics(object):
480
481 class Magics(Configurable):
481 """Base class for implementing magic functions.
482 """Base class for implementing magic functions.
482
483
483 Shell functions which can be reached as %function_name. All magic
484 Shell functions which can be reached as %function_name. All magic
484 functions should accept a string, which they can parse for their own
485 functions should accept a string, which they can parse for their own
485 needs. This can make some functions easier to type, eg `%cd ../`
486 needs. This can make some functions easier to type, eg `%cd ../`
486 vs. `%cd("../")`
487 vs. `%cd("../")`
487
488
488 Classes providing magic functions need to subclass this class, and they
489 Classes providing magic functions need to subclass this class, and they
489 MUST:
490 MUST:
490
491
491 - Use the method decorators `@line_magic` and `@cell_magic` to decorate
492 - Use the method decorators `@line_magic` and `@cell_magic` to decorate
492 individual methods as magic functions, AND
493 individual methods as magic functions, AND
493
494
494 - Use the class decorator `@magics_class` to ensure that the magic
495 - Use the class decorator `@magics_class` to ensure that the magic
495 methods are properly registered at the instance level upon instance
496 methods are properly registered at the instance level upon instance
496 initialization.
497 initialization.
497
498
498 See :mod:`magic_functions` for examples of actual implementation classes.
499 See :mod:`magic_functions` for examples of actual implementation classes.
499 """
500 """
500 # Dict holding all command-line options for each magic.
501 # Dict holding all command-line options for each magic.
501 options_table = None
502 options_table = None
502 # Dict for the mapping of magic names to methods, set by class decorator
503 # Dict for the mapping of magic names to methods, set by class decorator
503 magics = None
504 magics = None
504 # Flag to check that the class decorator was properly applied
505 # Flag to check that the class decorator was properly applied
505 registered = False
506 registered = False
506 # Instance of IPython shell
507 # Instance of IPython shell
507 shell = None
508 shell = None
508
509
509 def __init__(self, shell):
510 def __init__(self, shell=None, **kwargs):
511 if shell is not None:
512 kwargs['shell'] = shell
513 kwargs.setdefault('parent', shell)
514 super(Magics, self).__init__(**kwargs)
515
516 def __init__(self, shell=None, **kwargs):
510 if not(self.__class__.registered):
517 if not(self.__class__.registered):
511 raise ValueError('Magics subclass without registration - '
518 raise ValueError('Magics subclass without registration - '
512 'did you forget to apply @magics_class?')
519 'did you forget to apply @magics_class?')
520 if shell is not None:
521 if hasattr( shell, 'configurables'):
522 shell.configurables.append(self)
523 if hasattr( shell, 'config'):
524 kwargs.setdefault('parent', shell)
525 kwargs['shell'] = shell
526
513 self.shell = shell
527 self.shell = shell
514 self.options_table = {}
528 self.options_table = {}
515 # The method decorators are run when the instance doesn't exist yet, so
529 # The method decorators are run when the instance doesn't exist yet, so
516 # they can only record the names of the methods they are supposed to
530 # they can only record the names of the methods they are supposed to
517 # grab. Only now, that the instance exists, can we create the proper
531 # grab. Only now, that the instance exists, can we create the proper
518 # mapping to bound methods. So we read the info off the original names
532 # mapping to bound methods. So we read the info off the original names
519 # table and replace each method name by the actual bound method.
533 # table and replace each method name by the actual bound method.
520 # But we mustn't clobber the *class* mapping, in case of multiple instances.
534 # But we mustn't clobber the *class* mapping, in case of multiple instances.
521 class_magics = self.magics
535 class_magics = self.magics
522 self.magics = {}
536 self.magics = {}
523 for mtype in magic_kinds:
537 for mtype in magic_kinds:
524 tab = self.magics[mtype] = {}
538 tab = self.magics[mtype] = {}
525 cls_tab = class_magics[mtype]
539 cls_tab = class_magics[mtype]
526 for magic_name, meth_name in cls_tab.iteritems():
540 for magic_name, meth_name in cls_tab.iteritems():
527 if isinstance(meth_name, basestring):
541 if isinstance(meth_name, basestring):
528 # it's a method name, grab it
542 # it's a method name, grab it
529 tab[magic_name] = getattr(self, meth_name)
543 tab[magic_name] = getattr(self, meth_name)
530 else:
544 else:
531 # it's the real thing
545 # it's the real thing
532 tab[magic_name] = meth_name
546 tab[magic_name] = meth_name
547 # Configurable **need** to be initiated at the end or the config
548 # magics get screwed up.
549 super(Magics, self).__init__(**kwargs)
533
550
534 def arg_err(self,func):
551 def arg_err(self,func):
535 """Print docstring if incorrect arguments were passed"""
552 """Print docstring if incorrect arguments were passed"""
536 print 'Error in arguments:'
553 print 'Error in arguments:'
537 print oinspect.getdoc(func)
554 print oinspect.getdoc(func)
538
555
539 def format_latex(self, strng):
556 def format_latex(self, strng):
540 """Format a string for latex inclusion."""
557 """Format a string for latex inclusion."""
541
558
542 # Characters that need to be escaped for latex:
559 # Characters that need to be escaped for latex:
543 escape_re = re.compile(r'(%|_|\$|#|&)',re.MULTILINE)
560 escape_re = re.compile(r'(%|_|\$|#|&)',re.MULTILINE)
544 # Magic command names as headers:
561 # Magic command names as headers:
545 cmd_name_re = re.compile(r'^(%s.*?):' % ESC_MAGIC,
562 cmd_name_re = re.compile(r'^(%s.*?):' % ESC_MAGIC,
546 re.MULTILINE)
563 re.MULTILINE)
547 # Magic commands
564 # Magic commands
548 cmd_re = re.compile(r'(?P<cmd>%s.+?\b)(?!\}\}:)' % ESC_MAGIC,
565 cmd_re = re.compile(r'(?P<cmd>%s.+?\b)(?!\}\}:)' % ESC_MAGIC,
549 re.MULTILINE)
566 re.MULTILINE)
550 # Paragraph continue
567 # Paragraph continue
551 par_re = re.compile(r'\\$',re.MULTILINE)
568 par_re = re.compile(r'\\$',re.MULTILINE)
552
569
553 # The "\n" symbol
570 # The "\n" symbol
554 newline_re = re.compile(r'\\n')
571 newline_re = re.compile(r'\\n')
555
572
556 # Now build the string for output:
573 # Now build the string for output:
557 #strng = cmd_name_re.sub(r'\n\\texttt{\\textsl{\\large \1}}:',strng)
574 #strng = cmd_name_re.sub(r'\n\\texttt{\\textsl{\\large \1}}:',strng)
558 strng = cmd_name_re.sub(r'\n\\bigskip\n\\texttt{\\textbf{ \1}}:',
575 strng = cmd_name_re.sub(r'\n\\bigskip\n\\texttt{\\textbf{ \1}}:',
559 strng)
576 strng)
560 strng = cmd_re.sub(r'\\texttt{\g<cmd>}',strng)
577 strng = cmd_re.sub(r'\\texttt{\g<cmd>}',strng)
561 strng = par_re.sub(r'\\\\',strng)
578 strng = par_re.sub(r'\\\\',strng)
562 strng = escape_re.sub(r'\\\1',strng)
579 strng = escape_re.sub(r'\\\1',strng)
563 strng = newline_re.sub(r'\\textbackslash{}n',strng)
580 strng = newline_re.sub(r'\\textbackslash{}n',strng)
564 return strng
581 return strng
565
582
566 def parse_options(self, arg_str, opt_str, *long_opts, **kw):
583 def parse_options(self, arg_str, opt_str, *long_opts, **kw):
567 """Parse options passed to an argument string.
584 """Parse options passed to an argument string.
568
585
569 The interface is similar to that of getopt(), but it returns back a
586 The interface is similar to that of getopt(), but it returns back a
570 Struct with the options as keys and the stripped argument string still
587 Struct with the options as keys and the stripped argument string still
571 as a string.
588 as a string.
572
589
573 arg_str is quoted as a true sys.argv vector by using shlex.split.
590 arg_str is quoted as a true sys.argv vector by using shlex.split.
574 This allows us to easily expand variables, glob files, quote
591 This allows us to easily expand variables, glob files, quote
575 arguments, etc.
592 arguments, etc.
576
593
577 Options:
594 Options:
578 -mode: default 'string'. If given as 'list', the argument string is
595 -mode: default 'string'. If given as 'list', the argument string is
579 returned as a list (split on whitespace) instead of a string.
596 returned as a list (split on whitespace) instead of a string.
580
597
581 -list_all: put all option values in lists. Normally only options
598 -list_all: put all option values in lists. Normally only options
582 appearing more than once are put in a list.
599 appearing more than once are put in a list.
583
600
584 -posix (True): whether to split the input line in POSIX mode or not,
601 -posix (True): whether to split the input line in POSIX mode or not,
585 as per the conventions outlined in the shlex module from the
602 as per the conventions outlined in the shlex module from the
586 standard library."""
603 standard library."""
587
604
588 # inject default options at the beginning of the input line
605 # inject default options at the beginning of the input line
589 caller = sys._getframe(1).f_code.co_name
606 caller = sys._getframe(1).f_code.co_name
590 arg_str = '%s %s' % (self.options_table.get(caller,''),arg_str)
607 arg_str = '%s %s' % (self.options_table.get(caller,''),arg_str)
591
608
592 mode = kw.get('mode','string')
609 mode = kw.get('mode','string')
593 if mode not in ['string','list']:
610 if mode not in ['string','list']:
594 raise ValueError('incorrect mode given: %s' % mode)
611 raise ValueError('incorrect mode given: %s' % mode)
595 # Get options
612 # Get options
596 list_all = kw.get('list_all',0)
613 list_all = kw.get('list_all',0)
597 posix = kw.get('posix', os.name == 'posix')
614 posix = kw.get('posix', os.name == 'posix')
598 strict = kw.get('strict', True)
615 strict = kw.get('strict', True)
599
616
600 # Check if we have more than one argument to warrant extra processing:
617 # Check if we have more than one argument to warrant extra processing:
601 odict = {} # Dictionary with options
618 odict = {} # Dictionary with options
602 args = arg_str.split()
619 args = arg_str.split()
603 if len(args) >= 1:
620 if len(args) >= 1:
604 # If the list of inputs only has 0 or 1 thing in it, there's no
621 # If the list of inputs only has 0 or 1 thing in it, there's no
605 # need to look for options
622 # need to look for options
606 argv = arg_split(arg_str, posix, strict)
623 argv = arg_split(arg_str, posix, strict)
607 # Do regular option processing
624 # Do regular option processing
608 try:
625 try:
609 opts,args = getopt(argv, opt_str, long_opts)
626 opts,args = getopt(argv, opt_str, long_opts)
610 except GetoptError as e:
627 except GetoptError as e:
611 raise UsageError('%s ( allowed: "%s" %s)' % (e.msg,opt_str,
628 raise UsageError('%s ( allowed: "%s" %s)' % (e.msg,opt_str,
612 " ".join(long_opts)))
629 " ".join(long_opts)))
613 for o,a in opts:
630 for o,a in opts:
614 if o.startswith('--'):
631 if o.startswith('--'):
615 o = o[2:]
632 o = o[2:]
616 else:
633 else:
617 o = o[1:]
634 o = o[1:]
618 try:
635 try:
619 odict[o].append(a)
636 odict[o].append(a)
620 except AttributeError:
637 except AttributeError:
621 odict[o] = [odict[o],a]
638 odict[o] = [odict[o],a]
622 except KeyError:
639 except KeyError:
623 if list_all:
640 if list_all:
624 odict[o] = [a]
641 odict[o] = [a]
625 else:
642 else:
626 odict[o] = a
643 odict[o] = a
627
644
628 # Prepare opts,args for return
645 # Prepare opts,args for return
629 opts = Struct(odict)
646 opts = Struct(odict)
630 if mode == 'string':
647 if mode == 'string':
631 args = ' '.join(args)
648 args = ' '.join(args)
632
649
633 return opts,args
650 return opts,args
634
651
635 def default_option(self, fn, optstr):
652 def default_option(self, fn, optstr):
636 """Make an entry in the options_table for fn, with value optstr"""
653 """Make an entry in the options_table for fn, with value optstr"""
637
654
638 if fn not in self.lsmagic():
655 if fn not in self.lsmagic():
639 error("%s is not a magic function" % fn)
656 error("%s is not a magic function" % fn)
640 self.options_table[fn] = optstr
657 self.options_table[fn] = optstr
641
658
659
642 class MagicAlias(object):
660 class MagicAlias(object):
643 """An alias to another magic function.
661 """An alias to another magic function.
644
662
645 An alias is determined by its magic name and magic kind. Lookup
663 An alias is determined by its magic name and magic kind. Lookup
646 is done at call time, so if the underlying magic changes the alias
664 is done at call time, so if the underlying magic changes the alias
647 will call the new function.
665 will call the new function.
648
666
649 Use the :meth:`MagicsManager.register_alias` method or the
667 Use the :meth:`MagicsManager.register_alias` method or the
650 `%alias_magic` magic function to create and register a new alias.
668 `%alias_magic` magic function to create and register a new alias.
651 """
669 """
652 def __init__(self, shell, magic_name, magic_kind):
670 def __init__(self, shell, magic_name, magic_kind):
653 self.shell = shell
671 self.shell = shell
654 self.magic_name = magic_name
672 self.magic_name = magic_name
655 self.magic_kind = magic_kind
673 self.magic_kind = magic_kind
656
674
657 self.pretty_target = '%s%s' % (magic_escapes[self.magic_kind], self.magic_name)
675 self.pretty_target = '%s%s' % (magic_escapes[self.magic_kind], self.magic_name)
658 self.__doc__ = "Alias for `%s`." % self.pretty_target
676 self.__doc__ = "Alias for `%s`." % self.pretty_target
659
677
660 self._in_call = False
678 self._in_call = False
661
679
662 def __call__(self, *args, **kwargs):
680 def __call__(self, *args, **kwargs):
663 """Call the magic alias."""
681 """Call the magic alias."""
664 fn = self.shell.find_magic(self.magic_name, self.magic_kind)
682 fn = self.shell.find_magic(self.magic_name, self.magic_kind)
665 if fn is None:
683 if fn is None:
666 raise UsageError("Magic `%s` not found." % self.pretty_target)
684 raise UsageError("Magic `%s` not found." % self.pretty_target)
667
685
668 # Protect against infinite recursion.
686 # Protect against infinite recursion.
669 if self._in_call:
687 if self._in_call:
670 raise UsageError("Infinite recursion detected; "
688 raise UsageError("Infinite recursion detected; "
671 "magic aliases cannot call themselves.")
689 "magic aliases cannot call themselves.")
672 self._in_call = True
690 self._in_call = True
673 try:
691 try:
674 return fn(*args, **kwargs)
692 return fn(*args, **kwargs)
675 finally:
693 finally:
676 self._in_call = False
694 self._in_call = False
@@ -1,280 +1,279 b''
1 """Magic functions for running cells in various scripts."""
1 """Magic functions for running cells in various scripts."""
2 #-----------------------------------------------------------------------------
2 #-----------------------------------------------------------------------------
3 # Copyright (c) 2012 The IPython Development Team.
3 # Copyright (c) 2012 The IPython Development Team.
4 #
4 #
5 # Distributed under the terms of the Modified BSD License.
5 # Distributed under the terms of the Modified BSD License.
6 #
6 #
7 # The full license is in the file COPYING.txt, distributed with this software.
7 # The full license is in the file COPYING.txt, distributed with this software.
8 #-----------------------------------------------------------------------------
8 #-----------------------------------------------------------------------------
9
9
10 #-----------------------------------------------------------------------------
10 #-----------------------------------------------------------------------------
11 # Imports
11 # Imports
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13
13
14 # Stdlib
14 # Stdlib
15 import errno
15 import errno
16 import os
16 import os
17 import sys
17 import sys
18 import signal
18 import signal
19 import time
19 import time
20 from subprocess import Popen, PIPE
20 from subprocess import Popen, PIPE
21 import atexit
21 import atexit
22
22
23 # Our own packages
23 # Our own packages
24 from IPython.config.configurable import Configurable
24 from IPython.config.configurable import Configurable
25 from IPython.core import magic_arguments
25 from IPython.core import magic_arguments
26 from IPython.core.magic import (
26 from IPython.core.magic import (
27 Magics, magics_class, line_magic, cell_magic
27 Magics, magics_class, line_magic, cell_magic
28 )
28 )
29 from IPython.lib.backgroundjobs import BackgroundJobManager
29 from IPython.lib.backgroundjobs import BackgroundJobManager
30 from IPython.utils import py3compat
30 from IPython.utils import py3compat
31 from IPython.utils.process import arg_split
31 from IPython.utils.process import arg_split
32 from IPython.utils.traitlets import List, Dict
32 from IPython.utils.traitlets import List, Dict
33
33
34 #-----------------------------------------------------------------------------
34 #-----------------------------------------------------------------------------
35 # Magic implementation classes
35 # Magic implementation classes
36 #-----------------------------------------------------------------------------
36 #-----------------------------------------------------------------------------
37
37
38 def script_args(f):
38 def script_args(f):
39 """single decorator for adding script args"""
39 """single decorator for adding script args"""
40 args = [
40 args = [
41 magic_arguments.argument(
41 magic_arguments.argument(
42 '--out', type=str,
42 '--out', type=str,
43 help="""The variable in which to store stdout from the script.
43 help="""The variable in which to store stdout from the script.
44 If the script is backgrounded, this will be the stdout *pipe*,
44 If the script is backgrounded, this will be the stdout *pipe*,
45 instead of the stderr text itself.
45 instead of the stderr text itself.
46 """
46 """
47 ),
47 ),
48 magic_arguments.argument(
48 magic_arguments.argument(
49 '--err', type=str,
49 '--err', type=str,
50 help="""The variable in which to store stderr from the script.
50 help="""The variable in which to store stderr from the script.
51 If the script is backgrounded, this will be the stderr *pipe*,
51 If the script is backgrounded, this will be the stderr *pipe*,
52 instead of the stderr text itself.
52 instead of the stderr text itself.
53 """
53 """
54 ),
54 ),
55 magic_arguments.argument(
55 magic_arguments.argument(
56 '--bg', action="store_true",
56 '--bg', action="store_true",
57 help="""Whether to run the script in the background.
57 help="""Whether to run the script in the background.
58 If given, the only way to see the output of the command is
58 If given, the only way to see the output of the command is
59 with --out/err.
59 with --out/err.
60 """
60 """
61 ),
61 ),
62 magic_arguments.argument(
62 magic_arguments.argument(
63 '--proc', type=str,
63 '--proc', type=str,
64 help="""The variable in which to store Popen instance.
64 help="""The variable in which to store Popen instance.
65 This is used only when --bg option is given.
65 This is used only when --bg option is given.
66 """
66 """
67 ),
67 ),
68 ]
68 ]
69 for arg in args:
69 for arg in args:
70 f = arg(f)
70 f = arg(f)
71 return f
71 return f
72
72
73 @magics_class
73 @magics_class
74 class ScriptMagics(Magics, Configurable):
74 class ScriptMagics(Magics):
75 """Magics for talking to scripts
75 """Magics for talking to scripts
76
76
77 This defines a base `%%script` cell magic for running a cell
77 This defines a base `%%script` cell magic for running a cell
78 with a program in a subprocess, and registers a few top-level
78 with a program in a subprocess, and registers a few top-level
79 magics that call %%script with common interpreters.
79 magics that call %%script with common interpreters.
80 """
80 """
81 script_magics = List(config=True,
81 script_magics = List(config=True,
82 help="""Extra script cell magics to define
82 help="""Extra script cell magics to define
83
83
84 This generates simple wrappers of `%%script foo` as `%%foo`.
84 This generates simple wrappers of `%%script foo` as `%%foo`.
85
85
86 If you want to add script magics that aren't on your path,
86 If you want to add script magics that aren't on your path,
87 specify them in script_paths
87 specify them in script_paths
88 """,
88 """,
89 )
89 )
90 def _script_magics_default(self):
90 def _script_magics_default(self):
91 """default to a common list of programs"""
91 """default to a common list of programs"""
92
92
93 defaults = [
93 defaults = [
94 'sh',
94 'sh',
95 'bash',
95 'bash',
96 'perl',
96 'perl',
97 'ruby',
97 'ruby',
98 'python',
98 'python',
99 'python3',
99 'python3',
100 'pypy',
100 'pypy',
101 ]
101 ]
102 if os.name == 'nt':
102 if os.name == 'nt':
103 defaults.extend([
103 defaults.extend([
104 'cmd',
104 'cmd',
105 'powershell',
105 'powershell',
106 ])
106 ])
107
107
108 return defaults
108 return defaults
109
109
110 script_paths = Dict(config=True,
110 script_paths = Dict(config=True,
111 help="""Dict mapping short 'ruby' names to full paths, such as '/opt/secret/bin/ruby'
111 help="""Dict mapping short 'ruby' names to full paths, such as '/opt/secret/bin/ruby'
112
112
113 Only necessary for items in script_magics where the default path will not
113 Only necessary for items in script_magics where the default path will not
114 find the right interpreter.
114 find the right interpreter.
115 """
115 """
116 )
116 )
117
117
118 def __init__(self, shell=None):
118 def __init__(self, shell=None):
119 Configurable.__init__(self, config=shell.config)
119 super(ScriptMagics, self).__init__(shell=shell)
120 self._generate_script_magics()
120 self._generate_script_magics()
121 Magics.__init__(self, shell=shell)
122 self.job_manager = BackgroundJobManager()
121 self.job_manager = BackgroundJobManager()
123 self.bg_processes = []
122 self.bg_processes = []
124 atexit.register(self.kill_bg_processes)
123 atexit.register(self.kill_bg_processes)
125
124
126 def __del__(self):
125 def __del__(self):
127 self.kill_bg_processes()
126 self.kill_bg_processes()
128
127
129 def _generate_script_magics(self):
128 def _generate_script_magics(self):
130 cell_magics = self.magics['cell']
129 cell_magics = self.magics['cell']
131 for name in self.script_magics:
130 for name in self.script_magics:
132 cell_magics[name] = self._make_script_magic(name)
131 cell_magics[name] = self._make_script_magic(name)
133
132
134 def _make_script_magic(self, name):
133 def _make_script_magic(self, name):
135 """make a named magic, that calls %%script with a particular program"""
134 """make a named magic, that calls %%script with a particular program"""
136 # expand to explicit path if necessary:
135 # expand to explicit path if necessary:
137 script = self.script_paths.get(name, name)
136 script = self.script_paths.get(name, name)
138
137
139 @magic_arguments.magic_arguments()
138 @magic_arguments.magic_arguments()
140 @script_args
139 @script_args
141 def named_script_magic(line, cell):
140 def named_script_magic(line, cell):
142 # if line, add it as cl-flags
141 # if line, add it as cl-flags
143 if line:
142 if line:
144 line = "%s %s" % (script, line)
143 line = "%s %s" % (script, line)
145 else:
144 else:
146 line = script
145 line = script
147 return self.shebang(line, cell)
146 return self.shebang(line, cell)
148
147
149 # write a basic docstring:
148 # write a basic docstring:
150 named_script_magic.__doc__ = \
149 named_script_magic.__doc__ = \
151 """%%{name} script magic
150 """%%{name} script magic
152
151
153 Run cells with {script} in a subprocess.
152 Run cells with {script} in a subprocess.
154
153
155 This is a shortcut for `%%script {script}`
154 This is a shortcut for `%%script {script}`
156 """.format(**locals())
155 """.format(**locals())
157
156
158 return named_script_magic
157 return named_script_magic
159
158
160 @magic_arguments.magic_arguments()
159 @magic_arguments.magic_arguments()
161 @script_args
160 @script_args
162 @cell_magic("script")
161 @cell_magic("script")
163 def shebang(self, line, cell):
162 def shebang(self, line, cell):
164 """Run a cell via a shell command
163 """Run a cell via a shell command
165
164
166 The `%%script` line is like the #! line of script,
165 The `%%script` line is like the #! line of script,
167 specifying a program (bash, perl, ruby, etc.) with which to run.
166 specifying a program (bash, perl, ruby, etc.) with which to run.
168
167
169 The rest of the cell is run by that program.
168 The rest of the cell is run by that program.
170
169
171 Examples
170 Examples
172 --------
171 --------
173 ::
172 ::
174
173
175 In [1]: %%script bash
174 In [1]: %%script bash
176 ...: for i in 1 2 3; do
175 ...: for i in 1 2 3; do
177 ...: echo $i
176 ...: echo $i
178 ...: done
177 ...: done
179 1
178 1
180 2
179 2
181 3
180 3
182 """
181 """
183 argv = arg_split(line, posix = not sys.platform.startswith('win'))
182 argv = arg_split(line, posix = not sys.platform.startswith('win'))
184 args, cmd = self.shebang.parser.parse_known_args(argv)
183 args, cmd = self.shebang.parser.parse_known_args(argv)
185
184
186 try:
185 try:
187 p = Popen(cmd, stdout=PIPE, stderr=PIPE, stdin=PIPE)
186 p = Popen(cmd, stdout=PIPE, stderr=PIPE, stdin=PIPE)
188 except OSError as e:
187 except OSError as e:
189 if e.errno == errno.ENOENT:
188 if e.errno == errno.ENOENT:
190 print "Couldn't find program: %r" % cmd[0]
189 print "Couldn't find program: %r" % cmd[0]
191 return
190 return
192 else:
191 else:
193 raise
192 raise
194
193
195 cell = cell.encode('utf8', 'replace')
194 cell = cell.encode('utf8', 'replace')
196 if args.bg:
195 if args.bg:
197 self.bg_processes.append(p)
196 self.bg_processes.append(p)
198 self._gc_bg_processes()
197 self._gc_bg_processes()
199 if args.out:
198 if args.out:
200 self.shell.user_ns[args.out] = p.stdout
199 self.shell.user_ns[args.out] = p.stdout
201 if args.err:
200 if args.err:
202 self.shell.user_ns[args.err] = p.stderr
201 self.shell.user_ns[args.err] = p.stderr
203 self.job_manager.new(self._run_script, p, cell, daemon=True)
202 self.job_manager.new(self._run_script, p, cell, daemon=True)
204 if args.proc:
203 if args.proc:
205 self.shell.user_ns[args.proc] = p
204 self.shell.user_ns[args.proc] = p
206 return
205 return
207
206
208 try:
207 try:
209 out, err = p.communicate(cell)
208 out, err = p.communicate(cell)
210 except KeyboardInterrupt:
209 except KeyboardInterrupt:
211 try:
210 try:
212 p.send_signal(signal.SIGINT)
211 p.send_signal(signal.SIGINT)
213 time.sleep(0.1)
212 time.sleep(0.1)
214 if p.poll() is not None:
213 if p.poll() is not None:
215 print "Process is interrupted."
214 print "Process is interrupted."
216 return
215 return
217 p.terminate()
216 p.terminate()
218 time.sleep(0.1)
217 time.sleep(0.1)
219 if p.poll() is not None:
218 if p.poll() is not None:
220 print "Process is terminated."
219 print "Process is terminated."
221 return
220 return
222 p.kill()
221 p.kill()
223 print "Process is killed."
222 print "Process is killed."
224 except OSError:
223 except OSError:
225 pass
224 pass
226 except Exception as e:
225 except Exception as e:
227 print "Error while terminating subprocess (pid=%i): %s" \
226 print "Error while terminating subprocess (pid=%i): %s" \
228 % (p.pid, e)
227 % (p.pid, e)
229 return
228 return
230 out = py3compat.bytes_to_str(out)
229 out = py3compat.bytes_to_str(out)
231 err = py3compat.bytes_to_str(err)
230 err = py3compat.bytes_to_str(err)
232 if args.out:
231 if args.out:
233 self.shell.user_ns[args.out] = out
232 self.shell.user_ns[args.out] = out
234 else:
233 else:
235 sys.stdout.write(out)
234 sys.stdout.write(out)
236 sys.stdout.flush()
235 sys.stdout.flush()
237 if args.err:
236 if args.err:
238 self.shell.user_ns[args.err] = err
237 self.shell.user_ns[args.err] = err
239 else:
238 else:
240 sys.stderr.write(err)
239 sys.stderr.write(err)
241 sys.stderr.flush()
240 sys.stderr.flush()
242
241
243 def _run_script(self, p, cell):
242 def _run_script(self, p, cell):
244 """callback for running the script in the background"""
243 """callback for running the script in the background"""
245 p.stdin.write(cell)
244 p.stdin.write(cell)
246 p.stdin.close()
245 p.stdin.close()
247 p.wait()
246 p.wait()
248
247
249 @line_magic("killbgscripts")
248 @line_magic("killbgscripts")
250 def killbgscripts(self, _nouse_=''):
249 def killbgscripts(self, _nouse_=''):
251 """Kill all BG processes started by %%script and its family."""
250 """Kill all BG processes started by %%script and its family."""
252 self.kill_bg_processes()
251 self.kill_bg_processes()
253 print "All background processes were killed."
252 print "All background processes were killed."
254
253
255 def kill_bg_processes(self):
254 def kill_bg_processes(self):
256 """Kill all BG processes which are still running."""
255 """Kill all BG processes which are still running."""
257 for p in self.bg_processes:
256 for p in self.bg_processes:
258 if p.poll() is None:
257 if p.poll() is None:
259 try:
258 try:
260 p.send_signal(signal.SIGINT)
259 p.send_signal(signal.SIGINT)
261 except:
260 except:
262 pass
261 pass
263 time.sleep(0.1)
262 time.sleep(0.1)
264 for p in self.bg_processes:
263 for p in self.bg_processes:
265 if p.poll() is None:
264 if p.poll() is None:
266 try:
265 try:
267 p.terminate()
266 p.terminate()
268 except:
267 except:
269 pass
268 pass
270 time.sleep(0.1)
269 time.sleep(0.1)
271 for p in self.bg_processes:
270 for p in self.bg_processes:
272 if p.poll() is None:
271 if p.poll() is None:
273 try:
272 try:
274 p.kill()
273 p.kill()
275 except:
274 except:
276 pass
275 pass
277 self._gc_bg_processes()
276 self._gc_bg_processes()
278
277
279 def _gc_bg_processes(self):
278 def _gc_bg_processes(self):
280 self.bg_processes = [p for p in self.bg_processes if p.poll() is None]
279 self.bg_processes = [p for p in self.bg_processes if p.poll() is None]
@@ -1,933 +1,940 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 try:
18 try:
19 from importlib import invalidate_caches # Required from Python 3.3
19 from importlib import invalidate_caches # Required from Python 3.3
20 except ImportError:
20 except ImportError:
21 def invalidate_caches():
21 def invalidate_caches():
22 pass
22 pass
23
23
24 import nose.tools as nt
24 import nose.tools as nt
25
25
26 from IPython.core import magic
26 from IPython.core import magic
27 from IPython.core.magic import (Magics, magics_class, line_magic,
27 from IPython.core.magic import (Magics, magics_class, line_magic,
28 cell_magic, line_cell_magic,
28 cell_magic, line_cell_magic,
29 register_line_magic, register_cell_magic,
29 register_line_magic, register_cell_magic,
30 register_line_cell_magic)
30 register_line_cell_magic)
31 from IPython.core.magics import execution, script, code
31 from IPython.core.magics import execution, script, code
32 from IPython.nbformat.v3.tests.nbexamples import nb0
32 from IPython.nbformat.v3.tests.nbexamples import nb0
33 from IPython.nbformat import current
33 from IPython.nbformat import current
34 from IPython.testing import decorators as dec
34 from IPython.testing import decorators as dec
35 from IPython.testing import tools as tt
35 from IPython.testing import tools as tt
36 from IPython.utils import py3compat
36 from IPython.utils import py3compat
37 from IPython.utils.io import capture_output
37 from IPython.utils.io import capture_output
38 from IPython.utils.tempdir import TemporaryDirectory
38 from IPython.utils.tempdir import TemporaryDirectory
39 from IPython.utils.process import find_cmd
39 from IPython.utils.process import find_cmd
40
40
41 #-----------------------------------------------------------------------------
41 #-----------------------------------------------------------------------------
42 # Test functions begin
42 # Test functions begin
43 #-----------------------------------------------------------------------------
43 #-----------------------------------------------------------------------------
44
44
45 @magic.magics_class
45 @magic.magics_class
46 class DummyMagics(magic.Magics): pass
46 class DummyMagics(magic.Magics): pass
47
47
48 def test_extract_code_ranges():
48 def test_extract_code_ranges():
49 instr = "1 3 5-6 7-9 10:15 17: :10 10- -13 :"
49 instr = "1 3 5-6 7-9 10:15 17: :10 10- -13 :"
50 expected = [(0, 1),
50 expected = [(0, 1),
51 (2, 3),
51 (2, 3),
52 (4, 6),
52 (4, 6),
53 (6, 9),
53 (6, 9),
54 (9, 14),
54 (9, 14),
55 (16, None),
55 (16, None),
56 (None, 9),
56 (None, 9),
57 (9, None),
57 (9, None),
58 (None, 13),
58 (None, 13),
59 (None, None)]
59 (None, None)]
60 actual = list(code.extract_code_ranges(instr))
60 actual = list(code.extract_code_ranges(instr))
61 nt.assert_equal(actual, expected)
61 nt.assert_equal(actual, expected)
62
62
63
64 def test_extract_symbols():
63 def test_extract_symbols():
65 source = """import foo\na = 10\ndef b():\n return 42\n\n\nclass A: pass\n\n\n"""
64 source = """import foo\na = 10\ndef b():\n return 42\n\n\nclass A: pass\n\n\n"""
66 symbols_args = ["a", "b", "A", "A,b", "A,a", "z"]
65 symbols_args = ["a", "b", "A", "A,b", "A,a", "z"]
67 expected = [([], ['a']),
66 expected = [([], ['a']),
68 (["def b():\n return 42\n"], []),
67 (["def b():\n return 42\n"], []),
69 (["class A: pass\n"], []),
68 (["class A: pass\n"], []),
70 (["class A: pass\n", "def b():\n return 42\n"], []),
69 (["class A: pass\n", "def b():\n return 42\n"], []),
71 (["class A: pass\n"], ['a']),
70 (["class A: pass\n"], ['a']),
72 ([], ['z'])]
71 ([], ['z'])]
73 for symbols, exp in zip(symbols_args, expected):
72 for symbols, exp in zip(symbols_args, expected):
74 nt.assert_equal(code.extract_symbols(source, symbols), exp)
73 nt.assert_equal(code.extract_symbols(source, symbols), exp)
75
74
76
75
77 def test_extract_symbols_raises_exception_with_non_python_code():
76 def test_extract_symbols_raises_exception_with_non_python_code():
78 source = ("=begin A Ruby program :)=end\n"
77 source = ("=begin A Ruby program :)=end\n"
79 "def hello\n"
78 "def hello\n"
80 "puts 'Hello world'\n"
79 "puts 'Hello world'\n"
81 "end")
80 "end")
82 with nt.assert_raises(SyntaxError):
81 with nt.assert_raises(SyntaxError):
83 code.extract_symbols(source, "hello")
82 code.extract_symbols(source, "hello")
84
83
84 def test_config():
85 """ test that config magic does not raise
86 can happen if Configurable init is moved too early into
87 Magics.__init__ as then a Config object will be registerd as a
88 magic.
89 """
90 ## should not raise.
91 _ip.magic('config')
85
92
86 def test_rehashx():
93 def test_rehashx():
87 # clear up everything
94 # clear up everything
88 _ip = get_ipython()
95 _ip = get_ipython()
89 _ip.alias_manager.clear_aliases()
96 _ip.alias_manager.clear_aliases()
90 del _ip.db['syscmdlist']
97 del _ip.db['syscmdlist']
91
98
92 _ip.magic('rehashx')
99 _ip.magic('rehashx')
93 # Practically ALL ipython development systems will have more than 10 aliases
100 # Practically ALL ipython development systems will have more than 10 aliases
94
101
95 nt.assert_true(len(_ip.alias_manager.aliases) > 10)
102 nt.assert_true(len(_ip.alias_manager.aliases) > 10)
96 for name, cmd in _ip.alias_manager.aliases:
103 for name, cmd in _ip.alias_manager.aliases:
97 # we must strip dots from alias names
104 # we must strip dots from alias names
98 nt.assert_not_in('.', name)
105 nt.assert_not_in('.', name)
99
106
100 # rehashx must fill up syscmdlist
107 # rehashx must fill up syscmdlist
101 scoms = _ip.db['syscmdlist']
108 scoms = _ip.db['syscmdlist']
102 nt.assert_true(len(scoms) > 10)
109 nt.assert_true(len(scoms) > 10)
103
110
104
111
105 def test_magic_parse_options():
112 def test_magic_parse_options():
106 """Test that we don't mangle paths when parsing magic options."""
113 """Test that we don't mangle paths when parsing magic options."""
107 ip = get_ipython()
114 ip = get_ipython()
108 path = 'c:\\x'
115 path = 'c:\\x'
109 m = DummyMagics(ip)
116 m = DummyMagics(ip)
110 opts = m.parse_options('-f %s' % path,'f:')[0]
117 opts = m.parse_options('-f %s' % path,'f:')[0]
111 # argv splitting is os-dependent
118 # argv splitting is os-dependent
112 if os.name == 'posix':
119 if os.name == 'posix':
113 expected = 'c:x'
120 expected = 'c:x'
114 else:
121 else:
115 expected = path
122 expected = path
116 nt.assert_equal(opts['f'], expected)
123 nt.assert_equal(opts['f'], expected)
117
124
118 def test_magic_parse_long_options():
125 def test_magic_parse_long_options():
119 """Magic.parse_options can handle --foo=bar long options"""
126 """Magic.parse_options can handle --foo=bar long options"""
120 ip = get_ipython()
127 ip = get_ipython()
121 m = DummyMagics(ip)
128 m = DummyMagics(ip)
122 opts, _ = m.parse_options('--foo --bar=bubble', 'a', 'foo', 'bar=')
129 opts, _ = m.parse_options('--foo --bar=bubble', 'a', 'foo', 'bar=')
123 nt.assert_in('foo', opts)
130 nt.assert_in('foo', opts)
124 nt.assert_in('bar', opts)
131 nt.assert_in('bar', opts)
125 nt.assert_equal(opts['bar'], "bubble")
132 nt.assert_equal(opts['bar'], "bubble")
126
133
127
134
128 @dec.skip_without('sqlite3')
135 @dec.skip_without('sqlite3')
129 def doctest_hist_f():
136 def doctest_hist_f():
130 """Test %hist -f with temporary filename.
137 """Test %hist -f with temporary filename.
131
138
132 In [9]: import tempfile
139 In [9]: import tempfile
133
140
134 In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-')
141 In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-')
135
142
136 In [11]: %hist -nl -f $tfile 3
143 In [11]: %hist -nl -f $tfile 3
137
144
138 In [13]: import os; os.unlink(tfile)
145 In [13]: import os; os.unlink(tfile)
139 """
146 """
140
147
141
148
142 @dec.skip_without('sqlite3')
149 @dec.skip_without('sqlite3')
143 def doctest_hist_r():
150 def doctest_hist_r():
144 """Test %hist -r
151 """Test %hist -r
145
152
146 XXX - This test is not recording the output correctly. For some reason, in
153 XXX - This test is not recording the output correctly. For some reason, in
147 testing mode the raw history isn't getting populated. No idea why.
154 testing mode the raw history isn't getting populated. No idea why.
148 Disabling the output checking for now, though at least we do run it.
155 Disabling the output checking for now, though at least we do run it.
149
156
150 In [1]: 'hist' in _ip.lsmagic()
157 In [1]: 'hist' in _ip.lsmagic()
151 Out[1]: True
158 Out[1]: True
152
159
153 In [2]: x=1
160 In [2]: x=1
154
161
155 In [3]: %hist -rl 2
162 In [3]: %hist -rl 2
156 x=1 # random
163 x=1 # random
157 %hist -r 2
164 %hist -r 2
158 """
165 """
159
166
160
167
161 @dec.skip_without('sqlite3')
168 @dec.skip_without('sqlite3')
162 def doctest_hist_op():
169 def doctest_hist_op():
163 """Test %hist -op
170 """Test %hist -op
164
171
165 In [1]: class b(float):
172 In [1]: class b(float):
166 ...: pass
173 ...: pass
167 ...:
174 ...:
168
175
169 In [2]: class s(object):
176 In [2]: class s(object):
170 ...: def __str__(self):
177 ...: def __str__(self):
171 ...: return 's'
178 ...: return 's'
172 ...:
179 ...:
173
180
174 In [3]:
181 In [3]:
175
182
176 In [4]: class r(b):
183 In [4]: class r(b):
177 ...: def __repr__(self):
184 ...: def __repr__(self):
178 ...: return 'r'
185 ...: return 'r'
179 ...:
186 ...:
180
187
181 In [5]: class sr(s,r): pass
188 In [5]: class sr(s,r): pass
182 ...:
189 ...:
183
190
184 In [6]:
191 In [6]:
185
192
186 In [7]: bb=b()
193 In [7]: bb=b()
187
194
188 In [8]: ss=s()
195 In [8]: ss=s()
189
196
190 In [9]: rr=r()
197 In [9]: rr=r()
191
198
192 In [10]: ssrr=sr()
199 In [10]: ssrr=sr()
193
200
194 In [11]: 4.5
201 In [11]: 4.5
195 Out[11]: 4.5
202 Out[11]: 4.5
196
203
197 In [12]: str(ss)
204 In [12]: str(ss)
198 Out[12]: 's'
205 Out[12]: 's'
199
206
200 In [13]:
207 In [13]:
201
208
202 In [14]: %hist -op
209 In [14]: %hist -op
203 >>> class b:
210 >>> class b:
204 ... pass
211 ... pass
205 ...
212 ...
206 >>> class s(b):
213 >>> class s(b):
207 ... def __str__(self):
214 ... def __str__(self):
208 ... return 's'
215 ... return 's'
209 ...
216 ...
210 >>>
217 >>>
211 >>> class r(b):
218 >>> class r(b):
212 ... def __repr__(self):
219 ... def __repr__(self):
213 ... return 'r'
220 ... return 'r'
214 ...
221 ...
215 >>> class sr(s,r): pass
222 >>> class sr(s,r): pass
216 >>>
223 >>>
217 >>> bb=b()
224 >>> bb=b()
218 >>> ss=s()
225 >>> ss=s()
219 >>> rr=r()
226 >>> rr=r()
220 >>> ssrr=sr()
227 >>> ssrr=sr()
221 >>> 4.5
228 >>> 4.5
222 4.5
229 4.5
223 >>> str(ss)
230 >>> str(ss)
224 's'
231 's'
225 >>>
232 >>>
226 """
233 """
227
234
228
235
229 @dec.skip_without('sqlite3')
236 @dec.skip_without('sqlite3')
230 def test_macro():
237 def test_macro():
231 ip = get_ipython()
238 ip = get_ipython()
232 ip.history_manager.reset() # Clear any existing history.
239 ip.history_manager.reset() # Clear any existing history.
233 cmds = ["a=1", "def b():\n return a**2", "print(a,b())"]
240 cmds = ["a=1", "def b():\n return a**2", "print(a,b())"]
234 for i, cmd in enumerate(cmds, start=1):
241 for i, cmd in enumerate(cmds, start=1):
235 ip.history_manager.store_inputs(i, cmd)
242 ip.history_manager.store_inputs(i, cmd)
236 ip.magic("macro test 1-3")
243 ip.magic("macro test 1-3")
237 nt.assert_equal(ip.user_ns["test"].value, "\n".join(cmds)+"\n")
244 nt.assert_equal(ip.user_ns["test"].value, "\n".join(cmds)+"\n")
238
245
239 # List macros
246 # List macros
240 nt.assert_in("test", ip.magic("macro"))
247 nt.assert_in("test", ip.magic("macro"))
241
248
242
249
243 @dec.skip_without('sqlite3')
250 @dec.skip_without('sqlite3')
244 def test_macro_run():
251 def test_macro_run():
245 """Test that we can run a multi-line macro successfully."""
252 """Test that we can run a multi-line macro successfully."""
246 ip = get_ipython()
253 ip = get_ipython()
247 ip.history_manager.reset()
254 ip.history_manager.reset()
248 cmds = ["a=10", "a+=1", py3compat.doctest_refactor_print("print a"),
255 cmds = ["a=10", "a+=1", py3compat.doctest_refactor_print("print a"),
249 "%macro test 2-3"]
256 "%macro test 2-3"]
250 for cmd in cmds:
257 for cmd in cmds:
251 ip.run_cell(cmd, store_history=True)
258 ip.run_cell(cmd, store_history=True)
252 nt.assert_equal(ip.user_ns["test"].value,
259 nt.assert_equal(ip.user_ns["test"].value,
253 py3compat.doctest_refactor_print("a+=1\nprint a\n"))
260 py3compat.doctest_refactor_print("a+=1\nprint a\n"))
254 with tt.AssertPrints("12"):
261 with tt.AssertPrints("12"):
255 ip.run_cell("test")
262 ip.run_cell("test")
256 with tt.AssertPrints("13"):
263 with tt.AssertPrints("13"):
257 ip.run_cell("test")
264 ip.run_cell("test")
258
265
259
266
260 def test_magic_magic():
267 def test_magic_magic():
261 """Test %magic"""
268 """Test %magic"""
262 ip = get_ipython()
269 ip = get_ipython()
263 with capture_output() as captured:
270 with capture_output() as captured:
264 ip.magic("magic")
271 ip.magic("magic")
265
272
266 stdout = captured.stdout
273 stdout = captured.stdout
267 nt.assert_in('%magic', stdout)
274 nt.assert_in('%magic', stdout)
268 nt.assert_in('IPython', stdout)
275 nt.assert_in('IPython', stdout)
269 nt.assert_in('Available', stdout)
276 nt.assert_in('Available', stdout)
270
277
271
278
272 @dec.skipif_not_numpy
279 @dec.skipif_not_numpy
273 def test_numpy_reset_array_undec():
280 def test_numpy_reset_array_undec():
274 "Test '%reset array' functionality"
281 "Test '%reset array' functionality"
275 _ip.ex('import numpy as np')
282 _ip.ex('import numpy as np')
276 _ip.ex('a = np.empty(2)')
283 _ip.ex('a = np.empty(2)')
277 nt.assert_in('a', _ip.user_ns)
284 nt.assert_in('a', _ip.user_ns)
278 _ip.magic('reset -f array')
285 _ip.magic('reset -f array')
279 nt.assert_not_in('a', _ip.user_ns)
286 nt.assert_not_in('a', _ip.user_ns)
280
287
281 def test_reset_out():
288 def test_reset_out():
282 "Test '%reset out' magic"
289 "Test '%reset out' magic"
283 _ip.run_cell("parrot = 'dead'", store_history=True)
290 _ip.run_cell("parrot = 'dead'", store_history=True)
284 # test '%reset -f out', make an Out prompt
291 # test '%reset -f out', make an Out prompt
285 _ip.run_cell("parrot", store_history=True)
292 _ip.run_cell("parrot", store_history=True)
286 nt.assert_true('dead' in [_ip.user_ns[x] for x in '_','__','___'])
293 nt.assert_true('dead' in [_ip.user_ns[x] for x in '_','__','___'])
287 _ip.magic('reset -f out')
294 _ip.magic('reset -f out')
288 nt.assert_false('dead' in [_ip.user_ns[x] for x in '_','__','___'])
295 nt.assert_false('dead' in [_ip.user_ns[x] for x in '_','__','___'])
289 nt.assert_equal(len(_ip.user_ns['Out']), 0)
296 nt.assert_equal(len(_ip.user_ns['Out']), 0)
290
297
291 def test_reset_in():
298 def test_reset_in():
292 "Test '%reset in' magic"
299 "Test '%reset in' magic"
293 # test '%reset -f in'
300 # test '%reset -f in'
294 _ip.run_cell("parrot", store_history=True)
301 _ip.run_cell("parrot", store_history=True)
295 nt.assert_true('parrot' in [_ip.user_ns[x] for x in '_i','_ii','_iii'])
302 nt.assert_true('parrot' in [_ip.user_ns[x] for x in '_i','_ii','_iii'])
296 _ip.magic('%reset -f in')
303 _ip.magic('%reset -f in')
297 nt.assert_false('parrot' in [_ip.user_ns[x] for x in '_i','_ii','_iii'])
304 nt.assert_false('parrot' in [_ip.user_ns[x] for x in '_i','_ii','_iii'])
298 nt.assert_equal(len(set(_ip.user_ns['In'])), 1)
305 nt.assert_equal(len(set(_ip.user_ns['In'])), 1)
299
306
300 def test_reset_dhist():
307 def test_reset_dhist():
301 "Test '%reset dhist' magic"
308 "Test '%reset dhist' magic"
302 _ip.run_cell("tmp = [d for d in _dh]") # copy before clearing
309 _ip.run_cell("tmp = [d for d in _dh]") # copy before clearing
303 _ip.magic('cd ' + os.path.dirname(nt.__file__))
310 _ip.magic('cd ' + os.path.dirname(nt.__file__))
304 _ip.magic('cd -')
311 _ip.magic('cd -')
305 nt.assert_true(len(_ip.user_ns['_dh']) > 0)
312 nt.assert_true(len(_ip.user_ns['_dh']) > 0)
306 _ip.magic('reset -f dhist')
313 _ip.magic('reset -f dhist')
307 nt.assert_equal(len(_ip.user_ns['_dh']), 0)
314 nt.assert_equal(len(_ip.user_ns['_dh']), 0)
308 _ip.run_cell("_dh = [d for d in tmp]") #restore
315 _ip.run_cell("_dh = [d for d in tmp]") #restore
309
316
310 def test_reset_in_length():
317 def test_reset_in_length():
311 "Test that '%reset in' preserves In[] length"
318 "Test that '%reset in' preserves In[] length"
312 _ip.run_cell("print 'foo'")
319 _ip.run_cell("print 'foo'")
313 _ip.run_cell("reset -f in")
320 _ip.run_cell("reset -f in")
314 nt.assert_equal(len(_ip.user_ns['In']), _ip.displayhook.prompt_count+1)
321 nt.assert_equal(len(_ip.user_ns['In']), _ip.displayhook.prompt_count+1)
315
322
316 def test_tb_syntaxerror():
323 def test_tb_syntaxerror():
317 """test %tb after a SyntaxError"""
324 """test %tb after a SyntaxError"""
318 ip = get_ipython()
325 ip = get_ipython()
319 ip.run_cell("for")
326 ip.run_cell("for")
320
327
321 # trap and validate stdout
328 # trap and validate stdout
322 save_stdout = sys.stdout
329 save_stdout = sys.stdout
323 try:
330 try:
324 sys.stdout = StringIO()
331 sys.stdout = StringIO()
325 ip.run_cell("%tb")
332 ip.run_cell("%tb")
326 out = sys.stdout.getvalue()
333 out = sys.stdout.getvalue()
327 finally:
334 finally:
328 sys.stdout = save_stdout
335 sys.stdout = save_stdout
329 # trim output, and only check the last line
336 # trim output, and only check the last line
330 last_line = out.rstrip().splitlines()[-1].strip()
337 last_line = out.rstrip().splitlines()[-1].strip()
331 nt.assert_equal(last_line, "SyntaxError: invalid syntax")
338 nt.assert_equal(last_line, "SyntaxError: invalid syntax")
332
339
333
340
334 def test_time():
341 def test_time():
335 ip = get_ipython()
342 ip = get_ipython()
336
343
337 with tt.AssertPrints("Wall time: "):
344 with tt.AssertPrints("Wall time: "):
338 ip.run_cell("%time None")
345 ip.run_cell("%time None")
339
346
340 ip.run_cell("def f(kmjy):\n"
347 ip.run_cell("def f(kmjy):\n"
341 " %time print (2*kmjy)")
348 " %time print (2*kmjy)")
342
349
343 with tt.AssertPrints("Wall time: "):
350 with tt.AssertPrints("Wall time: "):
344 with tt.AssertPrints("hihi", suppress=False):
351 with tt.AssertPrints("hihi", suppress=False):
345 ip.run_cell("f('hi')")
352 ip.run_cell("f('hi')")
346
353
347
354
348 @dec.skip_win32
355 @dec.skip_win32
349 def test_time2():
356 def test_time2():
350 ip = get_ipython()
357 ip = get_ipython()
351
358
352 with tt.AssertPrints("CPU times: user "):
359 with tt.AssertPrints("CPU times: user "):
353 ip.run_cell("%time None")
360 ip.run_cell("%time None")
354
361
355 def test_time3():
362 def test_time3():
356 """Erroneous magic function calls, issue gh-3334"""
363 """Erroneous magic function calls, issue gh-3334"""
357 ip = get_ipython()
364 ip = get_ipython()
358 ip.user_ns.pop('run', None)
365 ip.user_ns.pop('run', None)
359
366
360 with tt.AssertNotPrints("not found", channel='stderr'):
367 with tt.AssertNotPrints("not found", channel='stderr'):
361 ip.run_cell("%%time\n"
368 ip.run_cell("%%time\n"
362 "run = 0\n"
369 "run = 0\n"
363 "run += 1")
370 "run += 1")
364
371
365 def test_doctest_mode():
372 def test_doctest_mode():
366 "Toggle doctest_mode twice, it should be a no-op and run without error"
373 "Toggle doctest_mode twice, it should be a no-op and run without error"
367 _ip.magic('doctest_mode')
374 _ip.magic('doctest_mode')
368 _ip.magic('doctest_mode')
375 _ip.magic('doctest_mode')
369
376
370
377
371 def test_parse_options():
378 def test_parse_options():
372 """Tests for basic options parsing in magics."""
379 """Tests for basic options parsing in magics."""
373 # These are only the most minimal of tests, more should be added later. At
380 # These are only the most minimal of tests, more should be added later. At
374 # the very least we check that basic text/unicode calls work OK.
381 # the very least we check that basic text/unicode calls work OK.
375 m = DummyMagics(_ip)
382 m = DummyMagics(_ip)
376 nt.assert_equal(m.parse_options('foo', '')[1], 'foo')
383 nt.assert_equal(m.parse_options('foo', '')[1], 'foo')
377 nt.assert_equal(m.parse_options(u'foo', '')[1], u'foo')
384 nt.assert_equal(m.parse_options(u'foo', '')[1], u'foo')
378
385
379
386
380 def test_dirops():
387 def test_dirops():
381 """Test various directory handling operations."""
388 """Test various directory handling operations."""
382 # curpath = lambda :os.path.splitdrive(os.getcwdu())[1].replace('\\','/')
389 # curpath = lambda :os.path.splitdrive(os.getcwdu())[1].replace('\\','/')
383 curpath = os.getcwdu
390 curpath = os.getcwdu
384 startdir = os.getcwdu()
391 startdir = os.getcwdu()
385 ipdir = os.path.realpath(_ip.ipython_dir)
392 ipdir = os.path.realpath(_ip.ipython_dir)
386 try:
393 try:
387 _ip.magic('cd "%s"' % ipdir)
394 _ip.magic('cd "%s"' % ipdir)
388 nt.assert_equal(curpath(), ipdir)
395 nt.assert_equal(curpath(), ipdir)
389 _ip.magic('cd -')
396 _ip.magic('cd -')
390 nt.assert_equal(curpath(), startdir)
397 nt.assert_equal(curpath(), startdir)
391 _ip.magic('pushd "%s"' % ipdir)
398 _ip.magic('pushd "%s"' % ipdir)
392 nt.assert_equal(curpath(), ipdir)
399 nt.assert_equal(curpath(), ipdir)
393 _ip.magic('popd')
400 _ip.magic('popd')
394 nt.assert_equal(curpath(), startdir)
401 nt.assert_equal(curpath(), startdir)
395 finally:
402 finally:
396 os.chdir(startdir)
403 os.chdir(startdir)
397
404
398
405
399 def test_xmode():
406 def test_xmode():
400 # Calling xmode three times should be a no-op
407 # Calling xmode three times should be a no-op
401 xmode = _ip.InteractiveTB.mode
408 xmode = _ip.InteractiveTB.mode
402 for i in range(3):
409 for i in range(3):
403 _ip.magic("xmode")
410 _ip.magic("xmode")
404 nt.assert_equal(_ip.InteractiveTB.mode, xmode)
411 nt.assert_equal(_ip.InteractiveTB.mode, xmode)
405
412
406 def test_reset_hard():
413 def test_reset_hard():
407 monitor = []
414 monitor = []
408 class A(object):
415 class A(object):
409 def __del__(self):
416 def __del__(self):
410 monitor.append(1)
417 monitor.append(1)
411 def __repr__(self):
418 def __repr__(self):
412 return "<A instance>"
419 return "<A instance>"
413
420
414 _ip.user_ns["a"] = A()
421 _ip.user_ns["a"] = A()
415 _ip.run_cell("a")
422 _ip.run_cell("a")
416
423
417 nt.assert_equal(monitor, [])
424 nt.assert_equal(monitor, [])
418 _ip.magic("reset -f")
425 _ip.magic("reset -f")
419 nt.assert_equal(monitor, [1])
426 nt.assert_equal(monitor, [1])
420
427
421 class TestXdel(tt.TempFileMixin):
428 class TestXdel(tt.TempFileMixin):
422 def test_xdel(self):
429 def test_xdel(self):
423 """Test that references from %run are cleared by xdel."""
430 """Test that references from %run are cleared by xdel."""
424 src = ("class A(object):\n"
431 src = ("class A(object):\n"
425 " monitor = []\n"
432 " monitor = []\n"
426 " def __del__(self):\n"
433 " def __del__(self):\n"
427 " self.monitor.append(1)\n"
434 " self.monitor.append(1)\n"
428 "a = A()\n")
435 "a = A()\n")
429 self.mktmp(src)
436 self.mktmp(src)
430 # %run creates some hidden references...
437 # %run creates some hidden references...
431 _ip.magic("run %s" % self.fname)
438 _ip.magic("run %s" % self.fname)
432 # ... as does the displayhook.
439 # ... as does the displayhook.
433 _ip.run_cell("a")
440 _ip.run_cell("a")
434
441
435 monitor = _ip.user_ns["A"].monitor
442 monitor = _ip.user_ns["A"].monitor
436 nt.assert_equal(monitor, [])
443 nt.assert_equal(monitor, [])
437
444
438 _ip.magic("xdel a")
445 _ip.magic("xdel a")
439
446
440 # Check that a's __del__ method has been called.
447 # Check that a's __del__ method has been called.
441 nt.assert_equal(monitor, [1])
448 nt.assert_equal(monitor, [1])
442
449
443 def doctest_who():
450 def doctest_who():
444 """doctest for %who
451 """doctest for %who
445
452
446 In [1]: %reset -f
453 In [1]: %reset -f
447
454
448 In [2]: alpha = 123
455 In [2]: alpha = 123
449
456
450 In [3]: beta = 'beta'
457 In [3]: beta = 'beta'
451
458
452 In [4]: %who int
459 In [4]: %who int
453 alpha
460 alpha
454
461
455 In [5]: %who str
462 In [5]: %who str
456 beta
463 beta
457
464
458 In [6]: %whos
465 In [6]: %whos
459 Variable Type Data/Info
466 Variable Type Data/Info
460 ----------------------------
467 ----------------------------
461 alpha int 123
468 alpha int 123
462 beta str beta
469 beta str beta
463
470
464 In [7]: %who_ls
471 In [7]: %who_ls
465 Out[7]: ['alpha', 'beta']
472 Out[7]: ['alpha', 'beta']
466 """
473 """
467
474
468 def test_whos():
475 def test_whos():
469 """Check that whos is protected against objects where repr() fails."""
476 """Check that whos is protected against objects where repr() fails."""
470 class A(object):
477 class A(object):
471 def __repr__(self):
478 def __repr__(self):
472 raise Exception()
479 raise Exception()
473 _ip.user_ns['a'] = A()
480 _ip.user_ns['a'] = A()
474 _ip.magic("whos")
481 _ip.magic("whos")
475
482
476 @py3compat.u_format
483 @py3compat.u_format
477 def doctest_precision():
484 def doctest_precision():
478 """doctest for %precision
485 """doctest for %precision
479
486
480 In [1]: f = get_ipython().display_formatter.formatters['text/plain']
487 In [1]: f = get_ipython().display_formatter.formatters['text/plain']
481
488
482 In [2]: %precision 5
489 In [2]: %precision 5
483 Out[2]: {u}'%.5f'
490 Out[2]: {u}'%.5f'
484
491
485 In [3]: f.float_format
492 In [3]: f.float_format
486 Out[3]: {u}'%.5f'
493 Out[3]: {u}'%.5f'
487
494
488 In [4]: %precision %e
495 In [4]: %precision %e
489 Out[4]: {u}'%e'
496 Out[4]: {u}'%e'
490
497
491 In [5]: f(3.1415927)
498 In [5]: f(3.1415927)
492 Out[5]: {u}'3.141593e+00'
499 Out[5]: {u}'3.141593e+00'
493 """
500 """
494
501
495 def test_psearch():
502 def test_psearch():
496 with tt.AssertPrints("dict.fromkeys"):
503 with tt.AssertPrints("dict.fromkeys"):
497 _ip.run_cell("dict.fr*?")
504 _ip.run_cell("dict.fr*?")
498
505
499 def test_timeit_shlex():
506 def test_timeit_shlex():
500 """test shlex issues with timeit (#1109)"""
507 """test shlex issues with timeit (#1109)"""
501 _ip.ex("def f(*a,**kw): pass")
508 _ip.ex("def f(*a,**kw): pass")
502 _ip.magic('timeit -n1 "this is a bug".count(" ")')
509 _ip.magic('timeit -n1 "this is a bug".count(" ")')
503 _ip.magic('timeit -r1 -n1 f(" ", 1)')
510 _ip.magic('timeit -r1 -n1 f(" ", 1)')
504 _ip.magic('timeit -r1 -n1 f(" ", 1, " ", 2, " ")')
511 _ip.magic('timeit -r1 -n1 f(" ", 1, " ", 2, " ")')
505 _ip.magic('timeit -r1 -n1 ("a " + "b")')
512 _ip.magic('timeit -r1 -n1 ("a " + "b")')
506 _ip.magic('timeit -r1 -n1 f("a " + "b")')
513 _ip.magic('timeit -r1 -n1 f("a " + "b")')
507 _ip.magic('timeit -r1 -n1 f("a " + "b ")')
514 _ip.magic('timeit -r1 -n1 f("a " + "b ")')
508
515
509
516
510 def test_timeit_arguments():
517 def test_timeit_arguments():
511 "Test valid timeit arguments, should not cause SyntaxError (GH #1269)"
518 "Test valid timeit arguments, should not cause SyntaxError (GH #1269)"
512 _ip.magic("timeit ('#')")
519 _ip.magic("timeit ('#')")
513
520
514
521
515 def test_timeit_special_syntax():
522 def test_timeit_special_syntax():
516 "Test %%timeit with IPython special syntax"
523 "Test %%timeit with IPython special syntax"
517 @register_line_magic
524 @register_line_magic
518 def lmagic(line):
525 def lmagic(line):
519 ip = get_ipython()
526 ip = get_ipython()
520 ip.user_ns['lmagic_out'] = line
527 ip.user_ns['lmagic_out'] = line
521
528
522 # line mode test
529 # line mode test
523 _ip.run_line_magic('timeit', '-n1 -r1 %lmagic my line')
530 _ip.run_line_magic('timeit', '-n1 -r1 %lmagic my line')
524 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
531 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
525 # cell mode test
532 # cell mode test
526 _ip.run_cell_magic('timeit', '-n1 -r1', '%lmagic my line2')
533 _ip.run_cell_magic('timeit', '-n1 -r1', '%lmagic my line2')
527 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
534 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
528
535
529 def test_timeit_return():
536 def test_timeit_return():
530 """
537 """
531 test wether timeit -o return object
538 test wether timeit -o return object
532 """
539 """
533
540
534 res = _ip.run_line_magic('timeit','-n10 -r10 -o 1')
541 res = _ip.run_line_magic('timeit','-n10 -r10 -o 1')
535 assert(res is not None)
542 assert(res is not None)
536
543
537 def test_timeit_quiet():
544 def test_timeit_quiet():
538 """
545 """
539 test quiet option of timeit magic
546 test quiet option of timeit magic
540 """
547 """
541 with tt.AssertNotPrints("loops"):
548 with tt.AssertNotPrints("loops"):
542 _ip.run_cell("%timeit -n1 -r1 -q 1")
549 _ip.run_cell("%timeit -n1 -r1 -q 1")
543
550
544 @dec.skipif(execution.profile is None)
551 @dec.skipif(execution.profile is None)
545 def test_prun_special_syntax():
552 def test_prun_special_syntax():
546 "Test %%prun with IPython special syntax"
553 "Test %%prun with IPython special syntax"
547 @register_line_magic
554 @register_line_magic
548 def lmagic(line):
555 def lmagic(line):
549 ip = get_ipython()
556 ip = get_ipython()
550 ip.user_ns['lmagic_out'] = line
557 ip.user_ns['lmagic_out'] = line
551
558
552 # line mode test
559 # line mode test
553 _ip.run_line_magic('prun', '-q %lmagic my line')
560 _ip.run_line_magic('prun', '-q %lmagic my line')
554 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
561 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line')
555 # cell mode test
562 # cell mode test
556 _ip.run_cell_magic('prun', '-q', '%lmagic my line2')
563 _ip.run_cell_magic('prun', '-q', '%lmagic my line2')
557 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
564 nt.assert_equal(_ip.user_ns['lmagic_out'], 'my line2')
558
565
559 @dec.skipif(execution.profile is None)
566 @dec.skipif(execution.profile is None)
560 def test_prun_quotes():
567 def test_prun_quotes():
561 "Test that prun does not clobber string escapes (GH #1302)"
568 "Test that prun does not clobber string escapes (GH #1302)"
562 _ip.magic(r"prun -q x = '\t'")
569 _ip.magic(r"prun -q x = '\t'")
563 nt.assert_equal(_ip.user_ns['x'], '\t')
570 nt.assert_equal(_ip.user_ns['x'], '\t')
564
571
565 def test_extension():
572 def test_extension():
566 tmpdir = TemporaryDirectory()
573 tmpdir = TemporaryDirectory()
567 orig_ipython_dir = _ip.ipython_dir
574 orig_ipython_dir = _ip.ipython_dir
568 try:
575 try:
569 _ip.ipython_dir = tmpdir.name
576 _ip.ipython_dir = tmpdir.name
570 nt.assert_raises(ImportError, _ip.magic, "load_ext daft_extension")
577 nt.assert_raises(ImportError, _ip.magic, "load_ext daft_extension")
571 url = os.path.join(os.path.dirname(__file__), "daft_extension.py")
578 url = os.path.join(os.path.dirname(__file__), "daft_extension.py")
572 _ip.magic("install_ext %s" % url)
579 _ip.magic("install_ext %s" % url)
573 _ip.user_ns.pop('arq', None)
580 _ip.user_ns.pop('arq', None)
574 invalidate_caches() # Clear import caches
581 invalidate_caches() # Clear import caches
575 _ip.magic("load_ext daft_extension")
582 _ip.magic("load_ext daft_extension")
576 nt.assert_equal(_ip.user_ns['arq'], 185)
583 nt.assert_equal(_ip.user_ns['arq'], 185)
577 _ip.magic("unload_ext daft_extension")
584 _ip.magic("unload_ext daft_extension")
578 assert 'arq' not in _ip.user_ns
585 assert 'arq' not in _ip.user_ns
579 finally:
586 finally:
580 _ip.ipython_dir = orig_ipython_dir
587 _ip.ipython_dir = orig_ipython_dir
581 tmpdir.cleanup()
588 tmpdir.cleanup()
582
589
583 def test_notebook_export_json():
590 def test_notebook_export_json():
584 with TemporaryDirectory() as td:
591 with TemporaryDirectory() as td:
585 outfile = os.path.join(td, "nb.ipynb")
592 outfile = os.path.join(td, "nb.ipynb")
586 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
593 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
587 _ip.magic("notebook -e %s" % outfile)
594 _ip.magic("notebook -e %s" % outfile)
588
595
589 def test_notebook_export_py():
596 def test_notebook_export_py():
590 with TemporaryDirectory() as td:
597 with TemporaryDirectory() as td:
591 outfile = os.path.join(td, "nb.py")
598 outfile = os.path.join(td, "nb.py")
592 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
599 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
593 _ip.magic("notebook -e %s" % outfile)
600 _ip.magic("notebook -e %s" % outfile)
594
601
595 def test_notebook_reformat_py():
602 def test_notebook_reformat_py():
596 with TemporaryDirectory() as td:
603 with TemporaryDirectory() as td:
597 infile = os.path.join(td, "nb.ipynb")
604 infile = os.path.join(td, "nb.ipynb")
598 with io.open(infile, 'w', encoding='utf-8') as f:
605 with io.open(infile, 'w', encoding='utf-8') as f:
599 current.write(nb0, f, 'json')
606 current.write(nb0, f, 'json')
600
607
601 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
608 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
602 _ip.magic("notebook -f py %s" % infile)
609 _ip.magic("notebook -f py %s" % infile)
603
610
604 def test_notebook_reformat_json():
611 def test_notebook_reformat_json():
605 with TemporaryDirectory() as td:
612 with TemporaryDirectory() as td:
606 infile = os.path.join(td, "nb.py")
613 infile = os.path.join(td, "nb.py")
607 with io.open(infile, 'w', encoding='utf-8') as f:
614 with io.open(infile, 'w', encoding='utf-8') as f:
608 current.write(nb0, f, 'py')
615 current.write(nb0, f, 'py')
609
616
610 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
617 _ip.ex(py3compat.u_format(u"u = {u}'hΓ©llo'"))
611 _ip.magic("notebook -f ipynb %s" % infile)
618 _ip.magic("notebook -f ipynb %s" % infile)
612 _ip.magic("notebook -f json %s" % infile)
619 _ip.magic("notebook -f json %s" % infile)
613
620
614 def test_env():
621 def test_env():
615 env = _ip.magic("env")
622 env = _ip.magic("env")
616 assert isinstance(env, dict), type(env)
623 assert isinstance(env, dict), type(env)
617
624
618
625
619 class CellMagicTestCase(TestCase):
626 class CellMagicTestCase(TestCase):
620
627
621 def check_ident(self, magic):
628 def check_ident(self, magic):
622 # Manually called, we get the result
629 # Manually called, we get the result
623 out = _ip.run_cell_magic(magic, 'a', 'b')
630 out = _ip.run_cell_magic(magic, 'a', 'b')
624 nt.assert_equal(out, ('a','b'))
631 nt.assert_equal(out, ('a','b'))
625 # Via run_cell, it goes into the user's namespace via displayhook
632 # Via run_cell, it goes into the user's namespace via displayhook
626 _ip.run_cell('%%' + magic +' c\nd')
633 _ip.run_cell('%%' + magic +' c\nd')
627 nt.assert_equal(_ip.user_ns['_'], ('c','d'))
634 nt.assert_equal(_ip.user_ns['_'], ('c','d'))
628
635
629 def test_cell_magic_func_deco(self):
636 def test_cell_magic_func_deco(self):
630 "Cell magic using simple decorator"
637 "Cell magic using simple decorator"
631 @register_cell_magic
638 @register_cell_magic
632 def cellm(line, cell):
639 def cellm(line, cell):
633 return line, cell
640 return line, cell
634
641
635 self.check_ident('cellm')
642 self.check_ident('cellm')
636
643
637 def test_cell_magic_reg(self):
644 def test_cell_magic_reg(self):
638 "Cell magic manually registered"
645 "Cell magic manually registered"
639 def cellm(line, cell):
646 def cellm(line, cell):
640 return line, cell
647 return line, cell
641
648
642 _ip.register_magic_function(cellm, 'cell', 'cellm2')
649 _ip.register_magic_function(cellm, 'cell', 'cellm2')
643 self.check_ident('cellm2')
650 self.check_ident('cellm2')
644
651
645 def test_cell_magic_class(self):
652 def test_cell_magic_class(self):
646 "Cell magics declared via a class"
653 "Cell magics declared via a class"
647 @magics_class
654 @magics_class
648 class MyMagics(Magics):
655 class MyMagics(Magics):
649
656
650 @cell_magic
657 @cell_magic
651 def cellm3(self, line, cell):
658 def cellm3(self, line, cell):
652 return line, cell
659 return line, cell
653
660
654 _ip.register_magics(MyMagics)
661 _ip.register_magics(MyMagics)
655 self.check_ident('cellm3')
662 self.check_ident('cellm3')
656
663
657 def test_cell_magic_class2(self):
664 def test_cell_magic_class2(self):
658 "Cell magics declared via a class, #2"
665 "Cell magics declared via a class, #2"
659 @magics_class
666 @magics_class
660 class MyMagics2(Magics):
667 class MyMagics2(Magics):
661
668
662 @cell_magic('cellm4')
669 @cell_magic('cellm4')
663 def cellm33(self, line, cell):
670 def cellm33(self, line, cell):
664 return line, cell
671 return line, cell
665
672
666 _ip.register_magics(MyMagics2)
673 _ip.register_magics(MyMagics2)
667 self.check_ident('cellm4')
674 self.check_ident('cellm4')
668 # Check that nothing is registered as 'cellm33'
675 # Check that nothing is registered as 'cellm33'
669 c33 = _ip.find_cell_magic('cellm33')
676 c33 = _ip.find_cell_magic('cellm33')
670 nt.assert_equal(c33, None)
677 nt.assert_equal(c33, None)
671
678
672 def test_file():
679 def test_file():
673 """Basic %%file"""
680 """Basic %%file"""
674 ip = get_ipython()
681 ip = get_ipython()
675 with TemporaryDirectory() as td:
682 with TemporaryDirectory() as td:
676 fname = os.path.join(td, 'file1')
683 fname = os.path.join(td, 'file1')
677 ip.run_cell_magic("file", fname, u'\n'.join([
684 ip.run_cell_magic("file", fname, u'\n'.join([
678 'line1',
685 'line1',
679 'line2',
686 'line2',
680 ]))
687 ]))
681 with open(fname) as f:
688 with open(fname) as f:
682 s = f.read()
689 s = f.read()
683 nt.assert_in('line1\n', s)
690 nt.assert_in('line1\n', s)
684 nt.assert_in('line2', s)
691 nt.assert_in('line2', s)
685
692
686 def test_file_var_expand():
693 def test_file_var_expand():
687 """%%file $filename"""
694 """%%file $filename"""
688 ip = get_ipython()
695 ip = get_ipython()
689 with TemporaryDirectory() as td:
696 with TemporaryDirectory() as td:
690 fname = os.path.join(td, 'file1')
697 fname = os.path.join(td, 'file1')
691 ip.user_ns['filename'] = fname
698 ip.user_ns['filename'] = fname
692 ip.run_cell_magic("file", '$filename', u'\n'.join([
699 ip.run_cell_magic("file", '$filename', u'\n'.join([
693 'line1',
700 'line1',
694 'line2',
701 'line2',
695 ]))
702 ]))
696 with open(fname) as f:
703 with open(fname) as f:
697 s = f.read()
704 s = f.read()
698 nt.assert_in('line1\n', s)
705 nt.assert_in('line1\n', s)
699 nt.assert_in('line2', s)
706 nt.assert_in('line2', s)
700
707
701 def test_file_unicode():
708 def test_file_unicode():
702 """%%file with unicode cell"""
709 """%%file with unicode cell"""
703 ip = get_ipython()
710 ip = get_ipython()
704 with TemporaryDirectory() as td:
711 with TemporaryDirectory() as td:
705 fname = os.path.join(td, 'file1')
712 fname = os.path.join(td, 'file1')
706 ip.run_cell_magic("file", fname, u'\n'.join([
713 ip.run_cell_magic("file", fname, u'\n'.join([
707 u'linΓ©1',
714 u'linΓ©1',
708 u'linΓ©2',
715 u'linΓ©2',
709 ]))
716 ]))
710 with io.open(fname, encoding='utf-8') as f:
717 with io.open(fname, encoding='utf-8') as f:
711 s = f.read()
718 s = f.read()
712 nt.assert_in(u'linΓ©1\n', s)
719 nt.assert_in(u'linΓ©1\n', s)
713 nt.assert_in(u'linΓ©2', s)
720 nt.assert_in(u'linΓ©2', s)
714
721
715 def test_file_amend():
722 def test_file_amend():
716 """%%file -a amends files"""
723 """%%file -a amends files"""
717 ip = get_ipython()
724 ip = get_ipython()
718 with TemporaryDirectory() as td:
725 with TemporaryDirectory() as td:
719 fname = os.path.join(td, 'file2')
726 fname = os.path.join(td, 'file2')
720 ip.run_cell_magic("file", fname, u'\n'.join([
727 ip.run_cell_magic("file", fname, u'\n'.join([
721 'line1',
728 'line1',
722 'line2',
729 'line2',
723 ]))
730 ]))
724 ip.run_cell_magic("file", "-a %s" % fname, u'\n'.join([
731 ip.run_cell_magic("file", "-a %s" % fname, u'\n'.join([
725 'line3',
732 'line3',
726 'line4',
733 'line4',
727 ]))
734 ]))
728 with open(fname) as f:
735 with open(fname) as f:
729 s = f.read()
736 s = f.read()
730 nt.assert_in('line1\n', s)
737 nt.assert_in('line1\n', s)
731 nt.assert_in('line3\n', s)
738 nt.assert_in('line3\n', s)
732
739
733
740
734 def test_script_config():
741 def test_script_config():
735 ip = get_ipython()
742 ip = get_ipython()
736 ip.config.ScriptMagics.script_magics = ['whoda']
743 ip.config.ScriptMagics.script_magics = ['whoda']
737 sm = script.ScriptMagics(shell=ip)
744 sm = script.ScriptMagics(shell=ip)
738 nt.assert_in('whoda', sm.magics['cell'])
745 nt.assert_in('whoda', sm.magics['cell'])
739
746
740 @dec.skip_win32
747 @dec.skip_win32
741 def test_script_out():
748 def test_script_out():
742 ip = get_ipython()
749 ip = get_ipython()
743 ip.run_cell_magic("script", "--out output sh", "echo 'hi'")
750 ip.run_cell_magic("script", "--out output sh", "echo 'hi'")
744 nt.assert_equal(ip.user_ns['output'], 'hi\n')
751 nt.assert_equal(ip.user_ns['output'], 'hi\n')
745
752
746 @dec.skip_win32
753 @dec.skip_win32
747 def test_script_err():
754 def test_script_err():
748 ip = get_ipython()
755 ip = get_ipython()
749 ip.run_cell_magic("script", "--err error sh", "echo 'hello' >&2")
756 ip.run_cell_magic("script", "--err error sh", "echo 'hello' >&2")
750 nt.assert_equal(ip.user_ns['error'], 'hello\n')
757 nt.assert_equal(ip.user_ns['error'], 'hello\n')
751
758
752 @dec.skip_win32
759 @dec.skip_win32
753 def test_script_out_err():
760 def test_script_out_err():
754 ip = get_ipython()
761 ip = get_ipython()
755 ip.run_cell_magic("script", "--out output --err error sh", "echo 'hi'\necho 'hello' >&2")
762 ip.run_cell_magic("script", "--out output --err error sh", "echo 'hi'\necho 'hello' >&2")
756 nt.assert_equal(ip.user_ns['output'], 'hi\n')
763 nt.assert_equal(ip.user_ns['output'], 'hi\n')
757 nt.assert_equal(ip.user_ns['error'], 'hello\n')
764 nt.assert_equal(ip.user_ns['error'], 'hello\n')
758
765
759 @dec.skip_win32
766 @dec.skip_win32
760 def test_script_bg_out():
767 def test_script_bg_out():
761 ip = get_ipython()
768 ip = get_ipython()
762 ip.run_cell_magic("script", "--bg --out output sh", "echo 'hi'")
769 ip.run_cell_magic("script", "--bg --out output sh", "echo 'hi'")
763 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
770 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
764
771
765 @dec.skip_win32
772 @dec.skip_win32
766 def test_script_bg_err():
773 def test_script_bg_err():
767 ip = get_ipython()
774 ip = get_ipython()
768 ip.run_cell_magic("script", "--bg --err error sh", "echo 'hello' >&2")
775 ip.run_cell_magic("script", "--bg --err error sh", "echo 'hello' >&2")
769 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
776 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
770
777
771 @dec.skip_win32
778 @dec.skip_win32
772 def test_script_bg_out_err():
779 def test_script_bg_out_err():
773 ip = get_ipython()
780 ip = get_ipython()
774 ip.run_cell_magic("script", "--bg --out output --err error sh", "echo 'hi'\necho 'hello' >&2")
781 ip.run_cell_magic("script", "--bg --out output --err error sh", "echo 'hi'\necho 'hello' >&2")
775 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
782 nt.assert_equal(ip.user_ns['output'].read(), b'hi\n')
776 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
783 nt.assert_equal(ip.user_ns['error'].read(), b'hello\n')
777
784
778 def test_script_defaults():
785 def test_script_defaults():
779 ip = get_ipython()
786 ip = get_ipython()
780 for cmd in ['sh', 'bash', 'perl', 'ruby']:
787 for cmd in ['sh', 'bash', 'perl', 'ruby']:
781 try:
788 try:
782 find_cmd(cmd)
789 find_cmd(cmd)
783 except Exception:
790 except Exception:
784 pass
791 pass
785 else:
792 else:
786 nt.assert_in(cmd, ip.magics_manager.magics['cell'])
793 nt.assert_in(cmd, ip.magics_manager.magics['cell'])
787
794
788
795
789 @magics_class
796 @magics_class
790 class FooFoo(Magics):
797 class FooFoo(Magics):
791 """class with both %foo and %%foo magics"""
798 """class with both %foo and %%foo magics"""
792 @line_magic('foo')
799 @line_magic('foo')
793 def line_foo(self, line):
800 def line_foo(self, line):
794 "I am line foo"
801 "I am line foo"
795 pass
802 pass
796
803
797 @cell_magic("foo")
804 @cell_magic("foo")
798 def cell_foo(self, line, cell):
805 def cell_foo(self, line, cell):
799 "I am cell foo, not line foo"
806 "I am cell foo, not line foo"
800 pass
807 pass
801
808
802 def test_line_cell_info():
809 def test_line_cell_info():
803 """%%foo and %foo magics are distinguishable to inspect"""
810 """%%foo and %foo magics are distinguishable to inspect"""
804 ip = get_ipython()
811 ip = get_ipython()
805 ip.magics_manager.register(FooFoo)
812 ip.magics_manager.register(FooFoo)
806 oinfo = ip.object_inspect('foo')
813 oinfo = ip.object_inspect('foo')
807 nt.assert_true(oinfo['found'])
814 nt.assert_true(oinfo['found'])
808 nt.assert_true(oinfo['ismagic'])
815 nt.assert_true(oinfo['ismagic'])
809
816
810 oinfo = ip.object_inspect('%%foo')
817 oinfo = ip.object_inspect('%%foo')
811 nt.assert_true(oinfo['found'])
818 nt.assert_true(oinfo['found'])
812 nt.assert_true(oinfo['ismagic'])
819 nt.assert_true(oinfo['ismagic'])
813 nt.assert_equal(oinfo['docstring'], FooFoo.cell_foo.__doc__)
820 nt.assert_equal(oinfo['docstring'], FooFoo.cell_foo.__doc__)
814
821
815 oinfo = ip.object_inspect('%foo')
822 oinfo = ip.object_inspect('%foo')
816 nt.assert_true(oinfo['found'])
823 nt.assert_true(oinfo['found'])
817 nt.assert_true(oinfo['ismagic'])
824 nt.assert_true(oinfo['ismagic'])
818 nt.assert_equal(oinfo['docstring'], FooFoo.line_foo.__doc__)
825 nt.assert_equal(oinfo['docstring'], FooFoo.line_foo.__doc__)
819
826
820 def test_multiple_magics():
827 def test_multiple_magics():
821 ip = get_ipython()
828 ip = get_ipython()
822 foo1 = FooFoo(ip)
829 foo1 = FooFoo(ip)
823 foo2 = FooFoo(ip)
830 foo2 = FooFoo(ip)
824 mm = ip.magics_manager
831 mm = ip.magics_manager
825 mm.register(foo1)
832 mm.register(foo1)
826 nt.assert_true(mm.magics['line']['foo'].im_self is foo1)
833 nt.assert_true(mm.magics['line']['foo'].im_self is foo1)
827 mm.register(foo2)
834 mm.register(foo2)
828 nt.assert_true(mm.magics['line']['foo'].im_self is foo2)
835 nt.assert_true(mm.magics['line']['foo'].im_self is foo2)
829
836
830 def test_alias_magic():
837 def test_alias_magic():
831 """Test %alias_magic."""
838 """Test %alias_magic."""
832 ip = get_ipython()
839 ip = get_ipython()
833 mm = ip.magics_manager
840 mm = ip.magics_manager
834
841
835 # Basic operation: both cell and line magics are created, if possible.
842 # Basic operation: both cell and line magics are created, if possible.
836 ip.run_line_magic('alias_magic', 'timeit_alias timeit')
843 ip.run_line_magic('alias_magic', 'timeit_alias timeit')
837 nt.assert_in('timeit_alias', mm.magics['line'])
844 nt.assert_in('timeit_alias', mm.magics['line'])
838 nt.assert_in('timeit_alias', mm.magics['cell'])
845 nt.assert_in('timeit_alias', mm.magics['cell'])
839
846
840 # --cell is specified, line magic not created.
847 # --cell is specified, line magic not created.
841 ip.run_line_magic('alias_magic', '--cell timeit_cell_alias timeit')
848 ip.run_line_magic('alias_magic', '--cell timeit_cell_alias timeit')
842 nt.assert_not_in('timeit_cell_alias', mm.magics['line'])
849 nt.assert_not_in('timeit_cell_alias', mm.magics['line'])
843 nt.assert_in('timeit_cell_alias', mm.magics['cell'])
850 nt.assert_in('timeit_cell_alias', mm.magics['cell'])
844
851
845 # Test that line alias is created successfully.
852 # Test that line alias is created successfully.
846 ip.run_line_magic('alias_magic', '--line env_alias env')
853 ip.run_line_magic('alias_magic', '--line env_alias env')
847 nt.assert_equal(ip.run_line_magic('env', ''),
854 nt.assert_equal(ip.run_line_magic('env', ''),
848 ip.run_line_magic('env_alias', ''))
855 ip.run_line_magic('env_alias', ''))
849
856
850 def test_save():
857 def test_save():
851 """Test %save."""
858 """Test %save."""
852 ip = get_ipython()
859 ip = get_ipython()
853 ip.history_manager.reset() # Clear any existing history.
860 ip.history_manager.reset() # Clear any existing history.
854 cmds = [u"a=1", u"def b():\n return a**2", u"print(a, b())"]
861 cmds = [u"a=1", u"def b():\n return a**2", u"print(a, b())"]
855 for i, cmd in enumerate(cmds, start=1):
862 for i, cmd in enumerate(cmds, start=1):
856 ip.history_manager.store_inputs(i, cmd)
863 ip.history_manager.store_inputs(i, cmd)
857 with TemporaryDirectory() as tmpdir:
864 with TemporaryDirectory() as tmpdir:
858 file = os.path.join(tmpdir, "testsave.py")
865 file = os.path.join(tmpdir, "testsave.py")
859 ip.run_line_magic("save", "%s 1-10" % file)
866 ip.run_line_magic("save", "%s 1-10" % file)
860 with open(file) as f:
867 with open(file) as f:
861 content = f.read()
868 content = f.read()
862 nt.assert_equal(content.count(cmds[0]), 1)
869 nt.assert_equal(content.count(cmds[0]), 1)
863 nt.assert_in('coding: utf-8', content)
870 nt.assert_in('coding: utf-8', content)
864 ip.run_line_magic("save", "-a %s 1-10" % file)
871 ip.run_line_magic("save", "-a %s 1-10" % file)
865 with open(file) as f:
872 with open(file) as f:
866 content = f.read()
873 content = f.read()
867 nt.assert_equal(content.count(cmds[0]), 2)
874 nt.assert_equal(content.count(cmds[0]), 2)
868 nt.assert_in('coding: utf-8', content)
875 nt.assert_in('coding: utf-8', content)
869
876
870
877
871 def test_store():
878 def test_store():
872 """Test %store."""
879 """Test %store."""
873 ip = get_ipython()
880 ip = get_ipython()
874 ip.run_line_magic('load_ext', 'storemagic')
881 ip.run_line_magic('load_ext', 'storemagic')
875
882
876 # make sure the storage is empty
883 # make sure the storage is empty
877 ip.run_line_magic('store', '-z')
884 ip.run_line_magic('store', '-z')
878 ip.user_ns['var'] = 42
885 ip.user_ns['var'] = 42
879 ip.run_line_magic('store', 'var')
886 ip.run_line_magic('store', 'var')
880 ip.user_ns['var'] = 39
887 ip.user_ns['var'] = 39
881 ip.run_line_magic('store', '-r')
888 ip.run_line_magic('store', '-r')
882 nt.assert_equal(ip.user_ns['var'], 42)
889 nt.assert_equal(ip.user_ns['var'], 42)
883
890
884 ip.run_line_magic('store', '-d var')
891 ip.run_line_magic('store', '-d var')
885 ip.user_ns['var'] = 39
892 ip.user_ns['var'] = 39
886 ip.run_line_magic('store' , '-r')
893 ip.run_line_magic('store' , '-r')
887 nt.assert_equal(ip.user_ns['var'], 39)
894 nt.assert_equal(ip.user_ns['var'], 39)
888
895
889
896
890 def _run_edit_test(arg_s, exp_filename=None,
897 def _run_edit_test(arg_s, exp_filename=None,
891 exp_lineno=-1,
898 exp_lineno=-1,
892 exp_contents=None,
899 exp_contents=None,
893 exp_is_temp=None):
900 exp_is_temp=None):
894 ip = get_ipython()
901 ip = get_ipython()
895 M = code.CodeMagics(ip)
902 M = code.CodeMagics(ip)
896 last_call = ['','']
903 last_call = ['','']
897 opts,args = M.parse_options(arg_s,'prxn:')
904 opts,args = M.parse_options(arg_s,'prxn:')
898 filename, lineno, is_temp = M._find_edit_target(ip, args, opts, last_call)
905 filename, lineno, is_temp = M._find_edit_target(ip, args, opts, last_call)
899
906
900 if exp_filename is not None:
907 if exp_filename is not None:
901 nt.assert_equal(exp_filename, filename)
908 nt.assert_equal(exp_filename, filename)
902 if exp_contents is not None:
909 if exp_contents is not None:
903 with io.open(filename, 'r') as f:
910 with io.open(filename, 'r') as f:
904 contents = f.read()
911 contents = f.read()
905 nt.assert_equal(exp_contents, contents)
912 nt.assert_equal(exp_contents, contents)
906 if exp_lineno != -1:
913 if exp_lineno != -1:
907 nt.assert_equal(exp_lineno, lineno)
914 nt.assert_equal(exp_lineno, lineno)
908 if exp_is_temp is not None:
915 if exp_is_temp is not None:
909 nt.assert_equal(exp_is_temp, is_temp)
916 nt.assert_equal(exp_is_temp, is_temp)
910
917
911
918
912 def test_edit_interactive():
919 def test_edit_interactive():
913 """%edit on interactively defined objects"""
920 """%edit on interactively defined objects"""
914 ip = get_ipython()
921 ip = get_ipython()
915 n = ip.execution_count
922 n = ip.execution_count
916 ip.run_cell(u"def foo(): return 1", store_history=True)
923 ip.run_cell(u"def foo(): return 1", store_history=True)
917
924
918 try:
925 try:
919 _run_edit_test("foo")
926 _run_edit_test("foo")
920 except code.InteractivelyDefined as e:
927 except code.InteractivelyDefined as e:
921 nt.assert_equal(e.index, n)
928 nt.assert_equal(e.index, n)
922 else:
929 else:
923 raise AssertionError("Should have raised InteractivelyDefined")
930 raise AssertionError("Should have raised InteractivelyDefined")
924
931
925
932
926 def test_edit_cell():
933 def test_edit_cell():
927 """%edit [cell id]"""
934 """%edit [cell id]"""
928 ip = get_ipython()
935 ip = get_ipython()
929
936
930 ip.run_cell(u"def foo(): return 1", store_history=True)
937 ip.run_cell(u"def foo(): return 1", store_history=True)
931
938
932 # test
939 # test
933 _run_edit_test("1", exp_contents=ip.user_ns['In'][1], exp_is_temp=True)
940 _run_edit_test("1", exp_contents=ip.user_ns['In'][1], exp_is_temp=True)
@@ -1,243 +1,241 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 %store magic for lightweight persistence.
3 %store magic for lightweight persistence.
4
4
5 Stores variables, aliases and macros in IPython's database.
5 Stores variables, aliases and macros in IPython's database.
6
6
7 To automatically restore stored variables at startup, add this to your
7 To automatically restore stored variables at startup, add this to your
8 :file:`ipython_config.py` file::
8 :file:`ipython_config.py` file::
9
9
10 c.StoreMagic.autorestore = True
10 c.StoreMagic.autorestore = True
11 """
11 """
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13 # Copyright (c) 2012, The IPython Development Team.
13 # Copyright (c) 2012, The IPython Development Team.
14 #
14 #
15 # Distributed under the terms of the Modified BSD License.
15 # Distributed under the terms of the Modified BSD License.
16 #
16 #
17 # The full license is in the file COPYING.txt, distributed with this software.
17 # The full license is in the file COPYING.txt, distributed with this software.
18 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
19
19
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21 # Imports
21 # Imports
22 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
23
23
24 # Stdlib
24 # Stdlib
25 import inspect, os, sys, textwrap
25 import inspect, os, sys, textwrap
26
26
27 # Our own
27 # Our own
28 from IPython.config.configurable import Configurable
29 from IPython.core.error import UsageError
28 from IPython.core.error import UsageError
30 from IPython.core.magic import Magics, magics_class, line_magic
29 from IPython.core.magic import Magics, magics_class, line_magic
31 from IPython.testing.skipdoctest import skip_doctest
30 from IPython.testing.skipdoctest import skip_doctest
32 from IPython.utils.traitlets import Bool
31 from IPython.utils.traitlets import Bool
33
32
34 #-----------------------------------------------------------------------------
33 #-----------------------------------------------------------------------------
35 # Functions and classes
34 # Functions and classes
36 #-----------------------------------------------------------------------------
35 #-----------------------------------------------------------------------------
37
36
38 def restore_aliases(ip):
37 def restore_aliases(ip):
39 staliases = ip.db.get('stored_aliases', {})
38 staliases = ip.db.get('stored_aliases', {})
40 for k,v in staliases.items():
39 for k,v in staliases.items():
41 #print "restore alias",k,v # dbg
40 #print "restore alias",k,v # dbg
42 #self.alias_table[k] = v
41 #self.alias_table[k] = v
43 ip.alias_manager.define_alias(k,v)
42 ip.alias_manager.define_alias(k,v)
44
43
45
44
46 def refresh_variables(ip):
45 def refresh_variables(ip):
47 db = ip.db
46 db = ip.db
48 for key in db.keys('autorestore/*'):
47 for key in db.keys('autorestore/*'):
49 # strip autorestore
48 # strip autorestore
50 justkey = os.path.basename(key)
49 justkey = os.path.basename(key)
51 try:
50 try:
52 obj = db[key]
51 obj = db[key]
53 except KeyError:
52 except KeyError:
54 print "Unable to restore variable '%s', ignoring (use %%store -d to forget!)" % justkey
53 print "Unable to restore variable '%s', ignoring (use %%store -d to forget!)" % justkey
55 print "The error was:", sys.exc_info()[0]
54 print "The error was:", sys.exc_info()[0]
56 else:
55 else:
57 #print "restored",justkey,"=",obj #dbg
56 #print "restored",justkey,"=",obj #dbg
58 ip.user_ns[justkey] = obj
57 ip.user_ns[justkey] = obj
59
58
60
59
61 def restore_dhist(ip):
60 def restore_dhist(ip):
62 ip.user_ns['_dh'] = ip.db.get('dhist',[])
61 ip.user_ns['_dh'] = ip.db.get('dhist',[])
63
62
64
63
65 def restore_data(ip):
64 def restore_data(ip):
66 refresh_variables(ip)
65 refresh_variables(ip)
67 restore_aliases(ip)
66 restore_aliases(ip)
68 restore_dhist(ip)
67 restore_dhist(ip)
69
68
70
69
71 @magics_class
70 @magics_class
72 class StoreMagics(Magics, Configurable):
71 class StoreMagics(Magics):
73 """Lightweight persistence for python variables.
72 """Lightweight persistence for python variables.
74
73
75 Provides the %store magic."""
74 Provides the %store magic."""
76
75
77 autorestore = Bool(False, config=True, help=
76 autorestore = Bool(False, config=True, help=
78 """If True, any %store-d variables will be automatically restored
77 """If True, any %store-d variables will be automatically restored
79 when IPython starts.
78 when IPython starts.
80 """
79 """
81 )
80 )
82
81
83 def __init__(self, shell):
82 def __init__(self, shell):
84 Configurable.__init__(self, config=shell.config)
83 super(StoreMagics, self).__init__(shell=shell)
85 Magics.__init__(self, shell=shell)
86 self.shell.configurables.append(self)
84 self.shell.configurables.append(self)
87 if self.autorestore:
85 if self.autorestore:
88 restore_data(self.shell)
86 restore_data(self.shell)
89
87
90 @skip_doctest
88 @skip_doctest
91 @line_magic
89 @line_magic
92 def store(self, parameter_s=''):
90 def store(self, parameter_s=''):
93 """Lightweight persistence for python variables.
91 """Lightweight persistence for python variables.
94
92
95 Example::
93 Example::
96
94
97 In [1]: l = ['hello',10,'world']
95 In [1]: l = ['hello',10,'world']
98 In [2]: %store l
96 In [2]: %store l
99 In [3]: exit
97 In [3]: exit
100
98
101 (IPython session is closed and started again...)
99 (IPython session is closed and started again...)
102
100
103 ville@badger:~$ ipython
101 ville@badger:~$ ipython
104 In [1]: l
102 In [1]: l
105 NameError: name 'l' is not defined
103 NameError: name 'l' is not defined
106 In [2]: %store -r
104 In [2]: %store -r
107 In [3]: l
105 In [3]: l
108 Out[3]: ['hello', 10, 'world']
106 Out[3]: ['hello', 10, 'world']
109
107
110 Usage:
108 Usage:
111
109
112 * ``%store`` - Show list of all variables and their current
110 * ``%store`` - Show list of all variables and their current
113 values
111 values
114 * ``%store spam`` - Store the *current* value of the variable spam
112 * ``%store spam`` - Store the *current* value of the variable spam
115 to disk
113 to disk
116 * ``%store -d spam`` - Remove the variable and its value from storage
114 * ``%store -d spam`` - Remove the variable and its value from storage
117 * ``%store -z`` - Remove all variables from storage
115 * ``%store -z`` - Remove all variables from storage
118 * ``%store -r`` - Refresh all variables from store (overwrite
116 * ``%store -r`` - Refresh all variables from store (overwrite
119 current vals)
117 current vals)
120 * ``%store -r spam bar`` - Refresh specified variables from store
118 * ``%store -r spam bar`` - Refresh specified variables from store
121 (delete current val)
119 (delete current val)
122 * ``%store foo >a.txt`` - Store value of foo to new file a.txt
120 * ``%store foo >a.txt`` - Store value of foo to new file a.txt
123 * ``%store foo >>a.txt`` - Append value of foo to file a.txt
121 * ``%store foo >>a.txt`` - Append value of foo to file a.txt
124
122
125 It should be noted that if you change the value of a variable, you
123 It should be noted that if you change the value of a variable, you
126 need to %store it again if you want to persist the new value.
124 need to %store it again if you want to persist the new value.
127
125
128 Note also that the variables will need to be pickleable; most basic
126 Note also that the variables will need to be pickleable; most basic
129 python types can be safely %store'd.
127 python types can be safely %store'd.
130
128
131 Also aliases can be %store'd across sessions.
129 Also aliases can be %store'd across sessions.
132 """
130 """
133
131
134 opts,argsl = self.parse_options(parameter_s,'drz',mode='string')
132 opts,argsl = self.parse_options(parameter_s,'drz',mode='string')
135 args = argsl.split(None,1)
133 args = argsl.split(None,1)
136 ip = self.shell
134 ip = self.shell
137 db = ip.db
135 db = ip.db
138 # delete
136 # delete
139 if 'd' in opts:
137 if 'd' in opts:
140 try:
138 try:
141 todel = args[0]
139 todel = args[0]
142 except IndexError:
140 except IndexError:
143 raise UsageError('You must provide the variable to forget')
141 raise UsageError('You must provide the variable to forget')
144 else:
142 else:
145 try:
143 try:
146 del db['autorestore/' + todel]
144 del db['autorestore/' + todel]
147 except:
145 except:
148 raise UsageError("Can't delete variable '%s'" % todel)
146 raise UsageError("Can't delete variable '%s'" % todel)
149 # reset
147 # reset
150 elif 'z' in opts:
148 elif 'z' in opts:
151 for k in db.keys('autorestore/*'):
149 for k in db.keys('autorestore/*'):
152 del db[k]
150 del db[k]
153
151
154 elif 'r' in opts:
152 elif 'r' in opts:
155 if args:
153 if args:
156 for arg in args:
154 for arg in args:
157 try:
155 try:
158 obj = db['autorestore/' + arg]
156 obj = db['autorestore/' + arg]
159 except KeyError:
157 except KeyError:
160 print "no stored variable %s" % arg
158 print "no stored variable %s" % arg
161 else:
159 else:
162 ip.user_ns[arg] = obj
160 ip.user_ns[arg] = obj
163 else:
161 else:
164 restore_data(ip)
162 restore_data(ip)
165
163
166 # run without arguments -> list variables & values
164 # run without arguments -> list variables & values
167 elif not args:
165 elif not args:
168 vars = db.keys('autorestore/*')
166 vars = db.keys('autorestore/*')
169 vars.sort()
167 vars.sort()
170 if vars:
168 if vars:
171 size = max(map(len, vars))
169 size = max(map(len, vars))
172 else:
170 else:
173 size = 0
171 size = 0
174
172
175 print 'Stored variables and their in-db values:'
173 print 'Stored variables and their in-db values:'
176 fmt = '%-'+str(size)+'s -> %s'
174 fmt = '%-'+str(size)+'s -> %s'
177 get = db.get
175 get = db.get
178 for var in vars:
176 for var in vars:
179 justkey = os.path.basename(var)
177 justkey = os.path.basename(var)
180 # print 30 first characters from every var
178 # print 30 first characters from every var
181 print fmt % (justkey, repr(get(var, '<unavailable>'))[:50])
179 print fmt % (justkey, repr(get(var, '<unavailable>'))[:50])
182
180
183 # default action - store the variable
181 # default action - store the variable
184 else:
182 else:
185 # %store foo >file.txt or >>file.txt
183 # %store foo >file.txt or >>file.txt
186 if len(args) > 1 and args[1].startswith('>'):
184 if len(args) > 1 and args[1].startswith('>'):
187 fnam = os.path.expanduser(args[1].lstrip('>').lstrip())
185 fnam = os.path.expanduser(args[1].lstrip('>').lstrip())
188 if args[1].startswith('>>'):
186 if args[1].startswith('>>'):
189 fil = open(fnam, 'a')
187 fil = open(fnam, 'a')
190 else:
188 else:
191 fil = open(fnam, 'w')
189 fil = open(fnam, 'w')
192 obj = ip.ev(args[0])
190 obj = ip.ev(args[0])
193 print "Writing '%s' (%s) to file '%s'." % (args[0],
191 print "Writing '%s' (%s) to file '%s'." % (args[0],
194 obj.__class__.__name__, fnam)
192 obj.__class__.__name__, fnam)
195
193
196
194
197 if not isinstance (obj, basestring):
195 if not isinstance (obj, basestring):
198 from pprint import pprint
196 from pprint import pprint
199 pprint(obj, fil)
197 pprint(obj, fil)
200 else:
198 else:
201 fil.write(obj)
199 fil.write(obj)
202 if not obj.endswith('\n'):
200 if not obj.endswith('\n'):
203 fil.write('\n')
201 fil.write('\n')
204
202
205 fil.close()
203 fil.close()
206 return
204 return
207
205
208 # %store foo
206 # %store foo
209 try:
207 try:
210 obj = ip.user_ns[args[0]]
208 obj = ip.user_ns[args[0]]
211 except KeyError:
209 except KeyError:
212 # it might be an alias
210 # it might be an alias
213 name = args[0]
211 name = args[0]
214 try:
212 try:
215 cmd = ip.alias_manager.retrieve_alias(name)
213 cmd = ip.alias_manager.retrieve_alias(name)
216 except ValueError:
214 except ValueError:
217 raise UsageError("Unknown variable '%s'" % name)
215 raise UsageError("Unknown variable '%s'" % name)
218
216
219 staliases = db.get('stored_aliases',{})
217 staliases = db.get('stored_aliases',{})
220 staliases[name] = cmd
218 staliases[name] = cmd
221 db['stored_aliases'] = staliases
219 db['stored_aliases'] = staliases
222 print "Alias stored: %s (%s)" % (name, cmd)
220 print "Alias stored: %s (%s)" % (name, cmd)
223 return
221 return
224
222
225 else:
223 else:
226 modname = getattr(inspect.getmodule(obj), '__name__', '')
224 modname = getattr(inspect.getmodule(obj), '__name__', '')
227 if modname == '__main__':
225 if modname == '__main__':
228 print textwrap.dedent("""\
226 print textwrap.dedent("""\
229 Warning:%s is %s
227 Warning:%s is %s
230 Proper storage of interactively declared classes (or instances
228 Proper storage of interactively declared classes (or instances
231 of those classes) is not possible! Only instances
229 of those classes) is not possible! Only instances
232 of classes in real modules on file system can be %%store'd.
230 of classes in real modules on file system can be %%store'd.
233 """ % (args[0], obj) )
231 """ % (args[0], obj) )
234 return
232 return
235 #pickled = pickle.dumps(obj)
233 #pickled = pickle.dumps(obj)
236 db[ 'autorestore/' + args[0] ] = obj
234 db[ 'autorestore/' + args[0] ] = obj
237 print "Stored '%s' (%s)" % (args[0], obj.__class__.__name__)
235 print "Stored '%s' (%s)" % (args[0], obj.__class__.__name__)
238
236
239
237
240 def load_ipython_extension(ip):
238 def load_ipython_extension(ip):
241 """Load the extension in IPython."""
239 """Load the extension in IPython."""
242 ip.register_magics(StoreMagics)
240 ip.register_magics(StoreMagics)
243
241
@@ -1,316 +1,317 b''
1 """Tests for autoreload extension.
1 """Tests for autoreload extension.
2 """
2 """
3 #-----------------------------------------------------------------------------
3 #-----------------------------------------------------------------------------
4 # Copyright (c) 2012 IPython Development Team.
4 # Copyright (c) 2012 IPython Development Team.
5 #
5 #
6 # Distributed under the terms of the Modified BSD License.
6 # Distributed under the terms of the Modified BSD License.
7 #
7 #
8 # The full license is in the file COPYING.txt, distributed with this software.
8 # The full license is in the file COPYING.txt, distributed with this software.
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10
10
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 # Imports
12 # Imports
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15 import os
15 import os
16 import sys
16 import sys
17 import tempfile
17 import tempfile
18 import shutil
18 import shutil
19 import random
19 import random
20 import time
20 import time
21 from StringIO import StringIO
21 from StringIO import StringIO
22
22
23 import nose.tools as nt
23 import nose.tools as nt
24 import IPython.testing.tools as tt
24 import IPython.testing.tools as tt
25
25
26 from IPython.extensions.autoreload import AutoreloadMagics
26 from IPython.extensions.autoreload import AutoreloadMagics
27 from IPython.core.hooks import TryNext
27 from IPython.core.hooks import TryNext
28
28
29 #-----------------------------------------------------------------------------
29 #-----------------------------------------------------------------------------
30 # Test fixture
30 # Test fixture
31 #-----------------------------------------------------------------------------
31 #-----------------------------------------------------------------------------
32
32
33 noop = lambda *a, **kw: None
33 noop = lambda *a, **kw: None
34
34
35 class FakeShell(object):
35 class FakeShell(object):
36
36 def __init__(self):
37 def __init__(self):
37 self.ns = {}
38 self.ns = {}
38 self.auto_magics = AutoreloadMagics(shell=self)
39 self.auto_magics = AutoreloadMagics(shell=self)
39
40
40 register_magics = set_hook = noop
41 register_magics = set_hook = noop
41
42
42 def run_code(self, code):
43 def run_code(self, code):
43 try:
44 try:
44 self.auto_magics.pre_run_code_hook(self)
45 self.auto_magics.pre_run_code_hook(self)
45 except TryNext:
46 except TryNext:
46 pass
47 pass
47 exec code in self.ns
48 exec code in self.ns
48
49
49 def push(self, items):
50 def push(self, items):
50 self.ns.update(items)
51 self.ns.update(items)
51
52
52 def magic_autoreload(self, parameter):
53 def magic_autoreload(self, parameter):
53 self.auto_magics.autoreload(parameter)
54 self.auto_magics.autoreload(parameter)
54
55
55 def magic_aimport(self, parameter, stream=None):
56 def magic_aimport(self, parameter, stream=None):
56 self.auto_magics.aimport(parameter, stream=stream)
57 self.auto_magics.aimport(parameter, stream=stream)
57
58
58
59
59 class Fixture(object):
60 class Fixture(object):
60 """Fixture for creating test module files"""
61 """Fixture for creating test module files"""
61
62
62 test_dir = None
63 test_dir = None
63 old_sys_path = None
64 old_sys_path = None
64 filename_chars = "abcdefghijklmopqrstuvwxyz0123456789"
65 filename_chars = "abcdefghijklmopqrstuvwxyz0123456789"
65
66
66 def setUp(self):
67 def setUp(self):
67 self.test_dir = tempfile.mkdtemp()
68 self.test_dir = tempfile.mkdtemp()
68 self.old_sys_path = list(sys.path)
69 self.old_sys_path = list(sys.path)
69 sys.path.insert(0, self.test_dir)
70 sys.path.insert(0, self.test_dir)
70 self.shell = FakeShell()
71 self.shell = FakeShell()
71
72
72 def tearDown(self):
73 def tearDown(self):
73 shutil.rmtree(self.test_dir)
74 shutil.rmtree(self.test_dir)
74 sys.path = self.old_sys_path
75 sys.path = self.old_sys_path
75
76
76 self.test_dir = None
77 self.test_dir = None
77 self.old_sys_path = None
78 self.old_sys_path = None
78 self.shell = None
79 self.shell = None
79
80
80 def get_module(self):
81 def get_module(self):
81 module_name = "tmpmod_" + "".join(random.sample(self.filename_chars,20))
82 module_name = "tmpmod_" + "".join(random.sample(self.filename_chars,20))
82 if module_name in sys.modules:
83 if module_name in sys.modules:
83 del sys.modules[module_name]
84 del sys.modules[module_name]
84 file_name = os.path.join(self.test_dir, module_name + ".py")
85 file_name = os.path.join(self.test_dir, module_name + ".py")
85 return module_name, file_name
86 return module_name, file_name
86
87
87 def write_file(self, filename, content):
88 def write_file(self, filename, content):
88 """
89 """
89 Write a file, and force a timestamp difference of at least one second
90 Write a file, and force a timestamp difference of at least one second
90
91
91 Notes
92 Notes
92 -----
93 -----
93 Python's .pyc files record the timestamp of their compilation
94 Python's .pyc files record the timestamp of their compilation
94 with a time resolution of one second.
95 with a time resolution of one second.
95
96
96 Therefore, we need to force a timestamp difference between .py
97 Therefore, we need to force a timestamp difference between .py
97 and .pyc, without having the .py file be timestamped in the
98 and .pyc, without having the .py file be timestamped in the
98 future, and without changing the timestamp of the .pyc file
99 future, and without changing the timestamp of the .pyc file
99 (because that is stored in the file). The only reliable way
100 (because that is stored in the file). The only reliable way
100 to achieve this seems to be to sleep.
101 to achieve this seems to be to sleep.
101 """
102 """
102
103
103 # Sleep one second + eps
104 # Sleep one second + eps
104 time.sleep(1.05)
105 time.sleep(1.05)
105
106
106 # Write
107 # Write
107 f = open(filename, 'w')
108 f = open(filename, 'w')
108 try:
109 try:
109 f.write(content)
110 f.write(content)
110 finally:
111 finally:
111 f.close()
112 f.close()
112
113
113 def new_module(self, code):
114 def new_module(self, code):
114 mod_name, mod_fn = self.get_module()
115 mod_name, mod_fn = self.get_module()
115 f = open(mod_fn, 'w')
116 f = open(mod_fn, 'w')
116 try:
117 try:
117 f.write(code)
118 f.write(code)
118 finally:
119 finally:
119 f.close()
120 f.close()
120 return mod_name, mod_fn
121 return mod_name, mod_fn
121
122
122 #-----------------------------------------------------------------------------
123 #-----------------------------------------------------------------------------
123 # Test automatic reloading
124 # Test automatic reloading
124 #-----------------------------------------------------------------------------
125 #-----------------------------------------------------------------------------
125
126
126 class TestAutoreload(Fixture):
127 class TestAutoreload(Fixture):
127 def _check_smoketest(self, use_aimport=True):
128 def _check_smoketest(self, use_aimport=True):
128 """
129 """
129 Functional test for the automatic reloader using either
130 Functional test for the automatic reloader using either
130 '%autoreload 1' or '%autoreload 2'
131 '%autoreload 1' or '%autoreload 2'
131 """
132 """
132
133
133 mod_name, mod_fn = self.new_module("""
134 mod_name, mod_fn = self.new_module("""
134 x = 9
135 x = 9
135
136
136 z = 123 # this item will be deleted
137 z = 123 # this item will be deleted
137
138
138 def foo(y):
139 def foo(y):
139 return y + 3
140 return y + 3
140
141
141 class Baz(object):
142 class Baz(object):
142 def __init__(self, x):
143 def __init__(self, x):
143 self.x = x
144 self.x = x
144 def bar(self, y):
145 def bar(self, y):
145 return self.x + y
146 return self.x + y
146 @property
147 @property
147 def quux(self):
148 def quux(self):
148 return 42
149 return 42
149 def zzz(self):
150 def zzz(self):
150 '''This method will be deleted below'''
151 '''This method will be deleted below'''
151 return 99
152 return 99
152
153
153 class Bar: # old-style class: weakref doesn't work for it on Python < 2.7
154 class Bar: # old-style class: weakref doesn't work for it on Python < 2.7
154 def foo(self):
155 def foo(self):
155 return 1
156 return 1
156 """)
157 """)
157
158
158 #
159 #
159 # Import module, and mark for reloading
160 # Import module, and mark for reloading
160 #
161 #
161 if use_aimport:
162 if use_aimport:
162 self.shell.magic_autoreload("1")
163 self.shell.magic_autoreload("1")
163 self.shell.magic_aimport(mod_name)
164 self.shell.magic_aimport(mod_name)
164 stream = StringIO()
165 stream = StringIO()
165 self.shell.magic_aimport("", stream=stream)
166 self.shell.magic_aimport("", stream=stream)
166 nt.assert_true(("Modules to reload:\n%s" % mod_name) in
167 nt.assert_true(("Modules to reload:\n%s" % mod_name) in
167 stream.getvalue())
168 stream.getvalue())
168
169
169 nt.assert_raises(
170 nt.assert_raises(
170 ImportError,
171 ImportError,
171 self.shell.magic_aimport, "tmpmod_as318989e89ds")
172 self.shell.magic_aimport, "tmpmod_as318989e89ds")
172 else:
173 else:
173 self.shell.magic_autoreload("2")
174 self.shell.magic_autoreload("2")
174 self.shell.run_code("import %s" % mod_name)
175 self.shell.run_code("import %s" % mod_name)
175 stream = StringIO()
176 stream = StringIO()
176 self.shell.magic_aimport("", stream=stream)
177 self.shell.magic_aimport("", stream=stream)
177 nt.assert_true("Modules to reload:\nall-except-skipped" in
178 nt.assert_true("Modules to reload:\nall-except-skipped" in
178 stream.getvalue())
179 stream.getvalue())
179 nt.assert_in(mod_name, self.shell.ns)
180 nt.assert_in(mod_name, self.shell.ns)
180
181
181 mod = sys.modules[mod_name]
182 mod = sys.modules[mod_name]
182
183
183 #
184 #
184 # Test module contents
185 # Test module contents
185 #
186 #
186 old_foo = mod.foo
187 old_foo = mod.foo
187 old_obj = mod.Baz(9)
188 old_obj = mod.Baz(9)
188 old_obj2 = mod.Bar()
189 old_obj2 = mod.Bar()
189
190
190 def check_module_contents():
191 def check_module_contents():
191 nt.assert_equal(mod.x, 9)
192 nt.assert_equal(mod.x, 9)
192 nt.assert_equal(mod.z, 123)
193 nt.assert_equal(mod.z, 123)
193
194
194 nt.assert_equal(old_foo(0), 3)
195 nt.assert_equal(old_foo(0), 3)
195 nt.assert_equal(mod.foo(0), 3)
196 nt.assert_equal(mod.foo(0), 3)
196
197
197 obj = mod.Baz(9)
198 obj = mod.Baz(9)
198 nt.assert_equal(old_obj.bar(1), 10)
199 nt.assert_equal(old_obj.bar(1), 10)
199 nt.assert_equal(obj.bar(1), 10)
200 nt.assert_equal(obj.bar(1), 10)
200 nt.assert_equal(obj.quux, 42)
201 nt.assert_equal(obj.quux, 42)
201 nt.assert_equal(obj.zzz(), 99)
202 nt.assert_equal(obj.zzz(), 99)
202
203
203 obj2 = mod.Bar()
204 obj2 = mod.Bar()
204 nt.assert_equal(old_obj2.foo(), 1)
205 nt.assert_equal(old_obj2.foo(), 1)
205 nt.assert_equal(obj2.foo(), 1)
206 nt.assert_equal(obj2.foo(), 1)
206
207
207 check_module_contents()
208 check_module_contents()
208
209
209 #
210 #
210 # Simulate a failed reload: no reload should occur and exactly
211 # Simulate a failed reload: no reload should occur and exactly
211 # one error message should be printed
212 # one error message should be printed
212 #
213 #
213 self.write_file(mod_fn, """
214 self.write_file(mod_fn, """
214 a syntax error
215 a syntax error
215 """)
216 """)
216
217
217 with tt.AssertPrints(('[autoreload of %s failed:' % mod_name), channel='stderr'):
218 with tt.AssertPrints(('[autoreload of %s failed:' % mod_name), channel='stderr'):
218 self.shell.run_code("pass") # trigger reload
219 self.shell.run_code("pass") # trigger reload
219 with tt.AssertNotPrints(('[autoreload of %s failed:' % mod_name), channel='stderr'):
220 with tt.AssertNotPrints(('[autoreload of %s failed:' % mod_name), channel='stderr'):
220 self.shell.run_code("pass") # trigger another reload
221 self.shell.run_code("pass") # trigger another reload
221 check_module_contents()
222 check_module_contents()
222
223
223 #
224 #
224 # Rewrite module (this time reload should succeed)
225 # Rewrite module (this time reload should succeed)
225 #
226 #
226 self.write_file(mod_fn, """
227 self.write_file(mod_fn, """
227 x = 10
228 x = 10
228
229
229 def foo(y):
230 def foo(y):
230 return y + 4
231 return y + 4
231
232
232 class Baz(object):
233 class Baz(object):
233 def __init__(self, x):
234 def __init__(self, x):
234 self.x = x
235 self.x = x
235 def bar(self, y):
236 def bar(self, y):
236 return self.x + y + 1
237 return self.x + y + 1
237 @property
238 @property
238 def quux(self):
239 def quux(self):
239 return 43
240 return 43
240
241
241 class Bar: # old-style class
242 class Bar: # old-style class
242 def foo(self):
243 def foo(self):
243 return 2
244 return 2
244 """)
245 """)
245
246
246 def check_module_contents():
247 def check_module_contents():
247 nt.assert_equal(mod.x, 10)
248 nt.assert_equal(mod.x, 10)
248 nt.assert_false(hasattr(mod, 'z'))
249 nt.assert_false(hasattr(mod, 'z'))
249
250
250 nt.assert_equal(old_foo(0), 4) # superreload magic!
251 nt.assert_equal(old_foo(0), 4) # superreload magic!
251 nt.assert_equal(mod.foo(0), 4)
252 nt.assert_equal(mod.foo(0), 4)
252
253
253 obj = mod.Baz(9)
254 obj = mod.Baz(9)
254 nt.assert_equal(old_obj.bar(1), 11) # superreload magic!
255 nt.assert_equal(old_obj.bar(1), 11) # superreload magic!
255 nt.assert_equal(obj.bar(1), 11)
256 nt.assert_equal(obj.bar(1), 11)
256
257
257 nt.assert_equal(old_obj.quux, 43)
258 nt.assert_equal(old_obj.quux, 43)
258 nt.assert_equal(obj.quux, 43)
259 nt.assert_equal(obj.quux, 43)
259
260
260 nt.assert_false(hasattr(old_obj, 'zzz'))
261 nt.assert_false(hasattr(old_obj, 'zzz'))
261 nt.assert_false(hasattr(obj, 'zzz'))
262 nt.assert_false(hasattr(obj, 'zzz'))
262
263
263 obj2 = mod.Bar()
264 obj2 = mod.Bar()
264 nt.assert_equal(old_obj2.foo(), 2)
265 nt.assert_equal(old_obj2.foo(), 2)
265 nt.assert_equal(obj2.foo(), 2)
266 nt.assert_equal(obj2.foo(), 2)
266
267
267 self.shell.run_code("pass") # trigger reload
268 self.shell.run_code("pass") # trigger reload
268 check_module_contents()
269 check_module_contents()
269
270
270 #
271 #
271 # Another failure case: deleted file (shouldn't reload)
272 # Another failure case: deleted file (shouldn't reload)
272 #
273 #
273 os.unlink(mod_fn)
274 os.unlink(mod_fn)
274
275
275 self.shell.run_code("pass") # trigger reload
276 self.shell.run_code("pass") # trigger reload
276 check_module_contents()
277 check_module_contents()
277
278
278 #
279 #
279 # Disable autoreload and rewrite module: no reload should occur
280 # Disable autoreload and rewrite module: no reload should occur
280 #
281 #
281 if use_aimport:
282 if use_aimport:
282 self.shell.magic_aimport("-" + mod_name)
283 self.shell.magic_aimport("-" + mod_name)
283 stream = StringIO()
284 stream = StringIO()
284 self.shell.magic_aimport("", stream=stream)
285 self.shell.magic_aimport("", stream=stream)
285 nt.assert_true(("Modules to skip:\n%s" % mod_name) in
286 nt.assert_true(("Modules to skip:\n%s" % mod_name) in
286 stream.getvalue())
287 stream.getvalue())
287
288
288 # This should succeed, although no such module exists
289 # This should succeed, although no such module exists
289 self.shell.magic_aimport("-tmpmod_as318989e89ds")
290 self.shell.magic_aimport("-tmpmod_as318989e89ds")
290 else:
291 else:
291 self.shell.magic_autoreload("0")
292 self.shell.magic_autoreload("0")
292
293
293 self.write_file(mod_fn, """
294 self.write_file(mod_fn, """
294 x = -99
295 x = -99
295 """)
296 """)
296
297
297 self.shell.run_code("pass") # trigger reload
298 self.shell.run_code("pass") # trigger reload
298 self.shell.run_code("pass")
299 self.shell.run_code("pass")
299 check_module_contents()
300 check_module_contents()
300
301
301 #
302 #
302 # Re-enable autoreload: reload should now occur
303 # Re-enable autoreload: reload should now occur
303 #
304 #
304 if use_aimport:
305 if use_aimport:
305 self.shell.magic_aimport(mod_name)
306 self.shell.magic_aimport(mod_name)
306 else:
307 else:
307 self.shell.magic_autoreload("")
308 self.shell.magic_autoreload("")
308
309
309 self.shell.run_code("pass") # trigger reload
310 self.shell.run_code("pass") # trigger reload
310 nt.assert_equal(mod.x, -99)
311 nt.assert_equal(mod.x, -99)
311
312
312 def test_smoketest_aimport(self):
313 def test_smoketest_aimport(self):
313 self._check_smoketest(use_aimport=True)
314 self._check_smoketest(use_aimport=True)
314
315
315 def test_smoketest_autoreload(self):
316 def test_smoketest_autoreload(self):
316 self._check_smoketest(use_aimport=False)
317 self._check_smoketest(use_aimport=False)
General Comments 0
You need to be logged in to leave comments. Login now