How to use the pfun.immutable.Immutable function in pfun

To help you get started, we’ve selected a few pfun examples, based on popular ways it is used in public projects.

Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.

github suned / pfun / pfun / subprocess.py View on Github external
import asyncio
from subprocess import PIPE, CalledProcessError
from typing import IO, Tuple, Union

from typing_extensions import Protocol

from .aio_trampoline import Done
from .effect import Effect, Try, add_repr, get_environment
from .either import Left, Right
from .immutable import Immutable


class Subprocess(Immutable):
    """
    Module that enables running commands in the shell
    """
    def run_in_shell(
        self,
        cmd: str,
        stdin: Union[IO, int] = PIPE,
        stdout: Union[IO, int] = PIPE,
        stderr: Union[IO, int] = PIPE
    ) -> Try[CalledProcessError, Tuple[bytes, bytes]]:
        """
        Get an `Effect` that runs `cmd` in the shell

        Example:
            >>> Subprocess().run_in_shell('cat foo.txt').run(None)
            (b'contents of foo.txt', b'')
github suned / pfun / pfun / reader.py View on Github external
from .curry import curry
from .immutable import Immutable
from .monad import Monad, filter_m_, map_m_, sequence_
from .trampoline import Call, Done, Trampoline
from .with_effect import with_effect_

Context = TypeVar('Context')
Result_ = TypeVar('Result_')
Next = TypeVar('Next')

A = TypeVar('A')
B = TypeVar('B')


class Reader(Immutable, Generic[Context, Result_], Monad):
    """
    Represents a computation that is not yet completed, but
    will complete once given an object of type ``Context``

    """

    f: Callable[[Context], Trampoline[Result_]]

    def and_then(
        self: 'Reader[Context, Result_]',
        f: 'Callable[[Result_], Reader[Context, Next]]'
    ) -> 'Reader[Context, Next]':
        """
        Compose ``f`` with the function wrapped by this
        :class:`Reader` instance
github suned / pfun / pfun / functions.py View on Github external
>>> f(None)
        1
        >>> f('')
        1
        >>> "... and so on..."

    Args:
        value: The value to return always

    Return:
        function that always returns `value`
    """
    return Always(value)


class Composition(Immutable):
    functions: Tuple[Callable, ...]

    def __call__(self, *args, **kwargs):
        fs = reversed(self.functions)
        first, *rest = fs
        last_result = first(*args, **kwargs)
        for f in rest:
            last_result = f(last_result)
        return last_result


def compose(
    f: Callable[[Any], Any],
    g: Callable[[Any], Any],
    *functions: Callable[[Any], Any]
) -> Callable[[Any], Any]:
github suned / pfun / pfun / effect.py View on Github external
return await resource.get.__aexit__(*args, **kwargs)


class RuntimeEnv(Immutable, Generic[A]):
    """
    Wraps the user supplied environment R and supplies various utilities
    for the effect runtime such as the resource AsyncExitStack

    :attribute r: The user supplied environment value
    :attribute exit_stack: AsyncExitStack used to enable Effect resources
    """
    r: A
    exit_stack: AsyncExitStack


class Effect(Generic[R, E, A], Immutable):
    """
    Wrapper for functions of type \
    `Callable[[R], Awaitable[pfun.Either[E, A]]]` that are allowed to \
    perform side-effects
    """
    run_e: Callable[[RuntimeEnv[R]], Awaitable[Trampoline[Either[E, A]]]]
    _repr: str = ''

    def with_repr(self, s: str) -> Effect[R, E, A]:
        return Effect(self.run_e, s)  # type: ignore

    def __repr__(self):
        if not self._repr:
            return f'Effect(run_e={repr(self.run_e)})'

        return self._repr
github suned / pfun / pfun / http.py View on Github external
from .either import Right
from .immutable import Immutable
from .maybe import Maybe, from_optional
from .parse import JSon

try:
    import aiohttp
    from aiohttp.client_exceptions import ClientError
except ImportError:
    raise ImportError(
        'Could not import aiohttp. To use pfun.effect.http, '
        'install pfun with \n\n\tpip install pfun[http]'
    )


class Response(Immutable):
    """
    The result of making a HTTP request.
    """
    content: bytes
    """
    The response content
    """
    status: int
    """
    The request status
    """
    reason: Maybe[str]
    """
    The reason for the request status, e.g "OK"
    """
    cookies: http.cookies.BaseCookie
github suned / pfun / pfun / maybe.py View on Github external
from functools import wraps
from typing import (Any, Callable, Generic, Iterable, Optional, Sequence,
                    TypeVar, Union, cast)

from .either import Either, Left
from .functions import curry
from .immutable import Immutable
from .list import List
from .monad import Monad, filter_m_, map_m_, sequence_

A = TypeVar('A', covariant=True)
B = TypeVar('B')
C = TypeVar('C')


class Maybe_(Immutable, Monad, ABC):
    """
    Abstract super class for classes that represent computations that can fail.
    Should not be instantiated directly.
    Use `Just` and `Nothing` instead.

    """
    @abstractmethod
    def and_then(self, f: Callable) -> Any:
        """
        Chain together functional calls, carrying along the state of the
        computation that may fail.

        Example:
            >>> f = lambda i: Just(1 / i) if i != 0 else Nothing()
            >>> Just(2).and_then(f)
            Just(0.5)
github suned / pfun / pfun / writer.py View on Github external
from typing import Callable, Generator, Generic, Iterable, TypeVar, cast

from pfun.monoid import M, append, empty

from .curry import curry
from .either import Either, Left
from .immutable import Immutable
from .monad import Monad, filter_m_, map_m_, sequence_
from .with_effect import with_effect_tail_rec

A = TypeVar('A')
B = TypeVar('B')


class Writer(Generic[A, M], Immutable, Monad):
    """
    Represents a value
    along with a monoid value that is accumulated as
    an effect

    """
    a: A
    m: M

    def and_then(self, f: 'Callable[[A], Writer[B, M]]') -> 'Writer[B, M]':
        """
        Pass the value in this value/monoid pair to ``f``,
        and then combine the resulting monoid with the monoid in this pair

        :example:
        >>> Writer(1, ['first element']).and_then(
github suned / pfun / pfun / effect.py View on Github external
    @wraps(f)
    def decorator(*args, **kwargs):
        effect = f(*args, **kwargs)
        self, *args = args
        args_repr = ', '.join([repr(arg) for arg in args])
        kwargs_repr = ', '.join(
            [f'{name}={repr(value)}' for name, value in kwargs.items()]
        )
        sig_repr = args_repr + ((', ' + kwargs_repr) if kwargs_repr else '')
        repr_ = f'{repr(self)}.{f.__name__}({sig_repr})'
        return effect.with_repr(repr_)

    return decorator  # type: ignore


class Resource(Immutable, Generic[E, C]):
    """
    Enables lazy initialisation of global async context managers that should \
    only be entered once per effect invocation. If the same resource is \
    acquired twice by an effect using `get`, the same context manager will \
    be returned. All context managers controlled by resources are guaranteed \
    to be entered before the effect that requires it is invoked, and exited \
    after it returns. The wrapped context manager is only available when the \
    resources context is entered.


    :example:
    >>> from aiohttp import ClientSession
    >>> resource = Resource(ClientSession)
    >>> r1, r2 = resource.get().and_then(
    ...     lambda r1: resource.get().map(lambda r2: (r1, r2))
    ... )
github suned / pfun / pfun / logging.py View on Github external
import logging
from types import TracebackType
from typing import Optional, Tuple, Type, Union

from typing_extensions import Protocol

from .aio_trampoline import Done
from .effect import Depends, Effect, Success, add_repr, get_environment
from .either import Right
from .immutable import Immutable

ExcInfo = Tuple[Type[BaseException], BaseException, TracebackType]


class Logger(Immutable):
    """
    Wrapper around built-in `logging.Logger` class that
    calls logging methods as effects
    """
    logger: logging.Logger

    def debug(
        self,
        msg: str,
        stack_info: bool = False,
        exc_info: Union[bool, ExcInfo] = False
    ) -> Success[None]:
        """
        Create an effect that calls built-in `logging.debug`

        Example:
github suned / pfun / pfun / sql.py View on Github external
"""

    try:
        return success(List(type_(**row) for row in results)  # type: ignore
                       )
    except TypeError as e:
        return error(e)


class MalformedConnectionStr(Exception):
    """
    Error returned when a malformed connection str is passed to `SQL`
    """


class SQL(Immutable, init=False):
    """
    Module providing postgres sql client capability
    """
    connection: Resource[asyncpg.PostgresError, PostgresConnection]

    def __init__(self, connection_str: str):
        """
        Create an SQL module

        Args:
            connection_str: connection string of the format \
            `postgres://:@/`
        """
        url = urllib.parse.urlparse(connection_str)
        if url.scheme not in {'postgresql', 'postgres'}:
            raise MalformedConnectionStr(connection_str)