Package: rm-options
rm-optionsPython package for easier cli options handling.Featureslong names and short names (-h and --help)default valuesauto generated usagevalue parsing (to get int, float, ... values)required logicautomatic interactive input option for needed optionsmultiple values for one optionExample output for the automatic generated usage:Usage
‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
pythontest.py

RequiredOptions
‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
--name-n:yourname{valueneeded}--test-t:test{valueneeded}{default:t}OptionalOptions
‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
--all:anytext
--delete:deletesomething{valueneeded}--force-f:forceinint{valueneeded}--help-h:showusage
--measures-m:forceinint{valueneeded}{multiplevaluespossible}--more:moretext
--values:somevalues{valueneeded}{multiplevaluespossible}Installpipinstallrm-optionsUsageImport the package, and create an option handler.fromrmoptionsimportRMOptionHandleroption_handler=RMOptionHandler()Create an option with the option handler.name_option=option_handler.create_option("name","defines the name")Parse, check and map all optionsresult=option_handler.check()Show error and usage if check wasn't successful.ifnotresult:option_handler.print_error()option_handler.print_usage()exit()Use the parsed value of an option.anyFunction(name_option.value)Advanced PossibilitiesCreate an option with a short name (default: None)name_option=option_handler.create_option("name","defines the name",short_name="n")Create an option which is required by the script (default: False)name_option=option_handler.create_option("name","defines the name",required=True)Define a default value for the option (default: None)name_option=option_handler.create_option("name","defines the name",default_value="john")Define if an option needs a value (default: False)name_option=option_handler.create_option("name","defines the name",needs_value=True)Define if an option can handle multiple values (with a space as seperator) (default: False)name_option=option_handler.create_option("name","defines the name",multiple_values=True)Define a mapper class, which maps the value to a specific type (default: None)It's also possible to write custom mappers.fromrmoptions.mapperimportIntMappername_option=option_handler.create_option("name","defines the name",mapper=IntMapper)print(type(name_option.value))#outputs: intOption HandlerPrevent the interactive mode, where the script will ask the user for missing values.
If you set this option to False (default: True), the check function will directly return False if something is missing.option_handler=RMOptionHandler(ask_for_missing_values=False)There are also other possibilities for the RMOptionHandler.option_handler=RMOptionHandler(usage_title="Usage",usage_description="python{}".format(sys.argv[0]),help_option_short_name="h",help_option_long_name="help",help_option_description="show usage",ask_for_missing_values=True,ask_for_required_options=True,automatic_help_command=True)Custom MapperYou also can define custom mappers for any type you want.In this example I created a custom mapper for a class named 'Node'.# class for the exampleclassNode(object):def__init__(self,x,y,name,color):self.x=xself.y=yself.name=nameself.color=colorNow I want to accept command line arguments to create objects of this class.In my case I would define the format as {x},{y},{name},{color}.So if the user inputspython myscript.py --node 1,5,MyNode,#f00it should map this input automatically to Node objects.So we'll write a custom mapper.fromrmoptions.mapperimportBaseMapperfrom.nodeimportNode# Override the BaseMapper class from rmoptions.mapperclassNodeMapper(BaseMapper):# override the init functiondef__init__(self):BaseMapper.__init__(self)# override the get_target_type_name function.# This is needed for the error messages.# Simply write the name of the target class here.defget_target_type_name(self):return"Node"# this is the real map class.# Here you'll get the value of the option,# which you should parse here.# If it's work return the object, and if it's not working return None.# For multiple_values = True: If you have multiple values for an option,# this function will be called for every element in the value's list.# So you will everytime get single values in this function, and never a list.defmap(self,value):try:value=value.split(",")returnNode(int(value[0]),int(value[1]),value[2],value[3])exceptValueError:returnNoneYou also can use this mapper for multiple values.So it's also working for options likepython myscript.py --node 1,5,MyNode,#f00 10,15,MyNode2,#f50ExampleIf you want to see a full project (with custom-mapper and a lot of options) with this package look here:https://github.com/MartinR2295/University-Exercises-Artificial-Intelligence/tree/main/traveling_salesman\Easy example to start with a scriptfromrmoptionsimportRMOptionHandlerfromrmoptions.mapperimportIntMapperdefmain():option_handler=RMOptionHandler()name_option=option_handler.create_option("name","your name",required=True)height_option=option_handler.create_option("height","height of the grid in blocks",needs_value=True,required=True,mapper=IntMapper)width_option=option_handler.create_option("width","width of the grid in blocks",short_name="w",needs_value=True,required=True,mapper=IntMapper)ifnotoption_handler.check():option_handler.print_error()option_handler.print_usage()exit()#do anything with the optionsarea=height_option.value*width_option.valueprint("Hello{}, the calculated area is:{}".format(name_option.value,area))if__name__=='__main__':main()