Merge pull request #986 from RonnyPfannschmidt/early-logging
replay initial warnings when terminalreporter is loaded
This commit is contained in:
commit
8625eb643e
|
@ -16,6 +16,8 @@ hookspec = HookspecMarker("pytest")
|
||||||
|
|
||||||
# pytest startup
|
# pytest startup
|
||||||
#
|
#
|
||||||
|
|
||||||
|
|
||||||
class ConftestImportFailure(Exception):
|
class ConftestImportFailure(Exception):
|
||||||
def __init__(self, path, excinfo):
|
def __init__(self, path, excinfo):
|
||||||
Exception.__init__(self, path, excinfo)
|
Exception.__init__(self, path, excinfo)
|
||||||
|
@ -135,7 +137,6 @@ class PytestPluginManager(PluginManager):
|
||||||
"""
|
"""
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(PytestPluginManager, self).__init__("pytest", implprefix="pytest_")
|
super(PytestPluginManager, self).__init__("pytest", implprefix="pytest_")
|
||||||
self._warnings = []
|
|
||||||
self._conftest_plugins = set()
|
self._conftest_plugins = set()
|
||||||
|
|
||||||
# state related to local conftest plugins
|
# state related to local conftest plugins
|
||||||
|
@ -166,7 +167,7 @@ class PytestPluginManager(PluginManager):
|
||||||
fslocation=py.code.getfslineno(sys._getframe(1)),
|
fslocation=py.code.getfslineno(sys._getframe(1)),
|
||||||
message="use pluginmanager.add_hookspecs instead of "
|
message="use pluginmanager.add_hookspecs instead of "
|
||||||
"deprecated addhooks() method.")
|
"deprecated addhooks() method.")
|
||||||
self._warnings.append(warning)
|
self._warn(warning)
|
||||||
return self.add_hookspecs(module_or_class)
|
return self.add_hookspecs(module_or_class)
|
||||||
|
|
||||||
def parse_hookimpl_opts(self, plugin, name):
|
def parse_hookimpl_opts(self, plugin, name):
|
||||||
|
@ -196,9 +197,10 @@ class PytestPluginManager(PluginManager):
|
||||||
fslineno = py.code.getfslineno(hookmethod.function)
|
fslineno = py.code.getfslineno(hookmethod.function)
|
||||||
warning = dict(code="I1",
|
warning = dict(code="I1",
|
||||||
fslocation=fslineno,
|
fslocation=fslineno,
|
||||||
|
nodeid=None,
|
||||||
message="%r hook uses deprecated __multicall__ "
|
message="%r hook uses deprecated __multicall__ "
|
||||||
"argument" % (hook.name))
|
"argument" % (hook.name))
|
||||||
self._warnings.append(warning)
|
self._warn(warning)
|
||||||
|
|
||||||
def register(self, plugin, name=None):
|
def register(self, plugin, name=None):
|
||||||
ret = super(PytestPluginManager, self).register(plugin, name)
|
ret = super(PytestPluginManager, self).register(plugin, name)
|
||||||
|
@ -224,11 +226,15 @@ class PytestPluginManager(PluginManager):
|
||||||
config.addinivalue_line("markers",
|
config.addinivalue_line("markers",
|
||||||
"trylast: mark a hook implementation function such that the "
|
"trylast: mark a hook implementation function such that the "
|
||||||
"plugin machinery will try to call it last/as late as possible.")
|
"plugin machinery will try to call it last/as late as possible.")
|
||||||
for warning in self._warnings:
|
|
||||||
if isinstance(warning, dict):
|
def _warn(self, message):
|
||||||
config.warn(**warning)
|
kwargs = message if isinstance(message, dict) else {
|
||||||
else:
|
'code': 'I1',
|
||||||
config.warn(code="I1", message=warning)
|
'message': message,
|
||||||
|
'fslocation': None,
|
||||||
|
'nodeid': None,
|
||||||
|
}
|
||||||
|
self.hook.pytest_logwarning.call_historic(kwargs=kwargs)
|
||||||
|
|
||||||
#
|
#
|
||||||
# internal API for local conftest plugin handling
|
# internal API for local conftest plugin handling
|
||||||
|
@ -381,7 +387,7 @@ class PytestPluginManager(PluginManager):
|
||||||
import pytest
|
import pytest
|
||||||
if not hasattr(pytest, 'skip') or not isinstance(e, pytest.skip.Exception):
|
if not hasattr(pytest, 'skip') or not isinstance(e, pytest.skip.Exception):
|
||||||
raise
|
raise
|
||||||
self._warnings.append("skipped plugin %r: %s" %((modname, e.msg)))
|
self._warn("skipped plugin %r: %s" %((modname, e.msg)))
|
||||||
else:
|
else:
|
||||||
mod = sys.modules[importspec]
|
mod = sys.modules[importspec]
|
||||||
self.register(mod, modname)
|
self.register(mod, modname)
|
||||||
|
@ -713,6 +719,7 @@ class MyOptionParser(argparse.ArgumentParser):
|
||||||
getattr(args, FILE_OR_DIR).extend(argv)
|
getattr(args, FILE_OR_DIR).extend(argv)
|
||||||
return args
|
return args
|
||||||
|
|
||||||
|
|
||||||
class DropShorterLongHelpFormatter(argparse.HelpFormatter):
|
class DropShorterLongHelpFormatter(argparse.HelpFormatter):
|
||||||
"""shorten help for long options that differ only in extra hyphens
|
"""shorten help for long options that differ only in extra hyphens
|
||||||
|
|
||||||
|
@ -802,6 +809,7 @@ class Config(object):
|
||||||
self._inicache = {}
|
self._inicache = {}
|
||||||
self._opt2dest = {}
|
self._opt2dest = {}
|
||||||
self._cleanup = []
|
self._cleanup = []
|
||||||
|
self._warn = self.pluginmanager._warn
|
||||||
self.pluginmanager.register(self, "pytestconfig")
|
self.pluginmanager.register(self, "pytestconfig")
|
||||||
self._configured = False
|
self._configured = False
|
||||||
def do_setns(dic):
|
def do_setns(dic):
|
||||||
|
@ -831,8 +839,9 @@ class Config(object):
|
||||||
|
|
||||||
def warn(self, code, message, fslocation=None):
|
def warn(self, code, message, fslocation=None):
|
||||||
""" generate a warning for this test session. """
|
""" generate a warning for this test session. """
|
||||||
self.hook.pytest_logwarning(code=code, message=message,
|
self.hook.pytest_logwarning.call_historic(kwargs=dict(
|
||||||
fslocation=fslocation, nodeid=None)
|
code=code, message=message,
|
||||||
|
fslocation=fslocation, nodeid=None))
|
||||||
|
|
||||||
def get_terminal_writer(self):
|
def get_terminal_writer(self):
|
||||||
return self.pluginmanager.get_plugin("terminalreporter")._tw
|
return self.pluginmanager.get_plugin("terminalreporter")._tw
|
||||||
|
@ -921,8 +930,7 @@ class Config(object):
|
||||||
if ns.help or ns.version:
|
if ns.help or ns.version:
|
||||||
# we don't want to prevent --help/--version to work
|
# we don't want to prevent --help/--version to work
|
||||||
# so just let is pass and print a warning at the end
|
# so just let is pass and print a warning at the end
|
||||||
self.pluginmanager._warnings.append(
|
self._warn("could not load initial conftests (%s)\n" % e.path)
|
||||||
"could not load initial conftests (%s)\n" % e.path)
|
|
||||||
else:
|
else:
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
|
|
@ -62,8 +62,8 @@ def pytest_cmdline_main(config):
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def showhelp(config):
|
def showhelp(config):
|
||||||
import _pytest.config
|
reporter = config.pluginmanager.get_plugin('terminalreporter')
|
||||||
tw = _pytest.config.create_terminal_writer(config)
|
tw = reporter._tw
|
||||||
tw.write(config._parser.optparser.format_help())
|
tw.write(config._parser.optparser.format_help())
|
||||||
tw.line()
|
tw.line()
|
||||||
tw.line()
|
tw.line()
|
||||||
|
@ -86,8 +86,9 @@ def showhelp(config):
|
||||||
tw.line("to see available fixtures type: py.test --fixtures")
|
tw.line("to see available fixtures type: py.test --fixtures")
|
||||||
tw.line("(shown according to specified file_or_dir or current dir "
|
tw.line("(shown according to specified file_or_dir or current dir "
|
||||||
"if not specified)")
|
"if not specified)")
|
||||||
for warning in config.pluginmanager._warnings:
|
tw.line(str(reporter.stats))
|
||||||
tw.line("warning: %s" % (warning,), red=True)
|
for warningreport in reporter.stats.get('warnings', []):
|
||||||
|
tw.line("warning : " + warningreport.message, red=True)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
|
@ -126,5 +127,3 @@ def pytest_report_header(config):
|
||||||
r = repr(plugin)
|
r = repr(plugin)
|
||||||
lines.append(" %-20s: %s" %(name, r))
|
lines.append(" %-20s: %s" %(name, r))
|
||||||
return lines
|
return lines
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -249,6 +249,8 @@ def pytest_report_teststatus(report):
|
||||||
def pytest_terminal_summary(terminalreporter):
|
def pytest_terminal_summary(terminalreporter):
|
||||||
""" add additional section in terminal summary reporting. """
|
""" add additional section in terminal summary reporting. """
|
||||||
|
|
||||||
|
|
||||||
|
@hookspec(historic=True)
|
||||||
def pytest_logwarning(message, code, nodeid, fslocation):
|
def pytest_logwarning(message, code, nodeid, fslocation):
|
||||||
""" process a warning specified by a message, a code string,
|
""" process a warning specified by a message, a code string,
|
||||||
a nodeid and fslocation (both of which may be None
|
a nodeid and fslocation (both of which may be None
|
||||||
|
|
|
@ -279,9 +279,9 @@ class Node(object):
|
||||||
else:
|
else:
|
||||||
fslocation = "%s:%s" % fslocation[:2]
|
fslocation = "%s:%s" % fslocation[:2]
|
||||||
|
|
||||||
self.ihook.pytest_logwarning(code=code, message=message,
|
self.ihook.pytest_logwarning.call_historic(kwargs=dict(
|
||||||
nodeid=self.nodeid,
|
code=code, message=message,
|
||||||
fslocation=fslocation)
|
nodeid=self.nodeid, fslocation=fslocation))
|
||||||
|
|
||||||
# methods for ordering nodes
|
# methods for ordering nodes
|
||||||
@property
|
@property
|
||||||
|
@ -742,5 +742,3 @@ class Session(FSCollector):
|
||||||
for x in self.genitems(subnode):
|
for x in self.genitems(subnode):
|
||||||
yield x
|
yield x
|
||||||
node.ihook.pytest_collectreport(report=rep)
|
node.ihook.pytest_collectreport(report=rep)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -129,14 +129,21 @@ class TestPytestPluginInteractions:
|
||||||
undo()
|
undo()
|
||||||
|
|
||||||
def test_warn_on_deprecated_multicall(self, pytestpm):
|
def test_warn_on_deprecated_multicall(self, pytestpm):
|
||||||
|
warnings = []
|
||||||
|
|
||||||
|
class get_warnings:
|
||||||
|
def pytest_logwarning(self, message):
|
||||||
|
warnings.append(message)
|
||||||
|
|
||||||
class Plugin:
|
class Plugin:
|
||||||
def pytest_configure(self, __multicall__):
|
def pytest_configure(self, __multicall__):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
before = list(pytestpm._warnings)
|
pytestpm.register(get_warnings())
|
||||||
|
before = list(warnings)
|
||||||
pytestpm.register(Plugin())
|
pytestpm.register(Plugin())
|
||||||
assert len(pytestpm._warnings) == len(before) + 1
|
assert len(warnings) == len(before) + 1
|
||||||
assert "deprecated" in pytestpm._warnings[-1]["message"]
|
assert "deprecated" in warnings[-1]
|
||||||
|
|
||||||
|
|
||||||
def test_namespace_has_default_and_env_plugins(testdir):
|
def test_namespace_has_default_and_env_plugins(testdir):
|
||||||
|
|
Loading…
Reference in New Issue