Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@ incremental in minor, bugfixes only are patches.
See [0Ver](https://0ver.org/).


## 0.29.1 WIP

### Bugfixes

- Relaxes `future` and `future_safe` decorator argument types from
`Coroutine` to `Awaitable`, so plain `async def` functions wrapping
another awaitable (instead of being coroutine functions themselves)
type-check correctly


## 0.29.0

### Features
Expand Down
35 changes: 6 additions & 29 deletions returns/future.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@

# Aliases:
_FirstType = TypeVar('_FirstType')
_SecondType = TypeVar('_SecondType')


# Public composition helpers:
Expand Down Expand Up @@ -471,10 +470,7 @@ def from_future_result(


def future(
function: Callable[
_FuncParams,
Coroutine[_FirstType, _SecondType, _ValueType_co],
],
function: Callable[_FuncParams, Awaitable[_ValueType_co]],
) -> Callable[_FuncParams, Future[_ValueType_co]]:
"""
Decorator to turn a coroutine definition into ``Future`` container.
Expand Down Expand Up @@ -1526,10 +1522,7 @@ def FutureFailure( # noqa: N802

@overload
def future_safe(
exceptions: Callable[
_FuncParams,
Coroutine[_FirstType, _SecondType, _ValueType_co],
],
exceptions: Callable[_FuncParams, Awaitable[_ValueType_co]],
/,
) -> Callable[_FuncParams, FutureResultE[_ValueType_co]]: ...

Expand All @@ -1538,33 +1531,20 @@ def future_safe(
def future_safe(
exceptions: tuple[type[_ExceptionType], ...],
) -> Callable[
[
Callable[
_FuncParams,
Coroutine[_FirstType, _SecondType, _ValueType_co],
],
],
[Callable[_FuncParams, Awaitable[_ValueType_co]]],
Callable[_FuncParams, FutureResult[_ValueType_co, _ExceptionType]],
]: ...


def future_safe( # noqa: WPS212, WPS234,
exceptions: (
Callable[
_FuncParams,
Coroutine[_FirstType, _SecondType, _ValueType_co],
]
Callable[_FuncParams, Awaitable[_ValueType_co]]
| tuple[type[_ExceptionType], ...]
),
) -> (
Callable[_FuncParams, FutureResultE[_ValueType_co]]
| Callable[
[
Callable[
_FuncParams,
Coroutine[_FirstType, _SecondType, _ValueType_co],
],
],
[Callable[_FuncParams, Awaitable[_ValueType_co]]],
Callable[_FuncParams, FutureResult[_ValueType_co, _ExceptionType]],
]
):
Expand Down Expand Up @@ -1621,10 +1601,7 @@ def future_safe( # noqa: WPS212, WPS234,
"""

def _future_safe_factory( # noqa: WPS430
function: Callable[
_FuncParams,
Coroutine[_FirstType, _SecondType, _ValueType_co],
],
function: Callable[_FuncParams, Awaitable[_ValueType_co]],
inner_exceptions: tuple[type[_ExceptionType], ...],
) -> Callable[_FuncParams, FutureResult[_ValueType_co, _ExceptionType]]:
async def factory(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,18 @@
...

reveal_type(future(test)) # N: Revealed type is "def (first: int) -> returns.future.Future[str]"


- case: future_decorator_with_awaitable_type
disable_cache: false
main: |
from typing import Awaitable, Callable
from returns.future import future

async def test(first: int) -> int:
return first

# `future` should accept plain `Awaitable`, not just `Coroutine`.
typed_test: Callable[[int], Awaitable[int]] = test

reveal_type(future(typed_test)) # N: Revealed type is "def (int) -> returns.future.Future[int]"
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,19 @@
return 1

reveal_type(test) # N: Revealed type is "def (first: int, second: str | None =, *, kw: bool =) -> returns.future.FutureResult[int, ValueError]"


- case: future_safe_decorator_with_awaitable_type
disable_cache: false
main: |
from typing import Awaitable, Callable
from returns.future import future_safe

async def test(first: int) -> int:
return first

# `future_safe` should accept plain `Awaitable`, not just `Coroutine`.
typed_test: Callable[[int], Awaitable[int]] = test

reveal_type(future_safe(typed_test)) # N: Revealed type is "def (int) -> returns.future.FutureResult[int, Exception]"
reveal_type(future_safe((ValueError,))(typed_test)) # N: Revealed type is "def (int) -> returns.future.FutureResult[int, ValueError]"