Skip to content

Commit 82f60ff

Browse files
committed
v0.10.1 - support for positional args in argparse
1 parent e7ae747 commit 82f60ff

File tree

4 files changed

+40
-8
lines changed

4 files changed

+40
-8
lines changed

.travis.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ env:
1818
# command to install dependencies
1919
install:
2020
- pip install --upgrade pip
21-
- pip install -r requirements-dev.txt
21+
- pip install -r requirements-dev.txt PyYAML
2222

2323
# command to run tests
2424
# require 100% coverage (not including test files) to pass Travis CI test

params/params.py

+18-6
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@
1414

1515
class Param:
1616
""" Provides a parameter specification to be used within a Params instance. """
17-
def __init__(self, value, doc: Text = None, dtype: Type = None, required: bool = False, params_class=None):
17+
def __init__(self, value, doc: Text = None, dtype: Type = None, required: bool = False,
18+
positional: bool = False, params_class=None):
1819
"""
1920
Constructs a parameter specification to be used in a Params instance:
2021
@@ -30,9 +31,12 @@ class MyParams(pp.Params):
3031
:param doc: (Optional) document string
3132
:param dtype: (Optional) type
3233
:param required: default is True.
34+
:param positional: defaults to False for making a CLI option argument like --foo. Set to True,
35+
for a positional argument.
3336
"""
3437
self.params_class = params_class
3538
self._default_value = value
39+
self.positional = positional
3640
self.doc_string = doc
3741
self.required = required
3842
self.dtype = dtype
@@ -233,8 +237,7 @@ def from_yaml_string(cls, yaml_string: Text, check_params=False):
233237
return cls.from_dict(lparams, return_instance=True, return_unused=False)
234238

235239
@classmethod
236-
@property
237-
def _open_file(cls):
240+
def _open_file(cls, *args, **kwargs):
238241
""" Selects an open() implementation.
239242
Tries to with Tensorflows first (tf.io.gfile.GFile)
240243
and if not available fall backs to python's default open().
@@ -244,7 +247,7 @@ def _open_file(cls):
244247
open_file = tf.io.gfile.GFile # pragma: no cover
245248
except Exception: # pragma: no cover
246249
open_file = open
247-
return open_file
250+
return open_file(*args, **kwargs)
248251

249252
@classmethod
250253
def from_json_file(cls, json_file, check_params=False):
@@ -309,8 +312,13 @@ def arg_name(param_name: Text):
309312
result = param_name.lower().replace("_", "-")
310313
return result
311314

315+
def sort_positional_args(attribs: dict):
316+
res = list(filter(lambda t: t[1].positional, attribs.items()))
317+
res += list(filter(lambda t: not t[1].positional, attribs.items()))
318+
return res
319+
312320
parser = argparse.ArgumentParser()
313-
for attr, spec in cls.__specs.items():
321+
for attr, spec in sort_positional_args(cls.__specs):
314322
if spec.doc_string is None:
315323
continue
316324
name = arg_name(spec.name)
@@ -324,7 +332,11 @@ def arg_name(param_name: Text):
324332
add_argument_args.update({
325333
"type": _str2bool, "nargs": "?", "const": True
326334
})
327-
parser.add_argument("--{}".format(name), **add_argument_args)
335+
if spec.positional:
336+
del add_argument_args['required']
337+
parser.add_argument("{}".format(name), **add_argument_args)
338+
else:
339+
parser.add_argument("--{}".format(name), **add_argument_args)
328340
return parser
329341

330342

params/version.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "0.10.0"
1+
__version__ = "0.10.1"

tests/test_decoration.py

+20
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ def get_something_else(self, value: int): # a derived callable
2727
return self.number_of_things + value
2828

2929

30+
class MyParamsWithCommand(MyParams):
31+
cmd = pp.Param(None, doc="Command to execute", positional=True)
32+
33+
3034
class ParamsDecorationTest(unittest.TestCase):
3135

3236
def test_decoration(self):
@@ -71,5 +75,21 @@ class AParams(pp.Params):
7175
except Exception:
7276
pass
7377

78+
def test_arg_parser_with_command(self):
79+
parser = MyParamsWithCommand.to_argument_parser()
80+
parser.print_help()
81+
82+
def error_fn(msg, *args, **kwargs):
83+
raise Exception(msg)
84+
parser.error = error_fn # supress sys.exit
85+
86+
args = parser.parse_args(["start", "--use-other-things", False, "--number-of-things", "7"])
87+
self.assertEqual(args.use_other_things, False)
88+
inst = MyParamsWithCommand(args._get_kwargs())
89+
self.assertEqual(inst.cmd, 'start')
7490

91+
args = parser.parse_args(["--use-other-things", False, "--number-of-things", "7", "stop"])
92+
self.assertEqual(args.use_other_things, False)
93+
inst = MyParamsWithCommand(args._get_kwargs())
94+
self.assertEqual(inst.cmd, 'stop')
7595

0 commit comments

Comments
 (0)