Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions Doc/whatsnew/3.15.rst
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,15 @@ tarfile
(Contributed by Christoph Walcher in :gh:`57911`.)


timeit
------

* The command-line interface now colorizes error tracebacks
by default. This can be controlled with
:ref:`environment variables <using-on-controlling-color>`.
(Contributed by Yi Hong in :gh:`139374`.)


types
------

Expand Down
7 changes: 5 additions & 2 deletions Lib/test/test_timeit.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@
import io
from textwrap import dedent

from test.support import captured_stdout
from test.support import captured_stderr
from test.support import (
captured_stdout, captured_stderr, force_not_colorized,
)

# timeit's default number of iterations.
DEFAULT_NUMBER = 1000000
Expand Down Expand Up @@ -351,11 +352,13 @@ def test_main_with_time_unit(self):
self.assertEqual(error_stringio.getvalue(),
"Unrecognized unit. Please select nsec, usec, msec, or sec.\n")

@force_not_colorized
def test_main_exception(self):
with captured_stderr() as error_stringio:
s = self.run_main(switches=['1/0'])
self.assert_exc_string(error_stringio.getvalue(), 'ZeroDivisionError')

@force_not_colorized
def test_main_exception_fixed_reps(self):
with captured_stderr() as error_stringio:
s = self.run_main(switches=['-n1', '1/0'])
Expand Down
19 changes: 14 additions & 5 deletions Lib/timeit.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ def __init__(self, stmt="pass", setup="pass", timer=default_timer,
exec(code, global_ns, local_ns)
self.inner = local_ns["inner"]

def print_exc(self, file=None):
def print_exc(self, file=None, **kwargs):
"""Helper to print a traceback from the timed code.

Typical use:
Expand All @@ -149,6 +149,11 @@ def print_exc(self, file=None):

The optional file argument directs where the traceback is
sent; it defaults to sys.stderr.

The optional colorize keyword argument controls whether the
traceback is colorized; it defaults to False for programmatic
usage. When used from the command line, this is automatically
set based on terminal capabilities.
"""
import linecache, traceback
if self.src is not None:
Expand All @@ -158,7 +163,8 @@ def print_exc(self, file=None):
dummy_src_name)
# else the source is already stored somewhere else

traceback.print_exc(file=file)
kwargs['colorize'] = kwargs.get('colorize', False)
traceback.print_exc(file=file, **kwargs)

def timeit(self, number=default_number):
"""Time 'number' executions of the main statement.
Expand Down Expand Up @@ -257,9 +263,12 @@ def main(args=None, *, _wrap_timer=None):
is not None, it must be a callable that accepts a timer function
and returns another timer function (used for unit testing).
"""
import getopt
if args is None:
args = sys.argv[1:]
import getopt
import _colorize
colorize = _colorize.can_colorize()

try:
opts, args = getopt.getopt(args, "n:u:s:r:pvh",
["number=", "setup=", "repeat=",
Expand Down Expand Up @@ -326,7 +335,7 @@ def callback(number, time_taken):
try:
number, _ = t.autorange(callback)
except:
t.print_exc()
t.print_exc(colorize=colorize)
return 1

if verbose:
Expand All @@ -335,7 +344,7 @@ def callback(number, time_taken):
try:
raw_timings = t.repeat(repeat, number)
except:
t.print_exc()
t.print_exc(colorize=colorize)
return 1

def format_time(dt):
Expand Down
4 changes: 2 additions & 2 deletions Lib/traceback.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,9 +206,9 @@ def _safe_string(value, what, func=str):

# --

def print_exc(limit=None, file=None, chain=True):
def print_exc(limit=None, file=None, chain=True, **kwargs):
"""Shorthand for 'print_exception(sys.exception(), limit=limit, file=file, chain=chain)'."""
print_exception(sys.exception(), limit=limit, file=file, chain=chain)
print_exception(sys.exception(), limit=limit, file=file, chain=chain, **kwargs)

def format_exc(limit=None, chain=True):
"""Like print_exc() but return a string."""
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
:mod:`timeit`: Add color to error tracebacks.
Loading