summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2015-05-30 16:44:55 (GMT)
committerSerhiy Storchaka <storchaka@gmail.com>2015-05-30 16:44:55 (GMT)
commit1b560cbf850fc1c8165b3505c4a137de0abf3668 (patch)
tree9c046095572c0e9b298cfa0c2902a912d458fbee
parent8c7ed012b87db4de66da61c2f7c0a11a61277384 (diff)
parentf28fa66351fe93b3fcdc98c7f35f05573ea93df2 (diff)
downloadcpython-1b560cbf850fc1c8165b3505c4a137de0abf3668.zip
cpython-1b560cbf850fc1c8165b3505c4a137de0abf3668.tar.gz
cpython-1b560cbf850fc1c8165b3505c4a137de0abf3668.tar.bz2
Issue #5633: Fixed timeit when the statement is a string and the setup is not.
Refactored timeit.__init__ for unified handling of stmt and setup parameters.
-rw-r--r--Lib/test/test_timeit.py7
-rwxr-xr-xLib/timeit.py53
-rw-r--r--Misc/NEWS2
3 files changed, 29 insertions, 33 deletions
diff --git a/Lib/test/test_timeit.py b/Lib/test/test_timeit.py
index 83c93f7..5e9d49e 100644
--- a/Lib/test/test_timeit.py
+++ b/Lib/test/test_timeit.py
@@ -124,6 +124,9 @@ class TestTimeit(unittest.TestCase):
def test_timeit_callable_stmt(self):
self.timeit(self.fake_callable_stmt, self.fake_setup, number=3)
+ def test_timeit_callable_setup(self):
+ self.timeit(self.fake_stmt, self.fake_callable_setup, number=3)
+
def test_timeit_callable_stmt_and_setup(self):
self.timeit(self.fake_callable_stmt,
self.fake_callable_setup, number=3)
@@ -184,6 +187,10 @@ class TestTimeit(unittest.TestCase):
self.repeat(self.fake_callable_stmt, self.fake_setup,
repeat=3, number=5)
+ def test_repeat_callable_setup(self):
+ self.repeat(self.fake_stmt, self.fake_callable_setup,
+ repeat=3, number=5)
+
def test_repeat_callable_stmt_and_setup(self):
self.repeat(self.fake_callable_stmt, self.fake_callable_setup,
repeat=3, number=5)
diff --git a/Lib/timeit.py b/Lib/timeit.py
index de7d550..d9f9563 100755
--- a/Lib/timeit.py
+++ b/Lib/timeit.py
@@ -68,7 +68,7 @@ _globals = globals
# in Timer.__init__() depend on setup being indented 4 spaces and stmt
# being indented 8 spaces.
template = """
-def inner(_it, _timer):
+def inner(_it, _timer{init}):
{setup}
_t0 = _timer()
for _i in _it:
@@ -81,17 +81,6 @@ def reindent(src, indent):
"""Helper to reindent a multi-line statement."""
return src.replace("\n", "\n" + " "*indent)
-def _template_func(setup, func):
- """Create a timer function. Used if the "statement" is a callable."""
- def inner(_it, _timer, _func=func):
- setup()
- _t0 = _timer()
- for _i in _it:
- _func()
- _t1 = _timer()
- return _t1 - _t0
- return inner
-
class Timer:
"""Class for timing execution speed of small code snippets.
@@ -116,37 +105,35 @@ class Timer:
self.timer = timer
local_ns = {}
global_ns = _globals() if globals is None else globals
+ init = ''
+ if isinstance(setup, str):
+ # Check that the code can be compiled outside a function
+ compile(setup, dummy_src_name, "exec")
+ setup = reindent(setup, 4)
+ elif callable(setup):
+ local_ns['_setup'] = setup
+ init += ', _setup=_setup'
+ setup = '_setup()'
+ else:
+ raise ValueError("setup is neither a string nor callable")
if isinstance(stmt, str):
# Check that the code can be compiled outside a function
if isinstance(setup, str):
- compile(setup, dummy_src_name, "exec")
compile(setup + '\n' + stmt, dummy_src_name, "exec")
else:
compile(stmt, dummy_src_name, "exec")
stmt = reindent(stmt, 8)
- if isinstance(setup, str):
- setup = reindent(setup, 4)
- src = template.format(stmt=stmt, setup=setup)
- elif callable(setup):
- src = template.format(stmt=stmt, setup='_setup()')
- local_ns['_setup'] = setup
- else:
- raise ValueError("setup is neither a string nor callable")
- self.src = src # Save for traceback display
- code = compile(src, dummy_src_name, "exec")
- exec(code, global_ns, local_ns)
- self.inner = local_ns["inner"]
elif callable(stmt):
- self.src = None
- if isinstance(setup, str):
- _setup = setup
- def setup():
- exec(_setup, global_ns, local_ns)
- elif not callable(setup):
- raise ValueError("setup is neither a string nor callable")
- self.inner = _template_func(setup, stmt)
+ local_ns['_stmt'] = stmt
+ init += ', _stmt=_stmt'
+ stmt = '_stmt()'
else:
raise ValueError("stmt is neither a string nor callable")
+ src = template.format(stmt=stmt, setup=setup, init=init)
+ self.src = src # Save for traceback display
+ code = compile(src, dummy_src_name, "exec")
+ exec(code, global_ns, local_ns)
+ self.inner = local_ns["inner"]
def print_exc(self, file=None):
"""Helper to print a traceback from the timed code.
diff --git a/Misc/NEWS b/Misc/NEWS
index d6ff9e4..2d41812 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -24,6 +24,8 @@ Core and Builtins
Library
-------
+- Issue #5633: Fixed timeit when the statement is a string and the setup is not.
+
- Issue #24326: Fixed audioop.ratecv() with non-default weightB argument.
Original patch by David Moore.