You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Make @safe(exceptions=(TypeError, ValueError)) variant #605
Hey @sobolevn, I'm working on this issue but I got a problem with typesafety tests :(
Here's the implementation:
@overloaddefsafe(
arg: Callable[..., _ValueType],
) ->Callable[..., ResultE[_ValueType]]:
"""Decorator to convert exception-throwing for any kind of Exception."""@overloaddefsafe(
arg: Tuple[Type[Exception], ...],
) ->Callable[
[Callable[..., _ValueType]],
Callable[..., ResultE[_ValueType]],
]:
"""Decorator to convert exception-throwing just for a set of Exceptions."""defsafe( # noqa: WPS234arg: Union[
Tuple[Type[Exception], ...],
Callable[..., _ValueType],
],
) ->Union[
Callable[
[Callable[..., _ValueType]],
Callable[..., ResultE[_ValueType]],
],
Callable[..., ResultE[_ValueType]],
]:
...
pytest output:
__________________________________________________________________________________________________________ safe_decorator_no_params __________________________________________________________________________________________________________
returns/typesafety/test_result/test_safe.yml:10:
E pytest_mypy_plugins.utils.TypecheckAssertionError: Invalid output:
E Expected:
E main:7: note: Revealed type is 'def () -> returns.result.Result[builtins.int, builtins.Exception]' (diff)
E Actual:
E main:7: note: Revealed type is 'def (*Any, **Any) -> returns.result.Result[builtins.int, builtins.Exception]' (diff)
It should work by the fact we have the overload signature correctly!
E Expected:
E main:7: note: Revealed type is 'def () -> returns.result.Result[builtins.int, builtins.Exception]' (diff)
E Actual:
E main:3: error: No overload variant of "safe" matches argument type "Tuple[Type[ValueError], Type[EOFError]]" (diff)
E main:3: note: def [_ValueType] safe(arg: Callable[..., _ValueType]) -> Callable[..., Result[_ValueType, Exception]] (diff)
E main:3: note: def safe(arg: Tuple[Type[Exception], ...]) -> Callable[[Callable[..., _ValueType]], Callable[..., Result[_ValueType, Exception]]] (diff)
E main:3: note: Possible overload variants: (diff)
E main:7: note: Revealed type is 'Any' (diff)
@decorator_argument(42)deftest() ->int:
return1reveal_type(test) # N: Revealed type is 'def () -> builtins.int'
Output:
E pytest_mypy_plugins.utils.TypecheckAssertionError: Invalid output:
E Expected:
E main:8: note: Revealed type is 'def () -> builtins.int' (diff)
E Actual:
E main:8: note: Revealed type is 'def (*Any, **Any) -> builtins.int' (diff)
I'm thinking, it is worth it now? I'm saying this because I can implement this and maintain the backward compatibility. The guys who use safe without passing the exceptions won't be affected.
Activity
sobolevn commentedon Sep 15, 2020
This also applies to
impure_safeandfuture_safethepabloaguilar commentedon Apr 24, 2021
Hey @sobolevn, I'm working on this issue but I got a problem with typesafety tests :(
Here's the implementation:
pytestoutput:It should work by the fact we have the
overloadsignature correctly!Do you have any idea of why it's not working?
sobolevn commentedon Apr 24, 2021
I think that the reason is https://github.com/dry-python/returns/blob/master/returns/contrib/mypy/_features/decorators.py#L26-L27
Try to catch
FunctionalLikeandOverloadedtypes there.thepabloaguilar commentedon Apr 24, 2021
Just a question, should it work if we don't use our plugin??
sobolevn commentedon Apr 24, 2021
It would work partially (except argument types). Because we don't have
ParamSpecsupport yet.thepabloaguilar commentedon Apr 24, 2021
@sobolevn You were right, the problem is in that statement!
I'll try to fix it!
thepabloaguilar commentedon Apr 24, 2021
It's not treating tuples correctly 😢
thepabloaguilar commentedon Apr 24, 2021
And that error isn't our fault (I guess), 'cause it is not executing our decorator plugin function!
thepabloaguilar commentedon Apr 24, 2021
Oh, my fault! I've used wrong parameter name
argsinstead ofargthepabloaguilar commentedon Apr 24, 2021
Ok, now I think I have the same feelings you have about
mypy!! 😠The problem is when decorator has parameters, like we trying to do here, see the example below:
Test case:
Output:
sobolevn commentedon Apr 25, 2021
Yeah, that's a known problem. We had solved it already in the previous versions.
Take a look at our definitions: https://github.com/dry-python/returns/blob/0.14.0/returns/_generated/pointfree/map.pyi#L22
And
mypyplugin for it: https://github.com/dry-python/returns/blob/0.14.0/returns/contrib/mypy/returns_plugin.py#L46 and https://github.com/dry-python/returns/blob/0.14.0/returns/contrib/mypy/_features/pointfree.pyI hope, it helps.
thepabloaguilar commentedon Apr 25, 2021
I'm thinking, it is worth it now? I'm saying this because I can implement this and maintain the backward compatibility. The guys who use
safewithout passing the exceptions won't be affected.In about 4 months we'll have
ParamSpecsobolevn commentedon Apr 25, 2021
Let's wait for it, I guess!
thepabloaguilar commentedon Apr 25, 2021
No prob!
thepabloaguilar commentedon Apr 25, 2021
Waiting for #823
internetimagery commentedon Aug 12, 2021
Could you use a helper function, to composition, and then employ that as the base for the decorator with a bit or currying? ie
internetimagery commentedon Aug 12, 2021
Or use an intermediate object to carry the typed parameters. Unsure if this helps, or I'm just missing the point. Sorry if the latter. :)