Note
I made this proposal first as this issue, which was obviously the wrong way to go. Sorry for the extra noise.
Problem
Often only certain values are allowed for command line argument values. For example, you may have an argument of type int that has to be positive, but setting type=int in argparse.ArgumentParser.add_argument allows also for negative values. So even in such a simple case you have to implement your own validator rejecting negative values.
It would be nice to have an easy way to integrate a validator into argparse.ArgumentParser.add_argument.
Proposed solution
Add an optional parameter validator to argparse.ArgumentParser.add_argument. It should accept a callable with one argument of the type of the added parameter and return a boolean. If present the following should happen:
- On argument parsing the usual type conversion and value checks should be executed
- Then the
validatorcallable is called with the parsed and type-converted argument - If the result is
Truenothing happens and parsing is resumed - If the result is
Falsethe value is rejected as invalid by raising anargparse.ArgumentErrorexplaining the failed validation
In addition, if a default value is given it should be validated similarly when add_argument is executed.
The validator may also have a second return value containing a string explaining why a value was rejected.
Maybe it would be useful to create a special exception ArgumentValidationError derived from ArgumentError that also receives the invalid parsed value.
Example
import argparse
def validate(val: int) -> bool:
return (val >= 10) and (val <= 100)
parser = argparse.ArgumentParser()
parser.add_argument('--foo', type=int, validator=validate, help="Set to value between 10 and 100")
args = parser.parse_args()
print(args.foo)
Now, if the program is called with --foo 5 an exception is raised pointing out the validation error.
Alternatives
In the issue @siren pointed out that such a validation can be achieved with a type function or an Action class, which is technically true.
However, creating a a type function or an Action class comes with some overhead compared to my proposal above. You have to do the type conversion yourself and eventually raise an argparse.ArgumentError exception, whose arguments are also not documented.
In addition, how to use those as validators is IMHO not obvious in the documentation. Using argparse in many projects I often scanned the documentation page and never stumbled over this possibility.
Other solution
If the proposal becomes rejected, I’d suggest to at least extend the argparse documentation page with a section about validation explaining how to properly use type or action arguments for that.
Final remarks
I’d be ready to implement the proposed validator argument or to create a draft for a documentation section about validation, whatever the final decision might be.