Package: argz
argz
'''Argument parsing for the lazy.Core ConceptsSimplicity over robustnessYour scriptrequiresarguments"Consumers" of scripts using this are devlopers themselvesUsage# $ cat example.pyimportjsondeffunc(jsondict,dbg=False):"""put descriptive docstring here"""pass# use jsondictif__name__=='__main__':importargzf=argz.route(func)f.jsondict.adapter=[open,json.load]# will be chainedargz.go()# will use sys.argv as inputRunning:$example.pyUsage:example.py jsondict [-dbg]for detailed help, use any of (-h, /h, -?, /?, /help, --help)$example.py-h|> jsondict [-dbg]||    jsondict|        adapter         |  [<built-in function open>, <function load at 0x0336B1B0>]|    dbg|        default         |  False|        adapter         |  <type 'bool'>||- - doc - -||    put descriptive docstring here|_ _ _ _ _ _InstallationDownload the file or use pip:pip install argzPassing Arguments: Named vs PositionalYou can pass any argument by name or by position.
An argument will be treated as named if it starts with a double dash--, otherwise* as positional.You can pass a mishmash of positional and named arguments, becauseargzwill keep track of which arguments are left to parse according to the order in the function's definition.* except forswitchesArguments From FileTo pass arguments from a file to your script you can prefix its path with@. This must be the first argument passed to the script. If there are multiple routes the route name must be included in the file as the first argument.Currentlyargzdoes not allow a mixture of file input and command line input.AdapterA callable object that accepts the string argument and returns the 'adapted' value, which will passed later to the routed function.If the adapter is instead a sequence, each will be chained so that the return value of the former is passed to the latter, using the last returned value as input to the routed function.To abort the parsing process, you may raise any exception. Themessageproperty will be printed to the user.ValidatorUsed to validate the input before any adapting is done. Can be one of the following types:regex string: will be used to match against the inputcallable object: will be called with the input string. Any exception or non-truthy value will abort the parsing process and display a message to the user.Any object that implements__contains__deffunc(alphanum,filepath,key,novalidation):"""put descriptive docstring here"""pass# ...f=argz.route(func)f.alphanum.validator='[a-zA-Z0-9]{2,}'f.filepath.validator=os.path.isfilef.key.validator={'option1':1,'option2':2}argz.go()Min / MaxYou can set a minimum and/or maximum value for an argument:deffunc(count):"""put descriptive docstring here"""pass# ...f=argz.route(func)f.count.min=1# same for maxargz.go()These constraints will be checked after validation and adapters have run.
Both values are inclusive. For example,unsigned charrange would be:min = 0; max = 0xFFFallback vs DefaultSetting either one will deem an argument optional, however, they have one major difference:Default is any value that will be passed to the called routewithout anyparsing or validation.Fallback is astringvalue that will pass all validations and parsing, as if it was specified via the commandline.If the argument was not provieded via the commandline,argzwill use eitherfallbackordefault. Thefallbackvalue takes precedence.If a default value is specified in the function definition,argzwill use it as the argument's default and infer a default adapter in some cases (seeSUPPORTED_INFERRED_ADAPTERS).SwitchesFunction arguments that have a defaultbooleanvalue will be inferred as a switch. This means this argument can also be passed using a single dash without a value following it (e.g.-dbg). Doing so will 'switch' the default value (FalsetoTrue, and vice versa)Thedbgargument from theexample.pycode above demonstrates this.Using SplitSetting thesplitmember of an argument changes a few things:the input will be split using that stringif set,min\maxvalue(s) will be checked against the length of the listthe validator and parser(s) will be called for each item in the listseparatelyVarargs and Kwargs:If the function accepts them, any additional positional and named arguments will be passed in varargs/kwargs respectively.Adapter(s) and validator will be called with the entire list/dictionary, and they must return a value of the same type.Accessing function argumentsSetting arguments properties can be done in two ways:by name:f=argz.route(func)f.myvar.min=1by index:f=argz.route(func)f[0].min=1Note: argument names are case sensitiveParsing FlowThe following graph illustrates the flow for parsing an argument (varargs\kwargs do not support splitting the input):+------------+  +-----------+          +-----------+
 |  fallback  |  |   input   |          |  default  |
 +-----+------+  +-----+-----+          +-----+-----+
       |               |                      |
       +-------+-------+                      |
               |                              |
               v                              |
          +----+-----+                        |
          |  split?  |                        |
          +---+-+----+                        |
              | |                             |
              | | Yes                         |
   +----------+ v                             |
   |   +--------+--------+                    |
No |   |  min / max len  |                    |
   |   +--------+--------+                    |
   +-------+    |                             |
           |    |    +-----------+            |
           V    v    v           |            |
       +--------+----+---+       |            |
       |                 |       |            |
       |    validator    |       |            |
       |        +        |       |            |
       |        v        |       |            |
       |  adapter chain  |       |            |
       |                 |       |            |
       +--------+----+---+       |            |
                |    |           |            |
                |    | split?    |            |
                |    |           |            |
                |    +-----------+            |
       +--------+---------+                   |
       |  min / max check | (if not split)    |
       +--------+---------+                   |
                |                             |
                v                             |
        +-------+--------+                    |
        |  return value  | <------------------+
        +----------------+Using Multiple RoutesYou can 'export' several different routes usingargz.
This means that the user must choose which one they want to run:# $ cat example_routes.pyfromos.pathimportisfiledefentry1(filepath,dbg=False):passdefentry2(count):pass# ...if__name__=='__main__':importargzargz.route(entry1).validator=isfileargz.route(entry2).count.min=1argz.go()Running:$example_routes.pyAvailable routes:> 'entry1' filepath [-dbg]> 'entry2' countfor detailed help, use any of (-h, /h, -?, /?, /help, --help)you can specify the route name (e.g. -h MY_ROUTE)$example_routes.py-h|> 'entry1' filepath [-dbg]||    filepath|    dbg|        default         |  False|        adapter         |  <type 'bool'>|_ _ _ _ _ _|> 'entry2' count||    count|        1 <= X|_ _ _ _ _ _Note: routes are allowed to run without arguments, so long as there is more than one route available.Overriding DefaultsYou can specify custom doc string to print when verbose help is shown by passingdocargument toroute. To completely suppress it pass an empty string.If you use a single route that accepts an argument whose name is inHELP_OPTIONS, you can replace those by specifying acustom_help_optionslist when callinggo.Tested onPython 2.7.15, windows 10Python 3.7.2, windows 10TroubleshootingTo enable logging:setARGZ_LOG=<LOG_LEVEL>LOG_LEVELwill be passed toLogger.setLevelTestingadded some unit-tests, runruntests.batLicenseMITTODOAllow mixture of file input and command-line inputNormalize/strip underscores (_) in argument namesHandle name collisions withRouteobject propertiesInfer from type annotaitons/hints (py3 signature?)Take a look at the code: