Skip to content

Commit

Permalink
Issue 1267 - Remove .success_type and .failure_type (#1677)
Browse files Browse the repository at this point in the history
* refactor: Remove Result.success_type and Result.failure_type

* refactor: Remove Maybe.success_type and Maybe.failure_type

* refactor: Remove IOResult.success_type and IOResult.failure_type

* docs: Update CHANGELOG

* chore(review): apply requested changes

* chore(review) Update CHANGELOG

* chore(review): Update CHANGELOG
  • Loading branch information
ducdetronquito authored Sep 1, 2023
1 parent 22d693e commit 8907464
Show file tree
Hide file tree
Showing 17 changed files with 35 additions and 132 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ incremental in minor, bugfixes only are patches.
See [0Ver](https://0ver.org/).


## 1.0.0 WIP

### Misc

- *Breaking*: Remove `success_type` and `failure_type` fields from `IOResult`, `Maybe` and `Result` types

## 0.22.0

### Features
Expand Down
18 changes: 9 additions & 9 deletions returns/_internal/futures/_future_result.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ async def async_bind(
) -> Result[_NewValueType, _ErrorType]:
"""Async binds a container over a value."""
container = await inner_value
if isinstance(container, Result.success_type):
if isinstance(container, Success):
return (await dekind(function(container.unwrap())))._inner_value
return container # type: ignore[return-value]

Expand All @@ -58,7 +58,7 @@ async def async_bind_awaitable(
) -> Result[_NewValueType, _ErrorType]:
"""Async binds a coroutine over a value."""
container = await inner_value
if isinstance(container, Result.success_type):
if isinstance(container, Success):
return Result.from_value(await function(container.unwrap()))
return container # type: ignore[return-value]

Expand All @@ -72,7 +72,7 @@ async def async_bind_async(
) -> Result[_NewValueType, _ErrorType]:
"""Async binds a coroutine with container over a value."""
container = await inner_value
if isinstance(container, Result.success_type):
if isinstance(container, Success):
return await dekind(await function(container.unwrap()))._inner_value
return container # type: ignore[return-value]

Expand All @@ -91,7 +91,7 @@ async def async_bind_ioresult(
) -> Result[_NewValueType, _ErrorType]:
"""Async binds a container returning ``IOResult`` over a value."""
container = await inner_value
if isinstance(container, Result.success_type):
if isinstance(container, Success):
return function(container.unwrap())._inner_value
return container # type: ignore[return-value]

Expand All @@ -102,7 +102,7 @@ async def async_bind_io(
) -> Result[_NewValueType, _ErrorType]:
"""Async binds a container returning ``IO`` over a value."""
container = await inner_value
if isinstance(container, Result.success_type):
if isinstance(container, Success):
return Success(function(container.unwrap())._inner_value)
return container # type: ignore[return-value]

Expand All @@ -113,7 +113,7 @@ async def async_bind_future(
) -> Result[_NewValueType, _ErrorType]:
"""Async binds a container returning ``IO`` over a value."""
container = await inner_value
if isinstance(container, Result.success_type):
if isinstance(container, Success):
return await async_from_success(function(container.unwrap()))
return container # type: ignore[return-value]

Expand All @@ -124,7 +124,7 @@ async def async_bind_async_future(
) -> Result[_NewValueType, _ErrorType]:
"""Async binds a container returning ``IO`` over a value."""
container = await inner_value
if isinstance(container, Result.success_type):
if isinstance(container, Success):
return await async_from_success(await function(container.unwrap()))
return container # type: ignore[return-value]

Expand All @@ -135,7 +135,7 @@ async def async_alt(
) -> Result[_ValueType, _NewErrorType]:
"""Async alts a function over a value."""
container = await inner_value
if isinstance(container, Result.success_type):
if isinstance(container, Success):
return container
return Failure(function(container.failure()))

Expand All @@ -149,7 +149,7 @@ async def async_lash(
) -> Result[_ValueType, _NewErrorType]:
"""Async lashes a function returning a container over a value."""
container = await inner_value
if isinstance(container, Result.success_type):
if isinstance(container, Success):
return container
return (await dekind(function(container.failure())))._inner_value

Expand Down
4 changes: 2 additions & 2 deletions returns/_internal/futures/_reader_future_result.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from typing import TYPE_CHECKING, Awaitable, Callable, TypeVar

from returns.primitives.hkt import Kind3, dekind
from returns.result import Result
from returns.result import Result, Success

if TYPE_CHECKING:
from returns.context import RequiresContextFutureResult # noqa: F401
Expand Down Expand Up @@ -29,7 +29,7 @@ async def async_bind_async(
) -> Result[_NewValueType, _ErrorType]:
"""Async binds a coroutine with container over a value."""
inner_value = await container(deps)._inner_value
if isinstance(inner_value, Result.success_type):
if isinstance(inner_value, Success):
return await dekind(
await function(inner_value.unwrap()),
)(deps)._inner_value
Expand Down
2 changes: 1 addition & 1 deletion returns/context/requires_context_ioresult.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ def bind_result(
.. code:: python
>>> from returns.context import RequiresContextIOResult
>>> from returns.result import Success, Failure, Result
>>> from returns.result import Failure, Result, Success
>>> from returns.io import IOSuccess, IOFailure
>>> def function(num: int) -> Result[int, str]:
Expand Down
4 changes: 2 additions & 2 deletions returns/context/requires_context_result.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ def apply(
.. code:: python
>>> from returns.context import RequiresContextResult
>>> from returns.result import Success, Failure, Result
>>> from returns.result import Failure, Success
>>> def transform(arg: str) -> str:
... return arg + 'b'
Expand All @@ -217,7 +217,7 @@ def apply(
>>> assert isinstance(RequiresContextResult.from_value('a').apply(
... RequiresContextResult.from_failure(transform),
... )(...), Result.failure_type) is True
... )(...), Failure) is True
"""
return RequiresContextResult(
Expand Down
2 changes: 1 addition & 1 deletion returns/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ def not_(function: Callable[_FuncParams, bool]) -> Callable[_FuncParams, bool]:
>>> from returns.result import Result, Success, Failure
>>> def is_successful(result_container: Result[float, int]) -> bool:
... return isinstance(result_container, Result.success_type)
... return isinstance(result_container, Success)
>>> assert not_(is_successful)(Success(1.0)) is False
>>> assert not_(is_successful)(Failure(1)) is True
Expand Down
4 changes: 2 additions & 2 deletions returns/future.py
Original file line number Diff line number Diff line change
Expand Up @@ -1478,7 +1478,7 @@ def future_safe(
>>> import anyio
>>> from returns.future import future_safe
>>> from returns.io import IOSuccess, IOResult
>>> from returns.io import IOFailure, IOSuccess
>>> @future_safe
... async def might_raise(arg: int) -> float:
Expand All @@ -1488,7 +1488,7 @@ def future_safe(
>>> assert anyio.run(might_raise(2).awaitable) == IOSuccess(0.5)
>>> assert isinstance(
... anyio.run(might_raise(0).awaitable),
... IOResult.failure_type,
... IOFailure,
... )
Similar to :func:`returns.io.impure_safe` and :func:`returns.result.safe`
Expand Down
20 changes: 4 additions & 16 deletions returns/io.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,10 @@
TYPE_CHECKING,
Any,
Callable,
ClassVar,
Generator,
Iterator,
List,
Optional,
Type,
TypeVar,
Union,
final,
Expand Down Expand Up @@ -342,12 +340,6 @@ class IOResult( # type: ignore[type-var]
_inner_value: Result[_ValueType, _ErrorType]
__match_args__ = ('_inner_value',)

# These two are required for projects like `classes`:
#: Success type that is used to represent the successful computation.
success_type: ClassVar[Type['IOSuccess']]
#: Failure type that is used to represent the failed computation.
failure_type: ClassVar[Type['IOFailure']]

#: Typesafe equality comparison with other `IOResult` objects.
equals = container_equality

Expand Down Expand Up @@ -441,9 +433,9 @@ def apply(
>>> assert IOFailure('a').apply(IOFailure('b')) == IOFailure('a')
"""
if isinstance(self, self.failure_type):
if isinstance(self, IOFailure):
return self
if isinstance(container, self.success_type):
if isinstance(container, IOSuccess):
return self.from_result(
self._inner_value.map(
container.unwrap()._inner_value, # noqa: WPS437
Expand Down Expand Up @@ -757,7 +749,7 @@ def from_result(
>>> assert IOResult.from_result(Failure(2)) == IOFailure(2)
"""
if isinstance(inner_value, inner_value.success_type):
if isinstance(inner_value, Success):
return IOSuccess(inner_value._inner_value) # noqa: WPS437
return IOFailure(inner_value._inner_value) # type: ignore[arg-type] # noqa: WPS437, E501

Expand Down Expand Up @@ -884,13 +876,9 @@ def lash(self, function):
"""Does nothing for ``IOSuccess``."""
return self


IOResult.success_type = IOSuccess
IOResult.failure_type = IOFailure


# Aliases:


#: Alias for a popular case when ``IOResult`` has ``Exception`` as error type.
IOResultE = IOResult[_ValueType, Exception]

Expand Down
13 changes: 1 addition & 12 deletions returns/maybe.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
Iterator,
NoReturn,
Optional,
Type,
TypeVar,
Union,
final,
Expand Down Expand Up @@ -55,13 +54,6 @@ class Maybe( # type: ignore[type-var]
#: Alias for `Nothing`
empty: ClassVar['Maybe[Any]']

# These two are required for projects like `classes`:

#: Success type that is used to represent the successful computation.
success_type: ClassVar[Type['Some']]
#: Failure type that is used to represent the failed computation.
failure_type: ClassVar[Type['_Nothing']]

#: Typesafe equality comparison with other `Result` objects.
equals = container_equality

Expand Down Expand Up @@ -431,7 +423,7 @@ def map(self, function):

def apply(self, container):
"""Calls a wrapped function in a container on this container."""
if isinstance(container, self.success_type):
if isinstance(container, Some):
return self.map(container.unwrap()) # type: ignore
return container

Expand All @@ -452,9 +444,6 @@ def failure(self):
raise UnwrapFailedError(self)


Maybe.success_type = Some
Maybe.failure_type = _Nothing

#: Public unit value of protected :class:`~_Nothing` type.
Nothing: Maybe[NoReturn] = _Nothing()
Maybe.empty = Nothing
Expand Down
20 changes: 5 additions & 15 deletions returns/result.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
TYPE_CHECKING,
Any,
Callable,
ClassVar,
Generator,
Iterator,
List,
Expand Down Expand Up @@ -60,12 +59,6 @@ class Result( # type: ignore[type-var]
_inner_value: Union[_ValueType, _ErrorType]
_trace: Optional[List[FrameInfo]]

# These two are required for projects like `classes`:
#: Success type that is used to represent the successful computation.
success_type: ClassVar[Type['Success']]
#: Failure type that is used to represent the failed computation.
failure_type: ClassVar[Type['Failure']]

#: Typesafe equality comparison with other `Result` objects.
equals = container_equality

Expand Down Expand Up @@ -453,7 +446,7 @@ def lash(self, function):

def apply(self, container):
"""Calls a wrapped function in a container on this container."""
if isinstance(container, self.success_type):
if isinstance(container, Success):
return self.map(container.unwrap())
return container

Expand All @@ -474,9 +467,6 @@ def failure(self) -> NoReturn:
raise UnwrapFailedError(self)


Result.success_type = Success
Result.failure_type = Failure

# Aliases:

#: Alias for a popular case when ``Result`` has ``Exception`` as error type.
Expand Down Expand Up @@ -524,27 +514,27 @@ def safe( # type: ignore # noqa: WPS234, C901
.. code:: python
>>> from returns.result import Result, Success, safe
>>> from returns.result import Failure, Success, safe
>>> @safe
... def might_raise(arg: int) -> float:
... return 1 / arg
>>> assert might_raise(1) == Success(1.0)
>>> assert isinstance(might_raise(0), Result.failure_type)
>>> assert isinstance(might_raise(0), Failure)
You can also use it with explicit exception types as the first argument:
.. code:: python
>>> from returns.result import Result, Success, safe
>>> from returns.result import Failure, Success, safe
>>> @safe(exceptions=(ZeroDivisionError,))
... def might_raise(arg: int) -> float:
... return 1 / arg
>>> assert might_raise(1) == Success(1.0)
>>> assert isinstance(might_raise(0), Result.failure_type)
>>> assert isinstance(might_raise(0), Failure)
In this case, only exceptions that are explicitly
listed are going to be caught.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import pytest

from returns.future import FutureResult, future_safe
from returns.io import IOResult, IOSuccess
from returns.io import IOFailure, IOSuccess


@future_safe
Expand All @@ -24,4 +24,4 @@ async def test_future_safe_decorator_failure():
future_instance = _coro(0)

assert isinstance(future_instance, FutureResult)
assert isinstance(await future_instance, IOResult.failure_type)
assert isinstance(await future_instance, IOFailure)
7 changes: 0 additions & 7 deletions tests/test_io/test_ioresult_container/test_ioresult_base.py

This file was deleted.

7 changes: 0 additions & 7 deletions tests/test_maybe/test_maybe_base.py

This file was deleted.

7 changes: 0 additions & 7 deletions tests/test_result/test_result_base.py

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,3 @@
container: IO[str]
reveal_type(IOResult.from_failed_io(container)) # N: Revealed type is "returns.io.IOResult[Any, builtins.str]"
- case: ioresult_success_type
disable_cache: false
main: |
from returns.io import IOResult
reveal_type(IOResult.success_type) # N: Revealed type is "Type[returns.io.IOSuccess[Any]]"
- case: ioresult_failure_type
disable_cache: false
main: |
from returns.io import IOResult
reveal_type(IOResult.failure_type) # N: Revealed type is "Type[returns.io.IOFailure[Any]]"
Loading

0 comments on commit 8907464

Please sign in to comment.