From 19b061c4daabfd35a9f56cfadeb321df7a3cdabe 2015-01-18 23:26:55 From: Min RK Date: 2015-01-18 23:26:55 Subject: [PATCH] copy timeit.Timer.timeit from CPython 3.4 we were relying on self.inner for %timeit, which is an undocumented implementation detail of Python, and no longer shared by PyPy. This copies the CPython implementation, so it is no longer an undocumented attribute. It will likely not be optimal for some PyPy timings, but at least it works. --- diff --git a/IPython/core/magics/execution.py b/IPython/core/magics/execution.py index e4ca148..b4b487c 100644 --- a/IPython/core/magics/execution.py +++ b/IPython/core/magics/execution.py @@ -1,25 +1,19 @@ # -*- coding: utf-8 -*- -"""Implementation of execution-related magic functions. -""" -from __future__ import print_function -#----------------------------------------------------------------------------- -# Copyright (c) 2012 The IPython Development Team. -# -# Distributed under the terms of the Modified BSD License. -# -# The full license is in the file COPYING.txt, distributed with this software. -#----------------------------------------------------------------------------- +"""Implementation of execution-related magic functions.""" -#----------------------------------------------------------------------------- -# Imports -#----------------------------------------------------------------------------- +# Copyright (c) IPython Development Team. +# Distributed under the terms of the Modified BSD License. + +from __future__ import print_function -# Stdlib import ast import bdb +import gc +import itertools import os import sys import time +import timeit from pdb import Restart # cProfile was added in Python2.5 @@ -33,7 +27,6 @@ except ImportError: except ImportError: profile = pstats = None -# Our own packages from IPython.core import debugger, oinspect from IPython.core import magic_arguments from IPython.core import page @@ -115,6 +108,34 @@ class TimeitTemplateFiller(ast.NodeTransformer): return node +class Timer(timeit.Timer): + """Timer class that explicitly uses self.inner + + which is an undocumented implementation detail of CPython, + not shared by PyPy. + """ + # Timer.timeit copied from CPython 3.4.2 + def timeit(self, number=timeit.default_number): + """Time 'number' executions of the main statement. + + To be precise, this executes the setup statement once, and + then returns the time it takes to execute the main statement + a number of times, as a float measured in seconds. The + argument is the number of times through the loop, defaulting + to one million. The main statement, the setup statement and + the timer function to be used are passed to the constructor. + """ + it = itertools.repeat(None, number) + gcold = gc.isenabled() + gc.disable() + try: + timing = self.inner(it, self.timer) + finally: + if gcold: + gc.enable() + return timing + + @magics_class class ExecutionMagics(Magics): """Magics related to code execution, debugging, profiling, etc. @@ -945,8 +966,6 @@ python-profiler package from non-free.""") does not matter as long as results from timeit.py are not mixed with those from %timeit.""" - import timeit - opts, stmt = self.parse_options(line,'n:r:tcp:qo', posix=False, strict=False) if stmt == "" and cell is None: @@ -963,7 +982,7 @@ python-profiler package from non-free.""") if hasattr(opts, "c"): timefunc = clock - timer = timeit.Timer(timer=timefunc) + timer = Timer(timer=timefunc) # this code has tight coupling to the inner workings of timeit.Timer, # but is there a better way to achieve that the code stmt has access # to the shell namespace?