Skip to content

[RFC] config: addini: support choices#5968

Closed
blueyed wants to merge 1 commit intopytest-dev:featuresfrom
blueyed:addini-choices
Closed

[RFC] config: addini: support choices#5968
blueyed wants to merge 1 commit intopytest-dev:featuresfrom
blueyed:addini-choices

Conversation

@blueyed
Copy link
Contributor

@blueyed blueyed commented Oct 16, 2019

Fixes #5057.

TODO:

@blueyed blueyed added topic: config related to config handling, argument parsing and config file type: enhancement new feature or API change, should be merged into features branch labels Oct 16, 2019
@blueyed blueyed changed the title config: addini: support choices [RFC] config: addini: support choices Oct 16, 2019
Copy link
Member

@nicoddemus nicoddemus left a comment

Choose a reason for hiding this comment

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

This looks great as a start, thanks!

Besides what you already mention in your TODO: list in the description, we should add an example to the documentation too.

raise

if ns.override_ini:
for ini_config in ns.override_ini:
Copy link
Member

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_value to avoid duplication?

Copy link
Contributor Author

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.

Copy link
Member

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

Copy link
Member

Choose a reason for hiding this comment

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

Sure.

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):
Copy link
Member

Choose a reason for hiding this comment

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

Let's take this opportunity and make choices keyword-only

Suggested change
def addini(self, name, help, type=None, default=None, choices=None):
def addini(self, name, help, type=None, default=None, *, choices=None):

:type: type of the variable, can be ``pathlist``, ``args``, ``linelist``
or ``bool``.
:type: type of the variable, can be ``pathlist``, ``args``, ``linelist``,
``bool``, or ``type``.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
``bool``, or ``type``.
``"bool"``, or ``"choice"``.

?

: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``,
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
:type: type of the variable, can be ``pathlist``, ``args``, ``linelist``,
:type: type of the variable, can be ``"pathlist"``, ``"args"``, ``"linelist"``,

"""
assert type in (None, "pathlist", "args", "linelist", "bool")
self._inidict[name] = (help, type, default)
# TODO: callable type?
Copy link
Member

Choose a reason for hiding this comment

The 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?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It was meant to work like type in argparse then - which is more universal than having choices (only).

Copy link
Member

Choose a reason for hiding this comment

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

Oh I thought you meant choices being able to be a callable, my bad.

We can add type here no problem, following the same semantics that type and choices have in argparser. I will leave this up to you if you prefer to do this in this PR or do it separately.

self._processopt = processopt
self._usage = usage
self._inidict = {} # type: Dict[str, Tuple[str, Optional[str], Any]]
self._inidict = (
Copy link
Member

Choose a reason for hiding this comment

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

I think this have grown enough to deserve a namedtuple or attrs instance. What do you think?

"""
)
config = testdir.parseconfig()
assert config.getini("mychoice") == "def"
Copy link
Member

Choose a reason for hiding this comment

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

I think the user should explicitly state "def" in the choices list.

print('\\nmychoice:%s\\n' % ini_val)"""
)
result = testdir.runpytest("-s", str(p1))
result.stdout.fnmatch_lines(
Copy link
Member

Choose a reason for hiding this comment

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

This seems to be tested by the previous with pytest.raises already

)
assert result.ret == ExitCode.TESTS_FAILED

p1 = testdir.makepyfile(
Copy link
Member

@nicoddemus nicoddemus Oct 22, 2019

Choose a reason for hiding this comment

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

I usually prefer to set the data in some module (say sys) and inspect it later:

        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.OK

But it is merely a comment in case you like this approach.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

topic: config related to config handling, argument parsing and config file type: enhancement new feature or API change, should be merged into features branch

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants