diff --git a/doc/customize.txt b/doc/customize.txt index 121377e92..bbaae35c9 100644 --- a/doc/customize.txt +++ b/doc/customize.txt @@ -4,7 +4,7 @@ basic test configuration 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 @@ -14,23 +14,31 @@ which were registered by installed plugins. 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 will look in the following dirs for a config file:: - path/to/testdir/setup.cfg - path/to/setup.cfg - path/setup.cfg - setup.cfg - ... # up until root of filesystem + path/to/testdir/pytest.ini path/to/testdir/tox.ini + path/to/testdir/setup.cfg + path/to/pytest.ini path/to/tox.ini - path/tox.ini + path/to/setup.cfg ... # 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 ---------------------------------------------- diff --git a/pytest/main.py b/pytest/main.py index 84e9bdc6b..840868a88 100644 --- a/pytest/main.py +++ b/pytest/main.py @@ -236,6 +236,11 @@ class PluginManager(object): for hint in self._hints: 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): assert not hasattr(self, '_config') self._config = config diff --git a/pytest/plugin/config.py b/pytest/plugin/config.py index e05898c23..68807d9ed 100644 --- a/pytest/plugin/config.py +++ b/pytest/plugin/config.py @@ -21,6 +21,7 @@ class Parser: self._processopt = processopt self._usage = usage self._inidict = {} + self._ininames = [] self.hints = [] def processoption(self, option): @@ -55,12 +56,12 @@ class Parser: def parse(self, args): self.optparser = optparser = MyOptionParser(self) - groups = list(reversed(self._groups)) + [self._anonymous] + groups = self._groups + [self._anonymous] for group in groups: if group.options: desc = group.description or group.name optgroup = py.std.optparse.OptionGroup(optparser, desc) - optgroup.add_options(reversed(group.options)) + optgroup.add_options(group.options) optparser.add_option_group(optgroup) 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. """ assert type in (None, "pathlist", "args", "linelist") self._inidict[name] = (help, type, default) + self._ininames.append(name) class OptionGroup: def __init__(self, name, description="", parser=None): @@ -290,7 +292,7 @@ class Config(object): raise 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('minversion', 'minimally required pytest version') @@ -303,7 +305,7 @@ class Config(object): self.pluginmanager.consider_env() self.pluginmanager.consider_preparse(args) self._setinitialconftest(args) - self.hook.pytest_addoption(parser=self._parser) + self.pluginmanager.do_addoption(self._parser) def _checkversion(self): minver = self.inicfg.get('minversion', None) @@ -426,13 +428,16 @@ def getcfg(args, inibasenames): args = [x for x in args if str(x)[0] != "-"] if not args: args = [py.path.local()] - for inibasename in inibasenames: - for p in args: - x = findupwards(p, inibasename) - if x is not None: - iniconfig = py.iniconfig.IniConfig(x) - if 'pytest' in iniconfig.sections: - return iniconfig['pytest'] + for arg in args: + arg = py.path.local(arg) + if arg.check(): + for base in arg.parts(reverse=True): + for inibasename in inibasenames: + p = base.join(inibasename) + if p.check(): + iniconfig = py.iniconfig.IniConfig(p) + if 'pytest' in iniconfig.sections: + return iniconfig['pytest'] return {} def findupwards(current, basename): diff --git a/pytest/plugin/helpconfig.py b/pytest/plugin/helpconfig.py index 4b632cf56..d1f1ad118 100644 --- a/pytest/plugin/helpconfig.py +++ b/pytest/plugin/helpconfig.py @@ -43,7 +43,8 @@ def showhelp(config): tw.line("setup.cfg or tox.ini options to be put into [pytest] section:") 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: type = "string" spec = "%s (%s)" % (name, type) diff --git a/testing/plugin/test_genscript.py b/testing/plugin/test_genscript.py index c71ac1526..5b202adc0 100644 --- a/testing/plugin/test_genscript.py +++ b/testing/plugin/test_genscript.py @@ -28,7 +28,6 @@ def test_gen(testdir, anypython, standalone): result = standalone.run(anypython, testdir, p) assert result.ret != 0 -@py.test.mark.xfail(reason="fix-dist", run=False) def test_rundist(testdir, pytestconfig, standalone): pytestconfig.pluginmanager.skipifmissing("xdist") testdir.makepyfile(""" diff --git a/testing/plugin/test_terminal.py b/testing/plugin/test_terminal.py index 74e7f9313..371f04042 100644 --- a/testing/plugin/test_terminal.py +++ b/testing/plugin/test_terminal.py @@ -418,7 +418,6 @@ class TestTerminalFunctional: "*test_verbose_reporting.py:10: test_gen*FAIL*", ]) assert result.ret == 1 - pytest.xfail("repair xdist") pytestconfig.pluginmanager.skipifmissing("xdist") result = testdir.runpytest(p1, '-v', '-n 1') result.stdout.fnmatch_lines([ diff --git a/testing/test_config.py b/testing/test_config.py index b835d9613..dfeb2f0c2 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -40,6 +40,30 @@ class TestParseIni: "*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") def test_confcutdir(self, testdir): sub = testdir.mkdir("sub") diff --git a/tox.ini b/tox.ini index 6427d100a..a9d4c6ccc 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,6 @@ [tox] distshare={homedir}/.tox/distshare -envlist=py26,py27,py31,py27-xdist,py25,py24 +envlist=py26,py27,py31,py32,py27-xdist,py25,py24 indexserver= default http://pypi.testrun.org pypi http://pypi.python.org/simple