Search code examples
pythonpython-typingmypy

Should I cast to string and then to int for mypy?


I have a config I loaded up into a dict. It contains an integer config["logging"]["backup_count"]. However, type(config["logging"]["backup_count"]) returns object. So, when I go to pass this into the following:

TimedRotatingFileHandler(log_file, backupCount=config["logging"]["backup_count"], when="midnight", interval=1)

mypy complains that I am trying to put an object where an int is expected. Of course, this is fixable by adding some type-casting:

TimedRotatingFileHandler(log_file, backupCount=int(str(config["logging"]["backup_count"])), when="midnight", interval=1)

but this seems clunky. Should I be doing this?

I'm new to mypy and typing in python. I'd like to know the proper protocol for dealing with something like this. Specifically, should I be doing the -to-str-to-int cast or something else?

EDIT: Should I use TypedDict? If my dictionary is being read out of a .toml file for example, is there an easy way to create a TypedDict from this with the correct typing (I know what the config types are supposed to be ahead of time)?


Solution

  • You should define TypedDicts that specify exactly what the type of config["logging"]["backup_count"] is. A minimal demonstration:

    from typing import TypedDict
    
    
    class LoggingConfig(TypedDict):
        backup_count: int
    
    class Config(TypedDict):
        logging: LoggingConfig
    
    
    config: Config = {"logging": {"backup_count": 3}}
    
    reveal_type(config["logging"]["backup_count"])  # int
    

    A quicker workaround is, assuming you trust that config["logging"]["backup_cont"] really is an int, to just tell mypy:

    from typing import cast
    
    TimedRotatingFileHandler(log_file, backupCount=cast(int, config["logging"]["backup_count"]), when="midnight", interval=1)
    

    (There is still the overhead of a call to cast, but at runtime, all it does is return its second argument, rather than actually creating a new int value. When type-checking, mypy assumes the second argument has the type specified by the first.)