##// END OF EJS Templates
Massive amount of work to improve the test suite, restores doctests....
Fernando Perez -
r2414:7fce7ae8
parent child
Show More
@@ -0,0 +1,185
1 """Tests for code execution (%run and related), which is particularly tricky.
2
3 Because of how %run manages namespaces, and the fact that we are trying here to
4 verify subtle object deletion and reference counting issues, the %run tests
5 will be kept in this separate file. This makes it easier to aggregate in one
6 place the tricks needed to handle it; most other magics are much easier to test
7 and we do so in a common test_magic file.
8 """
9 from __future__ import absolute_import
10
11 #-----------------------------------------------------------------------------
12 # Imports
13 #-----------------------------------------------------------------------------
14
15 # stdlib
16 import os
17 import sys
18 import tempfile
19
20 # third-party
21 import nose.tools as nt
22
23 # our own
24 from IPython.utils.platutils import find_cmd
25 from IPython.utils import genutils
26 from IPython.testing import decorators as dec
27 from IPython.testing import tools as tt
28
29 #-----------------------------------------------------------------------------
30 # Test functions begin
31 #-----------------------------------------------------------------------------
32
33 def doctest_refbug():
34 """Very nasty problem with references held by multiple runs of a script.
35 See: https://bugs.launchpad.net/ipython/+bug/269966
36
37 In [1]: _ip.clear_main_mod_cache()
38 # random
39
40 In [2]: %run refbug
41
42 In [3]: call_f()
43 lowercased: hello
44
45 In [4]: %run refbug
46
47 In [5]: call_f()
48 lowercased: hello
49 lowercased: hello
50 """
51
52
53 def doctest_run_builtins():
54 r"""Check that %run doesn't damage __builtins__.
55
56 In [1]: import tempfile
57
58 In [2]: bid1 = id(__builtins__)
59
60 In [3]: fname = tempfile.mkstemp('.py')[1]
61
62 In [3]: f = open(fname,'w')
63
64 In [4]: f.write('pass\n')
65
66 In [5]: f.flush()
67
68 In [6]: t1 = type(__builtins__)
69
70 In [7]: %run "$fname"
71
72 In [7]: f.close()
73
74 In [8]: bid2 = id(__builtins__)
75
76 In [9]: t2 = type(__builtins__)
77
78 In [10]: t1 == t2
79 Out[10]: True
80
81 In [10]: bid1 == bid2
82 Out[10]: True
83
84 In [12]: try:
85 ....: os.unlink(fname)
86 ....: except:
87 ....: pass
88 ....:
89 """
90
91 # For some tests, it will be handy to organize them in a class with a common
92 # setup that makes a temp file
93
94 class TempFileMixin(object):
95 def mktmp(self, src, ext='.py'):
96 """Make a valid python temp file."""
97 fname, f = tt.temp_pyfile(src, ext)
98 self.tmpfile = f
99 self.fname = fname
100
101 def teardown(self):
102 self.tmpfile.close()
103 try:
104 os.unlink(self.fname)
105 except:
106 # On Windows, even though we close the file, we still can't delete
107 # it. I have no clue why
108 pass
109
110
111 class TestMagicRunPass(TempFileMixin):
112
113 def setup(self):
114 """Make a valid python temp file."""
115 self.mktmp('pass\n')
116
117 def run_tmpfile(self):
118 _ip = get_ipython()
119 # This fails on Windows if self.tmpfile.name has spaces or "~" in it.
120 # See below and ticket https://bugs.launchpad.net/bugs/366353
121 _ip.magic('run "%s"' % self.fname)
122
123 def test_builtins_id(self):
124 """Check that %run doesn't damage __builtins__ """
125 _ip = get_ipython()
126 # Test that the id of __builtins__ is not modified by %run
127 bid1 = id(_ip.user_ns['__builtins__'])
128 self.run_tmpfile()
129 bid2 = id(_ip.user_ns['__builtins__'])
130 tt.assert_equals(bid1, bid2)
131
132 def test_builtins_type(self):
133 """Check that the type of __builtins__ doesn't change with %run.
134
135 However, the above could pass if __builtins__ was already modified to
136 be a dict (it should be a module) by a previous use of %run. So we
137 also check explicitly that it really is a module:
138 """
139 _ip = get_ipython()
140 self.run_tmpfile()
141 tt.assert_equals(type(_ip.user_ns['__builtins__']),type(sys))
142
143 def test_prompts(self):
144 """Test that prompts correctly generate after %run"""
145 self.run_tmpfile()
146 _ip = get_ipython()
147 p2 = str(_ip.outputcache.prompt2).strip()
148 nt.assert_equals(p2[:3], '...')
149
150
151 class TestMagicRunSimple(TempFileMixin):
152
153 def test_simpledef(self):
154 """Test that simple class definitions work."""
155 src = ("class foo: pass\n"
156 "def f(): return foo()")
157 self.mktmp(src)
158 _ip.magic('run "%s"' % self.fname)
159 _ip.runlines('t = isinstance(f(), foo)')
160 nt.assert_true(_ip.user_ns['t'])
161
162 def test_obj_del(self):
163 """Test that object's __del__ methods are called on exit."""
164
165 # This test is known to fail on win32.
166 # See ticket https://bugs.launchpad.net/bugs/366334
167 src = ("class A(object):\n"
168 " def __del__(self):\n"
169 " print 'object A deleted'\n"
170 "a = A()\n")
171 self.mktmp(src)
172 tt.ipexec_validate(self.fname, 'object A deleted')
173
174 def test_tclass(self):
175 mydir = os.path.dirname(__file__)
176 tc = os.path.join(mydir, 'tclass')
177 src = ("%%run '%s' C-first\n"
178 "%%run '%s' C-second\n") % (tc, tc)
179 self.mktmp(src, '.ipy')
180 out = """\
181 ARGV 1-: ['C-first']
182 ARGV 1-: ['C-second']
183 tclass.py: deleting object: C-first
184 """
185 tt.ipexec_validate(self.fname, out)
@@ -1,3611 +1,3612
1 # -*- coding: utf-8 -*-
1 # -*- coding: 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-2006 Fernando Perez <fperez@colorado.edu>
7 # Copyright (C) 2001-2006 Fernando Perez <fperez@colorado.edu>
8 #
8 #
9 # Distributed under the terms of the BSD License. The full license is in
9 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
10 # the file COPYING, distributed as part of this software.
11 #*****************************************************************************
11 #*****************************************************************************
12
12
13 #****************************************************************************
13 #****************************************************************************
14 # Modules and globals
14 # Modules and globals
15
15
16 # Python standard modules
16 # Python standard modules
17 import __builtin__
17 import __builtin__
18 import bdb
18 import bdb
19 import inspect
19 import inspect
20 import os
20 import os
21 import pdb
21 import pdb
22 import pydoc
22 import pydoc
23 import sys
23 import sys
24 import shutil
24 import shutil
25 import re
25 import re
26 import tempfile
26 import tempfile
27 import time
27 import time
28 import cPickle as pickle
28 import cPickle as pickle
29 import textwrap
29 import textwrap
30 from cStringIO import StringIO
30 from cStringIO import StringIO
31 from getopt import getopt,GetoptError
31 from getopt import getopt,GetoptError
32 from pprint import pprint, pformat
32 from pprint import pprint, pformat
33
33
34 # cProfile was added in Python2.5
34 # cProfile was added in Python2.5
35 try:
35 try:
36 import cProfile as profile
36 import cProfile as profile
37 import pstats
37 import pstats
38 except ImportError:
38 except ImportError:
39 # profile isn't bundled by default in Debian for license reasons
39 # profile isn't bundled by default in Debian for license reasons
40 try:
40 try:
41 import profile,pstats
41 import profile,pstats
42 except ImportError:
42 except ImportError:
43 profile = pstats = None
43 profile = pstats = None
44
44
45 # Homebrewed
45 # Homebrewed
46 import IPython
46 import IPython
47 import IPython.utils.generics
47 import IPython.utils.generics
48
48
49 from IPython.core import debugger, oinspect
49 from IPython.core import debugger, oinspect
50 from IPython.core.error import TryNext
50 from IPython.core.error import TryNext
51 from IPython.core.error import UsageError
51 from IPython.core.error import UsageError
52 from IPython.core.fakemodule import FakeModule
52 from IPython.core.fakemodule import FakeModule
53 from IPython.core.macro import Macro
53 from IPython.core.macro import Macro
54 from IPython.core.page import page
54 from IPython.core.page import page
55 from IPython.core.prefilter import ESC_MAGIC
55 from IPython.core.prefilter import ESC_MAGIC
56 from IPython.core.pylabtools import mpl_runner
56 from IPython.core.pylabtools import mpl_runner
57 from IPython.lib.inputhook import enable_gui
57 from IPython.lib.inputhook import enable_gui
58 from IPython.external.Itpl import Itpl, itpl, printpl,itplns
58 from IPython.external.Itpl import Itpl, itpl, printpl,itplns
59 from IPython.testing import decorators as testdec
59 from IPython.testing import decorators as testdec
60 from IPython.utils import platutils
60 from IPython.utils import platutils
61 from IPython.utils import wildcard
61 from IPython.utils import wildcard
62 from IPython.utils.PyColorize import Parser
62 from IPython.utils.PyColorize import Parser
63 from IPython.utils.ipstruct import Struct
63 from IPython.utils.ipstruct import Struct
64
64
65 # XXX - We need to switch to explicit imports here with genutils
65 # XXX - We need to switch to explicit imports here with genutils
66 from IPython.utils.genutils import *
66 from IPython.utils.genutils import *
67
67
68 #***************************************************************************
68 #***************************************************************************
69 # Utility functions
69 # Utility functions
70 def on_off(tag):
70 def on_off(tag):
71 """Return an ON/OFF string for a 1/0 input. Simple utility function."""
71 """Return an ON/OFF string for a 1/0 input. Simple utility function."""
72 return ['OFF','ON'][tag]
72 return ['OFF','ON'][tag]
73
73
74 class Bunch: pass
74 class Bunch: pass
75
75
76 def compress_dhist(dh):
76 def compress_dhist(dh):
77 head, tail = dh[:-10], dh[-10:]
77 head, tail = dh[:-10], dh[-10:]
78
78
79 newhead = []
79 newhead = []
80 done = set()
80 done = set()
81 for h in head:
81 for h in head:
82 if h in done:
82 if h in done:
83 continue
83 continue
84 newhead.append(h)
84 newhead.append(h)
85 done.add(h)
85 done.add(h)
86
86
87 return newhead + tail
87 return newhead + tail
88
88
89
89
90 #***************************************************************************
90 #***************************************************************************
91 # Main class implementing Magic functionality
91 # Main class implementing Magic functionality
92
92
93 # XXX - for some odd reason, if Magic is made a new-style class, we get errors
93 # XXX - for some odd reason, if Magic is made a new-style class, we get errors
94 # on construction of the main InteractiveShell object. Something odd is going
94 # on construction of the main InteractiveShell object. Something odd is going
95 # on with super() calls, Component and the MRO... For now leave it as-is, but
95 # on with super() calls, Component and the MRO... For now leave it as-is, but
96 # eventually this needs to be clarified.
96 # eventually this needs to be clarified.
97
97
98 class Magic:
98 class Magic:
99 """Magic functions for InteractiveShell.
99 """Magic functions for InteractiveShell.
100
100
101 Shell functions which can be reached as %function_name. All magic
101 Shell functions which can be reached as %function_name. All magic
102 functions should accept a string, which they can parse for their own
102 functions should accept a string, which they can parse for their own
103 needs. This can make some functions easier to type, eg `%cd ../`
103 needs. This can make some functions easier to type, eg `%cd ../`
104 vs. `%cd("../")`
104 vs. `%cd("../")`
105
105
106 ALL definitions MUST begin with the prefix magic_. The user won't need it
106 ALL definitions MUST begin with the prefix magic_. The user won't need it
107 at the command line, but it is is needed in the definition. """
107 at the command line, but it is is needed in the definition. """
108
108
109 # class globals
109 # class globals
110 auto_status = ['Automagic is OFF, % prefix IS needed for magic functions.',
110 auto_status = ['Automagic is OFF, % prefix IS needed for magic functions.',
111 'Automagic is ON, % prefix NOT needed for magic functions.']
111 'Automagic is ON, % prefix NOT needed for magic functions.']
112
112
113 #......................................................................
113 #......................................................................
114 # some utility functions
114 # some utility functions
115
115
116 def __init__(self,shell):
116 def __init__(self,shell):
117
117
118 self.options_table = {}
118 self.options_table = {}
119 if profile is None:
119 if profile is None:
120 self.magic_prun = self.profile_missing_notice
120 self.magic_prun = self.profile_missing_notice
121 self.shell = shell
121 self.shell = shell
122
122
123 # namespace for holding state we may need
123 # namespace for holding state we may need
124 self._magic_state = Bunch()
124 self._magic_state = Bunch()
125
125
126 def profile_missing_notice(self, *args, **kwargs):
126 def profile_missing_notice(self, *args, **kwargs):
127 error("""\
127 error("""\
128 The profile module could not be found. It has been removed from the standard
128 The profile module could not be found. It has been removed from the standard
129 python packages because of its non-free license. To use profiling, install the
129 python packages because of its non-free license. To use profiling, install the
130 python-profiler package from non-free.""")
130 python-profiler package from non-free.""")
131
131
132 def default_option(self,fn,optstr):
132 def default_option(self,fn,optstr):
133 """Make an entry in the options_table for fn, with value optstr"""
133 """Make an entry in the options_table for fn, with value optstr"""
134
134
135 if fn not in self.lsmagic():
135 if fn not in self.lsmagic():
136 error("%s is not a magic function" % fn)
136 error("%s is not a magic function" % fn)
137 self.options_table[fn] = optstr
137 self.options_table[fn] = optstr
138
138
139 def lsmagic(self):
139 def lsmagic(self):
140 """Return a list of currently available magic functions.
140 """Return a list of currently available magic functions.
141
141
142 Gives a list of the bare names after mangling (['ls','cd', ...], not
142 Gives a list of the bare names after mangling (['ls','cd', ...], not
143 ['magic_ls','magic_cd',...]"""
143 ['magic_ls','magic_cd',...]"""
144
144
145 # FIXME. This needs a cleanup, in the way the magics list is built.
145 # FIXME. This needs a cleanup, in the way the magics list is built.
146
146
147 # magics in class definition
147 # magics in class definition
148 class_magic = lambda fn: fn.startswith('magic_') and \
148 class_magic = lambda fn: fn.startswith('magic_') and \
149 callable(Magic.__dict__[fn])
149 callable(Magic.__dict__[fn])
150 # in instance namespace (run-time user additions)
150 # in instance namespace (run-time user additions)
151 inst_magic = lambda fn: fn.startswith('magic_') and \
151 inst_magic = lambda fn: fn.startswith('magic_') and \
152 callable(self.__dict__[fn])
152 callable(self.__dict__[fn])
153 # and bound magics by user (so they can access self):
153 # and bound magics by user (so they can access self):
154 inst_bound_magic = lambda fn: fn.startswith('magic_') and \
154 inst_bound_magic = lambda fn: fn.startswith('magic_') and \
155 callable(self.__class__.__dict__[fn])
155 callable(self.__class__.__dict__[fn])
156 magics = filter(class_magic,Magic.__dict__.keys()) + \
156 magics = filter(class_magic,Magic.__dict__.keys()) + \
157 filter(inst_magic,self.__dict__.keys()) + \
157 filter(inst_magic,self.__dict__.keys()) + \
158 filter(inst_bound_magic,self.__class__.__dict__.keys())
158 filter(inst_bound_magic,self.__class__.__dict__.keys())
159 out = []
159 out = []
160 for fn in set(magics):
160 for fn in set(magics):
161 out.append(fn.replace('magic_','',1))
161 out.append(fn.replace('magic_','',1))
162 out.sort()
162 out.sort()
163 return out
163 return out
164
164
165 def extract_input_slices(self,slices,raw=False):
165 def extract_input_slices(self,slices,raw=False):
166 """Return as a string a set of input history slices.
166 """Return as a string a set of input history slices.
167
167
168 Inputs:
168 Inputs:
169
169
170 - slices: the set of slices is given as a list of strings (like
170 - slices: the set of slices is given as a list of strings (like
171 ['1','4:8','9'], since this function is for use by magic functions
171 ['1','4:8','9'], since this function is for use by magic functions
172 which get their arguments as strings.
172 which get their arguments as strings.
173
173
174 Optional inputs:
174 Optional inputs:
175
175
176 - raw(False): by default, the processed input is used. If this is
176 - raw(False): by default, the processed input is used. If this is
177 true, the raw input history is used instead.
177 true, the raw input history is used instead.
178
178
179 Note that slices can be called with two notations:
179 Note that slices can be called with two notations:
180
180
181 N:M -> standard python form, means including items N...(M-1).
181 N:M -> standard python form, means including items N...(M-1).
182
182
183 N-M -> include items N..M (closed endpoint)."""
183 N-M -> include items N..M (closed endpoint)."""
184
184
185 if raw:
185 if raw:
186 hist = self.shell.input_hist_raw
186 hist = self.shell.input_hist_raw
187 else:
187 else:
188 hist = self.shell.input_hist
188 hist = self.shell.input_hist
189
189
190 cmds = []
190 cmds = []
191 for chunk in slices:
191 for chunk in slices:
192 if ':' in chunk:
192 if ':' in chunk:
193 ini,fin = map(int,chunk.split(':'))
193 ini,fin = map(int,chunk.split(':'))
194 elif '-' in chunk:
194 elif '-' in chunk:
195 ini,fin = map(int,chunk.split('-'))
195 ini,fin = map(int,chunk.split('-'))
196 fin += 1
196 fin += 1
197 else:
197 else:
198 ini = int(chunk)
198 ini = int(chunk)
199 fin = ini+1
199 fin = ini+1
200 cmds.append(hist[ini:fin])
200 cmds.append(hist[ini:fin])
201 return cmds
201 return cmds
202
202
203 def _ofind(self, oname, namespaces=None):
203 def _ofind(self, oname, namespaces=None):
204 """Find an object in the available namespaces.
204 """Find an object in the available namespaces.
205
205
206 self._ofind(oname) -> dict with keys: found,obj,ospace,ismagic
206 self._ofind(oname) -> dict with keys: found,obj,ospace,ismagic
207
207
208 Has special code to detect magic functions.
208 Has special code to detect magic functions.
209 """
209 """
210
210
211 oname = oname.strip()
211 oname = oname.strip()
212
212
213 alias_ns = None
213 alias_ns = None
214 if namespaces is None:
214 if namespaces is None:
215 # Namespaces to search in:
215 # Namespaces to search in:
216 # Put them in a list. The order is important so that we
216 # Put them in a list. The order is important so that we
217 # find things in the same order that Python finds them.
217 # find things in the same order that Python finds them.
218 namespaces = [ ('Interactive', self.shell.user_ns),
218 namespaces = [ ('Interactive', self.shell.user_ns),
219 ('IPython internal', self.shell.internal_ns),
219 ('IPython internal', self.shell.internal_ns),
220 ('Python builtin', __builtin__.__dict__),
220 ('Python builtin', __builtin__.__dict__),
221 ('Alias', self.shell.alias_manager.alias_table),
221 ('Alias', self.shell.alias_manager.alias_table),
222 ]
222 ]
223 alias_ns = self.shell.alias_manager.alias_table
223 alias_ns = self.shell.alias_manager.alias_table
224
224
225 # initialize results to 'null'
225 # initialize results to 'null'
226 found = 0; obj = None; ospace = None; ds = None;
226 found = 0; obj = None; ospace = None; ds = None;
227 ismagic = 0; isalias = 0; parent = None
227 ismagic = 0; isalias = 0; parent = None
228
228
229 # Look for the given name by splitting it in parts. If the head is
229 # Look for the given name by splitting it in parts. If the head is
230 # found, then we look for all the remaining parts as members, and only
230 # found, then we look for all the remaining parts as members, and only
231 # declare success if we can find them all.
231 # declare success if we can find them all.
232 oname_parts = oname.split('.')
232 oname_parts = oname.split('.')
233 oname_head, oname_rest = oname_parts[0],oname_parts[1:]
233 oname_head, oname_rest = oname_parts[0],oname_parts[1:]
234 for nsname,ns in namespaces:
234 for nsname,ns in namespaces:
235 try:
235 try:
236 obj = ns[oname_head]
236 obj = ns[oname_head]
237 except KeyError:
237 except KeyError:
238 continue
238 continue
239 else:
239 else:
240 #print 'oname_rest:', oname_rest # dbg
240 #print 'oname_rest:', oname_rest # dbg
241 for part in oname_rest:
241 for part in oname_rest:
242 try:
242 try:
243 parent = obj
243 parent = obj
244 obj = getattr(obj,part)
244 obj = getattr(obj,part)
245 except:
245 except:
246 # Blanket except b/c some badly implemented objects
246 # Blanket except b/c some badly implemented objects
247 # allow __getattr__ to raise exceptions other than
247 # allow __getattr__ to raise exceptions other than
248 # AttributeError, which then crashes IPython.
248 # AttributeError, which then crashes IPython.
249 break
249 break
250 else:
250 else:
251 # If we finish the for loop (no break), we got all members
251 # If we finish the for loop (no break), we got all members
252 found = 1
252 found = 1
253 ospace = nsname
253 ospace = nsname
254 if ns == alias_ns:
254 if ns == alias_ns:
255 isalias = 1
255 isalias = 1
256 break # namespace loop
256 break # namespace loop
257
257
258 # Try to see if it's magic
258 # Try to see if it's magic
259 if not found:
259 if not found:
260 if oname.startswith(ESC_MAGIC):
260 if oname.startswith(ESC_MAGIC):
261 oname = oname[1:]
261 oname = oname[1:]
262 obj = getattr(self,'magic_'+oname,None)
262 obj = getattr(self,'magic_'+oname,None)
263 if obj is not None:
263 if obj is not None:
264 found = 1
264 found = 1
265 ospace = 'IPython internal'
265 ospace = 'IPython internal'
266 ismagic = 1
266 ismagic = 1
267
267
268 # Last try: special-case some literals like '', [], {}, etc:
268 # Last try: special-case some literals like '', [], {}, etc:
269 if not found and oname_head in ["''",'""','[]','{}','()']:
269 if not found and oname_head in ["''",'""','[]','{}','()']:
270 obj = eval(oname_head)
270 obj = eval(oname_head)
271 found = 1
271 found = 1
272 ospace = 'Interactive'
272 ospace = 'Interactive'
273
273
274 return {'found':found, 'obj':obj, 'namespace':ospace,
274 return {'found':found, 'obj':obj, 'namespace':ospace,
275 'ismagic':ismagic, 'isalias':isalias, 'parent':parent}
275 'ismagic':ismagic, 'isalias':isalias, 'parent':parent}
276
276
277 def arg_err(self,func):
277 def arg_err(self,func):
278 """Print docstring if incorrect arguments were passed"""
278 """Print docstring if incorrect arguments were passed"""
279 print 'Error in arguments:'
279 print 'Error in arguments:'
280 print OInspect.getdoc(func)
280 print OInspect.getdoc(func)
281
281
282 def format_latex(self,strng):
282 def format_latex(self,strng):
283 """Format a string for latex inclusion."""
283 """Format a string for latex inclusion."""
284
284
285 # Characters that need to be escaped for latex:
285 # Characters that need to be escaped for latex:
286 escape_re = re.compile(r'(%|_|\$|#|&)',re.MULTILINE)
286 escape_re = re.compile(r'(%|_|\$|#|&)',re.MULTILINE)
287 # Magic command names as headers:
287 # Magic command names as headers:
288 cmd_name_re = re.compile(r'^(%s.*?):' % ESC_MAGIC,
288 cmd_name_re = re.compile(r'^(%s.*?):' % ESC_MAGIC,
289 re.MULTILINE)
289 re.MULTILINE)
290 # Magic commands
290 # Magic commands
291 cmd_re = re.compile(r'(?P<cmd>%s.+?\b)(?!\}\}:)' % ESC_MAGIC,
291 cmd_re = re.compile(r'(?P<cmd>%s.+?\b)(?!\}\}:)' % ESC_MAGIC,
292 re.MULTILINE)
292 re.MULTILINE)
293 # Paragraph continue
293 # Paragraph continue
294 par_re = re.compile(r'\\$',re.MULTILINE)
294 par_re = re.compile(r'\\$',re.MULTILINE)
295
295
296 # The "\n" symbol
296 # The "\n" symbol
297 newline_re = re.compile(r'\\n')
297 newline_re = re.compile(r'\\n')
298
298
299 # Now build the string for output:
299 # Now build the string for output:
300 #strng = cmd_name_re.sub(r'\n\\texttt{\\textsl{\\large \1}}:',strng)
300 #strng = cmd_name_re.sub(r'\n\\texttt{\\textsl{\\large \1}}:',strng)
301 strng = cmd_name_re.sub(r'\n\\bigskip\n\\texttt{\\textbf{ \1}}:',
301 strng = cmd_name_re.sub(r'\n\\bigskip\n\\texttt{\\textbf{ \1}}:',
302 strng)
302 strng)
303 strng = cmd_re.sub(r'\\texttt{\g<cmd>}',strng)
303 strng = cmd_re.sub(r'\\texttt{\g<cmd>}',strng)
304 strng = par_re.sub(r'\\\\',strng)
304 strng = par_re.sub(r'\\\\',strng)
305 strng = escape_re.sub(r'\\\1',strng)
305 strng = escape_re.sub(r'\\\1',strng)
306 strng = newline_re.sub(r'\\textbackslash{}n',strng)
306 strng = newline_re.sub(r'\\textbackslash{}n',strng)
307 return strng
307 return strng
308
308
309 def format_screen(self,strng):
309 def format_screen(self,strng):
310 """Format a string for screen printing.
310 """Format a string for screen printing.
311
311
312 This removes some latex-type format codes."""
312 This removes some latex-type format codes."""
313 # Paragraph continue
313 # Paragraph continue
314 par_re = re.compile(r'\\$',re.MULTILINE)
314 par_re = re.compile(r'\\$',re.MULTILINE)
315 strng = par_re.sub('',strng)
315 strng = par_re.sub('',strng)
316 return strng
316 return strng
317
317
318 def parse_options(self,arg_str,opt_str,*long_opts,**kw):
318 def parse_options(self,arg_str,opt_str,*long_opts,**kw):
319 """Parse options passed to an argument string.
319 """Parse options passed to an argument string.
320
320
321 The interface is similar to that of getopt(), but it returns back a
321 The interface is similar to that of getopt(), but it returns back a
322 Struct with the options as keys and the stripped argument string still
322 Struct with the options as keys and the stripped argument string still
323 as a string.
323 as a string.
324
324
325 arg_str is quoted as a true sys.argv vector by using shlex.split.
325 arg_str is quoted as a true sys.argv vector by using shlex.split.
326 This allows us to easily expand variables, glob files, quote
326 This allows us to easily expand variables, glob files, quote
327 arguments, etc.
327 arguments, etc.
328
328
329 Options:
329 Options:
330 -mode: default 'string'. If given as 'list', the argument string is
330 -mode: default 'string'. If given as 'list', the argument string is
331 returned as a list (split on whitespace) instead of a string.
331 returned as a list (split on whitespace) instead of a string.
332
332
333 -list_all: put all option values in lists. Normally only options
333 -list_all: put all option values in lists. Normally only options
334 appearing more than once are put in a list.
334 appearing more than once are put in a list.
335
335
336 -posix (True): whether to split the input line in POSIX mode or not,
336 -posix (True): whether to split the input line in POSIX mode or not,
337 as per the conventions outlined in the shlex module from the
337 as per the conventions outlined in the shlex module from the
338 standard library."""
338 standard library."""
339
339
340 # inject default options at the beginning of the input line
340 # inject default options at the beginning of the input line
341 caller = sys._getframe(1).f_code.co_name.replace('magic_','')
341 caller = sys._getframe(1).f_code.co_name.replace('magic_','')
342 arg_str = '%s %s' % (self.options_table.get(caller,''),arg_str)
342 arg_str = '%s %s' % (self.options_table.get(caller,''),arg_str)
343
343
344 mode = kw.get('mode','string')
344 mode = kw.get('mode','string')
345 if mode not in ['string','list']:
345 if mode not in ['string','list']:
346 raise ValueError,'incorrect mode given: %s' % mode
346 raise ValueError,'incorrect mode given: %s' % mode
347 # Get options
347 # Get options
348 list_all = kw.get('list_all',0)
348 list_all = kw.get('list_all',0)
349 posix = kw.get('posix',True)
349 posix = kw.get('posix',True)
350
350
351 # Check if we have more than one argument to warrant extra processing:
351 # Check if we have more than one argument to warrant extra processing:
352 odict = {} # Dictionary with options
352 odict = {} # Dictionary with options
353 args = arg_str.split()
353 args = arg_str.split()
354 if len(args) >= 1:
354 if len(args) >= 1:
355 # If the list of inputs only has 0 or 1 thing in it, there's no
355 # If the list of inputs only has 0 or 1 thing in it, there's no
356 # need to look for options
356 # need to look for options
357 argv = arg_split(arg_str,posix)
357 argv = arg_split(arg_str,posix)
358 # Do regular option processing
358 # Do regular option processing
359 try:
359 try:
360 opts,args = getopt(argv,opt_str,*long_opts)
360 opts,args = getopt(argv,opt_str,*long_opts)
361 except GetoptError,e:
361 except GetoptError,e:
362 raise UsageError('%s ( allowed: "%s" %s)' % (e.msg,opt_str,
362 raise UsageError('%s ( allowed: "%s" %s)' % (e.msg,opt_str,
363 " ".join(long_opts)))
363 " ".join(long_opts)))
364 for o,a in opts:
364 for o,a in opts:
365 if o.startswith('--'):
365 if o.startswith('--'):
366 o = o[2:]
366 o = o[2:]
367 else:
367 else:
368 o = o[1:]
368 o = o[1:]
369 try:
369 try:
370 odict[o].append(a)
370 odict[o].append(a)
371 except AttributeError:
371 except AttributeError:
372 odict[o] = [odict[o],a]
372 odict[o] = [odict[o],a]
373 except KeyError:
373 except KeyError:
374 if list_all:
374 if list_all:
375 odict[o] = [a]
375 odict[o] = [a]
376 else:
376 else:
377 odict[o] = a
377 odict[o] = a
378
378
379 # Prepare opts,args for return
379 # Prepare opts,args for return
380 opts = Struct(odict)
380 opts = Struct(odict)
381 if mode == 'string':
381 if mode == 'string':
382 args = ' '.join(args)
382 args = ' '.join(args)
383
383
384 return opts,args
384 return opts,args
385
385
386 #......................................................................
386 #......................................................................
387 # And now the actual magic functions
387 # And now the actual magic functions
388
388
389 # Functions for IPython shell work (vars,funcs, config, etc)
389 # Functions for IPython shell work (vars,funcs, config, etc)
390 def magic_lsmagic(self, parameter_s = ''):
390 def magic_lsmagic(self, parameter_s = ''):
391 """List currently available magic functions."""
391 """List currently available magic functions."""
392 mesc = ESC_MAGIC
392 mesc = ESC_MAGIC
393 print 'Available magic functions:\n'+mesc+\
393 print 'Available magic functions:\n'+mesc+\
394 (' '+mesc).join(self.lsmagic())
394 (' '+mesc).join(self.lsmagic())
395 print '\n' + Magic.auto_status[self.shell.automagic]
395 print '\n' + Magic.auto_status[self.shell.automagic]
396 return None
396 return None
397
397
398 def magic_magic(self, parameter_s = ''):
398 def magic_magic(self, parameter_s = ''):
399 """Print information about the magic function system.
399 """Print information about the magic function system.
400
400
401 Supported formats: -latex, -brief, -rest
401 Supported formats: -latex, -brief, -rest
402 """
402 """
403
403
404 mode = ''
404 mode = ''
405 try:
405 try:
406 if parameter_s.split()[0] == '-latex':
406 if parameter_s.split()[0] == '-latex':
407 mode = 'latex'
407 mode = 'latex'
408 if parameter_s.split()[0] == '-brief':
408 if parameter_s.split()[0] == '-brief':
409 mode = 'brief'
409 mode = 'brief'
410 if parameter_s.split()[0] == '-rest':
410 if parameter_s.split()[0] == '-rest':
411 mode = 'rest'
411 mode = 'rest'
412 rest_docs = []
412 rest_docs = []
413 except:
413 except:
414 pass
414 pass
415
415
416 magic_docs = []
416 magic_docs = []
417 for fname in self.lsmagic():
417 for fname in self.lsmagic():
418 mname = 'magic_' + fname
418 mname = 'magic_' + fname
419 for space in (Magic,self,self.__class__):
419 for space in (Magic,self,self.__class__):
420 try:
420 try:
421 fn = space.__dict__[mname]
421 fn = space.__dict__[mname]
422 except KeyError:
422 except KeyError:
423 pass
423 pass
424 else:
424 else:
425 break
425 break
426 if mode == 'brief':
426 if mode == 'brief':
427 # only first line
427 # only first line
428 if fn.__doc__:
428 if fn.__doc__:
429 fndoc = fn.__doc__.split('\n',1)[0]
429 fndoc = fn.__doc__.split('\n',1)[0]
430 else:
430 else:
431 fndoc = 'No documentation'
431 fndoc = 'No documentation'
432 else:
432 else:
433 if fn.__doc__:
433 if fn.__doc__:
434 fndoc = fn.__doc__.rstrip()
434 fndoc = fn.__doc__.rstrip()
435 else:
435 else:
436 fndoc = 'No documentation'
436 fndoc = 'No documentation'
437
437
438
438
439 if mode == 'rest':
439 if mode == 'rest':
440 rest_docs.append('**%s%s**::\n\n\t%s\n\n' %(ESC_MAGIC,
440 rest_docs.append('**%s%s**::\n\n\t%s\n\n' %(ESC_MAGIC,
441 fname,fndoc))
441 fname,fndoc))
442
442
443 else:
443 else:
444 magic_docs.append('%s%s:\n\t%s\n' %(ESC_MAGIC,
444 magic_docs.append('%s%s:\n\t%s\n' %(ESC_MAGIC,
445 fname,fndoc))
445 fname,fndoc))
446
446
447 magic_docs = ''.join(magic_docs)
447 magic_docs = ''.join(magic_docs)
448
448
449 if mode == 'rest':
449 if mode == 'rest':
450 return "".join(rest_docs)
450 return "".join(rest_docs)
451
451
452 if mode == 'latex':
452 if mode == 'latex':
453 print self.format_latex(magic_docs)
453 print self.format_latex(magic_docs)
454 return
454 return
455 else:
455 else:
456 magic_docs = self.format_screen(magic_docs)
456 magic_docs = self.format_screen(magic_docs)
457 if mode == 'brief':
457 if mode == 'brief':
458 return magic_docs
458 return magic_docs
459
459
460 outmsg = """
460 outmsg = """
461 IPython's 'magic' functions
461 IPython's 'magic' functions
462 ===========================
462 ===========================
463
463
464 The magic function system provides a series of functions which allow you to
464 The magic function system provides a series of functions which allow you to
465 control the behavior of IPython itself, plus a lot of system-type
465 control the behavior of IPython itself, plus a lot of system-type
466 features. All these functions are prefixed with a % character, but parameters
466 features. All these functions are prefixed with a % character, but parameters
467 are given without parentheses or quotes.
467