Skip to content

Report unicode #7609

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 16 commits into from
Closed
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
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ Vlad Dragos
Vlad Radziuk
Vladyslav Rachek
Volodymyr Piskun
Walter Dörwald
Wei Lin
Wil Cooley
William Lee
Expand Down
5 changes: 5 additions & 0 deletions changelog/7608.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Move characters used for drawing horizontal rules into class attributes of
TerminalReporter.

This allows those characters to be replaced by plugins (i.e. with Unicode
box drawing characters) and documents which characters are used.
4 changes: 3 additions & 1 deletion src/_pytest/junitxml.py
Original file line number Diff line number Diff line change
Expand Up @@ -673,7 +673,9 @@ def pytest_sessionfinish(self) -> None:
logfile.close()

def pytest_terminal_summary(self, terminalreporter: TerminalReporter) -> None:
terminalreporter.write_sep("-", "generated xml file: {}".format(self.logfile))
terminalreporter.write_hrule_single(
"generated xml file: {}".format(self.logfile)
)

def add_global_property(self, name: str, value: object) -> None:
__tracebackhide__ = True
Expand Down
4 changes: 2 additions & 2 deletions src/_pytest/pastebin.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ def pytest_unconfigure(config: Config) -> None:
tr = config.pluginmanager.getplugin("terminalreporter")
del tr._tw.__dict__["write"]
# Write summary.
tr.write_sep("=", "Sending information to Paste Service")
tr.write_hrule_double("Sending information to Paste Service")
pastebinurl = create_new_paste(sessionlog)
tr.write_line("pastebin session-log: %s\n" % pastebinurl)

Expand Down Expand Up @@ -95,7 +95,7 @@ def pytest_terminal_summary(terminalreporter: TerminalReporter) -> None:
if terminalreporter.config.option.pastebin != "failed":
return
if "failed" in terminalreporter.stats:
terminalreporter.write_sep("=", "Sending information to Paste Service")
terminalreporter.write_hrule_double("Sending information to Paste Service")
for rep in terminalreporter.stats["failed"]:
try:
msg = rep.longrepr.reprtraceback.reprentries[-1].reprfileloc
Expand Down
4 changes: 2 additions & 2 deletions src/_pytest/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,9 @@ def pytest_terminal_summary(terminalreporter: "TerminalReporter") -> None:
dlist.sort(key=lambda x: x.duration)
dlist.reverse()
if not durations:
tr.write_sep("=", "slowest durations")
tr.write_hrule_double("slowest durations")
else:
tr.write_sep("=", "slowest %s durations" % durations)
tr.write_hrule_double("slowest %s durations" % durations)
dlist = dlist[:durations]

for i, rep in enumerate(dlist):
Expand Down
64 changes: 51 additions & 13 deletions src/_pytest/terminal.py
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,12 @@ def get_location(self, config: Config) -> Optional[str]:


class TerminalReporter:
# Characters use for printing horizontal rules
hrule_single = "-"
hrule_double = "="
hrule_error = "!"
hrule_lower = "_"

def __init__(self, config: Config, file: Optional[TextIO] = None) -> None:
import _pytest.config

Expand Down Expand Up @@ -463,6 +469,38 @@ def write_sep(
self.ensure_newline()
self._tw.sep(sep, title, fullwidth, **markup)

def write_hrule_single(
self,
title: Optional[str] = None,
fullwidth: Optional[int] = None,
**markup: bool
) -> None:
self.write_sep(self.hrule_single, title, fullwidth, **markup)

def write_hrule_double(
self,
title: Optional[str] = None,
fullwidth: Optional[int] = None,
**markup: bool
) -> None:
self.write_sep(self.hrule_double, title, fullwidth, **markup)

def write_hrule_error(
self,
title: Optional[str] = None,
fullwidth: Optional[int] = None,
**markup: bool
) -> None:
self.write_sep(self.hrule_error, title, fullwidth, **markup)

def write_hrule_lower(
self,
title: Optional[str] = None,
fullwidth: Optional[int] = None,
**markup: bool
) -> None:
self.write_sep(self.hrule_lower, title, fullwidth, **markup)

def section(self, title: str, sep: str = "=", **kw: bool) -> None:
self._tw.sep(sep, title, **kw)

Expand Down Expand Up @@ -687,7 +725,7 @@ def pytest_sessionstart(self, session: "Session") -> None:
self._sessionstarttime = timing.time()
if not self.showheader:
return
self.write_sep("=", "test session starts", bold=True)
self.write_hrule_double("test session starts", bold=True)
verinfo = platform.python_version()
if not self.no_header:
msg = "platform {} -- Python {}".format(sys.platform, verinfo)
Expand Down Expand Up @@ -813,12 +851,12 @@ def pytest_sessionfinish(
terminalreporter=self, exitstatus=exitstatus, config=self.config
)
if session.shouldfail:
self.write_sep("!", str(session.shouldfail), red=True)
self.write_hrule_error(str(session.shouldfail), red=True)
if exitstatus == ExitCode.INTERRUPTED:
self._report_keyboardinterrupt()
self._keyboardinterrupt_memo = None
elif session.shouldstop:
self.write_sep("!", str(session.shouldstop), red=True)
self.write_hrule_error(str(session.shouldstop), red=True)
self.summary_stats()

@pytest.hookimpl(hookwrapper=True)
Expand All @@ -844,7 +882,7 @@ def _report_keyboardinterrupt(self) -> None:
assert excrepr is not None
assert excrepr.reprcrash is not None
msg = excrepr.reprcrash.message
self.write_sep("!", msg)
self.write_hrule_error(msg)
if "KeyboardInterrupt" in msg:
if self.config.option.fulltrace:
excrepr.toterminal(self._tw)
Expand Down Expand Up @@ -945,7 +983,7 @@ def collapsed_location_report(reports: List[WarningReport]) -> str:
)

title = "warnings summary (final)" if final else "warnings summary"
self.write_sep("=", title, yellow=True, bold=False)
self.write_hrule_double(title, yellow=True, bold=False)
for message, message_reports in reports_grouped_by_message.items():
maybe_location = collapsed_location_report(message_reports)
if maybe_location:
Expand All @@ -965,11 +1003,11 @@ def summary_passes(self) -> None:
reports = self.getreports("passed") # type: List[TestReport]
if not reports:
return
self.write_sep("=", "PASSES")
self.write_hrule_double("PASSES")
for rep in reports:
if rep.sections:
msg = self._getfailureheadline(rep)
self.write_sep("_", msg, green=True, bold=True)
self.write_hrule_lower(msg, green=True, bold=True)
self._outrep_summary(rep)
self._handle_teardown_sections(rep.nodeid)

Expand Down Expand Up @@ -1003,15 +1041,15 @@ def summary_failures(self) -> None:
reports = self.getreports("failed") # type: List[BaseReport]
if not reports:
return
self.write_sep("=", "FAILURES")
self.write_hrule_double("FAILURES")
if self.config.option.tbstyle == "line":
for rep in reports:
line = self._getcrashline(rep)
self.write_line(line)
else:
for rep in reports:
msg = self._getfailureheadline(rep)
self.write_sep("_", msg, red=True, bold=True)
self.write_hrule_lower(msg, red=True, bold=True)
self._outrep_summary(rep)
self._handle_teardown_sections(rep.nodeid)

Expand All @@ -1020,14 +1058,14 @@ def summary_errors(self) -> None:
reports = self.getreports("error") # type: List[BaseReport]
if not reports:
return
self.write_sep("=", "ERRORS")
self.write_hrule_double("ERRORS")
for rep in self.stats["error"]:
msg = self._getfailureheadline(rep)
if rep.when == "collect":
msg = "ERROR collecting " + msg
else:
msg = "ERROR at {} of {}".format(rep.when, msg)
self.write_sep("_", msg, red=True, bold=True)
self.write_hrule_lower(msg, red=True, bold=True)
self._outrep_summary(rep)

def _outrep_summary(self, rep: BaseReport) -> None:
Expand Down Expand Up @@ -1076,7 +1114,7 @@ def summary_stats(self) -> None:
msg += markup_for_end_sep

if display_sep:
self.write_sep("=", msg, fullwidth=fullwidth, **main_markup)
self.write_hrule_double(msg, fullwidth=fullwidth, **main_markup)
else:
self.write_line(msg, **main_markup)

Expand Down Expand Up @@ -1145,7 +1183,7 @@ def show_skipped(lines: List[str]) -> None:
action(lines)

if lines:
self.write_sep("=", "short test summary info")
self.write_hrule_double("short test summary info")
for line in lines:
self.write_line(line)

Expand Down