-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
[RFC] config: addini: support choices #5968
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -29,7 +29,9 @@ def __init__(self, usage=None, processopt=None): | |||||
| self._groups = [] # type: List[OptionGroup] | ||||||
| self._processopt = processopt | ||||||
| self._usage = usage | ||||||
| self._inidict = {} # type: Dict[str, Tuple[str, Optional[str], Any]] | ||||||
| self._inidict = ( | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this have grown enough to deserve a |
||||||
| {} | ||||||
| ) # type: Dict[str, Tuple[str, Optional[str], Any, Optional[List]]] | ||||||
| self._ininames = [] # type: List[str] | ||||||
| self.extra_info = {} # type: Dict[str, Any] | ||||||
|
|
||||||
|
|
@@ -65,9 +67,8 @@ def addoption(self, *opts, **attrs): | |||||
| """ register a command line option. | ||||||
|
|
||||||
| :opts: option names, can be short or long options. | ||||||
| :attrs: same attributes which the ``add_option()`` function of the | ||||||
| `argparse library | ||||||
| <http://docs.python.org/2/library/argparse.html>`_ | ||||||
| :attrs: same attributes which the ``add_argument()`` function of the | ||||||
| `argparse library <https://docs.python.org/3.7/library/argparse.html>`_ | ||||||
| accepts. | ||||||
|
|
||||||
| After command line parsing options are available on the pytest config | ||||||
|
|
@@ -127,19 +128,24 @@ def parse_known_and_unknown_args( | |||||
| args = [str(x) if isinstance(x, py.path.local) else x for x in args] | ||||||
| return optparser.parse_known_args(args, namespace=namespace) | ||||||
|
|
||||||
| def addini(self, name, help, type=None, default=None): | ||||||
| def addini(self, name, help, type=None, default=None, choices=None): | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's take this opportunity and make
Suggested change
|
||||||
| """ register an ini-file option. | ||||||
|
|
||||||
| :name: name of the ini-variable | ||||||
| :type: type of the variable, can be ``pathlist``, ``args``, ``linelist`` | ||||||
| or ``bool``. | ||||||
| :type: type of the variable, can be ``pathlist``, ``args``, ``linelist``, | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| ``bool``, or ``type``. | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
? |
||||||
| :default: default value if no ini-file option exists but is queried. | ||||||
|
|
||||||
| The value of ini-variables can be retrieved via a call to | ||||||
| :py:func:`config.getini(name) <_pytest.config.Config.getini>`. | ||||||
| """ | ||||||
| assert type in (None, "pathlist", "args", "linelist", "bool") | ||||||
| self._inidict[name] = (help, type, default) | ||||||
| # TODO: callable type? | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure we need to make this a callable, after all the user can always call the callable before passing the choices to this function... or do you have a specific use case in mind?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It was meant to work like
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh I thought you meant We can add |
||||||
| if type == "choice": | ||||||
| if choices is None: | ||||||
| raise ValueError("need to pass choices with type=choice") | ||||||
| else: | ||||||
| assert type in (None, "pathlist", "args", "linelist", "bool") | ||||||
| self._inidict[name] = (help, type, default, choices) | ||||||
| self._ininames.append(name) | ||||||
|
|
||||||
|
|
||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -365,6 +365,52 @@ def pytest_addoption(parser): | |
| config = testdir.parseconfig() | ||
| assert config.getini("strip") is bool_val | ||
|
|
||
| def test_addini_choices(self, testdir): | ||
| testdir.makeconftest( | ||
| """ | ||
| def pytest_addoption(parser): | ||
| parser.addini("mychoice", "", type="choice", default="def", choices=["one", "two"]) | ||
| """ | ||
| ) | ||
| config = testdir.parseconfig() | ||
| assert config.getini("mychoice") == "def" | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the user should explicitly state |
||
|
|
||
| testdir.makeini( | ||
| """ | ||
| [pytest] | ||
| mychoice=invalid | ||
| """ | ||
| ) | ||
| config = testdir.parseconfig() | ||
| with pytest.raises(UsageError, match="invalid value for mychoice: 'invalid'"): | ||
| config.getini("mychoice") | ||
|
|
||
| p1 = testdir.makepyfile( | ||
| """ | ||
| def test_pass(pytestconfig): | ||
| ini_val = pytestconfig.getini("mychoice") | ||
| print('\\nmychoice:%s\\n' % ini_val)""" | ||
| ) | ||
| result = testdir.runpytest("-s", str(p1)) | ||
| result.stdout.fnmatch_lines( | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems to be tested by the previous |
||
| ["E *UsageError: invalid value for mychoice: 'invalid'", "*= 1 failed in *"] | ||
| ) | ||
| assert result.ret == ExitCode.TESTS_FAILED | ||
|
|
||
| p1 = testdir.makepyfile( | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I usually prefer to set the data in some module (say monkeypatch.setattr(sys, "MY_INI_VAL", None, raising=False)
p1 = testdir.makepyfile(
"""
import sys
def test_pass(pytestconfig):
ini_val = pytestconfig.getini("mychoice")
sys.MY_INI_VAL = pytestconfig.getini("mychoice")
print('\\nmychoice:%s\\n' % ini_val)"""
)
result = testdir.runpytest("-s", "-o", "mychoice=one", str(p1))
assert sys.MY_INI_VAL == "one"
assert result.ret == ExitCode.OKBut it is merely a comment in case you like this approach. |
||
| """ | ||
| def test_pass(pytestconfig): | ||
| ini_val = pytestconfig.getini("mychoice") | ||
| print('\\nmychoice:%s\\n' % ini_val)""" | ||
| ) | ||
| result = testdir.runpytest("-s", "-o", "mychoice=one", str(p1)) | ||
| result.stdout.fnmatch_lines(["mychoice:one"]) | ||
| assert result.ret == ExitCode.OK | ||
|
|
||
| result = testdir.runpytest("-o", "mychoice=invalid2", str(p1)) | ||
| result.stderr.fnmatch_lines(["ERROR: invalid value for mychoice: 'invalid2'"]) | ||
| assert result.ret == ExitCode.USAGE_ERROR | ||
|
|
||
| def test_addinivalue_line_existing(self, testdir): | ||
| testdir.makeconftest( | ||
| """ | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion: can we please move all the validation code to a separate function, and make that function reuse the work done by
_validate_ini_valueto avoid duplication?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe, but I would also rather like to keep this "minimal" / "a no brainer" patch for now.
Can be refactored in the end maybe then.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yup, please add a follow-up issue
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure.