Skip to content

Checkable

Bases: Protocol


              flowchart TD
              pyochain.abc._mixins.Checkable[Checkable]

              

              click pyochain.abc._mixins.Checkable href "" "pyochain.abc._mixins.Checkable"
            

Mixin class providing conditional chaining methods based on truthiness.

This class provides methods inspired by Rust's bool type for conditional execution and wrapping in Option or Result types.

All methods evaluate the instance's truthiness to determine their behavior.

Truthiness being determined by:

  • __bool__() if defined
  • otherwise by __len__() if defined (returning False if length is 0)
  • otherwise all instances are truthy (Python's default behavior).

This can be very handy to cover the common pattern of checking if a collection is empty or not.

You can then explicitly handle each situation with Option or Result types, without breaking the fluent method chaining.

Tip

This class is compiled in Rust with Pyo3 bindings.

This means that even pure Python classes inheriting from Checkable can call these methods with builtin-like performance.

Example

Pyochain collections can efficiently check for emptiness and execute code conditionally natively.

from pyochain import Seq, Some

assert Seq(1, 2, 3).then(sum) == Some(6)
assert Seq().then(sum).is_none()
This can also be extended to any type, not just collections.
from pyochain.abc import Checkable

class MyString(str, Checkable): ...

assert MyString("hello").then(lambda s: s.upper()) == Some("HELLO")
assert MyString("").then(lambda s: s.upper()).is_none()
This means that you can handle complex business logic in the same way.
from pyochain import Err
from dataclasses import dataclass

@dataclass(slots=True)
class User(Checkable):
    name: str
    is_active: bool
    age: int
    def __bool__(self) -> bool:
        return self.is_active and self.age >= 18

    def describe(self) -> str:
        return f"{self.name} is an active adult"

alice = User("Alice", is_active=True, age=30).then(User.describe)
bob = (
    User("Bob", is_active=False, age=24)
    .then(User.describe)
    .ok_or("Expected an active adult user")
    .map_err(ValueError)
)
assert alice == Some("Alice is an active adult")
assert (
    bob.map_err(repr).unwrap_err()
    == "ValueError('Expected an active adult user')"
)

Source code in pyochain/abc/_mixins.pyi
 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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
class Checkable(Protocol):
    """Mixin class providing conditional chaining methods based on truthiness.

    This class provides methods inspired by Rust's `bool` type for conditional
    execution and wrapping in `Option` or `Result` types.

    All methods evaluate the instance's truthiness to determine their behavior.

    Truthiness being determined by:

    - `__bool__()` if defined
    - otherwise by `__len__()` if defined (returning `False` if length is 0)
    - otherwise all instances are truthy (Python's default behavior).

    This can be very handy to cover the common pattern of checking if a collection is empty or not.

    You can then explicitly handle each situation with `Option` or `Result` types, without breaking the fluent method chaining.

    Tip:
        This class is compiled in Rust with Pyo3 bindings.

        This means that even pure Python classes inheriting from `Checkable` can call these methods with builtin-like performance.

    Example:
        Pyochain collections can efficiently check for emptiness and execute code conditionally natively.
        ```python
        from pyochain import Seq, Some

        assert Seq(1, 2, 3).then(sum) == Some(6)
        assert Seq().then(sum).is_none()
        ```
        This can also be extended to any type, not just collections.
        ```python
        from pyochain.abc import Checkable

        class MyString(str, Checkable): ...

        assert MyString("hello").then(lambda s: s.upper()) == Some("HELLO")
        assert MyString("").then(lambda s: s.upper()).is_none()
        ```
        This means that you can handle complex business logic in the same way.
        ```python
        from pyochain import Err
        from dataclasses import dataclass

        @dataclass(slots=True)
        class User(Checkable):
            name: str
            is_active: bool
            age: int
            def __bool__(self) -> bool:
                return self.is_active and self.age >= 18

            def describe(self) -> str:
                return f"{self.name} is an active adult"

        alice = User("Alice", is_active=True, age=30).then(User.describe)
        bob = (
            User("Bob", is_active=False, age=24)
            .then(User.describe)
            .ok_or("Expected an active adult user")
            .map_err(ValueError)
        )
        assert alice == Some("Alice is an active adult")
        assert (
            bob.map_err(repr).unwrap_err()
            == "ValueError('Expected an active adult user')"
        )
        ```
    """

    def then[**P, R](
        self,
        func: Callable[Concatenate[Self, P], R],
        *args: P.args,
        **kwargs: P.kwargs,
    ) -> Option[R]:
        """Wrap `Self` in an `Option[R]` based on its truthiness.

        `R` being the return type of **func**.

        The function is only called if `Self` evaluates to `True` (lazy evaluation).

        Args:
            func (Callable[Concatenate[Self, P], R]): A callable that returns the value to wrap in Some.
            *args (P.args): Positional arguments to pass to **func**.
            **kwargs (P.kwargs): Keyword arguments to pass to **func**.

        Returns:
            Option[R]: `Some(R)` if self is truthy, `NONE` otherwise.

        Example:
            ```python
            from pyochain import Seq, Some

            assert Seq(1, 2, 3).then(lambda s: s.iter().sum()) == Some(6)
            assert Seq().then(lambda s: s.iter().sum()).is_none()
            ```
        """

    def then_some(self) -> Option[Self]:
        """Wraps `Self` in an `Option[Self]` based on its truthiness.

        Returns:
            Option[Self]: `Some(self)` if self is truthy, `NONE` otherwise.

        Example:
            ```python
            from pyochain import Seq, Some

            data = Seq(1, 2, 3)

            assert data.then_some() == Some(data)
            assert Seq().then_some().is_none()
            ```
        """
    def ok_or[E](self, err: E) -> Result[Self, E]:
        """Wrap `Self` in a `Result[Self, E]` based on its truthiness.

        This method is the inverse of `err_or`.

        Args:
            err (E): The error value to wrap in Err if self is falsy.

        Returns:
            Result[Self, E]: `Ok(self)` if self is truthy, `Err(err)` otherwise.

        Example:
            ```python
            from pyochain import Seq

            data = Seq(1, 2, 3)
            msg = "empty"

            assert data.ok_or(msg).unwrap() == data
            assert Seq().ok_or(msg).unwrap_err() == msg
            ```
        """
    def err_or[T](self, ok: T) -> Result[T, Self]:
        """Wrap `Self` in a `Result[T, Self]` based on its truthiness.

        This method is the inverse of `ok_or`.

        Args:
            ok (T): The ok value to wrap in Ok if self is falsy.

        Returns:
            Result[T, Self]: `Ok(ok)` if self is truthy, `Err(self)` otherwise.

        Example:
            ```python
            from pyochain import Seq

            msg = "should be empty"
            data = Seq(1, 2, 3)

            assert data.err_or(msg).unwrap_err() == data
            assert Seq().err_or(msg).unwrap() == msg
            ```
        """

    def ok_or_else[**P, E](
        self,
        func: Callable[Concatenate[Self, P], E],
        *args: P.args,
        **kwargs: P.kwargs,
    ) -> Result[Self, E]:
        """Wrap `Self` in a `Result[Self, E]` based on its truthiness.

        `E` being the return type of **func**.

        The function is only called if self evaluates to False.

        Args:
            func (Callable[Concatenate[Self, P], E]): A callable that returns the error value to wrap in Err.
            *args (P.args): Positional arguments to pass to the function.
            **kwargs (P.kwargs): Keyword arguments to pass to the function.

        Returns:
            Result[Self, E]: Ok(self) if self is truthy, Err(f(...)) otherwise.

        Example:
            ```python
            from pyochain import Seq

            data = Seq(1, 2, 3)
            msg = "empty seq"

            assert data.ok_or_else(lambda s: msg).unwrap() == data
            assert Seq().ok_or_else(lambda s: msg).unwrap_err() == msg
            ```
        """
    def err_or_else[**P, T](
        self,
        func: Callable[Concatenate[Self, P], T],
        *args: P.args,
        **kwargs: P.kwargs,
    ) -> Result[T, Self]:
        """Wrap `Self` in a `Result[T, Self]` based on its truthiness.

        `T` being the return type of **func**.

        The function is only called if self evaluates to False.


        Args:
            func (Callable[Concatenate[Self, P], T]): A callable that returns the error value to wrap in Err.
            *args (P.args): Positional arguments to pass to the function.
            **kwargs (P.kwargs): Keyword arguments to pass to the function.

        Returns:
            Result[T, Self]: Ok(f(...)) if self is falsy, Err(self) otherwise.

        Example:
            ```python
            from pyochain import Seq

            msg = "should be empty"

            data = Seq(1, 2, 3)

            assert data.err_or_else(lambda s: msg).unwrap_err() == data
            assert Seq().err_or_else(lambda s: msg).unwrap() == msg
            ```
        """

then(func, *args, **kwargs)

Wrap Self in an Option[R] based on its truthiness.

R being the return type of func.

The function is only called if Self evaluates to True (lazy evaluation).

Parameters:

Name Type Description Default
func Callable[Concatenate[Self, P], R]

A callable that returns the value to wrap in Some.

required
*args P.args

Positional arguments to pass to func.

()
**kwargs P.kwargs

Keyword arguments to pass to func.

{}

Returns:

Type Description
Option[R]

Option[R]: Some(R) if self is truthy, NONE otherwise.

Example
from pyochain import Seq, Some

assert Seq(1, 2, 3).then(lambda s: s.iter().sum()) == Some(6)
assert Seq().then(lambda s: s.iter().sum()).is_none()
Source code in pyochain/abc/_mixins.pyi
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
def then[**P, R](
    self,
    func: Callable[Concatenate[Self, P], R],
    *args: P.args,
    **kwargs: P.kwargs,
) -> Option[R]:
    """Wrap `Self` in an `Option[R]` based on its truthiness.

    `R` being the return type of **func**.

    The function is only called if `Self` evaluates to `True` (lazy evaluation).

    Args:
        func (Callable[Concatenate[Self, P], R]): A callable that returns the value to wrap in Some.
        *args (P.args): Positional arguments to pass to **func**.
        **kwargs (P.kwargs): Keyword arguments to pass to **func**.

    Returns:
        Option[R]: `Some(R)` if self is truthy, `NONE` otherwise.

    Example:
        ```python
        from pyochain import Seq, Some

        assert Seq(1, 2, 3).then(lambda s: s.iter().sum()) == Some(6)
        assert Seq().then(lambda s: s.iter().sum()).is_none()
        ```
    """

then_some()

Wraps Self in an Option[Self] based on its truthiness.

Returns:

Type Description
Option[Self]

Option[Self]: Some(self) if self is truthy, NONE otherwise.

Example
from pyochain import Seq, Some

data = Seq(1, 2, 3)

assert data.then_some() == Some(data)
assert Seq().then_some().is_none()
Source code in pyochain/abc/_mixins.pyi
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
def then_some(self) -> Option[Self]:
    """Wraps `Self` in an `Option[Self]` based on its truthiness.

    Returns:
        Option[Self]: `Some(self)` if self is truthy, `NONE` otherwise.

    Example:
        ```python
        from pyochain import Seq, Some

        data = Seq(1, 2, 3)

        assert data.then_some() == Some(data)
        assert Seq().then_some().is_none()
        ```
    """

ok_or(err)

Wrap Self in a Result[Self, E] based on its truthiness.

This method is the inverse of err_or.

Parameters:

Name Type Description Default
err E

The error value to wrap in Err if self is falsy.

required

Returns:

Type Description
Result[Self, E]

Result[Self, E]: Ok(self) if self is truthy, Err(err) otherwise.

Example
from pyochain import Seq

data = Seq(1, 2, 3)
msg = "empty"

assert data.ok_or(msg).unwrap() == data
assert Seq().ok_or(msg).unwrap_err() == msg
Source code in pyochain/abc/_mixins.pyi
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
def ok_or[E](self, err: E) -> Result[Self, E]:
    """Wrap `Self` in a `Result[Self, E]` based on its truthiness.

    This method is the inverse of `err_or`.

    Args:
        err (E): The error value to wrap in Err if self is falsy.

    Returns:
        Result[Self, E]: `Ok(self)` if self is truthy, `Err(err)` otherwise.

    Example:
        ```python
        from pyochain import Seq

        data = Seq(1, 2, 3)
        msg = "empty"

        assert data.ok_or(msg).unwrap() == data
        assert Seq().ok_or(msg).unwrap_err() == msg
        ```
    """

err_or(ok)

Wrap Self in a Result[T, Self] based on its truthiness.

This method is the inverse of ok_or.

Parameters:

Name Type Description Default
ok T

The ok value to wrap in Ok if self is falsy.

required

Returns:

Type Description
Result[T, Self]

Result[T, Self]: Ok(ok) if self is truthy, Err(self) otherwise.

Example
from pyochain import Seq

msg = "should be empty"
data = Seq(1, 2, 3)

assert data.err_or(msg).unwrap_err() == data
assert Seq().err_or(msg).unwrap() == msg
Source code in pyochain/abc/_mixins.pyi
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
def err_or[T](self, ok: T) -> Result[T, Self]:
    """Wrap `Self` in a `Result[T, Self]` based on its truthiness.

    This method is the inverse of `ok_or`.

    Args:
        ok (T): The ok value to wrap in Ok if self is falsy.

    Returns:
        Result[T, Self]: `Ok(ok)` if self is truthy, `Err(self)` otherwise.

    Example:
        ```python
        from pyochain import Seq

        msg = "should be empty"
        data = Seq(1, 2, 3)

        assert data.err_or(msg).unwrap_err() == data
        assert Seq().err_or(msg).unwrap() == msg
        ```
    """

ok_or_else(func, *args, **kwargs)

Wrap Self in a Result[Self, E] based on its truthiness.

E being the return type of func.

The function is only called if self evaluates to False.

Parameters:

Name Type Description Default
func Callable[Concatenate[Self, P], E]

A callable that returns the error value to wrap in Err.

required
*args P.args

Positional arguments to pass to the function.

()
**kwargs P.kwargs

Keyword arguments to pass to the function.

{}

Returns:

Type Description
Result[Self, E]

Result[Self, E]: Ok(self) if self is truthy, Err(f(...)) otherwise.

Example
from pyochain import Seq

data = Seq(1, 2, 3)
msg = "empty seq"

assert data.ok_or_else(lambda s: msg).unwrap() == data
assert Seq().ok_or_else(lambda s: msg).unwrap_err() == msg
Source code in pyochain/abc/_mixins.pyi
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
def ok_or_else[**P, E](
    self,
    func: Callable[Concatenate[Self, P], E],
    *args: P.args,
    **kwargs: P.kwargs,
) -> Result[Self, E]:
    """Wrap `Self` in a `Result[Self, E]` based on its truthiness.

    `E` being the return type of **func**.

    The function is only called if self evaluates to False.

    Args:
        func (Callable[Concatenate[Self, P], E]): A callable that returns the error value to wrap in Err.
        *args (P.args): Positional arguments to pass to the function.
        **kwargs (P.kwargs): Keyword arguments to pass to the function.

    Returns:
        Result[Self, E]: Ok(self) if self is truthy, Err(f(...)) otherwise.

    Example:
        ```python
        from pyochain import Seq

        data = Seq(1, 2, 3)
        msg = "empty seq"

        assert data.ok_or_else(lambda s: msg).unwrap() == data
        assert Seq().ok_or_else(lambda s: msg).unwrap_err() == msg
        ```
    """

err_or_else(func, *args, **kwargs)

Wrap Self in a Result[T, Self] based on its truthiness.

T being the return type of func.

The function is only called if self evaluates to False.

Parameters:

Name Type Description Default
func Callable[Concatenate[Self, P], T]

A callable that returns the error value to wrap in Err.

required
*args P.args

Positional arguments to pass to the function.

()
**kwargs P.kwargs

Keyword arguments to pass to the function.

{}

Returns:

Type Description
Result[T, Self]

Result[T, Self]: Ok(f(...)) if self is falsy, Err(self) otherwise.

Example
from pyochain import Seq

msg = "should be empty"

data = Seq(1, 2, 3)

assert data.err_or_else(lambda s: msg).unwrap_err() == data
assert Seq().err_or_else(lambda s: msg).unwrap() == msg
Source code in pyochain/abc/_mixins.pyi
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
def err_or_else[**P, T](
    self,
    func: Callable[Concatenate[Self, P], T],
    *args: P.args,
    **kwargs: P.kwargs,
) -> Result[T, Self]:
    """Wrap `Self` in a `Result[T, Self]` based on its truthiness.

    `T` being the return type of **func**.

    The function is only called if self evaluates to False.


    Args:
        func (Callable[Concatenate[Self, P], T]): A callable that returns the error value to wrap in Err.
        *args (P.args): Positional arguments to pass to the function.
        **kwargs (P.kwargs): Keyword arguments to pass to the function.

    Returns:
        Result[T, Self]: Ok(f(...)) if self is falsy, Err(self) otherwise.

    Example:
        ```python
        from pyochain import Seq

        msg = "should be empty"

        data = Seq(1, 2, 3)

        assert data.err_or_else(lambda s: msg).unwrap_err() == data
        assert Seq().err_or_else(lambda s: msg).unwrap() == msg
        ```
    """