Skip to content

Commit a520f94

Browse files
committed
Closes #245
1 parent 3b74931 commit a520f94

File tree

7 files changed

+47
-42
lines changed

7 files changed

+47
-42
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ See [0Ver](https://0ver.org/).
3737

3838
- Adds `Result.lift`, `Maybe.lift`, `RequiresContext.lift`,
3939
and `RequiresContextResult.lift` functions in addition to `IO.lift`
40+
- Adds
4041

4142

4243
### Bugfixes

returns/context/requires_context.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
from returns.functions import identity
88
from returns.primitives.container import BaseContainer
9+
from returns.primitives.types import Immutable, Stateless
910

1011
# Context:
1112
_EnvType = TypeVar('_EnvType', contravariant=True)
@@ -225,7 +226,11 @@ def from_value(
225226

226227

227228
@final
228-
class Context(Generic[_EnvType]):
229+
class Context(
230+
Immutable,
231+
Stateless,
232+
Generic[_EnvType],
233+
):
229234
"""
230235
Helpers that can be used to work with ``RequiresContext`` container.
231236

returns/context/requires_context_result.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
from returns.context.requires_context import RequiresContext
88
from returns.primitives.container import BaseContainer
9+
from returns.primitives.types import Immutable, Stateless
910
from returns.result import Failure, Result, Success
1011

1112
# Context:
@@ -648,7 +649,11 @@ def from_failure(
648649

649650

650651
@final
651-
class ContextResult(Generic[_EnvType]):
652+
class ContextResult(
653+
Immutable,
654+
Stateless,
655+
Generic[_EnvType],
656+
):
652657
"""
653658
Helpers that can be used to work with ``RequiresContextResult`` container.
654659

returns/primitives/container.py

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
# -*- coding: utf-8 -*-
22

33
from abc import ABCMeta
4-
from typing import Any, Callable, NoReturn, TypeVar, Union
4+
from typing import Any, Callable, TypeVar, Union
55

66
from typing_extensions import Protocol, runtime
77

8-
from returns.primitives.exceptions import ImmutableStateError
8+
from returns.primitives.types import Immutable
99

1010
_ValueType = TypeVar('_ValueType', covariant=True)
1111
_NewValueType = TypeVar('_NewValueType')
1212
_ErrorType = TypeVar('_ErrorType', covariant=True)
1313
_NewErrorType = TypeVar('_NewErrorType')
1414

1515

16-
class BaseContainer(object, metaclass=ABCMeta):
16+
class BaseContainer(Immutable, metaclass=ABCMeta):
1717
"""Utility class to provide all needed magic methods to the context."""
1818

1919
__slots__ = ('_inner_value',)
@@ -27,14 +27,6 @@ def __init__(self, inner_value) -> None:
2727
"""
2828
object.__setattr__(self, '_inner_value', inner_value) # noqa: WPS609
2929

30-
def __setattr__(self, attr_name: str, attr_value: Any) -> NoReturn:
31-
"""Makes inner state of the containers immutable."""
32-
raise ImmutableStateError()
33-
34-
def __delattr__(self, attr_name: str) -> NoReturn: # noqa: WPS603
35-
"""Makes inner state of the containers immutable."""
36-
raise ImmutableStateError()
37-
3830
def __str__(self) -> str:
3931
"""Converts to string."""
4032
return '<{0}: {1}>'.format(

returns/primitives/types.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# -*- coding: utf-8 -*-
2+
3+
from typing import Any, NoReturn
4+
5+
from returns.primitives.exceptions import ImmutableStateError
6+
7+
8+
class Immutable(object):
9+
"""Helper type for objects that should be immutable."""
10+
11+
def __setattr__(self, attr_name: str, attr_value: Any) -> NoReturn:
12+
"""Makes inner state of the containers immutable."""
13+
raise ImmutableStateError()
14+
15+
def __delattr__(self, attr_name: str) -> NoReturn: # noqa: WPS603
16+
"""Makes inner state of the containers immutable."""
17+
raise ImmutableStateError()
18+
19+
20+
class Stateless(object):
21+
"""Helper type for object that should be empty."""
22+
23+
__slots__ = ()

tests/test_context/test_requires_context/test_context.py

Lines changed: 4 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
from returns.context import Context, RequiresContext
66
from returns.primitives.container import Bindable, Mappable
7+
from returns.primitives.exceptions import ImmutableStateError
78

89

910
@pytest.mark.parametrize('container', [
@@ -20,28 +21,7 @@ def test_protocols(container, protocol):
2021
assert isinstance(container, protocol)
2122

2223

23-
def test_context_map():
24+
def test_context_immutable():
2425
"""Ensures that RequiresContext container supports ``.map()`` method."""
25-
context: RequiresContext[int, str] = RequiresContext.from_value(
26-
1.0,
27-
).map(
28-
str,
29-
)
30-
assert context(3) == RequiresContext.from_value(
31-
'1.0',
32-
)(RequiresContext.empty)
33-
34-
35-
def test_context_bind():
36-
"""Ensures that RequiresContext container supports ``.bind()`` method."""
37-
def factory(number: float) -> RequiresContext[int, str]:
38-
return RequiresContext(lambda deps: str(number + deps))
39-
40-
context: RequiresContext[int, str] = RequiresContext.from_value(
41-
1.0,
42-
).bind(
43-
factory,
44-
)
45-
assert context(3) == RequiresContext.from_value(
46-
'4.0',
47-
)(RequiresContext.empty)
26+
with pytest.raises(ImmutableStateError):
27+
Context().a = 1

tests/test_context/test_requires_context_result/test_context_result.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
Rescueable,
1212
Unwrapable,
1313
)
14+
from returns.primitives.exceptions import ImmutableStateError
1415
from returns.result import Failure, Success
1516

1617

@@ -34,9 +35,7 @@ def test_protocols(container, protocol):
3435
assert isinstance(container, protocol)
3536

3637

37-
def test_context_map():
38+
def test_context_result_immutable():
3839
"""Ensures that RequiresContext container supports ``.map()`` method."""
39-
context = RequiresContextResult.from_success(1.0).map(str)
40-
assert context(...) == RequiresContextResult.from_success(
41-
'1.0',
42-
)(RequiresContextResult.empty)
40+
with pytest.raises(ImmutableStateError):
41+
ContextResult().a = 1

0 commit comments

Comments
 (0)