jxramos
jxramos

Reputation: 8266

Does pytest restrict ALL lowercase options from custom command line arguments?

I'm trying to port some command line arguments from an argparse.ArgumentParser instance into the equivalent pytest conftest.py file using pytest's pytest_addoption

Looking at the pytest help function I find 12 used single character short options, namely k, m, x, c, s, v, q, r, l, h, p, o

MacBook-Pro:~ user$ pytest --help | grep " -[a-z]"
  -k EXPRESSION         only run tests which match the given substring
                        -k 'test_method or test_other' matches all test
                        'test_method' or 'test_other', while -k 'not
  -m MARKEXPR           only run tests matching given mark expression.
                        example: -m 'mark1 and not mark2'.
  -x, --exitfirst       exit instantly on first error or failed test.
  -c file               load configuration from `file` instead of trying to
  -s                    shortcut for --capture=no.
  -v, --verbose         increase verbosity.
  -q, --quiet           decrease verbosity.
  -r chars              show extra test summary info as specified by chars
  -l, --showlocals      show locals in tracebacks (disabled by default).
  -h, --help            show help message and configuration info
  -p name               early-load given plugin (multi-allowed). To avoid
  -o [OVERRIDE_INI [OVERRIDE_INI ...]], --override-ini=[OVERRIDE_INI [OVERRIDE_INI ...]]

And yet if I attempt to define an option outside that set I get the following exception

def pytest_addoption(parser):
    parser.addoption('-b', '--build_special' )


  File "/Library/Python/2.7/site-packages/_pytest/config/argparsing.py", line 72, in addoption
    self._anonymous.addoption(*opts, **attrs)
  File "/Library/Python/2.7/site-packages/_pytest/config/argparsing.py", line 305, in addoption
    self._addoption_instance(option, shortupper=False)
  File "/Library/Python/2.7/site-packages/_pytest/config/argparsing.py", line 315, in _addoption_instance
    raise ValueError("lowercase shortoptions reserved")
ValueError: lowercase shortoptions reserved

This seems to be the case no matter the character I choose which is making me think this is just restricted behavior period.

Question: does pytest restrict any and all uses of short options?


I'm a bit baffled because when you look at the relevant pytest source

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>`_
       accepts.
    After command line parsing options are available on the pytest config
    object via ``config.option.NAME`` where ``NAME`` is usually set
    by passing a ``dest`` attribute, for example
    ``addoption("--long", dest="NAME", ...)``.
    """
    self._anonymous.addoption(*opts, **attrs)

it seems to suggest I can use the exact same syntax as argparse's add_option, which interestingly enough in the argparse documentation mentions that

Replace all optparse.OptionParser.add_option() calls with ArgumentParser.add_argument() calls.

and the add_argument documentation explicitly lists this single flag option as allowed:

The add_argument() method must know whether an optional argument, like -f or --foo, or a positional argument, like a list of filenames, is expected. The first arguments passed to add_argument() must therefore be either a series of flags, or a simple argument name. For example, an optional argument could be created like:

>>> parser.add_argument('-f', '--foo')

Upvotes: 3

Views: 973

Answers (1)

Maspe36
Maspe36

Reputation: 356

From the pytest source code...

/src/_pytest/config/argparsing.py

def _addoption_instance(self, option: "Argument", shortupper: bool = False) -> None:
    if not shortupper:
        for opt in option._short_opts:
            if opt[0] == "-" and opt[1].islower():
                raise ValueError("lowercase shortoptions reserved")
    if self.parser:
        self.parser.processoption(option)
    self.options.append(option)

Yes they restrict all lowercase short options

Upvotes: 2

Related Questions