def pytest_sessionfinish(session, exitstatus): """Handle the end of the session.""" n = session.config.option.durations if n is None: return print('\n') try: import pytest_harvest except ImportError: print('Module-level timings require pytest-harvest') return from py.io import TerminalWriter # get the number to print res = pytest_harvest.get_session_synthesis_dct(session) files = dict() for key, val in res.items(): parts = Path(key.split(':')[0]).parts # split mne/tests/test_whatever.py into separate categories since these # are essentially submodule-level tests. Keeping just [:3] works, # except for mne/viz where we want level-4 granulatity split_submodules = (('mne', 'viz'), ('mne', 'preprocessing')) parts = parts[:4 if parts[:2] in split_submodules else 3] if not parts[-1].endswith('.py'): parts = parts + ('', ) file_key = '/'.join(parts) files[file_key] = files.get(file_key, 0) + val['pytest_duration_s'] files = sorted(list(files.items()), key=lambda x: x[1])[::-1] # print files = files[:n] if len(files): writer = TerminalWriter() writer.line() # newline writer.sep('=', f'slowest {n} test module{_pl(n)}') names, timings = zip(*files) timings = [f'{timing:0.2f}s total' for timing in timings] rjust = max(len(timing) for timing in timings) timings = [timing.rjust(rjust) for timing in timings] for name, timing in zip(names, timings): writer.line(f'{timing.ljust(15)}{name}')
class TerminalWriterWrapper(object): def __init__(self, file): super(TerminalWriterWrapper, self).__init__() self._writer = TerminalWriter(file=file) self._line = '' def sep(self, *args, **kw): self._line = '' return self._writer.sep(*args, **kw) def write(self, line, **kw): line = str(line) self._writer.write(line, **kw) if '\n' in line: line = line.rsplit('\n', 1)[-1].rsplit('\r', 1)[-1] self._line = line else: self._line += line def line(self, *args, **kw): self._writer.line(*args, **kw) self._line = '' def get_line_in_progress(self): return self._line def clear_line_in_progress(self): if self._line and self._writer.hasmarkup: self._writer.write('\r') self._writer.write(' ' * len(self._line)) self._writer.write('\r') def restore_line_in_progress(self): if self._writer.hasmarkup: self._writer.write(self._line)
class TerminalWriterWrapper(object): def __init__(self, file): super(TerminalWriterWrapper, self).__init__() if config.root.log.color_console is not None: os.environ[ 'PY_COLORS'] = '1' if config.root.log.color_console else '0' self._writer = TerminalWriter(file=file) self._isatty = file.isatty() self._line = '' def isatty(self): return self._isatty def _get_full_width(self): fullwidth = self._writer.fullwidth if sys.platform == "win32": # see py.io documentation for an explanation fullwidth -= 1 # pragma: no cover return fullwidth def lsep(self, sep, msg, **kw): """Write a left-justified line filled with the separator until the end of the line""" self._do_write( '{0} {1}\n'.format( msg, sep * ((self._get_full_width() - 1 - len(msg)) // len(sep))), **kw) def write_box(self, headline, msg, **kw): box_width = min(self._get_full_width(), 60) line_width = box_width - 4 max_headline_length = box_width - 6 if len(headline) > max_headline_length: headline = headline[max_headline_length:] def write_line(line_to_write): eol_padding = box_width - (len(line_to_write) + 3) self._do_write( '* {0}{1}*\n'.format(line_to_write, ' ' * eol_padding), **kw) self._do_write( '\n** {0} {1}\n'.format(headline, '*' * (box_width - (len(headline) + 4))), **kw) for line in msg.split('\n'): if not line: write_line('') else: for sub_line in wrap(line, line_width): write_line(sub_line) self._do_write('{0}\n\n'.format('*' * box_width), **kw) def sep(self, *args, **kw): self._line = '' return self._writer.sep(*args, **kw) def write(self, line, **kw): line = str(line) self._do_write(line, **kw) self._line = self._get_line_remainder(self._line + line) def _get_line_remainder(self, line): return line.rsplit('\r', 1)[-1].rsplit('\n', 1)[-1] def line(self, *args, **kw): self._writer.line(*args, **kw) self._line = '' def clear_line_in_progress(self): if self._line and self._writer.hasmarkup: self._do_write('\r') self._do_write(' ' * (len(self._line) % self._writer.fullwidth)) self._do_write('\r') def restore_line_in_progress(self): if self._writer.hasmarkup: idx = len(self._line) - (len(self._line) % self._writer.fullwidth) self._do_write(self._line[idx:]) def _do_write(self, *args, **kwargs): return self._writer.write(*args, **kwargs)
class TerminalWriterWrapper(object): def __init__(self, file): super(TerminalWriterWrapper, self).__init__() self._writer = TerminalWriter(file=file) self._isatty = file.isatty() self._line = '' def isatty(self): return self._isatty def _get_full_width(self): fullwidth = self._writer.fullwidth if sys.platform == "win32": # see py.io documentation for an explanation fullwidth -= 1 return fullwidth def lsep(self, sep, msg, **kw): """Write a left-justified line filled with the separator until the end of the line""" self._do_write( '{0} {1}\n'.format(msg, sep * ((self._get_full_width() - 1 - len(msg)) // len(sep))), **kw) def write_box(self, headline, msg, **kw): box_width = min(self._get_full_width(), 60) line_width = box_width - 4 max_headline_length = box_width - 6 if len(headline) > max_headline_length: headline = headline[max_headline_length:] def write_line(line_to_write): eol_padding = box_width - (len(line_to_write) + 3) self._do_write('* {0}{1}*\n'.format(line_to_write, ' ' * eol_padding), **kw) self._do_write('\n** {0} {1}\n'.format(headline, '*' * (box_width - (len(headline) + 4))), **kw) for line in msg.split('\n'): if not line: write_line('') else: for sub_line in wrap(line, line_width): write_line(sub_line) self._do_write('{0}\n\n'.format('*' * box_width), **kw) def sep(self, *args, **kw): self._line = '' return self._writer.sep(*args, **kw) def write(self, line, **kw): line = str(line) self._do_write(line, **kw) self._line = self._get_line_remainder(self._line + line) def _get_line_remainder(self, line): return line.rsplit('\r', 1)[-1].rsplit('\n', 1)[-1] def line(self, *args, **kw): self._writer.line(*args, **kw) self._line = '' def get_line_in_progress(self): return self._line def clear_line_in_progress(self): if self._line and self._writer.hasmarkup: self._do_write('\r') self._do_write(' ' * len(self._line)) self._do_write('\r') def restore_line_in_progress(self): if self._writer.hasmarkup: self._do_write(self._line) def _do_write(self, *args, **kwargs): return self._writer.write(*args, **kwargs)