Browse Source

Closes #200 substitute command line arguments for defaults

1.0.4-release-candidate
Jonathan Schultz 5 years ago
committed by Chris
parent
commit
8a240562d8
4 changed files with 146 additions and 0 deletions
  1. 1
      README.md
  2. 79
      gooey/python_bindings/cmd_args.py
  3. 5
      gooey/python_bindings/gooey_decorator.py
  4. 61
      gooey/tests/test_cmd_args.py

1
README.md

@ -264,6 +264,7 @@ Just about everything in Gooey's overall look and feel can be customized by pass
| show_restart_button | Toggles whether or not to show the restart button at the end of execution |
| run_validators | Controls whether or not to have Gooey perform validation before calling your program |
| poll_external_updates | (Experimental!) When True, Gooey will call your code with a `gooey-seed-ui` CLI argument and use the response to fill out dynamic values in the UI (See: [Using Dynamic Values](#using-dynamic-values))|
| use_cmd_args | Substitute any command line arguments provided at run time for the default values specified in the Gooey configuration |
| return_to_config | When True, Gooey will return to the configuration settings window upon successful run |
| progress_regex | A text regex used to pattern match runtime progress information. See: [Showing Progress](#showing-progress) for a detailed how-to |
| progress_expr | A python expression applied to any matches found via the `progress_regex`. See: [Showing Progress](#showing-progress) for a detailed how-to |

79
gooey/python_bindings/cmd_args.py

@ -0,0 +1,79 @@
'''
Created on Jan 15 2019
@author: Jonathan Schultz
This file contains code that allows the default argument values to be specified
on the command line.
'''
from argparse import _SubParsersAction
def parse_cmd_args(self, args=None):
def prepare_to_read_cmd_args(item):
'''
Before reading the command-line arguments, we need to fudge a few things:
1. If there are subparsers, we need a dest in order to know in which
subparser the command-line values should be stored.
2. Any required argument or mutex group needs to be made not required,
otherwise it will be compulsory to enter those values on the command
line.
We save the everything as it was before the fudge, so we can restore later.
'''
for action in item._actions:
if isinstance(action, _SubParsersAction):
action.save_dest = action.dest
if not action.dest:
action.dest = '_subparser'
else:
action.save_required = action.required
action.required = False
action.save_nargs = action.nargs
if action.nargs == '+':
action.nargs = '*'
elif action.nargs is None:
action.nargs = '?'
for mutex_group in item._mutually_exclusive_groups:
mutex_group.save_required = mutex_group.required
mutex_group.required = False
def overwrite_default_values(item, cmd_args):
'''
Subsistute arguments provided on the command line in the place of the
default values provided to argparse.
'''
for action in item._actions:
if isinstance(action, _SubParsersAction):
subparser_arg = getattr(cmd_args, action.dest, None)
if subparser_arg:
overwrite_default_values(action.choices[subparser_arg], cmd_args)
else:
dest = getattr(action, 'dest', None)
if dest:
cmd_arg = getattr(cmd_args, dest, None)
if cmd_arg:
action.default = cmd_arg
def restore_original_configuration(item):
'''
Restore the old values as they were to start with.
'''
for action in item._actions:
if isinstance(action, _SubParsersAction):
action.dest = action.save_dest
del action.save_dest
else:
action.required = action.save_required
del action.save_required
action.nargs = action.save_nargs
del action.save_nargs
for mutex_group in item._mutually_exclusive_groups:
mutex_group.required = mutex_group.save_required
del mutex_group.save_required
prepare_to_read_cmd_args(self)
overwrite_default_values(self, self.original_parse_args(args))
restore_original_configuration(self)

5
gooey/python_bindings/gooey_decorator.py

@ -14,6 +14,7 @@ from argparse import ArgumentParser
from gooey.gui.util.freeze import getResourcePath
from gooey.util.functional import merge
from . import config_generator
from . import cmd_args
IGNORE_COMMAND = '--ignore-gooey'
@ -43,6 +44,7 @@ def Gooey(f=None,
header_height=80,
navigation='SIDEBAR', # TODO: add this to the docs
tabbed_groups=False,
use_cmd_args=False,
**kwargs):
'''
Decorator for client code's main function.
@ -68,6 +70,9 @@ def Gooey(f=None,
sys.exit(1)
if not build_spec:
if use_cmd_args:
cmd_args.parse_cmd_args(self, args)
build_spec = config_generator.create_from_parser(
self,
source_path,

61
gooey/tests/test_cmd_args.py

@ -0,0 +1,61 @@
import unittest
from gooey import GooeyParser
from gooey.python_bindings import cmd_args
from argparse import ArgumentParser
class TextCommandLine(unittest.TestCase):
def test_default_overwritten(self):
parser = GooeyParser()
ArgumentParser.original_parse_args = ArgumentParser.parse_args
parser.add_argument('arg', type=int, default=0)
# Supply 1 as command line argument, check that it overwrites argparse default
cmd_args.parse_cmd_args(parser, ['1'])
argdefault = next(action for action in parser._actions if action.dest == 'arg').default
self.assertEqual(argdefault, 1)
def test_required_not_enforced(self):
parser = GooeyParser()
ArgumentParser.original_parse_args = ArgumentParser.parse_args
parser.add_argument('--arg', type=int, required=True)
parser.add_argument('--argn', type=int, nargs='+')
parser.add_argument('argp', type=int)
mutex=parser.add_mutually_exclusive_group(required=True)
mutex.add_argument('--one', action='store_true')
mutex.add_argument('--two', action='store_true')
# No error when we don't provide required arguments
cmd_args.parse_cmd_args(parser)
# Test that required/argn have been restored in parser
argrequired = next(action for action in parser._actions if action.dest == 'arg').required
self.assertEqual(argrequired, True)
argnnargs = next(action for action in parser._actions if action.dest == 'argn').nargs
self.assertEqual(argnnargs, '+')
argpnargs = next(action for action in parser._actions if action.dest == 'argp').nargs
self.assertEqual(argpnargs, None)
mutexrequired = next(mutex for mutex in parser._mutually_exclusive_groups).required
self.assertEqual(mutexrequired, True)
def test_cmd_args_subparser(self):
parser = GooeyParser()
subparsers = parser.add_subparsers(dest='subparser')
subparserA = subparsers.add_parser('A')
subparserB = subparsers.add_parser('B')
subparserA.add_argument('argA', type=int, default=0)
subparserB.add_argument('argB', type=int, default=0)
ArgumentParser.original_parse_args = ArgumentParser.parse_args
cmd_args.parse_cmd_args(parser, ['A', '1'])
# Check that argA is overwritten but not argB
subparseraction = next(action for action in parser._actions if action.dest == 'subparser')
argAdefault = next(action for action in subparseraction.choices['A']._actions if action.dest == 'argA').default
self.assertEqual(argAdefault, 1)
argBdefault = next(action for action in subparseraction.choices['B']._actions if action.dest == 'argB').default
self.assertEqual(argBdefault, 0)
Loading…
Cancel
Save