From c9e629c870a343c9bfefedd508376563e57c1783 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Wed, 27 Oct 2010 22:29:01 +0200 Subject: [PATCH] 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 --- CHANGELOG | 4 +- doc/customize.txt | 14 +++--- pytest/plugin/config.py | 46 ++++++------------- pytest/plugin/helpconfig.py | 75 +++++++++++++++---------------- pytest/plugin/pytester.py | 3 ++ testing/plugin/test_helpconfig.py | 8 ++-- testing/plugin/test_terminal.py | 4 +- testing/test_config.py | 37 +-------------- testing/test_parseopt.py | 4 +- 9 files changed, 72 insertions(+), 123 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index fc94aa771..80b93a01d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -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 diff --git a/doc/customize.txt b/doc/customize.txt index d4eb82bc7..88843556c 100644 --- a/doc/customize.txt +++ b/doc/customize.txt @@ -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 diff --git a/pytest/plugin/config.py b/pytest/plugin/config.py index 502ed7bdd..d6188dfa5 100644 --- a/pytest/plugin/config.py +++ b/pytest/plugin/config.py @@ -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()) diff --git a/pytest/plugin/helpconfig.py b/pytest/plugin/helpconfig.py index 18c810f70..7086d1072 100644 --- a/pytest/plugin/helpconfig.py +++ b/pytest/plugin/helpconfig.py @@ -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): diff --git a/pytest/plugin/pytester.py b/pytest/plugin/pytester.py index 7be9be3af..844d2e027 100644 --- a/pytest/plugin/pytester.py +++ b/pytest/plugin/pytester.py @@ -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) diff --git a/testing/plugin/test_helpconfig.py b/testing/plugin/test_helpconfig.py index ae49e45f0..e43df0541 100644 --- a/testing/plugin/test_helpconfig.py +++ b/testing/plugin/test_helpconfig.py @@ -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(): diff --git a/testing/plugin/test_terminal.py b/testing/plugin/test_terminal.py index 5e404f435..244cd0ece 100644 --- a/testing/plugin/test_terminal.py +++ b/testing/plugin/test_terminal.py @@ -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") diff --git a/testing/test_config.py b/testing/test_config.py index 1edd8ad0e..871f16955 100644 --- a/testing/test_config.py +++ b/testing/test_config.py @@ -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]) diff --git a/testing/test_parseopt.py b/testing/test_parseopt.py index 3d9672e1a..1fab2fdcb 100644 --- a/testing/test_parseopt.py +++ b/testing/test_parseopt.py @@ -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()