Package: argstruct
ArgStruct - Reusable Argument StructureArgStruct - Reusable Argument StructureAboutUsageExamplesExample StructureLoading ArgStruct for Console ProcessingLoading ArgStruct for API / Misc ProcessingInternalsAdditional NotesExample; Documentation generation with additional dataAboutThis library is intended to provide a structure for Arguments and API/ABI processing in a way that allows for the same structure to be reused for other things without duplication. This allows the same structure to generate documentation, code blocks, and other things, without having to duplicate data elsewhere.This library uses theArgStruct SpecificationArgStruct Specification: 1.0UsageFirst, anArgStructMap must be created. an ArgStruct is made up of many ArgStructCommands.EachArgStructCommandrequiressome optionsin order to build up a Command. Within eachArgStructCommandis a dictionary of arguments (can be converted to aArgStructArgument) and their configurations. Once theArgStructMap is built, it can be utilized by loading the file (or its contents) into anArgStructobject.This library provides 3 methods for processing:console: Build CLI/Console arguments viaargparse. A top levelargparse.ArgumentParsermust be created first.api: Build API/Misc arguments via callback methods. Callback methods must be created for command processing and argument processing.parse: Process either anargparse.ArgumentParseror a dictionary, validate and return the built values, including defaults from the ArgStruct MapAdditionally, this library provides a script,argstruct-docto generate Markdown documentation from anArgStruct. Theapimethod can be utilized for generating code or other structures that are not console specific.ExamplesExample Structure# These Arguments are automatically appended to any command which has `auth_required=True`[auth_args.some_argument]required=falsetype="str"cli_flag_names=["-s","--some-argument"]help="My Argument Help info"[auth_args.other_argument]required=falsetype="str"cli_flag_names=["-o","--other-argument"]help="My Other Help Info"# A new Command with Arguments[commands.mycommand]auth_required=falsecli_hidden=trueapi_hidden=falsehelp="My Command Level Help"group="My Group Label"ui_label="My UI/Documentation Label"[commands.mycommand.args.mycommand_first_arg]cli_flag_names=["-f","--my-first-arg"]type="int"required=falsedefault=5help="My First Arg Help"[commands.mycommand.args.second_arg]cli_flag_names=["-a","--some-second-arg"]type="str"required=truehelp="My Second Arg Help"[commands.othercommand]....Loading ArgStruct for Console Processing# Create a Path object pointing to the ArgMapcommandmap_file:Path=Path("./testmap.toml").resolve()# Load the ArgMap, if the file has a non-standard file extension (ex not `json`, `yml`, `yaml` or `toml`),#   then you need to specify the second argument accordingly. Default is `auto` and automatically determines#   based on file extensionargstruct_obj:ArgStruct=ArgStruct(commandmap_file,ArgStruct.OVERRIDE_TYPE_TOML)# Create a new argparse.ArgumentParser to serve as the root of all commands and argumentsparser:argparse.ArgumentParser=argparse.ArgumentParser(description="My CLI App")# Add any top level arguments, if requiredparser.add_argument("-v","--verbose",help="Turn on Debugging",action="store_true")# Create and utilize the Console(CLI)-specific Commands via argparse, creating a new subparser whose `dest="command"` and is `required`console(argstruct_obj,parser,True,{"dest":"command","required":True})# Parse arguments, set defaults, validate and return back a dictionary of CLI Argumentsrequest:typing.Union[dict[str,typing.Any],None]=parse(argstruct_obj,parser)# Output the Argumentsprint(request)Loading ArgStruct for API / Misc ProcessingUnlike the Console example, Not all API/ABIs are the same, so, you will need to define some callback methods that will be utilized.# Create a per-command Callback, this will be called for each Command in the ArgStruct. `result` and the return value 'should' be the same objectdefcommand_cb(command:str,command_config:ArgStructCommand,cb_args:typing.Any,result:typing.Any)->typing.Any:ifresultisNone:result=[]print(f"Hello I am Command{command}")result.append({"command":command,"auth":command_config.get("auth_required"),"args":{}})returnresult# Create a per-argument Callback, this will be called for Each Argument in each Command in the ArgStruct. `result` and the return value 'should' be the same objectdefarg_cb(command:str,command_config:ArgStructCommand,argument:str,arg_config:dict[str,typing.Any],cb_args:typing.Any,result:typing.Any)->typing.Any:argtype:str=arg_config["type"]print(f" - Command{command}Argument:{argument}, type:{argtype}")cmd_idx:int=len(result)-1if"args"notinresult[cmd_idx].keys():result[cmd_idx]["args"]={}result[cmd_idx]["args"][argument]={"argument":argument,"default":arg_config["default"]}returnresult# Create a Path object pointing to the ArgMapcommandmap_file:Path=Path("./testmap.toml").resolve()# Load the ArgMap, if the file has a non-standard file extension (ex not `json`, `yml`, `yaml` or `toml`),#   then you need to specify the second argument accordingly. Default is `auto` and automatically determines#   based on file extensionargstruct_obj:ArgStruct=ArgStruct(commandmap_file,ArgStruct.OVERRIDE_TYPE_TOML)# Build some Argument Structure for your API using the command and argument callbacksapi_argdata:dict[str,typing.Any]=api(argstruct_obj,command_cb,arg_cb,None,None)print(api_argdata)# Generate your API Request Datamy_request_data:dict[str,typing.Any]=...# Do something to generate your API data# Parse arguments, set defaults, validate and return back a dictionary of API Argumentsrequest:typing.Union[dict[str,typing.Any],None]=parse(argstruct_obj,my_request_data)print(request)InternalsThis library utilizesargparseat the core for its CLI/Console processing.speckermanages the argmap structure, validation and, defaults. Additionally usestabulatein order to generate markdown tables.Additional NotesIf you wish to add additional required values, etc, you can override any of the specs in theargstruct/specs/directory, and then load them when creating theArgStructobject viaadditional_argmap_specs. These values will not be documented throughargstruct-doc, and will need to runmarkdown_documentation()after creating some callback methods to include your additional data.Example; Documentation generation with additional data# Create a per-command Callback, this will be called for each Command in the ArgStruct. `result` and the return value 'should' be the same object.# This callbacks input `result` will be a str, and its return type should also be the same str with appended datadefcommand_cb(command:str,command_config:ArgStructCommand,cb_args:typing.Any,result:typing.Any)->typing.Any:ifresultisNone:result=""result+=f"Hello I am Command{command}\n"result+="'command': command\n"result+="'auth': "+("Y\n"ifcommand_config.get("auth_required")else"N\n")returnresult# Create a per-argument Callback, this will be called for Each Argument in each Command in the ArgStruct. `result` and the return value 'should' be the same object# This callbacks input `result` will be a list[str], and its return type should be the same list, with additional columns.defarg_cb(command:str,command_config:ArgStructCommand,argument:str,arg_config:dict[str,typing.Any],cb_args:typing.Any,result:typing.Any)->typing.Any:argtype:str=arg_config["type"]result.append(f" - Command{command}Argument:{argument}, type:{argtype}\n")result.append(f"'argument':{argument}\n")result.append(f"'default':{arg_config['default']}\n")returnresult# A List of additional argument columnsextra_cols:list[str]=["Rand 1","Rand 2","Rand 3"]print(markdown_documentation(argstruct_file,True,True,extra_cols,command_cb,None,arg_cb,None))