runtype does not respect transitivity of subtyping relation between MutableMapping and Mapping
(Pdb) runtype.issubclass(typing.MutableMapping[str, int], typing.Mapping[str, int])
True
(Pdb) runtype.issubclass(typing.Mapping[str, int], typing.Mapping[str, int | str])
True
(Pdb) runtype.issubclass(typing.MutableMapping[str, int], typing.Mapping[str, int | str])
False
By transitivity of subtype relation, if the first two expressions hold, then the third must hold as well. But according to the library, the third expression is False.
Environment: Python 3.12, runtype version 0.5.3
Thank you for reporting.
As a goal, I'm trying to align runtype's behavior with the official type hint system (i.e. mypy and such).
Here's what PEP 0484 says about this:
By default generic types are considered invariant in all type variables, which means that values for variables annotated with types like List[Employee] must exactly match the type annotation – no subclasses or superclasses of the type parameter (in this example Employee) are allowed.
The mutable collection classes (e.g. MutableMapping and MutableSequence) are declared invariant.
So while there's a lot of sense in your expectation of transitivity, in this case it would go against the Python spec!
But I'm open to new opinions on the matter.
TL;DR - while not intuitive, I think this is the correct behavior.