Show More
@@ -91,7 +91,13 b' class DisplayHook(Configurable):' | |||||
91 | # some uses of ipshellembed may fail here |
|
91 | # some uses of ipshellembed may fail here | |
92 | return False |
|
92 | return False | |
93 |
|
93 | |||
94 | sio = _io.StringIO(cell) |
|
94 | return self.semicolon_at_end_of_expression(cell) | |
|
95 | ||||
|
96 | @staticmethod | |||
|
97 | def semicolon_at_end_of_expression(expression): | |||
|
98 | """Parse Python expression and detects whether last token is ';'""" | |||
|
99 | ||||
|
100 | sio = _io.StringIO(expression) | |||
95 | tokens = list(tokenize.generate_tokens(sio.readline)) |
|
101 | tokens = list(tokenize.generate_tokens(sio.readline)) | |
96 |
|
102 | |||
97 | for token in reversed(tokens): |
|
103 | for token in reversed(tokens): |
@@ -2363,12 +2363,12 b' class InteractiveShell(SingletonConfigurable):' | |||||
2363 | with self.builtin_trap: |
|
2363 | with self.builtin_trap: | |
2364 | result = fn(*args, **kwargs) |
|
2364 | result = fn(*args, **kwargs) | |
2365 |
|
2365 | |||
2366 | # The code below prevents output from being displayed |
|
2366 | # The code below prevents the output from being displayed | |
2367 |
# when using magic |
|
2367 | # when using magics with decodator @output_can_be_disabled | |
2368 | # Output from '%time foo();', for instance, would never |
|
2368 | # when the last Python token in the expression is a ';'. | |
2369 | # be displayed. |
|
2369 | if getattr(fn, magic.MAGIC_OUTPUT_CAN_BE_DISABLED, False): | |
2370 | if magic_name == "time" and len(magic_arg_s) > 0 and magic_arg_s[-1] == ";": |
|
2370 | if DisplayHook.semicolon_at_end_of_expression(magic_arg_s): | |
2371 | return None |
|
2371 | return None | |
2372 |
|
2372 | |||
2373 | return result |
|
2373 | return result | |
2374 |
|
2374 |
@@ -258,7 +258,7 b' def _function_magic_marker(magic_kind):' | |||||
258 |
|
258 | |||
259 |
|
259 | |||
260 | MAGIC_NO_VAR_EXPAND_ATTR = '_ipython_magic_no_var_expand' |
|
260 | MAGIC_NO_VAR_EXPAND_ATTR = '_ipython_magic_no_var_expand' | |
261 |
|
261 | MAGIC_OUTPUT_CAN_BE_DISABLED = '_ipython_magic_output_can_be_disabled' | ||
262 |
|
262 | |||
263 | def no_var_expand(magic_func): |
|
263 | def no_var_expand(magic_func): | |
264 | """Mark a magic function as not needing variable expansion |
|
264 | """Mark a magic function as not needing variable expansion | |
@@ -275,6 +275,15 b' def no_var_expand(magic_func):' | |||||
275 | setattr(magic_func, MAGIC_NO_VAR_EXPAND_ATTR, True) |
|
275 | setattr(magic_func, MAGIC_NO_VAR_EXPAND_ATTR, True) | |
276 | return magic_func |
|
276 | return magic_func | |
277 |
|
277 | |||
|
278 | def output_can_be_disabled(magic_func): | |||
|
279 | """Mark a magic function so its output may be disabled. | |||
|
280 | ||||
|
281 | The output is disabled if the Python expression used as a parameter of | |||
|
282 | the magic ends in a semicolon, not counting a Python comment that can | |||
|
283 | follows it. | |||
|
284 | """ | |||
|
285 | setattr(magic_func, MAGIC_OUTPUT_CAN_BE_DISABLED, True) | |||
|
286 | return magic_func | |||
278 |
|
287 | |||
279 | # Create the actual decorators for public use |
|
288 | # Create the actual decorators for public use | |
280 |
|
289 |
@@ -37,6 +37,7 b' from IPython.core.magic import (' | |||||
37 | magics_class, |
|
37 | magics_class, | |
38 | needs_local_scope, |
|
38 | needs_local_scope, | |
39 | no_var_expand, |
|
39 | no_var_expand, | |
|
40 | output_can_be_disabled, | |||
40 | on_off, |
|
41 | on_off, | |
41 | ) |
|
42 | ) | |
42 | from IPython.testing.skipdoctest import skip_doctest |
|
43 | from IPython.testing.skipdoctest import skip_doctest | |
@@ -1194,6 +1195,7 b' class ExecutionMagics(Magics):' | |||||
1194 | @no_var_expand |
|
1195 | @no_var_expand | |
1195 | @needs_local_scope |
|
1196 | @needs_local_scope | |
1196 | @line_cell_magic |
|
1197 | @line_cell_magic | |
|
1198 | @output_can_be_disabled | |||
1197 | def time(self,line='', cell=None, local_ns=None): |
|
1199 | def time(self,line='', cell=None, local_ns=None): | |
1198 | """Time execution of a Python statement or expression. |
|
1200 | """Time execution of a Python statement or expression. | |
1199 |
|
1201 |
@@ -419,7 +419,7 b' def test_time():' | |||||
419 |
|
419 | |||
420 | # ';' at the end of %time prevents instruction value to be printed. |
|
420 | # ';' at the end of %time prevents instruction value to be printed. | |
421 | # This tests fix for #13837. |
|
421 | # This tests fix for #13837. | |
422 | def test_time_no_outputwith_semicolon(): |
|
422 | def test_time_no_output_with_semicolon(): | |
423 | ip = get_ipython() |
|
423 | ip = get_ipython() | |
424 |
|
424 | |||
425 | with tt.AssertPrints(" 123456"): |
|
425 | with tt.AssertPrints(" 123456"): | |
@@ -432,6 +432,21 b' def test_time_no_outputwith_semicolon():' | |||||
432 | with tt.AssertPrints("CPU times: ", suppress=False): |
|
432 | with tt.AssertPrints("CPU times: ", suppress=False): | |
433 | ip.run_cell("%time 123000+456;") |
|
433 | ip.run_cell("%time 123000+456;") | |
434 |
|
434 | |||
|
435 | with tt.AssertPrints(" 123456"): | |||
|
436 | with tt.AssertPrints("Wall time: ", suppress=False): | |||
|
437 | with tt.AssertPrints("CPU times: ", suppress=False): | |||
|
438 | ip.run_cell("%time 123000+456 # Comment") | |||
|
439 | ||||
|
440 | with tt.AssertNotPrints(" 123456"): | |||
|
441 | with tt.AssertPrints("Wall time: ", suppress=False): | |||
|
442 | with tt.AssertPrints("CPU times: ", suppress=False): | |||
|
443 | ip.run_cell("%time 123000+456; # Comment") | |||
|
444 | ||||
|
445 | with tt.AssertPrints(" 123456"): | |||
|
446 | with tt.AssertPrints("Wall time: ", suppress=False): | |||
|
447 | with tt.AssertPrints("CPU times: ", suppress=False): | |||
|
448 | ip.run_cell("%time 123000+456 # ;Comment") | |||
|
449 | ||||
435 |
|
450 | |||
436 | def test_time_last_not_expression(): |
|
451 | def test_time_last_not_expression(): | |
437 | ip.run_cell("%%time\n" |
|
452 | ip.run_cell("%%time\n" |
General Comments 0
You need to be logged in to leave comments.
Login now