##// END OF EJS Templates
separate %reset tests for finer granularity
Paul Ivanov -
Show More
@@ -1,387 +1,390 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 """
4 """
5 from __future__ import absolute_import
5 from __future__ import absolute_import
6
6
7 #-----------------------------------------------------------------------------
7 #-----------------------------------------------------------------------------
8 # Imports
8 # Imports
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10
10
11 import os
11 import os
12
12
13 import nose.tools as nt
13 import nose.tools as nt
14
14
15 from IPython.testing import decorators as dec
15 from IPython.testing import decorators as dec
16 from IPython.testing import tools as tt
16 from IPython.testing import tools as tt
17 from IPython.utils import py3compat
17 from IPython.utils import py3compat
18
18
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20 # Test functions begin
20 # Test functions begin
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22
22
23 def test_rehashx():
23 def test_rehashx():
24 # clear up everything
24 # clear up everything
25 _ip = get_ipython()
25 _ip = get_ipython()
26 _ip.alias_manager.alias_table.clear()
26 _ip.alias_manager.alias_table.clear()
27 del _ip.db['syscmdlist']
27 del _ip.db['syscmdlist']
28
28
29 _ip.magic('rehashx')
29 _ip.magic('rehashx')
30 # Practically ALL ipython development systems will have more than 10 aliases
30 # Practically ALL ipython development systems will have more than 10 aliases
31
31
32 yield (nt.assert_true, len(_ip.alias_manager.alias_table) > 10)
32 yield (nt.assert_true, len(_ip.alias_manager.alias_table) > 10)
33 for key, val in _ip.alias_manager.alias_table.iteritems():
33 for key, val in _ip.alias_manager.alias_table.iteritems():
34 # we must strip dots from alias names
34 # we must strip dots from alias names
35 nt.assert_true('.' not in key)
35 nt.assert_true('.' not in key)
36
36
37 # rehashx must fill up syscmdlist
37 # rehashx must fill up syscmdlist
38 scoms = _ip.db['syscmdlist']
38 scoms = _ip.db['syscmdlist']
39 yield (nt.assert_true, len(scoms) > 10)
39 yield (nt.assert_true, len(scoms) > 10)
40
40
41
41
42 def test_magic_parse_options():
42 def test_magic_parse_options():
43 """Test that we don't mangle paths when parsing magic options."""
43 """Test that we don't mangle paths when parsing magic options."""
44 ip = get_ipython()
44 ip = get_ipython()
45 path = 'c:\\x'
45 path = 'c:\\x'
46 opts = ip.parse_options('-f %s' % path,'f:')[0]
46 opts = ip.parse_options('-f %s' % path,'f:')[0]
47 # argv splitting is os-dependent
47 # argv splitting is os-dependent
48 if os.name == 'posix':
48 if os.name == 'posix':
49 expected = 'c:x'
49 expected = 'c:x'
50 else:
50 else:
51 expected = path
51 expected = path
52 nt.assert_equals(opts['f'], expected)
52 nt.assert_equals(opts['f'], expected)
53
53
54
54
55 @dec.skip_without('sqlite3')
55 @dec.skip_without('sqlite3')
56 def doctest_hist_f():
56 def doctest_hist_f():
57 """Test %hist -f with temporary filename.
57 """Test %hist -f with temporary filename.
58
58
59 In [9]: import tempfile
59 In [9]: import tempfile
60
60
61 In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-')
61 In [10]: tfile = tempfile.mktemp('.py','tmp-ipython-')
62
62
63 In [11]: %hist -nl -f $tfile 3
63 In [11]: %hist -nl -f $tfile 3
64
64
65 In [13]: import os; os.unlink(tfile)
65 In [13]: import os; os.unlink(tfile)
66 """
66 """
67
67
68
68
69 @dec.skip_without('sqlite3')
69 @dec.skip_without('sqlite3')
70 def doctest_hist_r():
70 def doctest_hist_r():
71 """Test %hist -r
71 """Test %hist -r
72
72
73 XXX - This test is not recording the output correctly. For some reason, in
73 XXX - This test is not recording the output correctly. For some reason, in
74 testing mode the raw history isn't getting populated. No idea why.
74 testing mode the raw history isn't getting populated. No idea why.
75 Disabling the output checking for now, though at least we do run it.
75 Disabling the output checking for now, though at least we do run it.
76
76
77 In [1]: 'hist' in _ip.lsmagic()
77 In [1]: 'hist' in _ip.lsmagic()
78 Out[1]: True
78 Out[1]: True
79
79
80 In [2]: x=1
80 In [2]: x=1
81
81
82 In [3]: %hist -rl 2
82 In [3]: %hist -rl 2
83 x=1 # random
83 x=1 # random
84 %hist -r 2
84 %hist -r 2
85 """
85 """
86
86
87
87
88 @dec.skip_without('sqlite3')
88 @dec.skip_without('sqlite3')
89 def doctest_hist_op():
89 def doctest_hist_op():
90 """Test %hist -op
90 """Test %hist -op
91
91
92 In [1]: class b(float):
92 In [1]: class b(float):
93 ...: pass
93 ...: pass
94 ...:
94 ...:
95
95
96 In [2]: class s(object):
96 In [2]: class s(object):
97 ...: def __str__(self):
97 ...: def __str__(self):
98 ...: return 's'
98 ...: return 's'
99 ...:
99 ...:
100
100
101 In [3]:
101 In [3]:
102
102
103 In [4]: class r(b):
103 In [4]: class r(b):
104 ...: def __repr__(self):
104 ...: def __repr__(self):
105 ...: return 'r'
105 ...: return 'r'
106 ...:
106 ...:
107
107
108 In [5]: class sr(s,r): pass
108 In [5]: class sr(s,r): pass
109 ...:
109 ...:
110
110
111 In [6]:
111 In [6]:
112
112
113 In [7]: bb=b()
113 In [7]: bb=b()
114
114
115 In [8]: ss=s()
115 In [8]: ss=s()
116
116
117 In [9]: rr=r()
117 In [9]: rr=r()
118
118
119 In [10]: ssrr=sr()
119 In [10]: ssrr=sr()
120
120
121 In [11]: 4.5
121 In [11]: 4.5
122 Out[11]: 4.5
122 Out[11]: 4.5
123
123
124 In [12]: str(ss)
124 In [12]: str(ss)
125 Out[12]: 's'
125 Out[12]: 's'
126
126
127 In [13]:
127 In [13]:
128
128
129 In [14]: %hist -op
129 In [14]: %hist -op
130 >>> class b:
130 >>> class b:
131 ... pass
131 ... pass
132 ...
132 ...
133 >>> class s(b):
133 >>> class s(b):
134 ... def __str__(self):
134 ... def __str__(self):
135 ... return 's'
135 ... return 's'
136 ...
136 ...
137 >>>
137 >>>
138 >>> class r(b):
138 >>> class r(b):
139 ... def __repr__(self):
139 ... def __repr__(self):
140 ... return 'r'
140 ... return 'r'
141 ...
141 ...
142 >>> class sr(s,r): pass
142 >>> class sr(s,r): pass
143 >>>
143 >>>
144 >>> bb=b()
144 >>> bb=b()
145 >>> ss=s()
145 >>> ss=s()
146 >>> rr=r()
146 >>> rr=r()
147 >>> ssrr=sr()
147 >>> ssrr=sr()
148 >>> 4.5
148 >>> 4.5
149 4.5
149 4.5
150 >>> str(ss)
150 >>> str(ss)
151 's'
151 's'
152 >>>
152 >>>
153 """
153 """
154
154
155
155
156 @dec.skip_without('sqlite3')
156 @dec.skip_without('sqlite3')
157 def test_macro():
157 def test_macro():
158 ip = get_ipython()
158 ip = get_ipython()
159 ip.history_manager.reset() # Clear any existing history.
159 ip.history_manager.reset() # Clear any existing history.
160 cmds = ["a=1", "def b():\n return a**2", "print(a,b())"]
160 cmds = ["a=1", "def b():\n return a**2", "print(a,b())"]
161 for i, cmd in enumerate(cmds, start=1):
161 for i, cmd in enumerate(cmds, start=1):
162 ip.history_manager.store_inputs(i, cmd)
162 ip.history_manager.store_inputs(i, cmd)
163 ip.magic("macro test 1-3")
163 ip.magic("macro test 1-3")
164 nt.assert_equal(ip.user_ns["test"].value, "\n".join(cmds)+"\n")
164 nt.assert_equal(ip.user_ns["test"].value, "\n".join(cmds)+"\n")
165
165
166 # List macros.
166 # List macros.
167 assert "test" in ip.magic("macro")
167 assert "test" in ip.magic("macro")
168
168
169
169
170 @dec.skip_without('sqlite3')
170 @dec.skip_without('sqlite3')
171 def test_macro_run():
171 def test_macro_run():
172 """Test that we can run a multi-line macro successfully."""
172 """Test that we can run a multi-line macro successfully."""
173 ip = get_ipython()
173 ip = get_ipython()
174 ip.history_manager.reset()
174 ip.history_manager.reset()
175 cmds = ["a=10", "a+=1", py3compat.doctest_refactor_print("print a"),
175 cmds = ["a=10", "a+=1", py3compat.doctest_refactor_print("print a"),
176 "%macro test 2-3"]
176 "%macro test 2-3"]
177 for cmd in cmds:
177 for cmd in cmds:
178 ip.run_cell(cmd, store_history=True)
178 ip.run_cell(cmd, store_history=True)
179 nt.assert_equal(ip.user_ns["test"].value,
179 nt.assert_equal(ip.user_ns["test"].value,
180 py3compat.doctest_refactor_print("a+=1\nprint a\n"))
180 py3compat.doctest_refactor_print("a+=1\nprint a\n"))
181 with tt.AssertPrints("12"):
181 with tt.AssertPrints("12"):
182 ip.run_cell("test")
182 ip.run_cell("test")
183 with tt.AssertPrints("13"):
183 with tt.AssertPrints("13"):
184 ip.run_cell("test")
184 ip.run_cell("test")
185
185
186
186
187 @dec.skipif_not_numpy
187 @dec.skipif_not_numpy
188 def test_numpy_reset_array_undec():
188 def test_numpy_reset_array_undec():
189 "Test '%reset array' functionality"
189 "Test '%reset array' functionality"
190 _ip.ex('import numpy as np')
190 _ip.ex('import numpy as np')
191 _ip.ex('a = np.empty(2)')
191 _ip.ex('a = np.empty(2)')
192 yield (nt.assert_true, 'a' in _ip.user_ns)
192 yield (nt.assert_true, 'a' in _ip.user_ns)
193 _ip.magic('reset -f array')
193 _ip.magic('reset -f array')
194 yield (nt.assert_false, 'a' in _ip.user_ns)
194 yield (nt.assert_false, 'a' in _ip.user_ns)
195
195
196 def test_reset_args():
196 def test_reset_out():
197 "Test '%reset' magic with args which used to be extensions.clearcmd"
197 "Test '%reset out' magic"
198 _ip = get_ipython()
199 _ip.run_cell("parrot = 'dead'", store_history=True)
198 _ip.run_cell("parrot = 'dead'", store_history=True)
200 # test '%reset -f out', make an Out prompt
199 # test '%reset -f out', make an Out prompt
201 _ip.run_cell("parrot", store_history=True)
200 _ip.run_cell("parrot", store_history=True)
202 nt.assert_true('dead' in [_ip.user_ns[x] for x in '_','__','___'])
201 nt.assert_true('dead' in [_ip.user_ns[x] for x in '_','__','___'])
203 _ip.magic('reset -f out')
202 _ip.magic('reset -f out')
204 nt.assert_false('dead' in [_ip.user_ns[x] for x in '_','__','___'])
203 nt.assert_false('dead' in [_ip.user_ns[x] for x in '_','__','___'])
205 nt.assert_true(len(_ip.user_ns['Out']) == 0)
204 nt.assert_true(len(_ip.user_ns['Out']) == 0)
206
205
206 def test_reset_in():
207 "Test '%reset in' magic"
207 # test '%reset -f in'
208 # test '%reset -f in'
208 _ip.run_cell("parrot", store_history=True)
209 _ip.run_cell("parrot", store_history=True)
209 nt.assert_true('parrot' in [_ip.user_ns[x] for x in '_i','_ii','_iii'])
210 nt.assert_true('parrot' in [_ip.user_ns[x] for x in '_i','_ii','_iii'])
210 _ip.magic('%reset -f in')
211 _ip.magic('%reset -f in')
211 nt.assert_false('parrot' in [_ip.user_ns[x] for x in '_i','_ii','_iii'])
212 nt.assert_false('parrot' in [_ip.user_ns[x] for x in '_i','_ii','_iii'])
212 nt.assert_true(len(set(_ip.user_ns['In'])) == 1)
213 nt.assert_true(len(set(_ip.user_ns['In'])) == 1)
213
214
214 # test '%reset -f dhist'
215 def test_reset_dhist():
216 "Test '%reset dhist' magic"
215 _ip.run_cell("tmp = [d for d in _dh]") # copy before clearing
217 _ip.run_cell("tmp = [d for d in _dh]") # copy before clearing
216 _ip.magic('cd')
218 _ip.magic('cd ' + os.path.dirname(nt.__file__))
217 _ip.magic('cd -')
219 _ip.magic('cd -')
218 nt.assert_true(len(_ip.user_ns['_dh']) > 0)
220 nt.assert_true(len(_ip.user_ns['_dh']) > 0)
219 _ip.magic('reset -f dhist')
221 _ip.magic('reset -f dhist')
220 nt.assert_true(len(_ip.user_ns['_dh']) == 0)
222 nt.assert_true(len(_ip.user_ns['_dh']) == 0)
221 _ip.run_cell("_dh = [d for d in tmp]") #restore
223 _ip.run_cell("_dh = [d for d in tmp]") #restore
222
224
223 # test that In length is preserved for %macro
225 def test_reset_in_length():
226 "Test that '%reset in' preserves In[] length"
224 _ip.run_cell("print 'foo'")
227 _ip.run_cell("print 'foo'")
225 _ip.run_cell("reset -f in")
228 _ip.run_cell("reset -f in")
226 nt.assert_true(len(_ip.user_ns['In']) == _ip.displayhook.prompt_count+1)
229 nt.assert_true(len(_ip.user_ns['In']) == _ip.displayhook.prompt_count+1)
227
230
228 def test_time():
231 def test_time():
229 _ip.magic('time None')
232 _ip.magic('time None')
230
233
231
234
232 @py3compat.doctest_refactor_print
235 @py3compat.doctest_refactor_print
233 def doctest_time():
236 def doctest_time():
234 """
237 """
235 In [10]: %time None
238 In [10]: %time None
236 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
239 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
237 Wall time: 0.00 s
240 Wall time: 0.00 s
238
241
239 In [11]: def f(kmjy):
242 In [11]: def f(kmjy):
240 ....: %time print 2*kmjy
243 ....: %time print 2*kmjy
241
244
242 In [12]: f(3)
245 In [12]: f(3)
243 6
246 6
244 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
247 CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
245 Wall time: 0.00 s
248 Wall time: 0.00 s
246 """
249 """
247
250
248
251
249 def test_doctest_mode():
252 def test_doctest_mode():
250 "Toggle doctest_mode twice, it should be a no-op and run without error"
253 "Toggle doctest_mode twice, it should be a no-op and run without error"
251 _ip.magic('doctest_mode')
254 _ip.magic('doctest_mode')
252 _ip.magic('doctest_mode')
255 _ip.magic('doctest_mode')
253
256
254
257
255 def test_parse_options():
258 def test_parse_options():
256 """Tests for basic options parsing in magics."""
259 """Tests for basic options parsing in magics."""
257 # These are only the most minimal of tests, more should be added later. At
260 # These are only the most minimal of tests, more should be added later. At
258 # the very least we check that basic text/unicode calls work OK.
261 # the very least we check that basic text/unicode calls work OK.
259 nt.assert_equal(_ip.parse_options('foo', '')[1], 'foo')
262 nt.assert_equal(_ip.parse_options('foo', '')[1], 'foo')
260 nt.assert_equal(_ip.parse_options(u'foo', '')[1], u'foo')
263 nt.assert_equal(_ip.parse_options(u'foo', '')[1], u'foo')
261
264
262
265
263 def test_dirops():
266 def test_dirops():
264 """Test various directory handling operations."""
267 """Test various directory handling operations."""
265 # curpath = lambda :os.path.splitdrive(os.getcwdu())[1].replace('\\','/')
268 # curpath = lambda :os.path.splitdrive(os.getcwdu())[1].replace('\\','/')
266 curpath = os.getcwdu
269 curpath = os.getcwdu
267 startdir = os.getcwdu()
270 startdir = os.getcwdu()
268 ipdir = os.path.realpath(_ip.ipython_dir)
271 ipdir = os.path.realpath(_ip.ipython_dir)
269 try:
272 try:
270 _ip.magic('cd "%s"' % ipdir)
273 _ip.magic('cd "%s"' % ipdir)
271 nt.assert_equal(curpath(), ipdir)
274 nt.assert_equal(curpath(), ipdir)
272 _ip.magic('cd -')
275 _ip.magic('cd -')
273 nt.assert_equal(curpath(), startdir)
276 nt.assert_equal(curpath(), startdir)
274 _ip.magic('pushd "%s"' % ipdir)
277 _ip.magic('pushd "%s"' % ipdir)
275 nt.assert_equal(curpath(), ipdir)
278 nt.assert_equal(curpath(), ipdir)
276 _ip.magic('popd')
279 _ip.magic('popd')
277 nt.assert_equal(curpath(), startdir)
280 nt.assert_equal(curpath(), startdir)
278 finally:
281 finally:
279 os.chdir(startdir)
282 os.chdir(startdir)
280
283
281
284
282 def test_xmode():
285 def test_xmode():
283 # Calling xmode three times should be a no-op
286 # Calling xmode three times should be a no-op
284 xmode = _ip.InteractiveTB.mode
287 xmode = _ip.InteractiveTB.mode
285 for i in range(3):
288 for i in range(3):
286 _ip.magic("xmode")
289 _ip.magic("xmode")
287 nt.assert_equal(_ip.InteractiveTB.mode, xmode)
290 nt.assert_equal(_ip.InteractiveTB.mode, xmode)
288
291
289 def test_reset_hard():
292 def test_reset_hard():
290 monitor = []
293 monitor = []
291 class A(object):
294 class A(object):
292 def __del__(self):
295 def __del__(self):
293 monitor.append(1)
296 monitor.append(1)
294 def __repr__(self):
297 def __repr__(self):
295 return "<A instance>"
298 return "<A instance>"
296
299
297 _ip.user_ns["a"] = A()
300 _ip.user_ns["a"] = A()
298 _ip.run_cell("a")
301 _ip.run_cell("a")
299
302
300 nt.assert_equal(monitor, [])
303 nt.assert_equal(monitor, [])
301 _ip.magic_reset("-f")
304 _ip.magic_reset("-f")
302 nt.assert_equal(monitor, [1])
305 nt.assert_equal(monitor, [1])
303
306
304 class TestXdel(tt.TempFileMixin):
307 class TestXdel(tt.TempFileMixin):
305 def test_xdel(self):
308 def test_xdel(self):
306 """Test that references from %run are cleared by xdel."""
309 """Test that references from %run are cleared by xdel."""
307 src = ("class A(object):\n"
310 src = ("class A(object):\n"
308 " monitor = []\n"
311 " monitor = []\n"
309 " def __del__(self):\n"
312 " def __del__(self):\n"
310 " self.monitor.append(1)\n"
313 " self.monitor.append(1)\n"
311 "a = A()\n")
314 "a = A()\n")
312 self.mktmp(src)
315 self.mktmp(src)
313 # %run creates some hidden references...
316 # %run creates some hidden references...
314 _ip.magic("run %s" % self.fname)
317 _ip.magic("run %s" % self.fname)
315 # ... as does the displayhook.
318 # ... as does the displayhook.
316 _ip.run_cell("a")
319 _ip.run_cell("a")
317
320
318 monitor = _ip.user_ns["A"].monitor
321 monitor = _ip.user_ns["A"].monitor
319 nt.assert_equal(monitor, [])
322 nt.assert_equal(monitor, [])
320
323
321 _ip.magic("xdel a")
324 _ip.magic("xdel a")
322
325
323 # Check that a's __del__ method has been called.
326 # Check that a's __del__ method has been called.
324 nt.assert_equal(monitor, [1])
327 nt.assert_equal(monitor, [1])
325
328
326 def doctest_who():
329 def doctest_who():
327 """doctest for %who
330 """doctest for %who
328
331
329 In [1]: %reset -f
332 In [1]: %reset -f
330
333
331 In [2]: alpha = 123
334 In [2]: alpha = 123
332
335
333 In [3]: beta = 'beta'
336 In [3]: beta = 'beta'
334
337
335 In [4]: %who int
338 In [4]: %who int
336 alpha
339 alpha
337
340
338 In [5]: %who str
341 In [5]: %who str
339 beta
342 beta
340
343
341 In [6]: %whos
344 In [6]: %whos
342 Variable Type Data/Info
345 Variable Type Data/Info
343 ----------------------------
346 ----------------------------
344 alpha int 123
347 alpha int 123
345 beta str beta
348 beta str beta
346
349
347 In [7]: %who_ls
350 In [7]: %who_ls
348 Out[7]: ['alpha', 'beta']
351 Out[7]: ['alpha', 'beta']
349 """
352 """
350
353
351 @py3compat.u_format
354 @py3compat.u_format
352 def doctest_precision():
355 def doctest_precision():
353 """doctest for %precision
356 """doctest for %precision
354
357
355 In [1]: f = get_ipython().shell.display_formatter.formatters['text/plain']
358 In [1]: f = get_ipython().shell.display_formatter.formatters['text/plain']
356
359
357 In [2]: %precision 5
360 In [2]: %precision 5
358 Out[2]: {u}'%.5f'
361 Out[2]: {u}'%.5f'
359
362
360 In [3]: f.float_format
363 In [3]: f.float_format
361 Out[3]: {u}'%.5f'
364 Out[3]: {u}'%.5f'
362
365
363 In [4]: %precision %e
366 In [4]: %precision %e
364 Out[4]: {u}'%e'
367 Out[4]: {u}'%e'
365
368
366 In [5]: f(3.1415927)
369 In [5]: f(3.1415927)
367 Out[5]: {u}'3.141593e+00'
370 Out[5]: {u}'3.141593e+00'
368 """
371 """
369
372
370 def test_psearch():
373 def test_psearch():
371 with tt.AssertPrints("dict.fromkeys"):
374 with tt.AssertPrints("dict.fromkeys"):
372 _ip.run_cell("dict.fr*?")
375 _ip.run_cell("dict.fr*?")
373
376
374 def test_timeit_shlex():
377 def test_timeit_shlex():
375 """test shlex issues with timeit (#1109)"""
378 """test shlex issues with timeit (#1109)"""
376 _ip.ex("def f(*a,**kw): pass")
379 _ip.ex("def f(*a,**kw): pass")
377 _ip.magic('timeit -n1 "this is a bug".count(" ")')
380 _ip.magic('timeit -n1 "this is a bug".count(" ")')
378 _ip.magic('timeit -r1 -n1 f(" ", 1)')
381 _ip.magic('timeit -r1 -n1 f(" ", 1)')
379 _ip.magic('timeit -r1 -n1 f(" ", 1, " ", 2, " ")')
382 _ip.magic('timeit -r1 -n1 f(" ", 1, " ", 2, " ")')
380 _ip.magic('timeit -r1 -n1 ("a " + "b")')
383 _ip.magic('timeit -r1 -n1 ("a " + "b")')
381 _ip.magic('timeit -r1 -n1 f("a " + "b")')
384 _ip.magic('timeit -r1 -n1 f("a " + "b")')
382 _ip.magic('timeit -r1 -n1 f("a " + "b ")')
385 _ip.magic('timeit -r1 -n1 f("a " + "b ")')
383
386
384
387
385 def test_timeit_arguments():
388 def test_timeit_arguments():
386 "Test valid timeit arguments, should not cause SyntaxError (GH #1269)"
389 "Test valid timeit arguments, should not cause SyntaxError (GH #1269)"
387 _ip.magic("timeit ('#')")
390 _ip.magic("timeit ('#')")
General Comments 0
You need to be logged in to leave comments. Login now