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

Skip to content

Commit 2bef585

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

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
@@ -64,12 +64,6 @@ The module defines three convenience functions and a public class:
6464
Create a :class:`Timer` instance with the given statement, *setup* code and
6565
*timer* function and run its :meth:`.timeit` method with *number* executions.
6666

67-
.. note::
68-
69-
Because :meth:`.timeit` is executing *stmt*, placing a return statement
70-
in *stmt* will prevent :meth:`.timeit` from returning execution time.
71-
It will instead return the data specified by your return statement.
72-
7367

7468
.. function:: repeat(stmt='pass', setup='pass', timer=<default timer>, repeat=3, number=1000000)
7569

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
@@ -109,6 +109,12 @@ def __init__(self, stmt="pass", setup="pass", timer=default_timer):
109109
self.timer = timer
110110
ns = {}
111111
if isinstance(stmt, str):
112+
# Check that the code can be compiled outside a function
113+
if isinstance(setup, str):
114+
compile(setup, dummy_src_name, "exec")
115+
compile(setup + '\n' + stmt, dummy_src_name, "exec")
116+
else:
117+
compile(stmt, dummy_src_name, "exec")
112118
stmt = reindent(stmt, 8)
113119
if isinstance(setup, str):
114120
setup = reindent(setup, 4)

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ Core and Builtins
5050
Library
5151
-------
5252

53+
- Issue #18518: timeit now rejects statements which can't be compiled outside
54+
a function or a loop (e.g. "return" or "break").
55+
5356
- Issue #23094: Fixed readline with frames in Python implementation of pickle.
5457

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

0 commit comments

Comments
 (0)