hintze
hintze

Reputation: 630

Mypy complains about incompatible type when variable type is subset of expected type

Trying to build an xarray Dataset, where we build the input to the arguments "coords" and "attrs" before passing it to the constructor:

coordinates = {"time": ("time", time_coordinates)}
attributes = {"some_flag": False}
...
ds = xr.Dataset(data_vars=variables, coords=coordinates, attrs=attributes)

What puzzles me is the output of mypy run against this code:

error: Argument "coords" to "Dataset" has incompatible type "Dict[str, Tuple[str, Any]]"; expected "Optional[Mapping[Hashable, Any]]"
error: Argument "attrs" to "Dataset" has incompatible type "Dict[str, bool]"; expected "Optional[Mapping[Hashable, Any]]"

Isn't a dict a Mapping? And isn't str also Hashable? And aren't Tuples and bools of type Any, in any case? What do I not understand about mypy and/or Python type hints here?

Upvotes: 2

Views: 2089

Answers (1)

hintze
hintze

Reputation: 630

Using the information from Selcuk, I found this somewhat verbose solution, as detailed in the mypy docs: As the keys of Mappings are invariant, one needs to hint explicitly that the str there is of type Hashable. (While strings are a subtype of Hashable, Mappings keys are not covariant, disallowing subtypes.). Or, as Selcuk puts it in his comment:

str is a Hashable, but since dict is a mutable data type you must be passing the exact same type for the keys, not a subtype. There is a possibility that the called function might add another Hashable key to the passed argument, breaking the source.

coordinates: Dict[Hashable, Tuple[str, Any]] = {
    "time": ("time", time_coordinates)
}
attributes: Dict[Hashable, Any] = {"some_flag": False}

Upvotes: 1

Related Questions