Skip to content

Commit 4e1609b

Browse files
committed
Add type validation.
Argparse driven argument type validation is added for the `--junit-xml` and `--confcutdir` arguments. The commit partially reverts #2080. Closes #2089.
1 parent 0735d45 commit 4e1609b

File tree

5 files changed

+37
-9
lines changed

5 files changed

+37
-9
lines changed

CHANGELOG.rst

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
3.0.5.dev0
22
==========
33

4+
* Now ``--confcutdir`` and ``--junit-xml`` are properly validated if they are directories
5+
and filenames, respectively (`#2089`_ and `#2078`_). Thanks to `@lwm`_ for the PR.
6+
47
* Add hint to error message hinting possible missing ``__init__.py`` (`#478`_). Thanks `@DuncanBetts`_.
58

69
* Provide ``:ref:`` targets for ``recwarn.rst`` so we can use intersphinx referencing.
@@ -10,10 +13,6 @@
1013
``pytest.Function``, ``pytest.Module``, etc., instead (`#2034`_).
1114
Thanks `@nmundar`_ for the PR.
1215

13-
* An error message is now displayed if ``--confcutdir`` is not a valid directory, avoiding
14-
subtle bugs (`#2078`_).
15-
Thanks `@nicoddemus`_ for the PR.
16-
1716
* Fix error message using ``approx`` with complex numbers (`#2082`_).
1817
Thanks `@adler-j`_ for the report and `@nicoddemus`_ for the PR.
1918

@@ -33,6 +32,7 @@
3332
.. _@nedbat: https://github.com/nedbat
3433
.. _@nmundar: https://github.com/nmundar
3534

35+
.. _#2089: https://github.com/pytest-dev/pytest/issues/2089
3636
.. _#478: https://github.com/pytest-dev/pytest/issues/478
3737
.. _#2034: https://github.com/pytest-dev/pytest/issues/2034
3838
.. _#2038: https://github.com/pytest-dev/pytest/issues/2038

_pytest/config.py

+23-4
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,28 @@ class UsageError(Exception):
7070
""" error in pytest usage or invocation"""
7171

7272

73+
def filename_arg(path, optname):
74+
""" Argparse type validator for filename arguments.
75+
76+
:path: path of filename
77+
:optname: name of the option
78+
"""
79+
if os.path.isdir(path):
80+
raise UsageError("{0} must be a filename, given: {1}".format(optname, path))
81+
return path
82+
83+
84+
def directory_arg(path, optname):
85+
"""Argparse type validator for directory arguments.
86+
87+
:path: path of directory
88+
:optname: name of the option
89+
"""
90+
if not os.path.isdir(path):
91+
raise UsageError("{0} must be a directory, given: {1}".format(optname, path))
92+
return path
93+
94+
7395
_preinit = []
7496

7597
default_plugins = (
@@ -996,7 +1018,6 @@ def _warn_about_missing_assertion(self, mode):
9961018
"(are you using python -O?)\n")
9971019

9981020
def _preparse(self, args, addopts=True):
999-
import pytest
10001021
self._initini(args)
10011022
if addopts:
10021023
args[:] = shlex.split(os.environ.get('PYTEST_ADDOPTS', '')) + args
@@ -1009,9 +1030,7 @@ def _preparse(self, args, addopts=True):
10091030
self.pluginmanager.consider_env()
10101031
self.known_args_namespace = ns = self._parser.parse_known_args(args, namespace=self.option.copy())
10111032
confcutdir = self.known_args_namespace.confcutdir
1012-
if confcutdir and not os.path.isdir(confcutdir):
1013-
raise pytest.UsageError('--confcutdir must be a directory, given: {0}'.format(confcutdir))
1014-
if confcutdir is None and self.inifile:
1033+
if self.known_args_namespace.confcutdir is None and self.inifile:
10151034
confcutdir = py.path.local(self.inifile).dirname
10161035
self.known_args_namespace.confcutdir = confcutdir
10171036
try:

_pytest/junitxml.py

+3
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,14 @@
88
# Output conforms to https://github.com/jenkinsci/xunit-plugin/blob/master/
99
# src/main/resources/org/jenkinsci/plugins/xunit/types/model/xsd/junit-10.xsd
1010

11+
import functools
1112
import py
1213
import os
1314
import re
1415
import sys
1516
import time
1617
import pytest
18+
from _pytest.config import filename_arg
1719

1820
# Python 2.X and 3.X compatibility
1921
if sys.version_info[0] < 3:
@@ -214,6 +216,7 @@ def pytest_addoption(parser):
214216
action="store",
215217
dest="xmlpath",
216218
metavar="path",
219+
type=functools.partial(filename_arg, optname="--junitxml"),
217220
default=None,
218221
help="create junit-xml style report file at given path.")
219222
group.addoption(

_pytest/main.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
""" core implementation of testing process: init, session, runtest loop. """
2+
import functools
23
import os
34
import sys
45

@@ -11,6 +12,7 @@
1112
except ImportError:
1213
from UserDict import DictMixin as MappingMixin
1314

15+
from _pytest.config import directory_arg
1416
from _pytest.runner import collect_one_node
1517

1618
tracebackcutdir = py.path.local(_pytest.__file__).dirpath()
@@ -58,7 +60,7 @@ def pytest_addoption(parser):
5860
# when changing this to --conf-cut-dir, config.py Conftest.setinitial
5961
# needs upgrading as well
6062
group.addoption('--confcutdir', dest="confcutdir", default=None,
61-
metavar="dir",
63+
metavar="dir", type=functools.partial(directory_arg, optname="--confcutdir"),
6264
help="only load conftest.py's relative to specified dir.")
6365
group.addoption('--noconftest', action="store_true",
6466
dest="noconftest", default=False,

testing/test_junitxml.py

+4
Original file line numberDiff line numberDiff line change
@@ -715,6 +715,10 @@ def test_pass():
715715
assert result.ret == 0
716716
assert testdir.tmpdir.join("path/to/results.xml").check()
717717

718+
def test_logxml_check_isdir(testdir):
719+
"""Give an error if --junit-xml is a directory (#2089)"""
720+
result = testdir.runpytest("--junit-xml=.")
721+
result.stderr.fnmatch_lines(["*--junitxml must be a filename*"])
718722

719723
def test_escaped_parametrized_names_xml(testdir):
720724
testdir.makepyfile("""

0 commit comments

Comments
 (0)