returns
returns copied to clipboard
Unit method like `IOResultE.from_value` must return `IOResult[_V, Exception]` type
Currently, they do return incorrect types:
reveal_type(IOResultE.from_value(int))
# => IOResult[int, Any]
# Should be:
# => IOResult[int, Exception]
To achieve what we want we might tweak the way we create an alias in some way:
- We can use inheritance instead of aliasing
- We can use some magic
- mypy plugin?
The same applies for all aliases with E suffix: ResultE, IOResultE, FutureResultE, ReaderResultE, etc
Inheritance does not work:
class IOResultE(IOResult[_ValueType, Exception]):
pass
reveal_type(IOResultE.from_value(42)) # N: Revealed type is 'returns.io.IOResult[builtins.int*, builtins.Exception*]'
Output:
main:6: note: Revealed type is 'returns.io.IOResult[builtins.int*, Any]'
I got it, the actual signature is:
class IOResult:
def from_value(cls, inner_value: _NewValueType) -> 'IOResult[_NewValueType, Any]':
...
I've just adjusted the return type to:
class IOResult:
def from_value(cls, inner_value: _NewValueType) -> 'IOResult[_NewValueType, _ErrorType]':
...
Test case:
- case: test_io_result_e_from_value
disable_cache: true
main: |
from returns.io import IOResultE
reveal_type(IOResultE.from_value(10)) # N: Revealed type is 'returns.io.IOResult[builtins.int*, builtins.Exception]'
@thepabloaguilar can you please test that these tests still work: https://github.com/dry-python/returns/blob/master/typesafety/test_io/test_ioresult_container/test_ioresult_typecast.yml ?
Just one test was broken:
- case: ioresult_from_value
disable_cache: true
main: |
from returns.io import IOResult
reveal_type(IOResult.from_value(1)) # N: Revealed type is 'returns.io.IOResult[builtins.int*, Any]'
Output:
E pytest_mypy_plugins.utils.TypecheckAssertionError: Invalid output:
E Expected:
E main:3: note: Revealed type is 'returns.io.IOResult[builtins.int*, Any]' (diff)
E Actual:
E main:3: note: Revealed type is 'returns.io.IOResult[builtins.int*, <nothing>]' (diff)
E
E Alignment of first line difference:
E E: ...io.IOResult[builtins.int*, Any]'
E A: ...io.IOResult[builtins.int*, <nothing>]'
I remember that we had problems with <nothing> somewhere. It does not compose with something.
Possible somewhere in:
- #124
- https://github.com/dry-python/returns/issues/196
- https://github.com/dry-python/returns/issues/134
- https://github.com/dry-python/returns/issues/140
Ok, I found it: https://github.com/dry-python/returns/issues/124
I am still not sure, why are we using Any?
In fact we have this problem (Any) with IOSuccess and IOFailure too!
>>> reveal_type(IOSuccess(1))
# note: Revealed type is 'returns.io.IOResult[builtins.int*, Any]'
Unless we annotate the type explicit:
>>> io: IOResult[int, str] = IOSuccess(10)
>>> reveal_type(io)
# note: Revealed type is 'returns.io.IOResult[builtins.int*, builtins.str*]'