##// END OF EJS Templates
Fix a number of bugs with %history, add proper tests....
Fernando Perez -
Show More
@@ -1,5 +1,4 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
3 """ History related magics and functionality """
2 """ History related magics and functionality """
4
3
5 # Stdlib imports
4 # Stdlib imports
@@ -7,7 +6,7 b' import fnmatch'
7 import os
6 import os
8
7
9 # IPython imports
8 # IPython imports
10 from IPython.genutils import Term, ask_yes_no
9 from IPython.genutils import Term, ask_yes_no, warn
11 import IPython.ipapi
10 import IPython.ipapi
12
11
13 def magic_history(self, parameter_s = ''):
12 def magic_history(self, parameter_s = ''):
@@ -47,8 +46,6 b" def magic_history(self, parameter_s = ''):"
47 -f FILENAME: instead of printing the output to the screen, redirect it to
46 -f FILENAME: instead of printing the output to the screen, redirect it to
48 the given file. The file is always overwritten, though IPython asks for
47 the given file. The file is always overwritten, though IPython asks for
49 confirmation first if it already exists.
48 confirmation first if it already exists.
50
51
52 """
49 """
53
50
54 ip = self.api
51 ip = self.api
@@ -62,31 +59,28 b" def magic_history(self, parameter_s = ''):"
62 try:
59 try:
63 outfname = opts['f']
60 outfname = opts['f']
64 except KeyError:
61 except KeyError:
65 outfile = Term.cout
62 outfile = Term.cout # default
66 # We don't want to close stdout at the end!
63 # We don't want to close stdout at the end!
67 close_at_end = False
64 close_at_end = False
68 else:
65 else:
69 if os.path.exists(outfname):
66 if os.path.exists(outfname):
70 ans = ask_yes_no("File %r exists. Overwrite?" % outfname)
67 if not ask_yes_no("File %r exists. Overwrite?" % outfname):
71 if not ans:
72 print 'Aborting.'
68 print 'Aborting.'
73 return
69 return
74 else:
75 outfile = open(outfname,'w')
76 close_at_end = True
77
78
70
79 if opts.has_key('t'):
71 outfile = open(outfname,'w')
72 close_at_end = True
73
74 if 't' in opts:
80 input_hist = shell.input_hist
75 input_hist = shell.input_hist
81 elif opts.has_key('r'):
76 elif 'r' in opts:
82 input_hist = shell.input_hist_raw
77 input_hist = shell.input_hist_raw
83 else:
78 else:
84 input_hist = shell.input_hist
79 input_hist = shell.input_hist
85
80
86
87 default_length = 40
81 default_length = 40
88 pattern = None
82 pattern = None
89 if opts.has_key('g'):
83 if 'g' in opts:
90 init = 1
84 init = 1
91 final = len(input_hist)
85 final = len(input_hist)
92 parts = parameter_s.split(None,1)
86 parts = parameter_s.split(None,1)
@@ -138,13 +132,11 b" def magic_history(self, parameter_s = ''):"
138 outfile.close()
132 outfile.close()
139
133
140
134
141
142 def magic_hist(self, parameter_s=''):
135 def magic_hist(self, parameter_s=''):
143 """Alternate name for %history."""
136 """Alternate name for %history."""
144 return self.magic_history(parameter_s)
137 return self.magic_history(parameter_s)
145
138
146
139
147
148 def rep_f(self, arg):
140 def rep_f(self, arg):
149 r""" Repeat a command, or get command to input line for editing
141 r""" Repeat a command, or get command to input line for editing
150
142
@@ -173,11 +165,9 b' def rep_f(self, arg):'
173 %rep foo
165 %rep foo
174
166
175 Place the most recent line that has the substring "foo" to next input.
167 Place the most recent line that has the substring "foo" to next input.
176 (e.g. 'svn ci -m foobar').
168 (e.g. 'svn ci -m foobar').
177
178 """
169 """
179
170
180
181 opts,args = self.parse_options(arg,'',mode='list')
171 opts,args = self.parse_options(arg,'',mode='list')
182 ip = self.api
172 ip = self.api
183 if not args:
173 if not args:
@@ -206,7 +196,6 b' def rep_f(self, arg):'
206 ip.set_next_input(str(h).rstrip())
196 ip.set_next_input(str(h).rstrip())
207 return
197 return
208
198
209
210 try:
199 try:
211 lines = self.extract_input_slices(args, True)
200 lines = self.extract_input_slices(args, True)
212 print "lines",lines
201 print "lines",lines
@@ -215,7 +204,6 b' def rep_f(self, arg):'
215 print "Not found in recent history:", args
204 print "Not found in recent history:", args
216
205
217
206
218
219 _sentinel = object()
207 _sentinel = object()
220
208
221 class ShadowHist:
209 class ShadowHist:
@@ -259,23 +247,12 b' class ShadowHist:'
259 if k == idx:
247 if k == idx:
260 return v
248 return v
261
249
262 def test_shist():
263 from IPython.Extensions import pickleshare
264 db = pickleshare.PickleShareDB('~/shist')
265 s = ShadowHist(db)
266 s.add('hello')
267 s.add('world')
268 s.add('hello')
269 s.add('hello')
270 s.add('karhu')
271 print "all",s.all()
272 print s.get(2)
273
250
274 def init_ipython(ip):
251 def init_ipython(ip):
252 import ipy_completers
253
275 ip.expose_magic("rep",rep_f)
254 ip.expose_magic("rep",rep_f)
276 ip.expose_magic("hist",magic_hist)
255 ip.expose_magic("hist",magic_hist)
277 ip.expose_magic("history",magic_history)
256 ip.expose_magic("history",magic_history)
278
257
279 import ipy_completers
280 ipy_completers.quick_completer('%hist' ,'-g -t -r -n')
258 ipy_completers.quick_completer('%hist' ,'-g -t -r -n')
281 #test_shist()
@@ -65,13 +65,28 b' log = logging.getLogger(__name__)'
65 # test globals. Once we move over to a clean magic system, this will be done
65 # test globals. Once we move over to a clean magic system, this will be done
66 # with much less ugliness.
66 # with much less ugliness.
67
67
68 class py_file_finder(object):
69 def __init__(self,test_filename):
70 self.test_filename = test_filename
71
72 def __call__(self,name):
73 from IPython.genutils import get_py_filename
74 try:
75 get_py_filename(name)
76 except IOError:
77 test_dir = os.path.dirname(self.test_filename)
78 new_path = os.path.join(test_dir,name)
79 return get_py_filename(new_path)
80
81
68 def _run_ns_sync(self,arg_s,runner=None):
82 def _run_ns_sync(self,arg_s,runner=None):
69 """Modified version of %run that syncs testing namespaces.
83 """Modified version of %run that syncs testing namespaces.
70
84
71 This is strictly needed for running doctests that call %run.
85 This is strictly needed for running doctests that call %run.
72 """
86 """
73
87
74 out = _ip.IP.magic_run_ori(arg_s,runner)
88 finder = py_file_finder(_run_ns_sync.test_filename)
89 out = _ip.IP.magic_run_ori(arg_s,runner,finder)
75 _run_ns_sync.test_globs.update(_ip.user_ns)
90 _run_ns_sync.test_globs.update(_ip.user_ns)
76 return out
91 return out
77
92
@@ -129,8 +144,7 b' def start_ipython():'
129
144
130 # Start IPython instance. We customize it to start with minimal frills.
145 # Start IPython instance. We customize it to start with minimal frills.
131 user_ns,global_ns = IPython.ipapi.make_user_namespaces(ipnsdict(),dict())
146 user_ns,global_ns = IPython.ipapi.make_user_namespaces(ipnsdict(),dict())
132
147 IPython.Shell.IPShell(['--colors=NoColor','--noterm_title'],
133 IPython.Shell.IPShell(['--classic','--noterm_title'],
134 user_ns,global_ns)
148 user_ns,global_ns)
135
149
136 # Deactivate the various python system hooks added by ipython for
150 # Deactivate the various python system hooks added by ipython for
@@ -638,7 +652,8 b' class IPDocTestRunner(doctest.DocTestRunner,object):'
638 # when called (rather than unconconditionally updating test.globs here
652 # when called (rather than unconconditionally updating test.globs here
639 # for all examples, most of which won't be calling %run anyway).
653 # for all examples, most of which won't be calling %run anyway).
640 _run_ns_sync.test_globs = test.globs
654 _run_ns_sync.test_globs = test.globs
641
655 _run_ns_sync.test_filename = test.filename
656
642 return super(IPDocTestRunner,self).run(test,
657 return super(IPDocTestRunner,self).run(test,
643 compileflags,out,clear_globs)
658 compileflags,out,clear_globs)
644
659
@@ -1,8 +1,10 b''
1 """ Tests for various magic functions
1 """ Tests for various magic functions
2
2
3 Needs to be run by nose (to make ipython session available)
3 Needs to be run by nose (to make ipython session available)
4
5 """
4 """
5
6 from IPython.testing import decorators as dec
7
6 def test_rehashx():
8 def test_rehashx():
7 # clear up everything
9 # clear up everything
8 _ip.IP.alias_table.clear()
10 _ip.IP.alias_table.clear()
@@ -19,3 +21,72 b' def test_rehashx():'
19 # rehashx must fill up syscmdlist
21 # rehashx must fill up syscmdlist
20 scoms = _ip.db['syscmdlist']
22 scoms = _ip.db['syscmdlist']
21 assert len(scoms) > 10
23 assert len(scoms) > 10
24
25
26 def doctest_run_ns():
27 """Classes declared %run scripts must be instantiable afterwards.
28
29 In [3]: run tclass.py
30
31 In [4]: f()
32 """
33 pass # doctest only
34
35
36 def doctest_hist_f():
37 """Test %hist -f with temporary filename.
38
39 In [9]: import tempfile
40
41 In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-')
42
43 In [11]: %history -n -f $tfile 3
44 """
45
46
47 def doctest_hist_r():
48 """Test %hist -r
49
50 XXX - This test is not recording the output correctly. Not sure why...
51
52 In [6]: x=1
53
54 In [7]: hist -n -r 2
55 x=1 # random
56 hist -n -r 2 # random
57 """
58
59
60 def test_shist():
61 # Simple tests of ShadowHist class
62 import os, shutil, tempfile
63 import nose.tools as nt
64
65 from IPython.Extensions import pickleshare
66 from IPython.history import ShadowHist
67
68
69 tfile = tempfile.mktemp('','tmp-ipython-')
70
71 db = pickleshare.PickleShareDB(tfile)
72 s = ShadowHist(db)
73 s.add('hello')
74 s.add('world')
75 s.add('hello')
76 s.add('hello')
77 s.add('karhu')
78
79 yield nt.assert_equals,s.all(),[(1, 'hello'), (2, 'world'), (3, 'karhu')]
80
81 yield nt.assert_equal,s.get(2),'world'
82
83 shutil.rmtree(tfile)
84
85
86 @dec.skip_numpy_not_avail
87 def doctest_clear_array():
88 """Check that array clearing works.
89
90 >>> 1/0
91 """
92 pass # doctest only
General Comments 0
You need to be logged in to leave comments. Login now