##// END OF EJS Templates
Added mean + stdv to the %timeit magic - New tests pending - Corrected old ones
Pablo Galindo -
Show More
@@ -15,6 +15,7 b' import os'
15 import sys
15 import sys
16 import time
16 import time
17 import timeit
17 import timeit
18 import math
18 from pdb import Restart
19 from pdb import Restart
19
20
20 # cProfile was added in Python2.5
21 # cProfile was added in Python2.5
@@ -71,23 +72,27 b' class TimeitResult(object):'
71
72
72 """
73 """
73
74
74 def __init__(self, loops, repeat, best, worst, all_runs, compile_time, precision):
75 def __init__(self, loops, repeat, average, stdev, all_runs, compile_time, precision):
75 self.loops = loops
76 self.loops = loops
76 self.repeat = repeat
77 self.repeat = repeat
77 self.best = best
78 self.average = average
78 self.worst = worst
79 self.stdev = stdev
79 self.all_runs = all_runs
80 self.all_runs = all_runs
80 self.compile_time = compile_time
81 self.compile_time = compile_time
81 self._precision = precision
82 self._precision = precision
82
83
83 def _repr_pretty_(self, p , cycle):
84 def _repr_pretty_(self, p , cycle):
84 if self.loops == 1: # No s at "loops" if only one loop
85 if self.loops == 1: # No s at "loops" if only one loop
85 unic = u"%d loop, best of %d: %s per loop" % (self.loops, self.repeat,
86 unic = (u"%s loop, average of %d: %s +- %s per loop (using standard deviation)"
86 _format_time(self.best, self._precision))
87 % (self.loops, self.repeat,
87 else:
88 _format_time(self.average, self._precision),
88 unic = u"%d loops, best of %d: %s per loop" % (self.loops, self.repeat,
89 _format_time(self.stdev, self._precision)))
89 _format_time(self.best, self._precision))
90 else:
90 p.text(u'<TimeitResult : '+unic+u'>')
91 unic = (u"%s loops, average of %d: %s +- %s per loop (using standard deviation)"
92 % (self.loops, self.repeat,
93 _format_time(self.average, self._precision),
94 _format_time(self.stdev, self._precision)))
95 p.text(u'<TimeitResult : '+unic+u'>')
91
96
92
97
93 class TimeitTemplateFiller(ast.NodeTransformer):
98 class TimeitTemplateFiller(ast.NodeTransformer):
@@ -117,7 +122,7 b' class TimeitTemplateFiller(ast.NodeTransformer):'
117
122
118 class Timer(timeit.Timer):
123 class Timer(timeit.Timer):
119 """Timer class that explicitly uses self.inner
124 """Timer class that explicitly uses self.inner
120
125
121 which is an undocumented implementation detail of CPython,
126 which is an undocumented implementation detail of CPython,
122 not shared by PyPy.
127 not shared by PyPy.
123 """
128 """
@@ -457,7 +462,7 b' python-profiler package from non-free.""")'
457 """Run the named file inside IPython as a program.
462 """Run the named file inside IPython as a program.
458
463
459 Usage::
464 Usage::
460
465
461 %run [-n -i -e -G]
466 %run [-n -i -e -G]
462 [( -t [-N<N>] | -d [-b<N>] | -p [profile options] )]
467 [( -t [-N<N>] | -d [-b<N>] | -p [profile options] )]
463 ( -m mod | file ) [args]
468 ( -m mod | file ) [args]
@@ -652,7 +657,7 b' python-profiler package from non-free.""")'
652 __name__save = self.shell.user_ns['__name__']
657 __name__save = self.shell.user_ns['__name__']
653 prog_ns['__name__'] = '__main__'
658 prog_ns['__name__'] = '__main__'
654 main_mod = self.shell.user_module
659 main_mod = self.shell.user_module
655
660
656 # Since '%run foo' emulates 'python foo.py' at the cmd line, we must
661 # Since '%run foo' emulates 'python foo.py' at the cmd line, we must
657 # set the __file__ global in the script's namespace
662 # set the __file__ global in the script's namespace
658 # TK: Is this necessary in interactive mode?
663 # TK: Is this necessary in interactive mode?
@@ -852,7 +857,7 b' python-profiler package from non-free.""")'
852 continue
857 continue
853 else:
858 else:
854 break
859 break
855
860
856
861
857 except:
862 except:
858 etype, value, tb = sys.exc_info()
863 etype, value, tb = sys.exc_info()
@@ -950,20 +955,20 b' python-profiler package from non-free.""")'
950 ::
955 ::
951
956
952 In [1]: %timeit pass
957 In [1]: %timeit pass
953 10000000 loops, best of 3: 53.3 ns per loop
958 100000000 loops, average of 7: 5.48 ns +- 0.354 ns per loop (using standard deviation)
954
959
955 In [2]: u = None
960 In [2]: u = None
956
961
957 In [3]: %timeit u is None
962 In [3]: %timeit u is None
958 10000000 loops, best of 3: 184 ns per loop
963 10000000 loops, average of 7: 22.7 ns +- 2.33 ns per loop (using standard deviation)
959
964
960 In [4]: %timeit -r 4 u == None
965 In [4]: %timeit -r 4 u == None
961 1000000 loops, best of 4: 242 ns per loop
966 10000000 loops, average of 4: 27.5 ns +- 2.91 ns per loop (using standard deviation)
962
967
963 In [5]: import time
968 In [5]: import time
964
969
965 In [6]: %timeit -n1 time.sleep(2)
970 In [6]: %timeit -n1 time.sleep(2)
966 1 loop, best of 3: 2 s per loop
971 1 loop, average of 7: 2 s +- 4.71 Β΅s per loop (using standard deviation)
967
972
968
973
969 The times reported by %timeit will be slightly higher than those
974 The times reported by %timeit will be slightly higher than those
@@ -978,10 +983,11 b' python-profiler package from non-free.""")'
978 posix=False, strict=False)
983 posix=False, strict=False)
979 if stmt == "" and cell is None:
984 if stmt == "" and cell is None:
980 return
985 return
981
986
982 timefunc = timeit.default_timer
987 timefunc = timeit.default_timer
983 number = int(getattr(opts, "n", 0))
988 number = int(getattr(opts, "n", 0))
984 repeat = int(getattr(opts, "r", timeit.default_repeat))
989 default_repeat = 7 if timeit.default_repeat < 7 else timeit.default_repeat
990 repeat = int(getattr(opts, "r", default_repeat))
985 precision = int(getattr(opts, "p", 3))
991 precision = int(getattr(opts, "p", 3))
986 quiet = 'q' in opts
992 quiet = 'q' in opts
987 return_result = 'o' in opts
993 return_result = 'o' in opts
@@ -1036,22 +1042,26 b' python-profiler package from non-free.""")'
1036 # This is used to check if there is a huge difference between the
1042 # This is used to check if there is a huge difference between the
1037 # best and worst timings.
1043 # best and worst timings.
1038 # Issue: https://github.com/ipython/ipython/issues/6471
1044 # Issue: https://github.com/ipython/ipython/issues/6471
1039 worst_tuning = 0
1040 if number == 0:
1045 if number == 0:
1041 # determine number so that 0.2 <= total time < 2.0
1046 # determine number so that 0.2 <= total time < 2.0
1042 number = 1
1047 for index in range(0, 10):
1043 for _ in range(1, 10):
1048 number = 10 ** index
1044 time_number = timer.timeit(number)
1049 time_number = timer.timeit(number)
1045 worst_tuning = max(worst_tuning, time_number / number)
1046 if time_number >= 0.2:
1050 if time_number >= 0.2:
1047 break
1051 break
1048 number *= 10
1052
1049 all_runs = timer.repeat(repeat, number)
1053 all_runs = timer.repeat(repeat, number)
1050 best = min(all_runs) / number
1054 timings = [ dt / number for dt in all_runs]
1055
1056 def _avg(numbers):
1057 return math.fsum(numbers) / len(numbers)
1058
1059 def _stdev(numbers):
1060 mean = _avg(numbers)
1061 return (math.fsum([(x - mean) ** 2 for x in numbers]) / len(numbers)) ** 0.5
1051
1062
1052 worst = max(all_runs) / number
1063 average = _avg(timings)
1053 if worst_tuning:
1064 stdev = _stdev(timings)
1054 worst = max(worst, worst_tuning)
1055
1065
1056 if not quiet :
1066 if not quiet :
1057 # Check best timing is greater than zero to avoid a
1067 # Check best timing is greater than zero to avoid a
@@ -1059,20 +1069,20 b' python-profiler package from non-free.""")'
1059 # In cases where the slowest timing is lesser than a micosecond
1069 # In cases where the slowest timing is lesser than a micosecond
1060 # we assume that it does not really matter if the fastest
1070 # we assume that it does not really matter if the fastest
1061 # timing is 4 times faster than the slowest timing or not.
1071 # timing is 4 times faster than the slowest timing or not.
1062 if worst > 4 * best and best > 0 and worst > 1e-6:
1063 print("The slowest run took %0.2f times longer than the "
1064 "fastest. This could mean that an intermediate result "
1065 "is being cached." % (worst / best))
1066 if number == 1: # No s at "loops" if only one loop
1072 if number == 1: # No s at "loops" if only one loop
1067 print(u"%d loop, best of %d: %s per loop" % (number, repeat,
1073 print(u"%s loop, average of %d: %s +- %s per loop (using standard deviation)"
1068 _format_time(best, precision)))
1074 % (number, repeat,
1075 _format_time(average, precision),
1076 _format_time(stdev, precision)))
1069 else:
1077 else:
1070 print(u"%d loops, best of %d: %s per loop" % (number, repeat,
1078 print(u"%s loops, average of %d: %s +- %s per loop (using standard deviation)"
1071 _format_time(best, precision)))
1079 % (number, repeat,
1080 _format_time(average, precision),
1081 _format_time(stdev, precision)))
1072 if tc > tc_min:
1082 if tc > tc_min:
1073 print("Compiler time: %.2f s" % tc)
1083 print("Compiler time: %.2f s" % tc)
1074 if return_result:
1084 if return_result:
1075 return TimeitResult(number, repeat, best, worst, all_runs, tc, precision)
1085 return TimeitResult(number, repeat, average, stdev, all_runs, tc, precision)
1076
1086
1077 @skip_doctest
1087 @skip_doctest
1078 @needs_local_scope
1088 @needs_local_scope
@@ -1083,16 +1093,16 b' python-profiler package from non-free.""")'
1083 The CPU and wall clock times are printed, and the value of the
1093 The CPU and wall clock times are printed, and the value of the
1084 expression (if any) is returned. Note that under Win32, system time
1094 expression (if any) is returned. Note that under Win32, system time
1085 is always reported as 0, since it can not be measured.
1095 is always reported as 0, since it can not be measured.
1086
1096
1087 This function can be used both as a line and cell magic:
1097 This function can be used both as a line and cell magic:
1088
1098
1089 - In line mode you can time a single-line statement (though multiple
1099 - In line mode you can time a single-line statement (though multiple
1090 ones can be chained with using semicolons).
1100 ones can be chained with using semicolons).
1091
1101
1092 - In cell mode, you can time the cell body (a directly
1102 - In cell mode, you can time the cell body (a directly
1093 following statement raises an error).
1103 following statement raises an error).
1094
1104
1095 This function provides very basic timing functionality. Use the timeit
1105 This function provides very basic timing functionality. Use the timeit
1096 magic for more control over the measurement.
1106 magic for more control over the measurement.
1097
1107
1098 Examples
1108 Examples
@@ -1133,10 +1143,10 b' python-profiler package from non-free.""")'
1133 """
1143 """
1134
1144
1135 # fail immediately if the given expression can't be compiled
1145 # fail immediately if the given expression can't be compiled
1136
1146
1137 if line and cell:
1147 if line and cell:
1138 raise UsageError("Can't use statement directly after '%%time'!")
1148 raise UsageError("Can't use statement directly after '%%time'!")
1139
1149
1140 if cell:
1150 if cell:
1141 expr = self.shell.input_transformer_manager.transform_cell(cell)
1151 expr = self.shell.input_transformer_manager.transform_cell(cell)
1142 else:
1152 else:
@@ -1186,7 +1196,7 b' python-profiler package from non-free.""")'
1186 cpu_user = end[0]-st[0]
1196 cpu_user = end[0]-st[0]
1187 cpu_sys = end[1]-st[1]
1197 cpu_sys = end[1]-st[1]
1188 cpu_tot = cpu_user+cpu_sys
1198 cpu_tot = cpu_user+cpu_sys
1189 # On windows cpu_sys is always zero, so no new information to the next print
1199 # On windows cpu_sys is always zero, so no new information to the next print
1190 if sys.platform != 'win32':
1200 if sys.platform != 'win32':
1191 print("CPU times: user %s, sys: %s, total: %s" % \
1201 print("CPU times: user %s, sys: %s, total: %s" % \
1192 (_format_time(cpu_user),_format_time(cpu_sys),_format_time(cpu_tot)))
1202 (_format_time(cpu_user),_format_time(cpu_sys),_format_time(cpu_tot)))
@@ -1212,9 +1222,9 b' python-profiler package from non-free.""")'
1212 so that magics are loaded in their transformed version to valid
1222 so that magics are loaded in their transformed version to valid
1213 Python. If this option is given, the raw input as typed at the
1223 Python. If this option is given, the raw input as typed at the
1214 command line is used instead.
1224 command line is used instead.
1215
1225
1216 -q: quiet macro definition. By default, a tag line is printed
1226 -q: quiet macro definition. By default, a tag line is printed
1217 to indicate the macro has been created, and then the contents of
1227 to indicate the macro has been created, and then the contents of
1218 the macro are printed. If this option is given, then no printout
1228 the macro are printed. If this option is given, then no printout
1219 is produced once the macro is created.
1229 is produced once the macro is created.
1220
1230
@@ -1277,7 +1287,7 b' python-profiler package from non-free.""")'
1277 return
1287 return
1278 macro = Macro(lines)
1288 macro = Macro(lines)
1279 self.shell.define_macro(name, macro)
1289 self.shell.define_macro(name, macro)
1280 if not ( 'q' in opts) :
1290 if not ( 'q' in opts) :
1281 print('Macro `%s` created. To execute, type its name (without quotes).' % name)
1291 print('Macro `%s` created. To execute, type its name (without quotes).' % name)
1282 print('=== Macro contents: ===')
1292 print('=== Macro contents: ===')
1283 print(macro, end=' ')
1293 print(macro, end=' ')
@@ -1323,11 +1333,11 b' def parse_breakpoint(text, current_file):'
1323 return current_file, int(text)
1333 return current_file, int(text)
1324 else:
1334 else:
1325 return text[:colon], int(text[colon+1:])
1335 return text[:colon], int(text[colon+1:])
1326
1336
1327 def _format_time(timespan, precision=3):
1337 def _format_time(timespan, precision=3):
1328 """Formats the timespan in a human readable form"""
1338 """Formats the timespan in a human readable form"""
1329 import math
1339 import math
1330
1340
1331 if timespan >= 60.0:
1341 if timespan >= 60.0:
1332 # we have more than a minute, format that in a human readable form
1342 # we have more than a minute, format that in a human readable form
1333 # Idea from http://snipplr.com/view/5713/
1343 # Idea from http://snipplr.com/view/5713/
@@ -1343,13 +1353,13 b' def _format_time(timespan, precision=3):'
1343 break
1353 break
1344 return " ".join(time)
1354 return " ".join(time)
1345
1355
1346
1356
1347 # Unfortunately the unicode 'micro' symbol can cause problems in
1357 # Unfortunately the unicode 'micro' symbol can cause problems in
1348 # certain terminals.
1358 # certain terminals.
1349 # See bug: https://bugs.launchpad.net/ipython/+bug/348466
1359 # See bug: https://bugs.launchpad.net/ipython/+bug/348466
1350 # Try to prevent crashes by being more secure than it needs to
1360 # Try to prevent crashes by being more secure than it needs to
1351 # E.g. eclipse is able to print a Β΅, but has no sys.stdout.encoding set.
1361 # E.g. eclipse is able to print a Β΅, but has no sys.stdout.encoding set.
1352 units = [u"s", u"ms",u'us',"ns"] # the save value
1362 units = [u"s", u"ms",u'us',"ns"] # the save value
1353 if hasattr(sys.stdout, 'encoding') and sys.stdout.encoding:
1363 if hasattr(sys.stdout, 'encoding') and sys.stdout.encoding:
1354 try:
1364 try:
1355 u'\xb5'.encode(sys.stdout.encoding)
1365 u'\xb5'.encode(sys.stdout.encoding)
@@ -1357,7 +1367,7 b' def _format_time(timespan, precision=3):'
1357 except:
1367 except:
1358 pass
1368 pass
1359 scaling = [1, 1e3, 1e6, 1e9]
1369 scaling = [1, 1e3, 1e6, 1e9]
1360
1370
1361 if timespan > 0.0:
1371 if timespan > 0.0:
1362 order = min(-int(math.floor(math.log10(timespan)) // 3), 3)
1372 order = min(-int(math.floor(math.log10(timespan)) // 3), 3)
1363 else:
1373 else:
@@ -120,16 +120,16 b' class InteractiveShellTestCase(unittest.TestCase):'
120 newlen = len(ip.user_ns['In'])
120 newlen = len(ip.user_ns['In'])
121 self.assertEqual(oldlen+1, newlen)
121 self.assertEqual(oldlen+1, newlen)
122 self.assertEqual(ip.user_ns['In'][-1],'1;')
122 self.assertEqual(ip.user_ns['In'][-1],'1;')
123
123
124 def test_magic_names_in_string(self):
124 def test_magic_names_in_string(self):
125 ip.run_cell('a = """\n%exit\n"""')
125 ip.run_cell('a = """\n%exit\n"""')
126 self.assertEqual(ip.user_ns['a'], '\n%exit\n')
126 self.assertEqual(ip.user_ns['a'], '\n%exit\n')
127
127
128 def test_trailing_newline(self):
128 def test_trailing_newline(self):
129 """test that running !(command) does not raise a SyntaxError"""
129 """test that running !(command) does not raise a SyntaxError"""
130 ip.run_cell('!(true)\n', False)
130 ip.run_cell('!(true)\n', False)
131 ip.run_cell('!(true)\n\n\n', False)
131 ip.run_cell('!(true)\n\n\n', False)
132
132
133 def test_gh_597(self):
133 def test_gh_597(self):
134 """Pretty-printing lists of objects with non-ascii reprs may cause
134 """Pretty-printing lists of objects with non-ascii reprs may cause
135 problems."""
135 problems."""
@@ -139,7 +139,7 b' class InteractiveShellTestCase(unittest.TestCase):'
139 import IPython.core.formatters
139 import IPython.core.formatters
140 f = IPython.core.formatters.PlainTextFormatter()
140 f = IPython.core.formatters.PlainTextFormatter()
141 f([Spam(),Spam()])
141 f([Spam(),Spam()])
142
142
143
143
144 def test_future_flags(self):
144 def test_future_flags(self):
145 """Check that future flags are used for parsing code (gh-777)"""
145 """Check that future flags are used for parsing code (gh-777)"""
@@ -162,7 +162,7 b' class InteractiveShellTestCase(unittest.TestCase):'
162 finally:
162 finally:
163 # Reset compiler flags so we don't mess up other tests.
163 # Reset compiler flags so we don't mess up other tests.
164 ip.compile.reset_compiler_flags()
164 ip.compile.reset_compiler_flags()
165
165
166 def test_can_pickle(self):
166 def test_can_pickle(self):
167 "Can we pickle objects defined interactively (GH-29)"
167 "Can we pickle objects defined interactively (GH-29)"
168 ip = get_ipython()
168 ip = get_ipython()
@@ -171,9 +171,9 b' class InteractiveShellTestCase(unittest.TestCase):'
171 " def __init__(self,x=[]):\n"
171 " def __init__(self,x=[]):\n"
172 " list.__init__(self,x)"))
172 " list.__init__(self,x)"))
173 ip.run_cell("w=Mylist([1,2,3])")
173 ip.run_cell("w=Mylist([1,2,3])")
174
174
175 from pickle import dumps
175 from pickle import dumps
176
176
177 # We need to swap in our main module - this is only necessary
177 # We need to swap in our main module - this is only necessary
178 # inside the test framework, because IPython puts the interactive module
178 # inside the test framework, because IPython puts the interactive module
179 # in place (but the test framework undoes this).
179 # in place (but the test framework undoes this).
@@ -184,7 +184,7 b' class InteractiveShellTestCase(unittest.TestCase):'
184 finally:
184 finally:
185 sys.modules['__main__'] = _main
185 sys.modules['__main__'] = _main
186 self.assertTrue(isinstance(res, bytes))
186 self.assertTrue(isinstance(res, bytes))
187
187
188 def test_global_ns(self):
188 def test_global_ns(self):
189 "Code in functions must be able to access variables outside them."
189 "Code in functions must be able to access variables outside them."
190 ip = get_ipython()
190 ip = get_ipython()
@@ -234,7 +234,7 b' class InteractiveShellTestCase(unittest.TestCase):'
234 ip.user_ns['f'] = b'Ca\xc3\xb1o'
234 ip.user_ns['f'] = b'Ca\xc3\xb1o'
235 # This should not raise any exception:
235 # This should not raise any exception:
236 ip.var_expand(u'echo $f')
236 ip.var_expand(u'echo $f')
237
237
238 def test_var_expand_local(self):
238 def test_var_expand_local(self):
239 """Test local variable expansion in !system and %magic calls"""
239 """Test local variable expansion in !system and %magic calls"""
240 # !system
240 # !system
@@ -244,7 +244,7 b' class InteractiveShellTestCase(unittest.TestCase):'
244 ' return ret[0]\n')
244 ' return ret[0]\n')
245 res = ip.user_ns['test']()
245 res = ip.user_ns['test']()
246 nt.assert_in('ttt', res)
246 nt.assert_in('ttt', res)
247
247
248 # %magic
248 # %magic
249 ip.run_cell('def makemacro():\n'
249 ip.run_cell('def makemacro():\n'
250 ' macroname = "macro_var_expand_locals"\n'
250 ' macroname = "macro_var_expand_locals"\n'
@@ -252,10 +252,10 b' class InteractiveShellTestCase(unittest.TestCase):'
252 ip.user_ns['codestr'] = "str(12)"
252 ip.user_ns['codestr'] = "str(12)"
253 ip.run_cell('makemacro()')
253 ip.run_cell('makemacro()')
254 nt.assert_in('macro_var_expand_locals', ip.user_ns)
254 nt.assert_in('macro_var_expand_locals', ip.user_ns)
255
255
256 def test_var_expand_self(self):
256 def test_var_expand_self(self):
257 """Test variable expansion with the name 'self', which was failing.
257 """Test variable expansion with the name 'self', which was failing.
258
258
259 See https://github.com/ipython/ipython/issues/1878#issuecomment-7698218
259 See https://github.com/ipython/ipython/issues/1878#issuecomment-7698218
260 """
260 """
261 ip.run_cell('class cTest:\n'
261 ip.run_cell('class cTest:\n'
@@ -264,7 +264,7 b' class InteractiveShellTestCase(unittest.TestCase):'
264 ' res = !echo Variable: {self.classvar}\n'
264 ' res = !echo Variable: {self.classvar}\n'
265 ' return res[0]\n')
265 ' return res[0]\n')
266 nt.assert_in('see me', ip.user_ns['cTest']().test())
266 nt.assert_in('see me', ip.user_ns['cTest']().test())
267
267
268 def test_bad_var_expand(self):
268 def test_bad_var_expand(self):
269 """var_expand on invalid formats shouldn't raise"""
269 """var_expand on invalid formats shouldn't raise"""
270 # SyntaxError
270 # SyntaxError
@@ -273,19 +273,19 b' class InteractiveShellTestCase(unittest.TestCase):'
273 self.assertEqual(ip.var_expand(u"{asdf}"), u"{asdf}")
273 self.assertEqual(ip.var_expand(u"{asdf}"), u"{asdf}")
274 # ZeroDivisionError
274 # ZeroDivisionError
275 self.assertEqual(ip.var_expand(u"{1/0}"), u"{1/0}")
275 self.assertEqual(ip.var_expand(u"{1/0}"), u"{1/0}")
276
276
277 def test_silent_postexec(self):
277 def test_silent_postexec(self):
278 """run_cell(silent=True) doesn't invoke pre/post_run_cell callbacks"""
278 """run_cell(silent=True) doesn't invoke pre/post_run_cell callbacks"""
279 pre_explicit = mock.Mock()
279 pre_explicit = mock.Mock()
280 pre_always = mock.Mock()
280 pre_always = mock.Mock()
281 post_explicit = mock.Mock()
281 post_explicit = mock.Mock()
282 post_always = mock.Mock()
282 post_always = mock.Mock()
283
283
284 ip.events.register('pre_run_cell', pre_explicit)
284 ip.events.register('pre_run_cell', pre_explicit)
285 ip.events.register('pre_execute', pre_always)
285 ip.events.register('pre_execute', pre_always)
286 ip.events.register('post_run_cell', post_explicit)
286 ip.events.register('post_run_cell', post_explicit)
287 ip.events.register('post_execute', post_always)
287 ip.events.register('post_execute', post_always)
288
288
289 try:
289 try:
290 ip.run_cell("1", silent=True)
290 ip.run_cell("1", silent=True)
291 assert pre_always.called
291 assert pre_always.called
@@ -303,29 +303,29 b' class InteractiveShellTestCase(unittest.TestCase):'
303 ip.events.unregister('pre_execute', pre_always)
303 ip.events.unregister('pre_execute', pre_always)
304 ip.events.unregister('post_run_cell', post_explicit)
304 ip.events.unregister('post_run_cell', post_explicit)
305 ip.events.unregister('post_execute', post_always)
305 ip.events.unregister('post_execute', post_always)
306
306
307 def test_silent_noadvance(self):
307 def test_silent_noadvance(self):
308 """run_cell(silent=True) doesn't advance execution_count"""
308 """run_cell(silent=True) doesn't advance execution_count"""
309 ec = ip.execution_count
309 ec = ip.execution_count
310 # silent should force store_history=False
310 # silent should force store_history=False
311 ip.run_cell("1", store_history=True, silent=True)
311 ip.run_cell("1", store_history=True, silent=True)
312
312
313 self.assertEqual(ec, ip.execution_count)
313 self.assertEqual(ec, ip.execution_count)
314 # double-check that non-silent exec did what we expected
314 # double-check that non-silent exec did what we expected
315 # silent to avoid
315 # silent to avoid
316 ip.run_cell("1", store_history=True)
316 ip.run_cell("1", store_history=True)
317 self.assertEqual(ec+1, ip.execution_count)
317 self.assertEqual(ec+1, ip.execution_count)
318
318
319 def test_silent_nodisplayhook(self):
319 def test_silent_nodisplayhook(self):
320 """run_cell(silent=True) doesn't trigger displayhook"""
320 """run_cell(silent=True) doesn't trigger displayhook"""
321 d = dict(called=False)
321 d = dict(called=False)
322
322
323 trap = ip.display_trap
323 trap = ip.display_trap
324 save_hook = trap.hook
324 save_hook = trap.hook
325
325
326 def failing_hook(*args, **kwargs):
326 def failing_hook(*args, **kwargs):
327 d['called'] = True
327 d['called'] = True
328
328
329 try:
329 try:
330 trap.hook = failing_hook
330 trap.hook = failing_hook
331 res = ip.run_cell("1", silent=True)
331 res = ip.run_cell("1", silent=True)
@@ -350,10 +350,10 b' class InteractiveShellTestCase(unittest.TestCase):'
350 In [2]: print 1,; print 2
350 In [2]: print 1,; print 2
351 1 2
351 1 2
352 """
352 """
353
353
354 def test_ofind_line_magic(self):
354 def test_ofind_line_magic(self):
355 from IPython.core.magic import register_line_magic
355 from IPython.core.magic import register_line_magic
356
356
357 @register_line_magic
357 @register_line_magic
358 def lmagic(line):
358 def lmagic(line):
359 "A line magic"
359 "A line magic"
@@ -364,10 +364,10 b' class InteractiveShellTestCase(unittest.TestCase):'
364 namespace = 'IPython internal', obj= lmagic.__wrapped__,
364 namespace = 'IPython internal', obj= lmagic.__wrapped__,
365 parent = None)
365 parent = None)
366 nt.assert_equal(lfind, info)
366 nt.assert_equal(lfind, info)
367
367
368 def test_ofind_cell_magic(self):
368 def test_ofind_cell_magic(self):
369 from IPython.core.magic import register_cell_magic
369 from IPython.core.magic import register_cell_magic
370
370
371 @register_cell_magic
371 @register_cell_magic
372 def cmagic(line, cell):
372 def cmagic(line, cell):
373 "A cell magic"
373 "A cell magic"
@@ -454,7 +454,7 b' class InteractiveShellTestCase(unittest.TestCase):'
454 def my_handler(shell, etype, value, tb, tb_offset=None):
454 def my_handler(shell, etype, value, tb, tb_offset=None):
455 called.append(etype)
455 called.append(etype)
456 shell.showtraceback((etype, value, tb), tb_offset=tb_offset)
456 shell.showtraceback((etype, value, tb), tb_offset=tb_offset)
457
457
458 ip.set_custom_exc((ValueError,), my_handler)
458 ip.set_custom_exc((ValueError,), my_handler)
459 try:
459 try:
460 res = ip.run_cell("raise ValueError('test')")
460 res = ip.run_cell("raise ValueError('test')")
@@ -465,7 +465,7 b' class InteractiveShellTestCase(unittest.TestCase):'
465 finally:
465 finally:
466 # Reset the custom exception hook
466 # Reset the custom exception hook
467 ip.set_custom_exc((), None)
467 ip.set_custom_exc((), None)
468
468
469 @skipif(sys.version_info[0] >= 3, "no differences with __future__ in py3")
469 @skipif(sys.version_info[0] >= 3, "no differences with __future__ in py3")
470 def test_future_environment(self):
470 def test_future_environment(self):
471 "Can we run code with & without the shell's __future__ imports?"
471 "Can we run code with & without the shell's __future__ imports?"
@@ -474,7 +474,7 b' class InteractiveShellTestCase(unittest.TestCase):'
474 self.assertEqual(ip.user_ns['a'], 0.5)
474 self.assertEqual(ip.user_ns['a'], 0.5)
475 ip.run_cell("b = 1/2", shell_futures=False)
475 ip.run_cell("b = 1/2", shell_futures=False)
476 self.assertEqual(ip.user_ns['b'], 0)
476 self.assertEqual(ip.user_ns['b'], 0)
477
477
478 ip.compile.reset_compiler_flags()
478 ip.compile.reset_compiler_flags()
479 # This shouldn't leak to the shell's compiler
479 # This shouldn't leak to the shell's compiler
480 ip.run_cell("from __future__ import division \nc=1/2", shell_futures=False)
480 ip.run_cell("from __future__ import division \nc=1/2", shell_futures=False)
@@ -551,7 +551,7 b' class ExitCodeChecks(tt.TempFileMixin):'
551 def test_exit_code_error(self):
551 def test_exit_code_error(self):
552 self.system('exit 1')
552 self.system('exit 1')
553 self.assertEqual(ip.user_ns['_exit_code'], 1)
553 self.assertEqual(ip.user_ns['_exit_code'], 1)
554
554
555 @skipif(not hasattr(signal, 'SIGALRM'))
555 @skipif(not hasattr(signal, 'SIGALRM'))
556 def test_exit_code_signal(self):
556 def test_exit_code_signal(self):
557 self.mktmp("import signal, time\n"
557 self.mktmp("import signal, time\n"
@@ -559,7 +559,7 b' class ExitCodeChecks(tt.TempFileMixin):'
559 "time.sleep(1)\n")
559 "time.sleep(1)\n")
560 self.system("%s %s" % (sys.executable, self.fname))
560 self.system("%s %s" % (sys.executable, self.fname))
561 self.assertEqual(ip.user_ns['_exit_code'], -signal.SIGALRM)
561 self.assertEqual(ip.user_ns['_exit_code'], -signal.SIGALRM)
562
562
563 @onlyif_cmds_exist("csh")
563 @onlyif_cmds_exist("csh")
564 def test_exit_code_signal_csh(self):
564 def test_exit_code_signal_csh(self):
565 SHELL = os.environ.get('SHELL', None)
565 SHELL = os.environ.get('SHELL', None)
@@ -630,56 +630,56 b' class TestAstTransform(unittest.TestCase):'
630 def setUp(self):
630 def setUp(self):
631 self.negator = Negator()
631 self.negator = Negator()
632 ip.ast_transformers.append(self.negator)
632 ip.ast_transformers.append(self.negator)
633
633
634 def tearDown(self):
634 def tearDown(self):
635 ip.ast_transformers.remove(self.negator)
635 ip.ast_transformers.remove(self.negator)
636
636
637 def test_run_cell(self):
637 def test_run_cell(self):
638 with tt.AssertPrints('-34'):
638 with tt.AssertPrints('-34'):
639 ip.run_cell('print (12 + 22)')
639 ip.run_cell('print (12 + 22)')
640
640
641 # A named reference to a number shouldn't be transformed.
641 # A named reference to a number shouldn't be transformed.
642 ip.user_ns['n'] = 55
642 ip.user_ns['n'] = 55
643 with tt.AssertNotPrints('-55'):
643 with tt.AssertNotPrints('-55'):
644 ip.run_cell('print (n)')
644 ip.run_cell('print (n)')
645
645
646 def test_timeit(self):
646 def test_timeit(self):
647 called = set()
647 called = set()
648 def f(x):
648 def f(x):
649 called.add(x)
649 called.add(x)
650 ip.push({'f':f})
650 ip.push({'f':f})
651
651
652 with tt.AssertPrints("best of "):
652 with tt.AssertPrints("average of "):
653 ip.run_line_magic("timeit", "-n1 f(1)")
653 ip.run_line_magic("timeit", "-n1 f(1)")
654 self.assertEqual(called, {-1})
654 self.assertEqual(called, {-1})
655 called.clear()
655 called.clear()
656
656
657 with tt.AssertPrints("best of "):
657 with tt.AssertPrints("average of "):
658 ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)")
658 ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)")
659 self.assertEqual(called, {-2, -3})
659 self.assertEqual(called, {-2, -3})
660
660
661 def test_time(self):
661 def test_time(self):
662 called = []
662 called = []
663 def f(x):
663 def f(x):
664 called.append(x)
664 called.append(x)
665 ip.push({'f':f})
665 ip.push({'f':f})
666
666
667 # Test with an expression
667 # Test with an expression
668 with tt.AssertPrints("Wall time: "):
668 with tt.AssertPrints("Wall time: "):
669 ip.run_line_magic("time", "f(5+9)")
669 ip.run_line_magic("time", "f(5+9)")
670 self.assertEqual(called, [-14])
670 self.assertEqual(called, [-14])
671 called[:] = []
671 called[:] = []
672
672
673 # Test with a statement (different code path)
673 # Test with a statement (different code path)
674 with tt.AssertPrints("Wall time: "):
674 with tt.AssertPrints("Wall time: "):
675 ip.run_line_magic("time", "a = f(-3 + -2)")
675 ip.run_line_magic("time", "a = f(-3 + -2)")
676 self.assertEqual(called, [5])
676 self.assertEqual(called, [5])
677
677
678 def test_macro(self):
678 def test_macro(self):
679 ip.push({'a':10})
679 ip.push({'a':10})
680 # The AST transformation makes this do a+=-1
680 # The AST transformation makes this do a+=-1
681 ip.define_macro("amacro", "a+=1\nprint(a)")
681 ip.define_macro("amacro", "a+=1\nprint(a)")
682
682
683 with tt.AssertPrints("9"):
683 with tt.AssertPrints("9"):
684 ip.run_cell("amacro")
684 ip.run_cell("amacro")
685 with tt.AssertPrints("8"):
685 with tt.AssertPrints("8"):
@@ -697,37 +697,37 b' class TestAstTransform2(unittest.TestCase):'
697 def setUp(self):
697 def setUp(self):
698 self.intwrapper = IntegerWrapper()
698 self.intwrapper = IntegerWrapper()
699 ip.ast_transformers.append(self.intwrapper)
699 ip.ast_transformers.append(self.intwrapper)
700
700
701 self.calls = []
701 self.calls = []
702 def Integer(*args):
702 def Integer(*args):
703 self.calls.append(args)
703 self.calls.append(args)
704 return args
704 return args
705 ip.push({"Integer": Integer})
705 ip.push({"Integer": Integer})
706
706
707 def tearDown(self):
707 def tearDown(self):
708 ip.ast_transformers.remove(self.intwrapper)
708 ip.ast_transformers.remove(self.intwrapper)
709 del ip.user_ns['Integer']
709 del ip.user_ns['Integer']
710
710
711 def test_run_cell(self):
711 def test_run_cell(self):
712 ip.run_cell("n = 2")
712 ip.run_cell("n = 2")
713 self.assertEqual(self.calls, [(2,)])
713 self.assertEqual(self.calls, [(2,)])
714
714
715 # This shouldn't throw an error
715 # This shouldn't throw an error
716 ip.run_cell("o = 2.0")
716 ip.run_cell("o = 2.0")
717 self.assertEqual(ip.user_ns['o'], 2.0)
717 self.assertEqual(ip.user_ns['o'], 2.0)
718
718
719 def test_timeit(self):
719 def test_timeit(self):
720 called = set()
720 called = set()
721 def f(x):
721 def f(x):
722 called.add(x)
722 called.add(x)
723 ip.push({'f':f})
723 ip.push({'f':f})
724
724
725 with tt.AssertPrints("best of "):
725 with tt.AssertPrints("average of "):
726 ip.run_line_magic("timeit", "-n1 f(1)")
726 ip.run_line_magic("timeit", "-n1 f(1)")
727 self.assertEqual(called, {(1,)})
727 self.assertEqual(called, {(1,)})
728 called.clear()
728 called.clear()
729
729
730 with tt.AssertPrints("best of "):
730 with tt.AssertPrints("average of "):
731 ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)")
731 ip.run_cell_magic("timeit", "-n1 f(2)", "f(3)")
732 self.assertEqual(called, {(2,), (3,)})
732 self.assertEqual(called, {(2,), (3,)})
733
733
@@ -740,10 +740,10 b' class TestAstTransformError(unittest.TestCase):'
740 def test_unregistering(self):
740 def test_unregistering(self):
741 err_transformer = ErrorTransformer()
741 err_transformer = ErrorTransformer()
742 ip.ast_transformers.append(err_transformer)
742 ip.ast_transformers.append(err_transformer)
743
743
744 with tt.AssertPrints("unregister", channel='stderr'):
744 with tt.AssertPrints("unregister", channel='stderr'):
745 ip.run_cell("1 + 2")
745 ip.run_cell("1 + 2")
746
746
747 # This should have been removed.
747 # This should have been removed.
748 nt.assert_not_in(err_transformer, ip.ast_transformers)
748 nt.assert_not_in(err_transformer, ip.ast_transformers)
749
749
@@ -792,18 +792,18 b' def test__IPYTHON__():'
792 class DummyRepr(object):
792 class DummyRepr(object):
793 def __repr__(self):
793 def __repr__(self):
794 return "DummyRepr"
794 return "DummyRepr"
795
795
796 def _repr_html_(self):
796 def _repr_html_(self):
797 return "<b>dummy</b>"
797 return "<b>dummy</b>"
798
798
799 def _repr_javascript_(self):
799 def _repr_javascript_(self):
800 return "console.log('hi');", {'key': 'value'}
800 return "console.log('hi');", {'key': 'value'}
801
801
802
802
803 def test_user_variables():
803 def test_user_variables():
804 # enable all formatters
804 # enable all formatters
805 ip.display_formatter.active_types = ip.display_formatter.format_types
805 ip.display_formatter.active_types = ip.display_formatter.format_types
806
806
807 ip.user_ns['dummy'] = d = DummyRepr()
807 ip.user_ns['dummy'] = d = DummyRepr()
808 keys = {'dummy', 'doesnotexist'}
808 keys = {'dummy', 'doesnotexist'}
809 r = ip.user_expressions({ key:key for key in keys})
809 r = ip.user_expressions({ key:key for key in keys})
@@ -818,14 +818,14 b' def test_user_variables():'
818 js, jsmd = d._repr_javascript_()
818 js, jsmd = d._repr_javascript_()
819 nt.assert_equal(data.get('application/javascript'), js)
819 nt.assert_equal(data.get('application/javascript'), js)
820 nt.assert_equal(metadata.get('application/javascript'), jsmd)
820 nt.assert_equal(metadata.get('application/javascript'), jsmd)
821
821
822 dne = r['doesnotexist']
822 dne = r['doesnotexist']
823 nt.assert_equal(dne['status'], 'error')
823 nt.assert_equal(dne['status'], 'error')
824 nt.assert_equal(dne['ename'], 'NameError')
824 nt.assert_equal(dne['ename'], 'NameError')
825
825
826 # back to text only
826 # back to text only
827 ip.display_formatter.active_types = ['text/plain']
827 ip.display_formatter.active_types = ['text/plain']
828
828
829 def test_user_expression():
829 def test_user_expression():
830 # enable all formatters
830 # enable all formatters
831 ip.display_formatter.active_types = ip.display_formatter.format_types
831 ip.display_formatter.active_types = ip.display_formatter.format_types
@@ -843,14 +843,14 b' def test_user_expression():'
843 data = a['data']
843 data = a['data']
844 metadata = a['metadata']
844 metadata = a['metadata']
845 nt.assert_equal(data.get('text/plain'), '3')
845 nt.assert_equal(data.get('text/plain'), '3')
846
846
847 b = r['b']
847 b = r['b']
848 nt.assert_equal(b['status'], 'error')
848 nt.assert_equal(b['status'], 'error')
849 nt.assert_equal(b['ename'], 'ZeroDivisionError')
849 nt.assert_equal(b['ename'], 'ZeroDivisionError')
850
850
851 # back to text only
851 # back to text only
852 ip.display_formatter.active_types = ['text/plain']
852 ip.display_formatter.active_types = ['text/plain']
853
853
854
854
855
855
856
856
General Comments 0
You need to be logged in to leave comments. Login now