Closed hjalmarlucius closed 2 years ago
This function seems to work:
from numbers import Integral
from typing import get_origin
from typing import get_args
def replace_type(structure: Any, fromtype: type, totype: type) -> Any:
if structure is fromtype:
return totype
if (origin := get_origin(structure)) is fromtype:
structure.__origin__ = totype
oldargs = get_args(structure)
newargs = tuple(replace_type(arg, fromtype, totype) for arg in oldargs)
if origin is not None and oldargs != newargs:
return origin[newargs]
return structure
# example
replace_type(dict[str, int], int, Integral)
what about this??
from numbers import Integral, Real
Number = Union[Integral, Real]
@match_typing
def adder(x: int, y: Number):
return x + y
# passes
> adder(2, 2.5)
> adder(2, 5)
Agree that works natively but that would not solve the conflict between native python and mypy/mypyc - so it would be the user that actively chooses to use Integral
instead of int
and Real
instead of float:
x: float = 1 # mypy approves and mypyc compiles
assert isinstance(x, float) # TypeError
What I was thinking was adding a match_duck_typing
function:
@match_duck_typing
def adder(x: int, y: float):
return x + y
# passes
> adder(2, 2.5)
> adder(2, 5)
Will your issue be solved with the following solution https://github.com/FelixTheC/strongtyping/blob/93-duck-type-compatability/docs/match_typing.md#allow-duck_typing??
No, my point was that mypy checks some things differently than python's isinstance
check - the below is ok according to mypy because it follows the numbers hierarchy but not at runtime as int
is not a subclass of float
.
x: float = 3
assert isinstance(x, float)
These are the tests according to your Initial comment https://github.com/FelixTheC/strongtyping/blob/93-duck-type-compatability/strongtyping/tests/test_duck_typing.py
Please feel free to create some too which I can add
That looks like a very good implementation, thanks! (I didn't see the check_duck_typing
change upon first answering)
Ok then I will create a new release with this include.
It would be great if there were a switch to allow duck type compatability - e.g. ints pass float checks. This would make the type checking consistent with mypy and mypyc. I would think the easiest solution would be to replace
float->Real
andint->Integral
in checks. https://mypy.readthedocs.io/en/stable/duck_type_compatibility.html