Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support [tool:pytest] in setup.cfg files #1813

Merged
merged 1 commit into from
Aug 17, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,11 @@ time or change existing behaviors in order to make them less surprising/more use
* ``yield``-based tests are considered deprecated and will be removed in pytest-4.0.
Thanks `@nicoddemus`_ for the PR.

* ``[pytest]`` sections in ``setup.cfg`` files should now be named ``[tool:pytest]``
to avoid conflicts with other distutils commands (see `#567`_). ``[pytest]`` sections in
``pytest.ini`` or ``tox.ini`` files are supported and unchanged.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick (feel free to ignore): "[pytest] sections in ...." or "is supported"

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, thanks, it is better really.

Thanks `@nicoddemus`_ for the PR.

* Using ``pytest_funcarg__`` prefix to declare fixtures is considered deprecated and will be
removed in pytest-4.0 (`#1684`_).
Thanks `@nicoddemus`_ for the PR.
Expand Down Expand Up @@ -374,6 +379,7 @@ time or change existing behaviors in order to make them less surprising/more use
.. _#372: https://github.com/pytest-dev/pytest/issues/372
.. _#457: https://github.com/pytest-dev/pytest/issues/457
.. _#460: https://github.com/pytest-dev/pytest/pull/460
.. _#567: https://github.com/pytest-dev/pytest/pull/567
.. _#607: https://github.com/pytest-dev/pytest/issues/607
.. _#634: https://github.com/pytest-dev/pytest/issues/634
.. _#717: https://github.com/pytest-dev/pytest/issues/717
Expand Down
27 changes: 20 additions & 7 deletions _pytest/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -927,7 +927,7 @@ def pytest_load_initial_conftests(self, early_config):

def _initini(self, args):
ns, unknown_args = self._parser.parse_known_and_unknown_args(args, namespace=self.option.copy())
r = determine_setup(ns.inifilename, ns.file_or_dir + unknown_args)
r = determine_setup(ns.inifilename, ns.file_or_dir + unknown_args, warnfunc=self.warn)
self.rootdir, self.inifile, self.inicfg = r
self._parser.extra_info['rootdir'] = self.rootdir
self._parser.extra_info['inifile'] = self.inifile
Expand Down Expand Up @@ -1154,7 +1154,18 @@ def exists(path, ignore=EnvironmentError):
except ignore:
return False

def getcfg(args, inibasenames):
def getcfg(args, warnfunc=None):
"""
Search the list of arguments for a valid ini-file for pytest,
and return a tuple of (rootdir, inifile, cfg-dict).
note: warnfunc is an optional function used to warn
about ini-files that use deprecated features.
This parameter should be removed when pytest
adopts standard deprecation warnings (#1804).
"""
from _pytest.deprecated import SETUP_CFG_PYTEST
inibasenames = ["pytest.ini", "tox.ini", "setup.cfg"]
args = [x for x in args if not str(x).startswith("-")]
if not args:
args = [py.path.local()]
Expand All @@ -1166,7 +1177,11 @@ def getcfg(args, inibasenames):
if exists(p):
iniconfig = py.iniconfig.IniConfig(p)
if 'pytest' in iniconfig.sections:
if inibasename == 'setup.cfg' and warnfunc:
warnfunc('C1', SETUP_CFG_PYTEST)
return base, p, iniconfig['pytest']
if inibasename == 'setup.cfg' and 'tool:pytest' in iniconfig.sections:
return base, p, iniconfig['tool:pytest']
elif inibasename == "pytest.ini":
# allowed to be empty
return base, p, {}
Expand Down Expand Up @@ -1207,7 +1222,7 @@ def get_dirs_from_args(args):
if d.exists()]


def determine_setup(inifile, args):
def determine_setup(inifile, args, warnfunc=None):
dirs = get_dirs_from_args(args)
if inifile:
iniconfig = py.iniconfig.IniConfig(inifile)
Expand All @@ -1218,15 +1233,13 @@ def determine_setup(inifile, args):
rootdir = get_common_ancestor(dirs)
else:
ancestor = get_common_ancestor(dirs)
rootdir, inifile, inicfg = getcfg(
[ancestor], ["pytest.ini", "tox.ini", "setup.cfg"])
rootdir, inifile, inicfg = getcfg([ancestor], warnfunc=warnfunc)
if rootdir is None:
for rootdir in ancestor.parts(reverse=True):
if rootdir.join("setup.py").exists():
break
else:
rootdir, inifile, inicfg = getcfg(
dirs, ["pytest.ini", "tox.ini", "setup.cfg"])
rootdir, inifile, inicfg = getcfg(dirs, warnfunc=warnfunc)
if rootdir is None:
rootdir = get_common_ancestor([py.path.local(), ancestor])
is_fs_root = os.path.splitdrive(str(rootdir))[1] == os.sep
Expand Down
2 changes: 2 additions & 0 deletions _pytest/deprecated.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,7 @@
'and scheduled to be removed in pytest 4.0. '
'Please remove the prefix and use the @pytest.fixture decorator instead.')

SETUP_CFG_PYTEST = '[pytest] section in setup.cfg files is deprecated, use [tool:pytest] instead.'

GETFUNCARGVALUE = "use of getfuncargvalue is deprecated, use getfixturevalue"

1 change: 0 additions & 1 deletion _pytest/helpconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ def showhelp(config):
tw.write(config._parser.optparser.format_help())
tw.line()
tw.line()
#tw.sep( "=", "config file settings")
tw.line("[pytest] ini-options in the next "
"pytest.ini|tox.ini|setup.cfg file:")
tw.line()
Expand Down
6 changes: 3 additions & 3 deletions doc/en/customize.rst
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ Here is the algorithm which finds the rootdir from ``args``:

Note that an existing ``pytest.ini`` file will always be considered a match,
whereas ``tox.ini`` and ``setup.cfg`` will only match if they contain a
``[pytest]`` section. Options from multiple ini-files candidates are never
``[pytest]`` or ``[tool:pytest]`` section, respectively. Options from multiple ini-files candidates are never
merged - the first one wins (``pytest.ini`` always wins, even if it does not
contain a ``[pytest]`` section).

Expand All @@ -73,7 +73,7 @@ check for ini-files as follows::

# first look for pytest.ini files
path/pytest.ini
path/setup.cfg # must also contain [pytest] section to match
path/setup.cfg # must also contain [tool:pytest] section to match
path/tox.ini # must also contain [pytest] section to match
pytest.ini
... # all the way down to the root
Expand Down Expand Up @@ -154,7 +154,7 @@ Builtin configuration file options

.. code-block:: ini
# content of setup.cfg
# content of pytest.ini
[pytest]
norecursedirs = .svn _build tmp*
Expand Down
9 changes: 5 additions & 4 deletions doc/en/example/pythoncollection.rst
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,9 @@ Example::
Changing directory recursion
-----------------------------------------------------

You can set the :confval:`norecursedirs` option in an ini-file, for example your ``setup.cfg`` in the project root directory::
You can set the :confval:`norecursedirs` option in an ini-file, for example your ``pytest.ini`` in the project root directory::

# content of setup.cfg
# content of pytest.ini
[pytest]
norecursedirs = .svn _build tmp*

Expand All @@ -94,8 +94,9 @@ You can configure different naming conventions by setting
the :confval:`python_files`, :confval:`python_classes` and
:confval:`python_functions` configuration options. Example::

# content of setup.cfg
# can also be defined in in tox.ini or pytest.ini file
# content of pytest.ini
# can also be defined in in tox.ini or setup.cfg file, although the section
# name in setup.cfg files should be "tool:pytest"
[pytest]
python_files=check_*.py
python_classes=Check
Expand Down
18 changes: 18 additions & 0 deletions doc/en/goodpractices.rst
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,24 @@ required for calling the test command. You can also pass additional
arguments to pytest such as your test directory or other
options using ``--addopts``.

You can also specify other pytest-ini options in your ``setup.cfg`` file
by putting them into a ``[tool:pytest]`` section:

.. code-block:: ini

[tool:pytest]
addopts = --verbose
python_files = testing/*/*.py


.. note::
Prior to 3.0, the supported section name was ``[pytest]``. Due to how
this may collide with some distutils commands, the recommended
section name for ``setup.cfg`` files is now ``[tool:pytest]``.

Note that for ``pytest.ini`` and ``tox.ini`` files the section
name is ``[pytest]``.


Manual Integration
^^^^^^^^^^^^^^^^^^
Expand Down
4 changes: 2 additions & 2 deletions doc/en/xdist.rst
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ and ``pytest`` will run your tests. Assuming you have failures it will then
wait for file changes and re-run the failing test set. File changes are detected by looking at ``looponfailingroots`` root directories and all of their contents (recursively). If the default for this value does not work for you you
can change it in your project by setting a configuration option::

# content of a pytest.ini, setup.cfg or tox.ini file
# content of a pytest.ini or tox.ini file
[pytest]
looponfailroots = mypkg testdir

Expand Down Expand Up @@ -181,7 +181,7 @@ to run tests in each of the environments.
Specifying "rsync" dirs in an ini-file
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

In a ``tox.ini`` or ``setup.cfg`` file in your root project directory
In a ``pytest.ini`` or ``tox.ini`` file in your root project directory
you may specify directories to include or to exclude in synchronisation::

[pytest]
Expand Down
9 changes: 9 additions & 0 deletions testing/deprecated_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,15 @@ def test_funcarg_prefix(value):
])


def test_pytest_setup_cfg_deprecated(testdir):
testdir.makefile('.cfg', setup='''
[pytest]
addopts = --verbose
''')
result = testdir.runpytest()
result.stdout.fnmatch_lines(['*pytest*section in setup.cfg files is deprecated*use*tool:pytest*instead*'])


def test_str_args_deprecated(tmpdir, testdir):
"""Deprecate passing strings to pytest.main(). Scheduled for removal in pytest-4.0."""
from _pytest.main import EXIT_NOTESTSCOLLECTED
Expand Down
36 changes: 20 additions & 16 deletions testing/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,28 @@
from _pytest.main import EXIT_NOTESTSCOLLECTED

class TestParseIni:
def test_getcfg_and_config(self, testdir, tmpdir):

@pytest.mark.parametrize('section, filename',
[('pytest', 'pytest.ini'), ('tool:pytest', 'setup.cfg')])
def test_getcfg_and_config(self, testdir, tmpdir, section, filename):
sub = tmpdir.mkdir("sub")
sub.chdir()
tmpdir.join("setup.cfg").write(_pytest._code.Source("""
[pytest]
tmpdir.join(filename).write(_pytest._code.Source("""
[{section}]
name = value
"""))
rootdir, inifile, cfg = getcfg([sub], ["setup.cfg"])
""".format(section=section)))
rootdir, inifile, cfg = getcfg([sub])
assert cfg['name'] == "value"
config = testdir.parseconfigure(sub)
assert config.inicfg['name'] == 'value'

def test_getcfg_empty_path(self, tmpdir):
getcfg([''], ['setup.cfg']) #happens on pytest ""
def test_getcfg_empty_path(self):
"""correctly handle zero length arguments (a la pytest '')"""
getcfg([''])

def test_append_parse_args(self, testdir, tmpdir, monkeypatch):
monkeypatch.setenv('PYTEST_ADDOPTS', '--color no -rs --tb="short"')
tmpdir.join("setup.cfg").write(_pytest._code.Source("""
tmpdir.join("pytest.ini").write(_pytest._code.Source("""
[pytest]
addopts = --verbose
"""))
Expand All @@ -31,10 +35,6 @@ def test_append_parse_args(self, testdir, tmpdir, monkeypatch):
assert config.option.reportchars == 's'
assert config.option.tbstyle == 'short'
assert config.option.verbose
#config = testdir.Config()
#args = [tmpdir,]
#config._preparse(args, addopts=False)
#assert len(args) == 1

def test_tox_ini_wrong_version(self, testdir):
testdir.makefile('.ini', tox="""
Expand All @@ -47,12 +47,16 @@ def test_tox_ini_wrong_version(self, testdir):
"*tox.ini:2*requires*9.0*actual*"
])

@pytest.mark.parametrize("name", "setup.cfg tox.ini pytest.ini".split())
def test_ini_names(self, testdir, name):
@pytest.mark.parametrize("section, name", [
('tool:pytest', 'setup.cfg'),
('pytest', 'tox.ini'),
('pytest', 'pytest.ini')],
)
def test_ini_names(self, testdir, name, section):
testdir.tmpdir.join(name).write(py.std.textwrap.dedent("""
[pytest]
[{section}]
minversion = 1.0
"""))
""".format(section=section)))
config = testdir.parseconfig()
assert config.getini("minversion") == "1.0"

Expand Down