Search code examples
pythonpython-typingmypypylint

How to provide type hints for argparse arguments?


I would like to get proper linting and type hints by [PyFlakes, Pylint] and mypy.

For example, in the following code, we cannot get type error for the last line. We cannot even know if float_input exists.

import argparse

parser = argparse.ArgumentParser()
parser.add_argument('--float_input', type=float)
args = parser.parse_args()


def int_sum(a: int, b: int):
    return a + b

c = int_sum(args.float_input, args.float_input)

Is there a good way to improve this?


Solution

  • You can use typed-argument-parser to provide type hints for your arguments. You can define your arguments in a typesafe manner.

    from typing import Optional
    from tap import Tap
    
    class FooArgumentParser(Tap):
        float_input: Optional[float] = None
    
    args = FooArgumentParser().parse_args()
    
    
    def int_sum(a: int, b: int):
        return a + b
    
    
    c = int_sum(args.float_input, args.float_input)
    c = int_sum(args.foo, args.bar)
    

    which gives you:

    foo.py:13:13: error: Argument 1 to "int_sum" has incompatible type "Optional[float]"; expected "int"
    foo.py:13:31: error: Argument 2 to "int_sum" has incompatible type "Optional[float]"; expected "int"
    foo.py:14:13: error: "FooArgumentParser" has no attribute "foo"
    foo.py:14:23: error: "FooArgumentParser" has no attribute "bar"
    

    For required arguments, note that:

    Variables defined as name: type are required arguments while variables defined as name: type = value are not required and default to the provided value.

    You have to give the argument a default value to make it optional.