Skip to content

Commit

Permalink
Add special handling for optional boolean flags
Browse files Browse the repository at this point in the history
  • Loading branch information
evanunderscore committed Apr 24, 2016
1 parent 1a5151a commit 09bdead
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 0 deletions.
12 changes: 12 additions & 0 deletions defopt.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,18 @@ def _populate_parser(func, parser, parsers=None):
type_ = _get_type(func, name, doc, hints)
if param.kind == param.VAR_KEYWORD:
raise ValueError('**kwargs not supported')
if type_.type == bool and param.default != param.empty:
# Special case: just add parameterless --name and --no-name flags.
parser.add_argument('--' + name,
action='store_true',
default=param.default,
# Add help if available.
**kwargs)
parser.add_argument('--no-' + name,

This comment has been minimized.

Copy link
@flying-sheep

flying-sheep Apr 24, 2016

maybe there is a way to make this show up in the docs as --param/--no-param

This comment has been minimized.

Copy link
@evanunderscore

evanunderscore Apr 24, 2016

Author Collaborator

I'm not aware of any way to do this using argparse short of building the whole usage string myself, which I'd prefer not to do if I can avoid it.

This comment has been minimized.

Copy link
@flying-sheep

flying-sheep Apr 24, 2016

yes. well i guess it’ll do 😉

thanks for your work!

action='store_false',
default=param.default,
dest=name)
continue
if type_.container:
assert type_.container == list
name_or_flag = '--' + name
Expand Down
32 changes: 32 additions & 0 deletions examples/booleans.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"""Example showing boolean flags in defopt.
Optional boolean parameters are automatically converted to
``--name`` and ``--no-name`` flags which take no arguments
and store `True` and `False` respectively.
Code usage::
>>> main('hello!', upper=False, repeat=True)
Command line usage::
$ python booleans.py 'hello!' --no-upper --repeat
"""
import defopt


def main(message, upper=True, repeat=False):
"""Example function with boolean flags.
:param str message: Message to display
:param bool upper: Display the message in upper case
:param bool repeat: Display the message twice
"""
if upper:
message = message.upper()
for _ in range(1 + repeat):
print(message)


if __name__ == '__main__':
defopt.run(main)
19 changes: 19 additions & 0 deletions test_defopt.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,25 @@ def test_list_bare(self):
with self.assertRaises(ValueError):
defopt._get_parser(list)

def test_bool(self):
def main(foo):
""":type foo: bool"""
return foo
self.assertIs(defopt.run(main, argv=['1']), True)
self.assertIs(defopt.run(main, argv=['0']), False)
with self.assertRaises(SystemExit):
defopt.run(main, argv=[])

def test_bool_kwarg(self):
default = object()

def main(foo=default):
""":type foo: bool"""
return foo
self.assertIs(defopt.run(main, argv=['--foo']), True)
self.assertIs(defopt.run(main, argv=['--no-foo']), False)
self.assertIs(defopt.run(main, argv=[]), default)


class TestParsersDeprecated(unittest.TestCase):
def setUp(self):
Expand Down

0 comments on commit 09bdead

Please sign in to comment.