Description
Consider this function (It is a simplified version of a function in Zulip).
ItemT = TypeVar('ItemT')
CItemT = TypeVar('CItemT') # compressed Item
# data is low-speed storage. cache is high-speed storage
def fetch(key, data, cache, compress, decompress):
# type: (str, Mapping[str, ItemT], MutableMapping[str, CItemT], Callable[[ItemT], CItemT], Callable[[CItemT], ItemT]) -> Tuple[ItemT, bool]
try:
cvalue = cache[key]
return (decompress(cvalue), True)
except KeyError:
pass
value = data[key]
cache[key] = compress(value)
return (value, False)
This works as expected (see complete example here).
Compression can be useful, but I usually don't require it. So in most cases, CItemT
will be the same as ItemT
and I'll pass lambda x: x
as compress
and decompress
.
However, if I add default values to compress and decompress like this:
def fetch(key, data, cache, compress=lambda x: x, decompress=lambda x: x)
:
I get these errors:
cache.py:7: error: Incompatible return value type (got "ItemT", expected "CItemT")
cache.py:7: error: Incompatible types in assignment (expression has type Callable[[ItemT], ItemT], variable has type Callable[[ItemT], CItemT])
cache.py:7: error: Incompatible return value type (got "CItemT", expected "ItemT")
cache.py:7: error: Incompatible types in assignment (expression has type Callable[[CItemT], CItemT], variable has type Callable[[CItemT], ItemT])
I think if I use default values for compress
and decompress
, mypy should not give errors. It should instead enforce CItemT
to be the same as ItemT
at the place where I'm calling this function using default arguments for compress
and decompress
.
This behavior has recently come up. It was not present in mypy 0.4.2.