Skip to content

Commit 22cd266

Browse files
committed
Closes #256
1 parent b657c32 commit 22cd266

File tree

7 files changed

+76
-3
lines changed

7 files changed

+76
-3
lines changed

CHANGELOG.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ See [0Ver](https://0ver.org/).
1515
- **Breaking**: removes `Maybe.rescue` and `Maybe.fix` methods
1616
- **Breaking**: renames `io_squash` to `squash_io`
1717
and moves it to `returns.converters`
18+
- **Breaking**: moves all interfaces from `returns.primitives.container` to
19+
`returns.primitives.interfaces`
1820

1921
- Adds `rescue` pointfree function
2022
- Adds `ResultE` alias for `Result[..., Exception]`
@@ -47,14 +49,17 @@ See [0Ver](https://0ver.org/).
4749

4850
- Adds `Result.lift`, `Maybe.lift`, `RequiresContext.lift`,
4951
and `RequiresContextResult.lift` functions in addition to `IO.lift`
52+
5053
- Adds `Immutable` primitive type
5154
- Adds `Unitable` protocol and `.from_success()` and `.from_failure()`
5255
methods for all `Result` realted classes
56+
- Adds `Instanceable` protocol and `.from_value()` method
57+
for `IO` and `RequiresContext`
58+
5359
- Adds `flow` function, which is similar to `pipe`
5460
- Adds `swap` coverter for `Result` and `IOResult`
5561
- Adds `squash_context` function to squash `RequiresContext` similar to `IO`
5662

57-
5863
### Bugfixes
5964

6065
- Now `Success` and `Failure` (both `io` and pure) return `Any` and not `NoReturn`

returns/context/requires_context.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,8 @@ def from_value(
221221
222222
Might be used with or without direct type hint.
223223
224+
Part of the :class:`returns.primitives.interfaces.Instanceable`
225+
protocol.
224226
"""
225227
return RequiresContext(lambda _: inner_value)
226228

returns/io.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,23 @@ def lift(
149149
"""
150150
return lambda container: container.map(function)
151151

152+
@classmethod
153+
def from_value(cls, inner_value: _NewValueType) -> 'IO[_NewValueType]':
154+
"""
155+
Unit function to construct new ``IO`` values.
156+
157+
Is the same as regular constructor:
158+
159+
.. code:: python
160+
161+
>>> from returns.io import IO
162+
>>> assert IO(1) == IO.from_value(1)
163+
164+
Part of the :class:`returns.primitives.interfaces.Instanceable`
165+
protocol.
166+
"""
167+
return IO(inner_value)
168+
152169

153170
# Helper functions:
154171

returns/primitives/interfaces.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,22 @@ def alt(
136136
"""
137137

138138

139+
@runtime
140+
class Instanceable(Protocol[_ValueType]):
141+
"""
142+
Allows to create unit containers from raw values.
143+
144+
This is heavily related to classes that do not have conunter-parts.
145+
Like ``IO`` and ``RequiresContext``.
146+
"""
147+
148+
@classmethod
149+
def from_value(
150+
cls, inner_value: _NewValueType,
151+
) -> 'Unitable[_NewValueType, Any]':
152+
"""This method is required to create new containers."""
153+
154+
139155
@runtime
140156
class Unitable(Protocol[_ValueType, _ErrorType]):
141157
"""

tests/test_context/test_requires_context/test_context.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
from returns.context import Context, RequiresContext
66
from returns.primitives.exceptions import ImmutableStateError
7-
from returns.primitives.interfaces import Bindable, Mappable
7+
from returns.primitives.interfaces import Bindable, Instanceable, Mappable
88

99

1010
@pytest.mark.parametrize('container', [
@@ -15,6 +15,7 @@
1515
@pytest.mark.parametrize('protocol', [
1616
Bindable,
1717
Mappable,
18+
Instanceable,
1819
])
1920
def test_protocols(container, protocol):
2021
"""Ensures that RequiresContext has all the right protocols."""

tests/test_io/test_io_container/test_io.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import pytest
44

55
from returns.io import IO
6-
from returns.primitives.interfaces import Bindable, Mappable
6+
from returns.primitives.interfaces import Bindable, Instanceable, Mappable
77

88

99
@pytest.mark.parametrize('container', [
@@ -12,6 +12,7 @@
1212
@pytest.mark.parametrize('protocol', [
1313
Bindable,
1414
Mappable,
15+
Instanceable,
1516
])
1617
def test_protocols(container, protocol):
1718
"""Ensures that IO has all the right protocols."""

typesafety/test_context/test_requires_context/test_requires_context_cast.yml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,34 @@
1818
second: RequiresContext[Exception, Exception] = first
1919
out: |
2020
main:4: error: Incompatible types in assignment (expression has type "RequiresContext[ValueError, TypeError]", variable has type "RequiresContext[Exception, Exception]")
21+
22+
23+
- case: context_covariant_cast
24+
disable_cache: true
25+
main: |
26+
from returns.context import RequiresContext
27+
28+
class A(object):
29+
a = 1
30+
31+
class B(A):
32+
b = 2
33+
34+
class C(A):
35+
c = 3
36+
37+
def func() -> RequiresContext[B, int]:
38+
return RequiresContext(lambda deps: deps.a + deps.b)
39+
40+
def second(a: int) -> RequiresContext[A, int]:
41+
return RequiresContext(lambda deps: deps.a + a)
42+
43+
def third(a: int) -> RequiresContext[C, int]:
44+
return RequiresContext(lambda deps: deps.c + a)
45+
46+
reveal_type(func().bind(second))
47+
reveal_type(func().bind(third))
48+
out: |
49+
main:21: note: Revealed type is 'returns.context.requires_context.RequiresContext[main.B, builtins.int*]'
50+
main:22: error: Argument 1 to "bind" of "RequiresContext" has incompatible type "Callable[[int], RequiresContext[C, int]]"; expected "Callable[[int], RequiresContext[B, int]]"
51+
main:22: note: Revealed type is 'returns.context.requires_context.RequiresContext[main.B, builtins.int*]'

0 commit comments

Comments
 (0)