File: reader_result.py

package info (click to toggle)
python-returns 0.26.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 2,652 kB
  • sloc: python: 11,000; makefile: 18
file content (138 lines) | stat: -rw-r--r-- 3,987 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
from __future__ import annotations

from abc import abstractmethod
from collections.abc import Callable, Sequence
from typing import TYPE_CHECKING, ClassVar, TypeVar, final

from returns.interfaces.specific import reader, result
from returns.primitives.hkt import KindN
from returns.primitives.laws import (
    Law,
    Law2,
    Lawful,
    LawSpecDef,
    law_definition,
)

if TYPE_CHECKING:
    from returns.context import Reader, ReaderResult  # noqa: WPS433
    from returns.result import Result  # noqa: F401, WPS433

_FirstType = TypeVar('_FirstType')
_SecondType = TypeVar('_SecondType')
_ThirdType = TypeVar('_ThirdType')
_UpdatedType = TypeVar('_UpdatedType')

_ValueType = TypeVar('_ValueType')
_ErrorType = TypeVar('_ErrorType')
_EnvType = TypeVar('_EnvType')

_ReaderResultLikeType = TypeVar(
    '_ReaderResultLikeType',
    bound='ReaderResultLikeN',
)


class ReaderResultLikeN(
    reader.ReaderLike3[_FirstType, _SecondType, _ThirdType],
    result.ResultLikeN[_FirstType, _SecondType, _ThirdType],
):
    """
    Base interface for all types that do look like ``ReaderResult`` instance.

    Cannot be called.
    """

    __slots__ = ()

    @abstractmethod
    def bind_context_result(
        self: _ReaderResultLikeType,
        function: Callable[
            [_FirstType],
            ReaderResult[_UpdatedType, _SecondType, _ThirdType],
        ],
    ) -> KindN[_ReaderResultLikeType, _UpdatedType, _SecondType, _ThirdType]:
        """Binds a ``ReaderResult`` returning function over a container."""

    @classmethod
    @abstractmethod
    def from_failed_context(
        cls: type[_ReaderResultLikeType],
        inner_value: Reader[_ErrorType, _EnvType],
    ) -> KindN[_ReaderResultLikeType, _FirstType, _ErrorType, _EnvType]:
        """Unit method to create new containers from failed ``Reader``."""

    @classmethod
    @abstractmethod
    def from_result_context(
        cls: type[_ReaderResultLikeType],
        inner_value: ReaderResult[_ValueType, _ErrorType, _EnvType],
    ) -> KindN[_ReaderResultLikeType, _ValueType, _ErrorType, _EnvType]:
        """Unit method to create new containers from ``ReaderResult``."""


#: Type alias for kinds with three type arguments.
ReaderResultLike3 = ReaderResultLikeN[_FirstType, _SecondType, _ThirdType]


@final
class _LawSpec(LawSpecDef):
    """
    Concrete laws for ``ReaderResulBasedN``.

    See: https://github.com/haskell/mtl/pull/61/files
    """

    __slots__ = ()

    @law_definition
    def purity_law(
        container: ReaderResultBasedN[_FirstType, _SecondType, _ThirdType],
        env: _ThirdType,
    ) -> None:
        """Calling a ``Reader`` twice has the same result with the same env."""
        assert container(env) == container(env)

    @law_definition
    def asking_law(
        container: ReaderResultBasedN[_FirstType, _SecondType, _ThirdType],
        env: _ThirdType,
    ) -> None:
        """Asking for an env, always returns the env."""
        assert container.ask().__call__(  # noqa: PLC2801
            env,
        ) == container.from_value(env).__call__(env)  # noqa: PLC2801


class ReaderResultBasedN(
    ReaderResultLikeN[_FirstType, _SecondType, _ThirdType],
    reader.CallableReader3[
        _FirstType,
        _SecondType,
        _ThirdType,
        # Calls:
        'Result[_FirstType, _SecondType]',
        _ThirdType,
    ],
    Lawful['ReaderResultBasedN[_FirstType, _SecondType, _ThirdType]'],
):
    """
    This interface is very specific to our ``ReaderResult`` type.

    The only thing that differs from ``ReaderResultLikeN`` is that we know
    the specific types for its ``__call__`` method.

    In this case the return type of ``__call__`` is ``Result``.
    """

    __slots__ = ()

    _laws: ClassVar[Sequence[Law]] = (
        Law2(_LawSpec.purity_law),
        Law2(_LawSpec.asking_law),
    )


#: Type alias for kinds with three type arguments.
ReaderResultBased3 = ReaderResultBasedN[_FirstType, _SecondType, _ThirdType]