Last active
January 4, 2016 11:48
-
-
Save georgepsarakis/8617110 to your computer and use it in GitHub Desktop.
Extended version of the argparse Python module for command line option parsing.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from __future__ import unicode_literals | |
import re | |
import argparse | |
from functools import partial | |
class Options(argparse.ArgumentParser): | |
def __init__(self, **kwargs): | |
self._parsed = False | |
self._options = None | |
self._re_numeric = re.compile(r'^([np]*)(float|int)$') | |
super(Options, self).__init__(**kwargs) | |
def __add_argument(self, name, *args, **kwargs): | |
extra = {} | |
parse_numeric_arg = self._re_numeric.search(name) | |
if parse_numeric_arg is not None: | |
mode, number_type = parse_numeric_arg.groups() | |
kwargs['type'] = partial( | |
Options._number, | |
number_type=number_type, | |
mode=mode | |
) | |
elif name == "list": | |
if kwargs.get('required', False): | |
nargs = '+' | |
else: | |
nargs = '*' | |
kwargs['nargs'] = nargs | |
elif name == "counter": | |
kwargs['action'] = 'count' | |
extra['default'] = 0 | |
elif name in ["true", "false"]: | |
kwargs["action"] = "store_{}".format(name) | |
kwargs['default'] = True if name == 'false' else False | |
extra.update(kwargs) | |
help_message = extra.get('help', '') | |
help_message += ' (default={})'.format(extra.get('default', None)) | |
extra['help'] = help_message.strip() | |
self.add_argument(*args, **extra) | |
@staticmethod | |
def _number(item, number_type, mode=None): | |
if number_type == "int": | |
display = "integer" | |
transform = int | |
elif number_type == "float": | |
display = "float" | |
transform = float | |
message_parameters = (item, display) | |
try: | |
item = transform(item) | |
except ValueError: | |
raise argparse.ArgumentTypeError( | |
"%s not a %s" % message_parameters | |
) | |
if mode == 'p': | |
if not item >= 0: | |
raise argparse.ArgumentTypeError( | |
"%s not a positive %s" % message_parameters | |
) | |
elif mode == 'n': | |
if not item < 0: | |
raise argparse.ArgumentTypeError( | |
"%s not a negative %s" % message_parameters | |
) | |
return item | |
@property | |
def options(self): | |
if not self._parsed: | |
self._parse_arguments() | |
return self._options | |
def __getattr__(self, name): | |
if name in [ | |
'int', 'pint', 'nint', | |
'nfloat', 'pfloat', | |
'true', 'false', | |
'counter', 'list' | |
]: | |
def f(*args, **kwargs): | |
return self.__add_argument(name, *args, **kwargs) | |
return f | |
elif name in self.options: | |
return getattr(self.options, name) | |
def _parse_arguments(self): | |
parameters, extra = self.parse_known_args() | |
parameters._extra = extra | |
self._options = parameters | |
self._parsed = True | |
def __repr__(self): | |
return self.options.__repr__() | |
if __name__ == "__main__": | |
options = Options(description="Example Program") | |
options.pint( | |
'--delay', | |
default=0, | |
help='--delay parameter is of type integer & greater/equal to zero') | |
options.counter('-v', '--verbose', help='Verbosity level') | |
options.list('--list-items', default=[10, 20, 30], type=int) | |
options.true( | |
'--log', | |
help='Flag that acquires the value True when set' | |
) | |
print 'delay -> {}'.format(options.delay) | |
print 'list_items -> {}'.format(options.list_items) | |
print 'log -> {}'.format(options.log) | |
print 'verbose -> {}'.format(options.verbose) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add support for date/datetime parameters.