Source code for returns.primitives.container
# -*- coding: utf-8 -*-
from abc import ABCMeta, abstractmethod
from typing import Generic, TypeVar
from returns.primitives.exceptions import ImmutableStateError
_ValueType = TypeVar('_ValueType')
_ErrorType = TypeVar('_ErrorType')
class _BaseContainer(object, metaclass=ABCMeta):
"""Utility class to provide all needed magic methods to the contest."""
__slots__ = ('_inner_value',)
def __init__(self, inner_value):
"""
Wraps the given value in the Container.
'value' is any arbitrary value of any type including functions.
"""
object.__setattr__(self, '_inner_value', inner_value)
def __setattr__(self, attr_name, attr_value):
"""Makes inner state of the monads immutable."""
raise ImmutableStateError()
def __delattr__(self, attr_name): # noqa: Z434
"""Makes inner state of the monads immutable."""
raise ImmutableStateError()
def __str__(self):
"""Converts to string."""
return '{0}: {1}'.format(
self.__class__.__qualname__,
str(self._inner_value),
)
def __eq__(self, other):
"""Used to compare two 'Container' objects."""
if not isinstance(other, _BaseContainer):
return False
if type(self) != type(other):
return False
return self._inner_value == other._inner_value # noqa: Z441
[docs]class Container(_BaseContainer, metaclass=ABCMeta):
"""
Represents a "context" in which calculations can be executed.
You won't create 'Container' instances directly.
Instead, sub-classes implement specific contexts.
Monads allow you to bind together
a series of calculations while maintaining
the context of that specific monad.
This is an abstract class with the API declaration.
Attributes:
_inner_value: Wrapped internal immutable state.
"""
[docs] @abstractmethod # noqa: A003
def map(self, function): # pragma: no cover
"""
Applies 'function' to the contents of the functor.
And returns a new functor value.
Works for monads that represent success.
Is the opposite of :meth:`~fix`.
"""
raise NotImplementedError()
[docs] @abstractmethod
def bind(self, function): # pragma: no cover
"""
Applies 'function' to the result of a previous calculation.
And returns a new monad.
Works for monads that represent success.
Is the opposite of :meth:`~rescue`.
"""
raise NotImplementedError()
[docs] @abstractmethod
def fix(self, function): # pragma: no cover
"""
Applies 'function' to the contents of the functor.
And returns a new functor value.
Works for monads that represent failure.
Is the opposite of :meth:`~map`.
"""
raise NotImplementedError()
[docs] @abstractmethod
def rescue(self, function): # pragma: no cover
"""
Applies 'function' to the result of a previous calculation.
And returns a new monad.
Works for monads that represent failure.
Is the opposite of :meth:`~bind`.
"""
raise NotImplementedError()
[docs] @abstractmethod
def value_or(self, default_value): # pragma: no cover
"""Forces to unwrap value from monad or return a default."""
raise NotImplementedError()
[docs] @abstractmethod
def unwrap(self): # pragma: no cover
"""
Custom magic method to unwrap inner value from monad.
Should be redefined for ones that actually have values.
And for ones that raise an exception for no values.
This method is the opposite of :meth:`~failure`.
"""
raise NotImplementedError()
[docs] @abstractmethod
def failure(self): # pragma: no cover
"""
Custom magic method to unwrap inner value from the failed monad.
This method is the opposite of :meth:`~unwrap`.
"""
raise NotImplementedError()
[docs]class GenericContainerOneSlot(Generic[_ValueType], Container):
"""
Base class for monads with one typed slot.
Use this type for generic inheritance only.
Use :class:`~Container` as a general type for polymorphism.
"""
[docs]class GenericContainerTwoSlots(Generic[_ValueType, _ErrorType], Container):
"""
Base class for monads with two typed slot.
Use this type for generic inheritance only.
Use :class:`~Container` as a general type for polymorphism.
"""