6

I am trying to use mypy to type check my program. The program uses argparse to parse command line arguments. I want to add type hints for the command line arguments.

import argparse
import typing


# define example types and a function that uses them
Seconds = typing.NewType("Seconds", float)
Minutes = typing.NewType("Minutes", float)

def sec_to_min(s: Seconds) -> Minutes:
    return Minutes(s / 60)

# specify arguments and parse them
parser = argparse.ArgumentParser()
parser.add_argument("-t", "--time", default=1., type=float,
                    help="time in seconds")
args = parser.parse_args()

try:
    # mypy reveals type Any
    reveal_type(args.time)
except NameError:
    pass


# (1) passes type check
seconds: Seconds = args.time
# (2) passes type check
sec_to_min(args.time)

I would like mypy to recognize args.time as Seconds. The current code should recognize args.time as float and complain since passing a float to sec_to_min complains as well.

I tried changing the type argument of add_argument to type=lambda x: Seconds(float(x)). This had no effect, mypy still identified args.time as any.
As mentioned here, I have also tried to provide a custom NameSpace. This changed the revealed type of args.time to Seconds. I would like to avoid this, since I would have to duplicate the name for every argument and the default value from add_argument is overridden by the custom namespace.

class TypedNameSpace(argparse.Namespace):
    def __init__(self, *args, **kwargs):
        self.time: Seconds = Seconds(0.)
        super(TypedNameSpace, self).__init__(*args, **kwargs)
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Olaf
  • 586
  • 5
  • 18
  • The argparse `type` parameter is a function that converts a string to something, and raises an error if it can't. It does not add typehints information. Values are placed in the namespace with general purpose `setattr`. I doubt if mypy can trace this action through argparse code. – hpaulj Jun 04 '19 at 15:31
  • @hpaulj I know, I was just hoping there is something I missed in my search. Seems like the only way to add type hints is to duplicate the parameters. – Olaf Jun 04 '19 at 15:40
  • Oops, I should have checked your link; I gave a much longer answer, but same basic idea, two years ago. – hpaulj Jun 04 '19 at 16:21
  • I tend to avoid tools like argparse and instead do manual command line argument parsing. It's much easier for something like mypy or pylint to scrutinize. I be happy to switch to argparse once it becomes less risky though. – dstromberg Apr 28 '21 at 16:30

0 Answers0