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)?
You should define TypedDict
s 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.)