Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit c959b0c

Browse files
Issue #18518: timeit now rejects statements which can't be compiled outside
a function or a loop (e.g. "return" or "break").
2 parents 2305867 + 2bef585 commit c959b0c

4 files changed

Lines changed: 21 additions & 6 deletions

File tree

Doc/library/timeit.rst

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,6 @@ The module defines three convenience functions and a public class:
6969
.. versionchanged:: 3.5
7070
The optional *globals* parameter was added.
7171

72-
.. note::
73-
74-
Because :meth:`.timeit` is executing *stmt*, placing a return statement
75-
in *stmt* will prevent :meth:`.timeit` from returning execution time.
76-
It will instead return the data specified by your return statement.
77-
7872

7973
.. function:: repeat(stmt='pass', setup='pass', timer=<default timer>, repeat=3, number=1000000, globals=None)
8074

Lib/test/test_timeit.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,21 @@ def test_reindent_multi(self):
7373

7474
def test_timer_invalid_stmt(self):
7575
self.assertRaises(ValueError, timeit.Timer, stmt=None)
76+
self.assertRaises(SyntaxError, timeit.Timer, stmt='return')
77+
self.assertRaises(SyntaxError, timeit.Timer, stmt='yield')
78+
self.assertRaises(SyntaxError, timeit.Timer, stmt='yield from ()')
79+
self.assertRaises(SyntaxError, timeit.Timer, stmt='break')
80+
self.assertRaises(SyntaxError, timeit.Timer, stmt='continue')
81+
self.assertRaises(SyntaxError, timeit.Timer, stmt='from timeit import *')
7682

7783
def test_timer_invalid_setup(self):
7884
self.assertRaises(ValueError, timeit.Timer, setup=None)
85+
self.assertRaises(SyntaxError, timeit.Timer, setup='return')
86+
self.assertRaises(SyntaxError, timeit.Timer, setup='yield')
87+
self.assertRaises(SyntaxError, timeit.Timer, setup='yield from ()')
88+
self.assertRaises(SyntaxError, timeit.Timer, setup='break')
89+
self.assertRaises(SyntaxError, timeit.Timer, setup='continue')
90+
self.assertRaises(SyntaxError, timeit.Timer, setup='from timeit import *')
7991

8092
fake_setup = "import timeit; timeit._fake_timer.setup()"
8193
fake_stmt = "import timeit; timeit._fake_timer.inc()"

Lib/timeit.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,12 @@ def __init__(self, stmt="pass", setup="pass", timer=default_timer,
115115
local_ns = {}
116116
global_ns = _globals() if globals is None else globals
117117
if isinstance(stmt, str):
118+
# Check that the code can be compiled outside a function
119+
if isinstance(setup, str):
120+
compile(setup, dummy_src_name, "exec")
121+
compile(setup + '\n' + stmt, dummy_src_name, "exec")
122+
else:
123+
compile(stmt, dummy_src_name, "exec")
118124
stmt = reindent(stmt, 8)
119125
if isinstance(setup, str):
120126
setup = reindent(setup, 4)

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,9 @@ Core and Builtins
218218
Library
219219
-------
220220

221+
- Issue #18518: timeit now rejects statements which can't be compiled outside
222+
a function or a loop (e.g. "return" or "break").
223+
221224
- Issue #23094: Fixed readline with frames in Python implementation of pickle.
222225

223226
- Issue #23268: Fixed bugs in the comparison of ipaddress classes.

0 commit comments

Comments
 (0)