refine initilization: read config also from a "pytest.ini" file if exists

and revert earlier commandline option and group ordering change.
This commit is contained in:
holger krekel 2010-11-07 16:10:22 +01:00
parent fefac66079
commit 55dff651f4
8 changed files with 65 additions and 24 deletions

View File

@ -4,7 +4,7 @@ basic test configuration
Command line options and configuration file settings Command line options and configuration file settings
----------------------------------------------------------------- -----------------------------------------------------------------
You can get help on options and configuration options by running:: You can get help on options and ini-config values by running::
py.test -h # prints options _and_ config file settings py.test -h # prints options _and_ config file settings
@ -14,23 +14,31 @@ which were registered by installed plugins.
how test configuration is read from setup/tox ini-files how test configuration is read from setup/tox ini-files
-------------------------------------------------------- --------------------------------------------------------
py.test looks for the first ``[pytest]`` section in either the first ``setup.cfg`` or the first ``tox.ini`` file found upwards from the arguments. Example:: py.test searched for the first matching ini-style configuration file
in the directories of command line argument and the directories above.
It looks for filenames in this order::
pytest.ini
tox.ini
setup.cfg
Searching stops when the first ``[pytest]`` section is found.
There is no merging of configuration values from multiple files. Example::
py.test path/to/testdir py.test path/to/testdir
will look in the following dirs for a config file:: will look in the following dirs for a config file::
path/to/testdir/setup.cfg path/to/testdir/pytest.ini
path/to/setup.cfg
path/setup.cfg
setup.cfg
... # up until root of filesystem
path/to/testdir/tox.ini path/to/testdir/tox.ini
path/to/testdir/setup.cfg
path/to/pytest.ini
path/to/tox.ini path/to/tox.ini
path/tox.ini path/to/setup.cfg
... # up until root of filesystem ... # up until root of filesystem
If no path was provided at all the current working directory is used for the lookup. If argument is provided to a py.test run, the current working directory
is used to start the search.
builtin configuration file options builtin configuration file options
---------------------------------------------- ----------------------------------------------

View File

@ -236,6 +236,11 @@ class PluginManager(object):
for hint in self._hints: for hint in self._hints:
tw.line("hint: %s" % hint) tw.line("hint: %s" % hint)
def do_addoption(self, parser):
mname = "pytest_addoption"
methods = reversed(self.listattr(mname))
MultiCall(methods, {'parser': parser}).execute()
def do_configure(self, config): def do_configure(self, config):
assert not hasattr(self, '_config') assert not hasattr(self, '_config')
self._config = config self._config = config

View File

@ -21,6 +21,7 @@ class Parser:
self._processopt = processopt self._processopt = processopt
self._usage = usage self._usage = usage
self._inidict = {} self._inidict = {}
self._ininames = []
self.hints = [] self.hints = []
def processoption(self, option): def processoption(self, option):
@ -55,12 +56,12 @@ class Parser:
def parse(self, args): def parse(self, args):
self.optparser = optparser = MyOptionParser(self) self.optparser = optparser = MyOptionParser(self)
groups = list(reversed(self._groups)) + [self._anonymous] groups = self._groups + [self._anonymous]
for group in groups: for group in groups:
if group.options: if group.options:
desc = group.description or group.name desc = group.description or group.name
optgroup = py.std.optparse.OptionGroup(optparser, desc) optgroup = py.std.optparse.OptionGroup(optparser, desc)
optgroup.add_options(reversed(group.options)) optgroup.add_options(group.options)
optparser.add_option_group(optgroup) optparser.add_option_group(optgroup)
return self.optparser.parse_args([str(x) for x in args]) return self.optparser.parse_args([str(x) for x in args])
@ -74,6 +75,7 @@ class Parser:
""" add an ini-file option with the given name and description. """ """ add an ini-file option with the given name and description. """
assert type in (None, "pathlist", "args", "linelist") assert type in (None, "pathlist", "args", "linelist")
self._inidict[name] = (help, type, default) self._inidict[name] = (help, type, default)
self._ininames.append(name)
class OptionGroup: class OptionGroup:
def __init__(self, name, description="", parser=None): def __init__(self, name, description="", parser=None):
@ -290,7 +292,7 @@ class Config(object):
raise raise
def _initini(self, args): def _initini(self, args):
self.inicfg = getcfg(args, ["setup.cfg", "tox.ini",]) self.inicfg = getcfg(args, ["pytest.ini", "tox.ini", "setup.cfg"])
self._parser.addini('addopts', 'extra command line options', 'args') self._parser.addini('addopts', 'extra command line options', 'args')
self._parser.addini('minversion', 'minimally required pytest version') self._parser.addini('minversion', 'minimally required pytest version')
@ -303,7 +305,7 @@ class Config(object):
self.pluginmanager.consider_env() self.pluginmanager.consider_env()
self.pluginmanager.consider_preparse(args) self.pluginmanager.consider_preparse(args)
self._setinitialconftest(args) self._setinitialconftest(args)
self.hook.pytest_addoption(parser=self._parser) self.pluginmanager.do_addoption(self._parser)
def _checkversion(self): def _checkversion(self):
minver = self.inicfg.get('minversion', None) minver = self.inicfg.get('minversion', None)
@ -426,11 +428,14 @@ def getcfg(args, inibasenames):
args = [x for x in args if str(x)[0] != "-"] args = [x for x in args if str(x)[0] != "-"]
if not args: if not args:
args = [py.path.local()] args = [py.path.local()]
for arg in args:
arg = py.path.local(arg)
if arg.check():
for base in arg.parts(reverse=True):
for inibasename in inibasenames: for inibasename in inibasenames:
for p in args: p = base.join(inibasename)
x = findupwards(p, inibasename) if p.check():
if x is not None: iniconfig = py.iniconfig.IniConfig(p)
iniconfig = py.iniconfig.IniConfig(x)
if 'pytest' in iniconfig.sections: if 'pytest' in iniconfig.sections:
return iniconfig['pytest'] return iniconfig['pytest']
return {} return {}

View File

@ -43,7 +43,8 @@ def showhelp(config):
tw.line("setup.cfg or tox.ini options to be put into [pytest] section:") tw.line("setup.cfg or tox.ini options to be put into [pytest] section:")
tw.line() tw.line()
for name, (help, type, default) in sorted(config._parser._inidict.items()): for name in config._parser._ininames:
help, type, default = config._parser._inidict[name]
if type is None: if type is None:
type = "string" type = "string"
spec = "%s (%s)" % (name, type) spec = "%s (%s)" % (name, type)

View File

@ -28,7 +28,6 @@ def test_gen(testdir, anypython, standalone):
result = standalone.run(anypython, testdir, p) result = standalone.run(anypython, testdir, p)
assert result.ret != 0 assert result.ret != 0
@py.test.mark.xfail(reason="fix-dist", run=False)
def test_rundist(testdir, pytestconfig, standalone): def test_rundist(testdir, pytestconfig, standalone):
pytestconfig.pluginmanager.skipifmissing("xdist") pytestconfig.pluginmanager.skipifmissing("xdist")
testdir.makepyfile(""" testdir.makepyfile("""

View File

@ -418,7 +418,6 @@ class TestTerminalFunctional:
"*test_verbose_reporting.py:10: test_gen*FAIL*", "*test_verbose_reporting.py:10: test_gen*FAIL*",
]) ])
assert result.ret == 1 assert result.ret == 1
pytest.xfail("repair xdist")
pytestconfig.pluginmanager.skipifmissing("xdist") pytestconfig.pluginmanager.skipifmissing("xdist")
result = testdir.runpytest(p1, '-v', '-n 1') result = testdir.runpytest(p1, '-v', '-n 1')
result.stdout.fnmatch_lines([ result.stdout.fnmatch_lines([

View File

@ -40,6 +40,30 @@ class TestParseIni:
"*tox.ini:2*requires*9.0*actual*" "*tox.ini:2*requires*9.0*actual*"
]) ])
@py.test.mark.multi(name="setup.cfg tox.ini pytest.ini".split())
def test_ini_names(self, testdir, name):
testdir.tmpdir.join(name).write(py.std.textwrap.dedent("""
[pytest]
minversion = 1.0
"""))
config = Config()
config.parse([testdir.tmpdir])
assert config.getini("minversion") == "1.0"
def test_toxini_before_lower_pytestini(self, testdir):
sub = testdir.tmpdir.mkdir("sub")
sub.join("tox.ini").write(py.std.textwrap.dedent("""
[pytest]
minversion = 2.0
"""))
testdir.tmpdir.join("pytest.ini").write(py.std.textwrap.dedent("""
[pytest]
minversion = 1.5
"""))
config = Config()
config.parse([sub])
assert config.getini("minversion") == "2.0"
@py.test.mark.xfail(reason="probably not needed") @py.test.mark.xfail(reason="probably not needed")
def test_confcutdir(self, testdir): def test_confcutdir(self, testdir):
sub = testdir.mkdir("sub") sub = testdir.mkdir("sub")

View File

@ -1,6 +1,6 @@
[tox] [tox]
distshare={homedir}/.tox/distshare distshare={homedir}/.tox/distshare
envlist=py26,py27,py31,py27-xdist,py25,py24 envlist=py26,py27,py31,py32,py27-xdist,py25,py24
indexserver= indexserver=
default http://pypi.testrun.org default http://pypi.testrun.org
pypi http://pypi.python.org/simple pypi http://pypi.python.org/simple