From 3b30c93f73dbda3f96ee5d9ec1c27626bd66a0be Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Wed, 27 Sep 2017 16:00:55 -0300 Subject: [PATCH] Deprecate TerminalReporter._tw Fix #2803 --- _pytest/config.py | 2 +- _pytest/debugging.py | 2 +- _pytest/helpconfig.py | 2 +- _pytest/pastebin.py | 6 +-- _pytest/skipping.py | 4 +- _pytest/terminal.py | 110 +++++++++++++++++++++++------------------ changelog/2803.removal | 1 + 7 files changed, 71 insertions(+), 56 deletions(-) create mode 100644 changelog/2803.removal diff --git a/_pytest/config.py b/_pytest/config.py index 690f98587..2f28bb7bf 100644 --- a/_pytest/config.py +++ b/_pytest/config.py @@ -931,7 +931,7 @@ class Config(object): fslocation=fslocation, nodeid=nodeid)) def get_terminal_writer(self): - return self.pluginmanager.get_plugin("terminalreporter")._tw + return self.pluginmanager.get_plugin("terminalreporter").writer def pytest_cmdline_parse(self, pluginmanager, args): # REF1 assert self == pluginmanager.config, (self, pluginmanager.config) diff --git a/_pytest/debugging.py b/_pytest/debugging.py index aa9c9a386..15a5670e0 100644 --- a/_pytest/debugging.py +++ b/_pytest/debugging.py @@ -83,7 +83,7 @@ def _enter_pdb(node, excinfo, rep): # XXX we re-use the TerminalReporter's terminalwriter # because this seems to avoid some encoding related troubles # for not completely clear reasons. - tw = node.config.pluginmanager.getplugin("terminalreporter")._tw + tw = node.config.pluginmanager.getplugin("terminalreporter").writer tw.line() tw.sep(">", "traceback") rep.toterminal(tw) diff --git a/_pytest/helpconfig.py b/_pytest/helpconfig.py index e744637f8..8438c3004 100644 --- a/_pytest/helpconfig.py +++ b/_pytest/helpconfig.py @@ -107,7 +107,7 @@ def pytest_cmdline_main(config): def showhelp(config): reporter = config.pluginmanager.get_plugin('terminalreporter') - tw = reporter._tw + tw = reporter.writer tw.write(config._parser.optparser.format_help()) tw.line() tw.line() diff --git a/_pytest/pastebin.py b/_pytest/pastebin.py index b588b021b..68aa331f7 100644 --- a/_pytest/pastebin.py +++ b/_pytest/pastebin.py @@ -25,7 +25,7 @@ def pytest_configure(config): if tr is not None: # pastebin file will be utf-8 encoded binary file config._pastebinfile = tempfile.TemporaryFile('w+b') - oldwrite = tr._tw.write + oldwrite = tr.writer.write def tee_write(s, **kwargs): oldwrite(s, **kwargs) @@ -33,7 +33,7 @@ def pytest_configure(config): s = s.encode('utf-8') config._pastebinfile.write(s) - tr._tw.write = tee_write + tr.writer.write = tee_write def pytest_unconfigure(config): @@ -45,7 +45,7 @@ def pytest_unconfigure(config): del config._pastebinfile # undo our patching in the terminal reporter tr = config.pluginmanager.getplugin('terminalreporter') - del tr._tw.__dict__['write'] + del tr.writer.__dict__['write'] # write summary tr.write_sep("=", "Sending information to Paste Service") pastebinurl = create_new_paste(sessionlog) diff --git a/_pytest/skipping.py b/_pytest/skipping.py index 2b5d0dded..ef9f601ca 100644 --- a/_pytest/skipping.py +++ b/_pytest/skipping.py @@ -295,9 +295,9 @@ def pytest_terminal_summary(terminalreporter): show_simple(terminalreporter, lines, 'passed', "PASSED %s") if lines: - tr._tw.sep("=", "short test summary info") + tr.writer.sep("=", "short test summary info") for line in lines: - tr._tw.line(line) + tr.writer.line(line) def show_simple(terminalreporter, lines, stat, format): diff --git a/_pytest/terminal.py b/_pytest/terminal.py index 5dd8ac940..92f319766 100644 --- a/_pytest/terminal.py +++ b/_pytest/terminal.py @@ -5,15 +5,18 @@ This is a good source for looking at the various reporting hooks. from __future__ import absolute_import, division, print_function import itertools -from _pytest.main import EXIT_OK, EXIT_TESTSFAILED, EXIT_INTERRUPTED, \ - EXIT_USAGEERROR, EXIT_NOTESTSCOLLECTED -import pytest -import py -import six +import platform import sys import time -import platform +import warnings + +import py +import six + import pluggy +import pytest +from _pytest.main import EXIT_OK, EXIT_TESTSFAILED, EXIT_INTERRUPTED, \ + EXIT_USAGEERROR, EXIT_NOTESTSCOLLECTED def pytest_addoption(parser): @@ -136,13 +139,22 @@ class TerminalReporter: self.startdir = py.path.local() if file is None: file = sys.stdout - self._tw = self.writer = _pytest.config.create_terminal_writer(config, - file) + self._writer = _pytest.config.create_terminal_writer(config, file) self.currentfspath = None self.reportchars = getreportopt(config) - self.hasmarkup = self._tw.hasmarkup + self.hasmarkup = self.writer.hasmarkup self.isatty = file.isatty() + @property + def writer(self): + return self._writer + + @property + def _tw(self): + warnings.warn(DeprecationWarning('TerminalReporter._tw is deprecated, use TerminalReporter.writer instead'), + stacklevel=2) + return self.writer + def hasopt(self, char): char = {'xfailed': 'x', 'skipped': 's'}.get(char, char) return char in self.reportchars @@ -152,32 +164,32 @@ class TerminalReporter: if fspath != self.currentfspath: self.currentfspath = fspath fspath = self.startdir.bestrelpath(fspath) - self._tw.line() - self._tw.write(fspath + " ") - self._tw.write(res) + self.writer.line() + self.writer.write(fspath + " ") + self.writer.write(res) def write_ensure_prefix(self, prefix, extra="", **kwargs): if self.currentfspath != prefix: - self._tw.line() + self.writer.line() self.currentfspath = prefix - self._tw.write(prefix) + self.writer.write(prefix) if extra: - self._tw.write(extra, **kwargs) + self.writer.write(extra, **kwargs) self.currentfspath = -2 def ensure_newline(self): if self.currentfspath: - self._tw.line() + self.writer.line() self.currentfspath = None def write(self, content, **markup): - self._tw.write(content, **markup) + self.writer.write(content, **markup) def write_line(self, line, **markup): if not isinstance(line, six.text_type): line = six.text_type(line, errors="replace") self.ensure_newline() - self._tw.line(line, **markup) + self.writer.line(line, **markup) def rewrite(self, line, **markup): """ @@ -190,22 +202,22 @@ class TerminalReporter: """ erase = markup.pop('erase', False) if erase: - fill_count = self._tw.fullwidth - len(line) + fill_count = self.writer.fullwidth - len(line) fill = ' ' * fill_count else: fill = '' line = str(line) - self._tw.write("\r" + line + fill, **markup) + self.writer.write("\r" + line + fill, **markup) def write_sep(self, sep, title=None, **markup): self.ensure_newline() - self._tw.sep(sep, title, **markup) + self.writer.sep(sep, title, **markup) def section(self, title, sep="=", **kw): - self._tw.sep(sep, title, **kw) + self.writer.sep(sep, title, **kw) def line(self, msg, **kw): - self._tw.line(msg, **kw) + self.writer.line(msg, **kw) def pytest_internalerror(self, excrepr): for line in six.text_type(excrepr).split("\n"): @@ -252,7 +264,7 @@ class TerminalReporter: if not hasattr(rep, 'node') and self.showfspath: self.write_fspath_result(rep.nodeid, letter) else: - self._tw.write(letter) + self.writer.write(letter) else: if isinstance(word, tuple): word, markup = word @@ -263,16 +275,18 @@ class TerminalReporter: markup = {'red': True} elif rep.skipped: markup = {'yellow': True} + else: + markup = {} line = self._locationline(rep.nodeid, *rep.location) if not hasattr(rep, 'node'): self.write_ensure_prefix(line, word, **markup) - # self._tw.write(word, **markup) + # self.writer.write(word, **markup) else: self.ensure_newline() if hasattr(rep, 'node'): - self._tw.write("[%s] " % rep.node.gateway.id) - self._tw.write(word, **markup) - self._tw.write(" " + line) + self.writer.write("[%s] " % rep.node.gateway.id) + self.writer.write(word, **markup) + self.writer.write(" " + line) self.currentfspath = -2 def pytest_collection(self): @@ -358,9 +372,9 @@ class TerminalReporter: if self.config.option.collectonly: self._printcollecteditems(session.items) if self.stats.get('failed'): - self._tw.sep("!", "collection failures") + self.writer.sep("!", "collection failures") for rep in self.stats.get('failed'): - rep.toterminal(self._tw) + rep.toterminal(self.writer) return 1 return 0 lines = self.config.hook.pytest_report_collectionfinish( @@ -378,12 +392,12 @@ class TerminalReporter: name = item.nodeid.split('::', 1)[0] counts[name] = counts.get(name, 0) + 1 for name, count in sorted(counts.items()): - self._tw.line("%s: %d" % (name, count)) + self.writer.line("%s: %d" % (name, count)) else: for item in items: nodeid = item.nodeid nodeid = nodeid.replace("::()::", "::") - self._tw.line(nodeid) + self.writer.line(nodeid) return stack = [] indent = "" @@ -398,13 +412,13 @@ class TerminalReporter: # if col.name == "()": # continue indent = (len(stack) - 1) * " " - self._tw.line("%s%s" % (indent, col)) + self.writer.line("%s%s" % (indent, col)) @pytest.hookimpl(hookwrapper=True) def pytest_sessionfinish(self, exitstatus): outcome = yield outcome.get_result() - self._tw.line("") + self.writer.line("") summary_exit_codes = ( EXIT_OK, EXIT_TESTSFAILED, EXIT_INTERRUPTED, EXIT_USAGEERROR, EXIT_NOTESTSCOLLECTED) @@ -434,10 +448,10 @@ class TerminalReporter: self.write_sep("!", msg) if "KeyboardInterrupt" in msg: if self.config.option.fulltrace: - excrepr.toterminal(self._tw) + excrepr.toterminal(self.writer) else: - self._tw.line("to show a full traceback on KeyboardInterrupt use --fulltrace", yellow=True) - excrepr.reprcrash.toterminal(self._tw) + self.writer.line("to show a full traceback on KeyboardInterrupt use --fulltrace", yellow=True) + excrepr.reprcrash.toterminal(self.writer) def _locationline(self, nodeid, fspath, lineno, domain): def mkrel(nodeid): @@ -493,14 +507,14 @@ class TerminalReporter: grouped = itertools.groupby(all_warnings, key=lambda wr: wr.get_location(self.config)) self.write_sep("=", "warnings summary", yellow=True, bold=False) - for location, warnings in grouped: - self._tw.line(str(location) or '') - for w in warnings: + for location, warning_records in grouped: + self.writer.line(str(location) or '') + for w in warning_records: lines = w.message.splitlines() indented = '\n'.join(' ' + x for x in lines) - self._tw.line(indented) - self._tw.line() - self._tw.line('-- Docs: http://doc.pytest.org/en/latest/warnings.html') + self.writer.line(indented) + self.writer.line() + self.writer.line('-- Docs: http://doc.pytest.org/en/latest/warnings.html') def summary_passes(self): if self.config.option.tbstyle != "no": @@ -517,10 +531,10 @@ class TerminalReporter: def print_teardown_sections(self, rep): for secname, content in rep.sections: if 'teardown' in secname: - self._tw.sep('-', secname) + self.writer.sep('-', secname) if content[-1:] == "\n": content = content[:-1] - self._tw.line(content) + self.writer.line(content) def summary_failures(self): if self.config.option.tbstyle != "no": @@ -560,12 +574,12 @@ class TerminalReporter: self._outrep_summary(rep) def _outrep_summary(self, rep): - rep.toterminal(self._tw) + rep.toterminal(self.writer) for secname, content in rep.sections: - self._tw.sep("-", secname) + self.writer.sep("-", secname) if content[-1:] == "\n": content = content[:-1] - self._tw.line(content) + self.writer.line(content) def summary_stats(self): session_duration = time.time() - self._sessionstarttime diff --git a/changelog/2803.removal b/changelog/2803.removal new file mode 100644 index 000000000..4ebdb903e --- /dev/null +++ b/changelog/2803.removal @@ -0,0 +1 @@ +``TerminalReporter._tw`` has been deprecated in favor of ``TerminalReporter.writer`` and will be removed in a future version. Also, ``TerminalReporter.writer`` is now read-only.