Skip to content

Commit d73a043

Browse files
committed
New interfaces
1 parent c030d82 commit d73a043

20 files changed

+279
-195
lines changed

CHANGELOG.md

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,14 @@ We follow Semantic Versions since the `0.1.0` release.
55

66
## WIP
77

8+
### Features
9+
10+
- Provides a bunch of primitive interfaces to write your own containers
11+
12+
### Bugfixes
13+
14+
- Fixes type of `Maybe.fix` and `Maybe.rescue` to work with both `lambda: 1` and `lambda _: 1`
15+
816
### Misc
917

1018
- Improves `README`
@@ -14,7 +22,7 @@ We follow Semantic Versions since the `0.1.0` release.
1422

1523
### Features
1624

17-
- Reintroduces the `Maybe` monad, typed!
25+
- Reintroduces the `Maybe` container, typed!
1826
- Introduces converters from one type to another
1927
- Adds `mypy` plugin to type decorators
2028
- Complete rewrite of `Result` types
@@ -80,7 +88,7 @@ We follow Semantic Versions since the `0.1.0` release.
8088
- Fixes copyright notice in the docs
8189

8290

83-
## Version 0.4.0 aka Goodbye, Monads!
91+
## Version 0.4.0 aka Goodbye, containers!
8492

8593
### Features
8694

@@ -91,8 +99,8 @@ We follow Semantic Versions since the `0.1.0` release.
9199
- Renames `do_notation` to `pipeline`, moves it to `functions.py`
92100
- Renames `ebind` to `rescue`
93101
- Renames `efmap` to `fix`
94-
- Renames `Monad` to `Container`
95-
- Removes `Maybe` monad, since typing does not have `NonNullable` type
102+
- Renames `container` to `Container`
103+
- Removes `Maybe` container, since typing does not have `NonNullable` type
96104

97105

98106
## Version 0.3.1
@@ -116,16 +124,16 @@ The project is renamed to `returns` and moved to `dry-python` org.
116124

117125
### Features
118126

119-
- Adds `Maybe` monad
120-
- Adds immutability and `__slots__` to all monads
127+
- Adds `Maybe` container
128+
- Adds immutability and `__slots__` to all containers
121129
- Adds methods to work with failures
122-
- Adds `safe` decorator to convert exceptions to `Result` monad
130+
- Adds `safe` decorator to convert exceptions to `Result` container
123131
- Adds `is_successful()` function to detect if your result is a success
124-
- Adds `failure()` method to unwrap values from failed monads
132+
- Adds `failure()` method to unwrap values from failed containers
125133

126134
### Bugfixes
127135

128-
- Changes the type of `.bind` method for `Success` monad
136+
- Changes the type of `.bind` method for `Success` container
129137
- Changes how equality works, so now `Failure(1) != Success(1)`
130138
- Changes how new instances created on unused methods
131139

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@ pip install returns
2525
```
2626

2727
You might also want to [configure](https://returns.readthedocs.io/en/latest/pages/container.html#type-safety)
28-
`mypy` correctly and install our plugin:
28+
`mypy` correctly and install our plugin
29+
to fix [this existing issue](https://github.com/python/mypy/issues/3157):
2930

3031
```ini
3132
# In setup.cfg or mypy.ini:

docs/pages/container.rst

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ List of supported containers:
1111

1212
- :class:`IO <returns.io.IO>` to mark explicit ``IO`` actions
1313
- :class:`Result <returns.result.Result>` to handle possible exceptions
14+
- :class:`Maybe <returns.maybe.Maybe>` to handle ``None`` cases
1415

1516
We will show you container's simple API of one attribute
1617
and several simple methods.
@@ -49,7 +50,7 @@ The difference is simple:
4950
- ``map`` works with functions that return regular value
5051
- ``bind`` works with functions that return new container of the same type
5152

52-
:func:`.bind <returns.primitives.container.Container.bind>`
53+
:func:`.bind <returns.primitives.container.Bindable.bind>`
5354
is used to literally bind two different containers together.
5455

5556
.. code:: python
@@ -62,7 +63,7 @@ is used to literally bind two different containers together.
6263
# Can be assumed as either Success[int] or Failure[str]:
6364
result: Result[int, str] = Success(1).bind(may_fail)
6465
65-
And we have :func:`.map <returns.primitives.container.Container.map>`
66+
And we have :func:`.map <returns.primitives.container.Mappable.map>`
6667
to use containers with regular functions.
6768

6869
.. code:: python
@@ -139,10 +140,10 @@ Returning execution to the right track
139140
We also support two special methods to work with "failed"
140141
types like ``Failure``:
141142

142-
- :func:`.fix <returns.primitives.container.FixableContainer.fix>`
143+
- :func:`.fix <returns.primitives.container.Fixable.fix>`
143144
is the opposite of ``map`` method
144145
that works only when container is in failed state
145-
- :func:`.rescue <returns.primitives.container.FixableContainer.rescue>`
146+
- :func:`.rescue <returns.primitives.container.Rescueable.rescue>`
146147
is the opposite of ``bind`` method
147148
that works only when container is in failed state
148149

@@ -193,19 +194,20 @@ Unwrapping values
193194
And we have two more functions to unwrap
194195
inner state of containers into a regular types:
195196

196-
- :func:`.value_or <returns.primitives.container.ValueUnwrapContainer.value_or>`
197+
- :func:`.value_or <returns.primitives.container.Unwrapable.value_or>`
197198
returns a value if it is possible, returns ``default_value`` otherwise
198-
- :func:`.unwrap <returns.primitives.container.ValueUnwrapContainer.unwrap>`
199+
- :func:`.unwrap <returns.primitives.container.Unwrapable.unwrap>`
199200
returns a value if it is possible, raises ``UnwrapFailedError`` otherwise
200201

201202
.. code:: python
202203
203204
from returns.result import Failure, Success
205+
from returns.maybe import Some, Nothing
204206
205207
Success(1).value_or(None)
206208
# => 1
207209
208-
Success(0).unwrap()
210+
Some(0).unwrap()
209211
# => 0
210212
211213
Failure(1).value_or(default_value=100)
@@ -214,11 +216,14 @@ inner state of containers into a regular types:
214216
Failure(1).unwrap()
215217
# => Traceback (most recent call last): UnwrapFailedError
216218
217-
The most user-friendly way to use ``unwrap`` method is with :ref:`pipeline`.
219+
Nothing.unwrap()
220+
# => Traceback (most recent call last): UnwrapFailedError
221+
222+
The most user-friendly way to use ``.unwrap()`` method is with :ref:`pipeline`.
218223
We even discourage using ``.unwrap()`` without a ``@pipeline``.
219224

220225
For failing containers you can
221-
use :func:`.failure <returns.primitives.container.FixableContainer.failure>`
226+
use :func:`.failure <returns.primitives.container.Unwrapable.failure>`
222227
to unwrap the failed state:
223228

224229
.. code:: python
@@ -230,7 +235,7 @@ to unwrap the failed state:
230235
# => Traceback (most recent call last): UnwrapFailedError
231236
232237
Be careful, since this method will raise an exception
233-
when you try to ``failure`` a successful container.
238+
when you try to ``.failure()`` a successful container.
234239

235240
Note::
236241

@@ -307,7 +312,7 @@ You can use :ref:`converters` to convert ``Maybe`` and ``Result`` containers.
307312
So, you don't have to compose them.
308313

309314

310-
.. converters_:
315+
.. _converters:
311316

312317
Converters
313318
----------

docs/pages/maybe.rst

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,9 @@ It might be very useful for complex operations like the following one:
4747
4848
order: Order # some existing Order instance
4949
street: Maybe[str] = Maybe.new(order.user).map(
50-
lambda user: user.address,
50+
lambda user: user.address,
5151
).map(
52-
lambda address: address.street,
52+
lambda address: address.street,
5353
)
5454
# => `Some('address street info')` if all fields are not None
5555
# => `Nothing` if at least one field is `None`
@@ -81,7 +81,8 @@ when new logic will be introduced.
8181
Sometimes we have to deal with functions
8282
that dears to return ``Optional`` values!
8383

84-
We have to work with the carefully and write ``if x is not None:`` everywhere.
84+
We have to work with it the carefully
85+
and write ``if x is not None:`` everywhere.
8586
Luckily, we have your back! ``maybe`` function decorates
8687
any other function that returns ``Optional``
8788
and converts it to return ``Maybe`` instead:
@@ -98,7 +99,7 @@ and converts it to return ``Maybe`` instead:
9899
return None
99100
100101
result: Maybe[int] = number(1)
101-
# => 1
102+
# => Some(1)
102103
103104
104105
API Reference

poetry.lock

Lines changed: 10 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

returns/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
See: https://github.com/dry-python/returns/issues/73
1414
"""
1515

16+
from returns.converters import maybe_to_result, result_to_maybe
1617
from returns.functions import compose, raise_exception
1718
from returns.io import IO, impure
1819
from returns.maybe import Maybe, Nothing, Some, maybe
@@ -45,4 +46,8 @@
4546
# pipeline:
4647
'is_successful',
4748
'pipeline',
49+
50+
# Converters:
51+
'result_to_maybe',
52+
'maybe_to_result',
4853
)

returns/io.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22

33
from functools import wraps
44
from inspect import iscoroutinefunction
5-
from typing import Callable, Coroutine, TypeVar, overload
5+
from typing import Callable, Coroutine, Generic, TypeVar, overload
66

77
from typing_extensions import final
88

9-
from returns.primitives.container import Container, GenericContainerOneSlot
9+
from returns.primitives.container import BaseContainer
1010

1111
_ValueType = TypeVar('_ValueType')
1212
_NewValueType = TypeVar('_NewValueType')
@@ -17,7 +17,7 @@
1717

1818

1919
@final
20-
class IO(GenericContainerOneSlot[_ValueType]):
20+
class IO(Generic[_ValueType], BaseContainer):
2121
"""
2222
Explicit marker for impure function results.
2323
@@ -33,7 +33,7 @@ class IO(GenericContainerOneSlot[_ValueType]):
3333

3434
def __init__(self, inner_value: _ValueType) -> None:
3535
"""Required for typing."""
36-
Container.__init__(self, inner_value) # type: ignore # noqa: Z462
36+
BaseContainer.__init__(self, inner_value) # type: ignore # noqa: Z462
3737

3838
def map( # noqa: A003
3939
self,

0 commit comments

Comments
 (0)