Skip to content

Commit

Permalink
add Partition #1905 (#1908)
Browse files Browse the repository at this point in the history
  • Loading branch information
RomanMIzulin committed Aug 15, 2024
1 parent e444ea7 commit e96a354
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 0 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ See [0Ver](https://0ver.org/).
- Improve inference of `ResultLike` objects when exception catching
decorator is applied with explicit exception types
- Add picky exceptions to `impure_safe` decorator like `safe` has. Issue #1543
- Add partition function to result module. Issue #1905
- Adds `default_error` parameter to `returns.converters.maybe_to_result`,
which provides a default error value for `Failure`


### Misc

- Now requires `mypy>=1.11`
Expand Down
16 changes: 16 additions & 0 deletions docs/pages/methods.rst
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,22 @@ Here's a full example:
>>> error_handled = pointfree.bimap(lambda inr: inr + 1, lambda _: 0)(instance)
>>> assert isinstance(methods.unwrap_or_failure(error_handled), int)
partition
~~~~~~~~~

:func:`partition <returns.result.partition>` is used to convert
list of :class:`~returns.interfaces.Unwrappable`
instances like :class:`~returns.result.Result`,
:class:`~returns.io.IOResult`, and :class:`~returns.maybe.Maybe`
to a tuple of two lists: successes and failures.

.. code:: python
>>> from returns.result import Failure, Success
>>> from returns.methods import partition
>>> results = [Success(1), Failure(2), Success(3), Failure(4)]
>>> partition(results)
([1, 3], [2, 4])
API Reference
-------------
Expand Down
1 change: 1 addition & 0 deletions returns/methods/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from returns.methods.cond import cond as cond
from returns.methods.partition import partition as partition
from returns.methods.unwrap_or_failure import (
unwrap_or_failure as unwrap_or_failure,
)
38 changes: 38 additions & 0 deletions returns/methods/partition.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@

from typing import Iterable, List, TypeVar

from returns.interfaces.unwrappable import Unwrappable
from returns.primitives.exceptions import UnwrapFailedError

_ValueType = TypeVar('_ValueType', covariant=True)
_ErrorType = TypeVar('_ErrorType', covariant=True)


def partition(
containers: Iterable[
Unwrappable[_ValueType, _ErrorType],
],
) -> tuple[List[_ValueType], List[_ErrorType]]:
"""
Partition a list of unwrappables into successful and failed values.
Preserves order.
.. code:: python
>>> from returns.result import Failure, Success
>>> from returns.methods import partition
>>> results = [Success(1), Failure(2), Success(3), Failure(4)]
>>> partition(results)
([1, 3], [2, 4])
"""
successes: list[_ValueType] = []
failures: list[_ErrorType] = []
for container in containers:
try:
successes.append(container.unwrap())
except UnwrapFailedError:
failures.append(container.failure())
return successes, failures
32 changes: 32 additions & 0 deletions tests/test_methods/test_partition.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@

import pytest

from returns.io import IO, IOResult
from returns.maybe import Nothing, Some
from returns.methods import partition
from returns.result import Failure, Success


@pytest.mark.parametrize(('containers', 'expected'), [
(
(Success(1), Success(2), Failure(None), Success(3)),
([1, 2, 3], [None]),
),
(
(
IOResult.from_value(1),
IOResult.from_failure(2),
IOResult.from_value(3),
IOResult.from_failure(4),
),
([IO(1), IO(3)], [IO(2), IO(4)]),
),
(
(Some(1), Some(2), Nothing),
([1, 2], [None]),
),
((), ([], [])),
])
def test_partition(containers, expected):
"""Test partition function."""
assert partition(containers) == expected
32 changes: 32 additions & 0 deletions typesafety/test_methods/test_partition.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
- case: partition_result
disable_cache: false
main: |
from typing import List
from returns.result import Success, Failure, Result
from returns.methods import partition
x: List[Result[int, str]]
reveal_type(partition(x)) # N: Revealed type is "Tuple[builtins.list[builtins.int], builtins.list[builtins.str]]"
- case: partition_io_results
disable_cache: false
main: |
from typing import Tuple
from returns.result import Success, Failure
from returns.methods import partition
from returns.io import IO, IOResult, IOSuccess
x: Tuple[IOResult[int, str], IOResult[int, str]]
reveal_type(partition(x)) # N: Revealed type is "Tuple[builtins.list[returns.io.IO[builtins.int]], builtins.list[returns.io.IO[builtins.str]]]"
- case: partition_maybe
disable_cache: false
main: |
from typing import List, Tuple
from returns.maybe import Maybe
from returns.methods import partition
x: List[Maybe[int]]
reveal_type(partition(x)) # N: Revealed type is "Tuple[builtins.list[builtins.int], builtins.list[None]]"

0 comments on commit e96a354

Please sign in to comment.