remove old ways to set option defaults, relying on global setup.cfg or tox.ini files now.

revamp py.test --help-config

--HG--
branch : trunk
This commit is contained in:
holger krekel 2010-10-27 22:29:01 +02:00
parent b86b1628bb
commit c9e629c870
9 changed files with 72 additions and 123 deletions

View File

@ -3,7 +3,9 @@ Changes between 1.3.4 and 2.0.0dev0
- pytest-2.0 is now its own package and depends on pylib-2.0
- introduce a new way to set config options via ini-style files,
by default setup.cfg and tox.ini files are searched.
by default setup.cfg and tox.ini files are searched. The old
ways (certain environment variables, dynamic conftest.py reading
is removed).
- fix issue126 - introduce py.test.set_trace() to trace execution via
PDB during the running of tests even if capturing is ongoing.
- fix issue123 - new "python -m py.test" invocation for py.test

View File

@ -8,12 +8,12 @@ basic test configuration
Command line options
---------------------------------
You can see command line options by running::
You can get help on options and configuration by running::
py.test -h
py.test -h # or --help
This will display all available command line options
in your specific environment.
This will display command line options, ini-settings and conftest.py
settings in your specific environment.
reading test configuration from ini-files
--------------------------------------------------------
@ -28,12 +28,12 @@ Possible entries in a ``[pytest]`` section are:
minversion = 2.1 # will fail if we run with pytest-2.0
.. confval:: appendargs = OPTS
.. confval:: addargs = OPTS
append the specified ``OPTS`` to the command line arguments as if they
add the specified ``OPTS`` to the set of command line arguments as if they
had been specified by the user. Example::
appendargs = --maxfail=2 -rf # exit after 2 failures, report fail info
addargs = --maxfail=2 -rf # exit after 2 failures, report fail info
setting persistent option defaults

View File

@ -45,7 +45,7 @@ class Parser:
self._anonymous.addoption(*opts, **attrs)
def parse(self, args):
optparser = MyOptionParser(self)
self.optparser = optparser = MyOptionParser(self)
groups = self._groups + [self._anonymous]
for group in groups:
if group.options:
@ -53,7 +53,7 @@ class Parser:
optgroup = py.std.optparse.OptionGroup(optparser, desc)
optgroup.add_options(group.options)
optparser.add_option_group(optgroup)
return optparser.parse_args([str(x) for x in args])
return self.optparser.parse_args([str(x) for x in args])
def parse_setoption(self, args, option):
parsedoption, args = self.parse(args)
@ -91,7 +91,8 @@ class OptionGroup:
class MyOptionParser(py.std.optparse.OptionParser):
def __init__(self, parser):
self._parser = parser
py.std.optparse.OptionParser.__init__(self, usage=parser._usage)
py.std.optparse.OptionParser.__init__(self, usage=parser._usage,
add_help_option=False)
def format_epilog(self, formatter):
hints = self._parser.hints
if hints:
@ -248,6 +249,12 @@ class Config(object):
self.trace("loaded conftestmodule %r" %(conftestmodule,))
self.pluginmanager.consider_conftest(conftestmodule)
def _processopt(self, opt):
if hasattr(opt, 'default') and opt.dest:
if not hasattr(self.option, opt.dest):
setattr(self.option, opt.dest, opt.default)
def _getmatchingplugins(self, fspath):
allconftests = self._conftest._conftestpath2mod.values()
plugins = [x for x in self.pluginmanager.getplugins()
@ -259,31 +266,6 @@ class Config(object):
if getattr(self.option, 'traceconfig', None):
self.hook.pytest_trace(category="config", msg=msg)
def _processopt(self, opt):
if hasattr(opt, 'default') and opt.dest:
val = os.environ.get("PYTEST_OPTION_" + opt.dest.upper(), None)
if val is not None:
if opt.type == "int":
val = int(val)
elif opt.type == "long":
val = long(val)
elif opt.type == "float":
val = float(val)
elif not opt.type and opt.action in ("store_true", "store_false"):
val = eval(val)
opt.default = val
else:
name = "option_" + opt.dest
try:
opt.default = self._conftest.rget(name)
except (ValueError, KeyError):
try:
opt.default = self.inicfg[opt.dest]
except KeyError:
pass
if not hasattr(self.option, opt.dest):
setattr(self.option, opt.dest, opt.default)
def _setinitialconftest(self, args):
# capture output during conftest init (#issue93)
name = hasattr(os, 'dup') and 'StdCaptureFD' or 'StdCapture'
@ -300,6 +282,10 @@ class Config(object):
def _preparse(self, args):
self.inicfg = getcfg(args, ["setup.cfg", "tox.ini",])
if self.inicfg:
newargs = self.inicfg.get("addargs", None)
if newargs:
args[:] = args + py.std.shlex.split(newargs)
self._checkversion()
self.pluginmanager.consider_setuptools_entrypoints()
self.pluginmanager.consider_env()
@ -325,10 +311,6 @@ class Config(object):
"can only parse cmdline args at most once per Config object")
self._preparse(args)
self._parser.hints.extend(self.pluginmanager._hints)
if self.inicfg:
newargs = self.inicfg.get("appendargs", None)
if newargs:
args += py.std.shlex.split(newargs)
args = self._parser.parse_setoption(args, self.option)
if not args:
args.append(py.std.os.getcwd())

View File

@ -1,12 +1,15 @@
""" provide version info, conftest/environment config names.
"""
import py
import pytest
import inspect, sys
def pytest_addoption(parser):
group = parser.getgroup('debugconfig')
group.addoption('--version', action="store_true",
help="display py lib version and import information.")
group._addoption("-h", "--help", action="store_true", dest="help",
help="show help message and configuration info")
group._addoption('-p', action="append", dest="plugins", default = [],
metavar="name",
help="early-load given plugin (multi-allowed).")
@ -19,56 +22,47 @@ def pytest_addoption(parser):
group.addoption('--debug',
action="store_true", dest="debug", default=False,
help="generate and show internal debugging information.")
group.addoption("--help-config", action="store_true", dest="helpconfig",
help="show available conftest.py and ENV-variable names.")
def pytest_cmdline_main(config):
if config.option.version:
p = py.path.local(py.__file__).dirpath()
p = py.path.local(pytest.__file__).dirpath()
sys.stderr.write("This is py.test version %s, imported from %s\n" %
(py.__version__, p))
return 0
elif config.option.helpconfig:
elif config.option.help:
config.pluginmanager.do_configure(config)
showpluginhelp(config)
showhelp(config)
return 0
def showpluginhelp(config):
options = []
for group in config._parser._groups:
options.extend(group.options)
widths = [0] * 10
def showhelp(config):
tw = py.io.TerminalWriter()
tw.sep("-")
tw.line("%-13s | %-18s | %-25s | %s" %(
"cmdline name", "conftest.py name", "ENV-variable name", "help"))
tw.sep("-")
tw.write(config._parser.optparser.format_help())
tw.line()
tw.line()
tw.sep( "=", "ini-settings")
tw.line("the following values can be defined in [pytest] sections of")
tw.line("setup.cfg or tox.ini files:")
tw.line()
options = [opt for opt in options if opt._long_opts]
options.sort(key=lambda x: x._long_opts)
for opt in options:
if not opt._long_opts or not opt.dest:
continue
optstrings = list(opt._long_opts) # + list(opt._short_opts)
optstrings = filter(None, optstrings)
optstring = "|".join(optstrings)
line = "%-13s | %-18s | %-25s | %s" %(
optstring,
"option_%s" % opt.dest,
"PYTEST_OPTION_%s" % opt.dest.upper(),
opt.help and opt.help or "",
)
for name, help in ini_settings:
line = " %-15s %s" %(name, help)
tw.line(line[:tw.fullwidth])
tw.line() ; tw.line()
#tw.sep( "=", "conftest.py settings")
tw.line("the following values can be defined in conftest.py files")
tw.line()
for name, help in conftest_options:
line = "%-13s | %-18s | %-25s | %s" %(
"",
name,
"",
help,
)
line = " %-15s %s" %(name, help)
tw.line(line[:tw.fullwidth])
tw.sep("-")
tw.line()
tw.sep( "=")
ini_settings = (
('addargs', 'extra command line arguments'),
('minversion', 'minimally required pytest version'),
)
conftest_options = (
('pytest_plugins', 'list of plugin names to load'),
@ -79,7 +73,9 @@ conftest_options = (
def pytest_report_header(config):
lines = []
if config.option.debug or config.option.traceconfig:
lines.append("using py lib: %s" % (py.path.local(py.__file__).dirpath()))
lines.append("using: pytest-%s pylib-%s" %
(pytest.__version__,py.__version__))
if config.option.traceconfig:
lines.append("active plugins:")
plugins = []
@ -149,12 +145,11 @@ def getargs(func):
startindex = inspect.ismethod(func) and 1 or 0
return args[startindex:]
def collectattr(obj, prefixes=("pytest_",)):
def collectattr(obj):
methods = {}
for apiname in dir(obj):
for prefix in prefixes:
if apiname.startswith(prefix):
methods[apiname] = getattr(obj, apiname)
if apiname.startswith("pytest_"):
methods[apiname] = getattr(obj, apiname)
return methods
def formatdef(func):

View File

@ -242,6 +242,9 @@ class TmpTestdir:
def makefile(self, ext, *args, **kwargs):
return self._makefile(ext, args, kwargs)
def makeini(self, source):
return self.makefile('cfg', setup=source)
def makeconftest(self, source):
return self.makepyfile(conftest=source)

View File

@ -10,11 +10,13 @@ def test_version(testdir):
'*py.test*%s*imported from*' % (py.version, )
])
def test_helpconfig(testdir):
result = testdir.runpytest("--help-config")
def test_help(testdir):
result = testdir.runpytest("--help")
assert result.ret == 0
result.stdout.fnmatch_lines([
"*cmdline*conftest*ENV*",
"*-v*verbose*",
"*ini-settings*",
"*conftest.py*",
])
def test_collectattr():

View File

@ -466,8 +466,8 @@ def test_getreportopt():
testdict.update(dict(reportchars="sfx"))
assert getreportopt(config) == "sfx"
def test_terminalreporter_reportopt_conftestsetting(testdir):
testdir.makeconftest("option_report = 'skipped'")
def test_terminalreporter_reportopt_addargs(testdir):
testdir.makeini("[pytest]\naddargs=-rs")
p = testdir.makepyfile("""
def pytest_funcarg__tr(request):
tr = request.config.pluginmanager.getplugin("terminalreporter")

View File

@ -16,19 +16,10 @@ class TestParseIni:
config._preparse([sub])
assert config.inicfg['name'] == 'value'
def test_getvalue(self, tmpdir):
tmpdir.join("setup.cfg").write(py.code.Source("""
[pytest]
verbose = True
"""))
config = Config()
config._preparse([tmpdir])
assert config.option.verbose
def test_append_parse_args(self, tmpdir):
tmpdir.join("setup.cfg").write(py.code.Source("""
[pytest]
appendargs = --verbose
addargs = --verbose
"""))
config = Config()
config.parse([tmpdir])
@ -46,32 +37,6 @@ class TestParseIni:
])
class TestConfigCmdlineParsing:
def test_parser_addoption_default_env(self, testdir, monkeypatch):
import os
config = testdir.Config()
config._preparse([testdir.tmpdir])
group = config._parser.getgroup("hello")
monkeypatch.setitem(os.environ, 'PYTEST_OPTION_OPTION1', 'True')
group.addoption("--option1", action="store_true")
assert group.options[0].default == True
monkeypatch.setitem(os.environ, 'PYTEST_OPTION_OPTION2', 'abc')
group.addoption("--option2", action="store", default="x")
assert group.options[1].default == "abc"
monkeypatch.setitem(os.environ, 'PYTEST_OPTION_OPTION3', '32')
group.addoption("--option3", action="store", type="int")
assert group.options[2].default == 32
group.addoption("--option4", action="store", type="int")
assert group.options[3].default == ("NO", "DEFAULT")
def test_parser_addoption_default_conftest(self, testdir, monkeypatch):
import os
testdir.makeconftest("option_verbose=True")
config = testdir.parseconfig()
assert config.option.verbose
def test_parsing_again_fails(self, testdir):
config = testdir.reparseconfig([testdir.tmpdir])

View File

@ -2,11 +2,11 @@ import py
from pytest.plugin import config as parseopt
class TestParser:
def test_init(self, capsys):
def test_no_help_by_default(self, capsys):
parser = parseopt.Parser(usage="xyz")
py.test.raises(SystemExit, 'parser.parse(["-h"])')
out, err = capsys.readouterr()
assert out.find("xyz") != -1
assert err.find("no such option") != -1
def test_group_add_and_get(self):
parser = parseopt.Parser()