PK!]JJoption/__init__.py# MIT License # # Copyright (c) 2018 Peijun Ma # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. # pylint: skip-file """ .. data:: NONE Represents a None value. """ from .option_ import NONE, Option, Some, maybe from .result import Err, Ok, Result __version__ = '0.2.3' __all__ = ['NONE', 'Option', 'Some', 'maybe', 'Result', 'Ok', 'Err'] PK!]JJoption/__init__.py# MIT License # # Copyright (c) 2018 Peijun Ma # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. # pylint: skip-file """ .. data:: NONE Represents a None value. """ from .option_ import NONE, Option, Some, maybe from .result import Err, Ok, Result __version__ = '0.2.3' __all__ = ['NONE', 'Option', 'Some', 'maybe', 'Result', 'Ok', 'Err'] PK!cx"2"2option/option_.py# MIT License # Copyright (c) 2018 Peijun Ma # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. """ This module contains the Option class. .. data:: NONE Represents a None value. """ from typing import Callable, Generic, Mapping, Union from option.types_ import A, K, T, U, V class Option(Generic[T]): """ :py:class:`Option` represents an optional value. Every :py:class:`Option` is either ``Some`` and contains a value, or :py:data:`NONE` and does not. To create a ``Some`` value, please use :py:meth:`Option.Some` or :py:func:`Some`. To create a :py:data:`NONE` value, please use :py:meth:`Option.NONE` or import the constant :py:data:`NONE` directly. To let :py:class:`Option` guess the type of :py:class:`Option` to create, please use :py:meth:`Option.maybe` or :py:func:`maybe`. Calling the ``__init__`` method directly will raise a ``TypeError``. Examples: >>> Option.Some(1) Some(1) >>> Option.NONE() NONE >>> Option.maybe(1) Some(1) >>> Option.maybe(None) NONE """ __slots__ = ('_val', '_is_some', '_type') def __init__(self, value: T, is_some: bool, *, _force: bool = False) -> None: if not _force: raise TypeError( 'Cannot directly initialize, ' 'please use one of the factory functions instead.' ) self._val = value self._is_some = is_some self._type = type(self) @classmethod def Some(cls, val: T) -> 'Option[T]': """Some value ``val``.""" return cls(val, True, _force=True) @classmethod def NONE(cls) -> 'Option[None]': """No Value.""" return NONE @classmethod def maybe(cls, val: T) -> 'Option[T]': """ Shortcut method to return ``Some`` or :py:data:`NONE` based on ``val``. Args: val: Some value. Returns: ``Some(val)`` if the ``val`` is not None, otherwise :py:data:`NONE`. Examples: >>> Option.maybe(0) Some(0) >>> Option.maybe(None) NONE """ return NONE if val is None else cls.Some(val) def __bool__(self): """ Returns the truth value of the :py:class:`Option` based on its value. Returns: True if the :py:class:`Option` is ``Some`` value, otherwise False. Examples: >>> bool(Some(False)) True >>> bool(NONE) False """ return self._is_some @property def is_some(self) -> bool: """ Returns ``True`` if the option is a ``Some`` value. Examples: >>> Some(0).is_some True >>> NONE.is_some False """ return self.__bool__() @property def is_none(self) -> bool: """ Returns ``True`` if the option is a :py:data:`NONE` value. Examples: >>> Some(0).is_none False >>> NONE.is_none True """ return not self.__bool__() def expect(self, msg) -> T: """ Unwraps the option. Raises an exception if the value is :py:data:`NONE`. Args: msg: The exception message. Returns: The wrapped value. Raises: ``ValueError`` with message provided by ``msg`` if the value is :py:data:`NONE`. Examples: >>> Some(0).expect('sd') 0 >>> try: ... NONE.expect('Oh No!') ... except ValueError as e: ... print(e) Oh No! """ if self._is_some: return self._val raise ValueError(msg) def unwrap(self) -> T: """ Returns the value in the :py:class:`Option` if it is ``Some``. Returns: The ```Some`` value of the :py:class:`Option`. Raises: ``ValueError`` if the value is :py:data:`NONE`. Examples: >>> Some(0).unwrap() 0 >>> try: ... NONE.unwrap() ... except ValueError as e: ... print(e) Value is NONE. """ return self.value @property def value(self) -> T: """Property version of :py:meth:`unwrap`.""" if self._is_some: return self._val raise ValueError('Value is NONE.') def unwrap_or(self, default: U) -> Union[T, U]: """ Returns the contained value or ``default``. Args: default: The default value. Returns: The contained value if the :py:class:`Option` is ``Some``, otherwise ``default``. Notes: If you wish to use a result of a function call as the default, it is recommnded to use :py:meth:`unwrap_or_else` instead. Examples: >>> Some(0).unwrap_or(3) 0 >>> NONE.unwrap_or(0) 0 """ return self.unwrap_or_else(lambda: default) def unwrap_or_else(self, callback: Callable[[], U]) -> Union[T, U]: """ Returns the contained value or computes it from ``callback``. Args: callback: The the default callback. Returns: The contained value if the :py:class:`Option` is ``Some``, otherwise ``callback()``. Examples: >>> Some(0).unwrap_or_else(lambda: 111) 0 >>> NONE.unwrap_or_else(lambda: 'ha') 'ha' """ return self._val if self._is_some else callback() def map(self, callback: Callable[[T], U]) -> 'Union[Option[U], Option[None]]': """ Applies the ``callback`` with the contained value as its argument or returns :py:data:`NONE`. Args: callback: The callback to apply to the contained value. Returns: The ``callback`` result wrapped in an :class:`Option` if the contained value is ``Some``, otherwise :py:data:`NONE` Examples: >>> Some(10).map(lambda x: x * x) Some(100) >>> NONE.map(lambda x: x * x) NONE """ if self._is_some: return self._type.Some(callback(self._val)) else: return NONE def map_or(self, callback: Callable[[T], U], default: A) -> Union[U, A]: """ Applies the ``callback`` to the contained value or returns ``default``. Args: callback: The callback to apply to the contained value. default: The default value. Returns: The ``callback`` result if the contained value is ``Some``, otherwise ``default``. Notes: If you wish to use the result of a function call as ``default``, it is recommended to use :py:meth:`map_or_else` instead. Examples: >>> Some(0).map_or(lambda x: x + 1, 1000) 1 >>> NONE.map_or(lambda x: x * x, 1) 1 """ return callback(self._val) if self._is_some else default def map_or_else(self, callback: Callable[[T], U], default: Callable[[], A]) -> Union[U, A]: """ Applies the ``callback`` to the contained value or computes a default with ``default``. Args: callback: The callback to apply to the contained value. default: The callback fot the default value. Returns: The ``callback`` result if the contained value is ``Some``, otherwise the result of ``default``. Examples: >>> Some(0).map_or_else(lambda x: x * x, lambda: 1) 0 >>> NONE.map_or_else(lambda x: x * x, lambda: 1) 1 """ return callback(self._val) if self._is_some else default() def filter(self, predicate: Callable[[T], bool]) -> 'Union[Option[T], Option[None]]': """ Returns :py:data:`NONE` if the :py:class:`Option` is :py:data:`NONE`, otherwise filter the contained value by ``predicate``. Args: predicate: The fitler function. Returns: :py:data:`NONE` if the contained value is :py:data:`NONE`, otherwise: * The option itself if the predicate returns True * :py:data:`NONE` if the predicate returns False Examples: >>> Some(0).filter(lambda x: x % 2 == 1) NONE >>> Some(1).filter(lambda x: x % 2 == 1) Some(1) >>> NONE.filter(lambda x: True) NONE """ if self._is_some and predicate(self._val): return self else: return NONE def get( self: 'Option[Mapping[K,V]]', key: K, default=None ) -> 'Union[Option[V], Option[None]]': """ Gets a mapping value by key in the contained value or returns ``default`` if the key doesn't exist. Args: key: The mapping key. default: The defauilt value. Returns: * ``Some`` variant of the mapping value if the key exists and the value is not None. * ``Some(default)`` if ``default`` is not None. * :py:data:`NONE` if ``default`` is None. Examples: >>> Some({'hi': 1}).get('hi') Some(1) >>> Some({}).get('hi', 12) Some(12) >>> NONE.get('hi', 12) Some(12) >>> NONE.get('hi') NONE """ if self._is_some: return self._type.maybe(self._val.get(key, default)) return self._type.maybe(default) def __hash__(self): return hash((self.__class__, self._is_some, self._val)) def __eq__(self, other): return (isinstance(other, self._type) and self._is_some == other._is_some and self._val == other._val) def __ne__(self, other): return (not isinstance(other, self._type) or self._is_some != other._is_some or self._val != other._val) def __lt__(self, other): if isinstance(other, self._type): if self._is_some == other._is_some: return self._val < other._val if self._is_some else False else: return other._is_some return NotImplemented def __le__(self, other): if isinstance(other, self._type): if self._is_some == other._is_some: return self._val <= other._val if self._is_some else True return other._is_some return NotImplemented def __gt__(self, other): if isinstance(other, self._type): if self._is_some == other._is_some: return self._val > other._val if self._is_some else False else: return self._is_some return NotImplemented def __ge__(self, other): if isinstance(other, self._type): if self._is_some == other._is_some: return self._val >= other._val if self._is_some else True return self._is_some return NotImplemented def __repr__(self): return 'NONE' if self.is_none else f'Some({self._val!r})' def Some(val: T) -> Option[T]: """Shortcut function to :py:meth:`Option.Some`.""" return Option.Some(val) def maybe(val: T) -> Option[T]: """Shortcut function to :py:meth:`Option.maybe`.""" return Option.maybe(val) NONE = Option(None, False, _force=True) if __name__ == '__main__': import doctest doctest.testmod() PK!cx"2"2option/option_.py# MIT License # Copyright (c) 2018 Peijun Ma # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. """ This module contains the Option class. .. data:: NONE Represents a None value. """ from typing import Callable, Generic, Mapping, Union from option.types_ import A, K, T, U, V class Option(Generic[T]): """ :py:class:`Option` represents an optional value. Every :py:class:`Option` is either ``Some`` and contains a value, or :py:data:`NONE` and does not. To create a ``Some`` value, please use :py:meth:`Option.Some` or :py:func:`Some`. To create a :py:data:`NONE` value, please use :py:meth:`Option.NONE` or import the constant :py:data:`NONE` directly. To let :py:class:`Option` guess the type of :py:class:`Option` to create, please use :py:meth:`Option.maybe` or :py:func:`maybe`. Calling the ``__init__`` method directly will raise a ``TypeError``. Examples: >>> Option.Some(1) Some(1) >>> Option.NONE() NONE >>> Option.maybe(1) Some(1) >>> Option.maybe(None) NONE """ __slots__ = ('_val', '_is_some', '_type') def __init__(self, value: T, is_some: bool, *, _force: bool = False) -> None: if not _force: raise TypeError( 'Cannot directly initialize, ' 'please use one of the factory functions instead.' ) self._val = value self._is_some = is_some self._type = type(self) @classmethod def Some(cls, val: T) -> 'Option[T]': """Some value ``val``.""" return cls(val, True, _force=True) @classmethod def NONE(cls) -> 'Option[None]': """No Value.""" return NONE @classmethod def maybe(cls, val: T) -> 'Option[T]': """ Shortcut method to return ``Some`` or :py:data:`NONE` based on ``val``. Args: val: Some value. Returns: ``Some(val)`` if the ``val`` is not None, otherwise :py:data:`NONE`. Examples: >>> Option.maybe(0) Some(0) >>> Option.maybe(None) NONE """ return NONE if val is None else cls.Some(val) def __bool__(self): """ Returns the truth value of the :py:class:`Option` based on its value. Returns: True if the :py:class:`Option` is ``Some`` value, otherwise False. Examples: >>> bool(Some(False)) True >>> bool(NONE) False """ return self._is_some @property def is_some(self) -> bool: """ Returns ``True`` if the option is a ``Some`` value. Examples: >>> Some(0).is_some True >>> NONE.is_some False """ return self.__bool__() @property def is_none(self) -> bool: """ Returns ``True`` if the option is a :py:data:`NONE` value. Examples: >>> Some(0).is_none False >>> NONE.is_none True """ return not self.__bool__() def expect(self, msg) -> T: """ Unwraps the option. Raises an exception if the value is :py:data:`NONE`. Args: msg: The exception message. Returns: The wrapped value. Raises: ``ValueError`` with message provided by ``msg`` if the value is :py:data:`NONE`. Examples: >>> Some(0).expect('sd') 0 >>> try: ... NONE.expect('Oh No!') ... except ValueError as e: ... print(e) Oh No! """ if self._is_some: return self._val raise ValueError(msg) def unwrap(self) -> T: """ Returns the value in the :py:class:`Option` if it is ``Some``. Returns: The ```Some`` value of the :py:class:`Option`. Raises: ``ValueError`` if the value is :py:data:`NONE`. Examples: >>> Some(0).unwrap() 0 >>> try: ... NONE.unwrap() ... except ValueError as e: ... print(e) Value is NONE. """ return self.value @property def value(self) -> T: """Property version of :py:meth:`unwrap`.""" if self._is_some: return self._val raise ValueError('Value is NONE.') def unwrap_or(self, default: U) -> Union[T, U]: """ Returns the contained value or ``default``. Args: default: The default value. Returns: The contained value if the :py:class:`Option` is ``Some``, otherwise ``default``. Notes: If you wish to use a result of a function call as the default, it is recommnded to use :py:meth:`unwrap_or_else` instead. Examples: >>> Some(0).unwrap_or(3) 0 >>> NONE.unwrap_or(0) 0 """ return self.unwrap_or_else(lambda: default) def unwrap_or_else(self, callback: Callable[[], U]) -> Union[T, U]: """ Returns the contained value or computes it from ``callback``. Args: callback: The the default callback. Returns: The contained value if the :py:class:`Option` is ``Some``, otherwise ``callback()``. Examples: >>> Some(0).unwrap_or_else(lambda: 111) 0 >>> NONE.unwrap_or_else(lambda: 'ha') 'ha' """ return self._val if self._is_some else callback() def map(self, callback: Callable[[T], U]) -> 'Union[Option[U], Option[None]]': """ Applies the ``callback`` with the contained value as its argument or returns :py:data:`NONE`. Args: callback: The callback to apply to the contained value. Returns: The ``callback`` result wrapped in an :class:`Option` if the contained value is ``Some``, otherwise :py:data:`NONE` Examples: >>> Some(10).map(lambda x: x * x) Some(100) >>> NONE.map(lambda x: x * x) NONE """ if self._is_some: return self._type.Some(callback(self._val)) else: return NONE def map_or(self, callback: Callable[[T], U], default: A) -> Union[U, A]: """ Applies the ``callback`` to the contained value or returns ``default``. Args: callback: The callback to apply to the contained value. default: The default value. Returns: The ``callback`` result if the contained value is ``Some``, otherwise ``default``. Notes: If you wish to use the result of a function call as ``default``, it is recommended to use :py:meth:`map_or_else` instead. Examples: >>> Some(0).map_or(lambda x: x + 1, 1000) 1 >>> NONE.map_or(lambda x: x * x, 1) 1 """ return callback(self._val) if self._is_some else default def map_or_else(self, callback: Callable[[T], U], default: Callable[[], A]) -> Union[U, A]: """ Applies the ``callback`` to the contained value or computes a default with ``default``. Args: callback: The callback to apply to the contained value. default: The callback fot the default value. Returns: The ``callback`` result if the contained value is ``Some``, otherwise the result of ``default``. Examples: >>> Some(0).map_or_else(lambda x: x * x, lambda: 1) 0 >>> NONE.map_or_else(lambda x: x * x, lambda: 1) 1 """ return callback(self._val) if self._is_some else default() def filter(self, predicate: Callable[[T], bool]) -> 'Union[Option[T], Option[None]]': """ Returns :py:data:`NONE` if the :py:class:`Option` is :py:data:`NONE`, otherwise filter the contained value by ``predicate``. Args: predicate: The fitler function. Returns: :py:data:`NONE` if the contained value is :py:data:`NONE`, otherwise: * The option itself if the predicate returns True * :py:data:`NONE` if the predicate returns False Examples: >>> Some(0).filter(lambda x: x % 2 == 1) NONE >>> Some(1).filter(lambda x: x % 2 == 1) Some(1) >>> NONE.filter(lambda x: True) NONE """ if self._is_some and predicate(self._val): return self else: return NONE def get( self: 'Option[Mapping[K,V]]', key: K, default=None ) -> 'Union[Option[V], Option[None]]': """ Gets a mapping value by key in the contained value or returns ``default`` if the key doesn't exist. Args: key: The mapping key. default: The defauilt value. Returns: * ``Some`` variant of the mapping value if the key exists and the value is not None. * ``Some(default)`` if ``default`` is not None. * :py:data:`NONE` if ``default`` is None. Examples: >>> Some({'hi': 1}).get('hi') Some(1) >>> Some({}).get('hi', 12) Some(12) >>> NONE.get('hi', 12) Some(12) >>> NONE.get('hi') NONE """ if self._is_some: return self._type.maybe(self._val.get(key, default)) return self._type.maybe(default) def __hash__(self): return hash((self.__class__, self._is_some, self._val)) def __eq__(self, other): return (isinstance(other, self._type) and self._is_some == other._is_some and self._val == other._val) def __ne__(self, other): return (not isinstance(other, self._type) or self._is_some != other._is_some or self._val != other._val) def __lt__(self, other): if isinstance(other, self._type): if self._is_some == other._is_some: return self._val < other._val if self._is_some else False else: return other._is_some return NotImplemented def __le__(self, other): if isinstance(other, self._type): if self._is_some == other._is_some: return self._val <= other._val if self._is_some else True return other._is_some return NotImplemented def __gt__(self, other): if isinstance(other, self._type): if self._is_some == other._is_some: return self._val > other._val if self._is_some else False else: return self._is_some return NotImplemented def __ge__(self, other): if isinstance(other, self._type): if self._is_some == other._is_some: return self._val >= other._val if self._is_some else True return self._is_some return NotImplemented def __repr__(self): return 'NONE' if self.is_none else f'Some({self._val!r})' def Some(val: T) -> Option[T]: """Shortcut function to :py:meth:`Option.Some`.""" return Option.Some(val) def maybe(val: T) -> Option[T]: """Shortcut function to :py:meth:`Option.maybe`.""" return Option.maybe(val) NONE = Option(None, False, _force=True) if __name__ == '__main__': import doctest doctest.testmod() PK!option/py.typedPK!option/py.typedPK!8//option/result.py# MIT License # Copyright (c) 2018 Peijun Ma # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. """This module contains the Result type.""" from typing import Any, Callable, Generic, Union, cast from option.option_ import NONE, Option from option.types_ import E, F, T, U class Result(Generic[T, E]): """ :class:`Result` is a type that either success (:meth:`Result.Ok`) or failure (:meth:`Result.Err`). To create an Ok value, use :meth:`Result.Ok` or :func:`Ok`. To create a Err value, use :meth:`Result.Err` or :func:`Err`. Calling the :class:`Result` constructor directly will raise a ``TypeError``. Examples: >>> Result.Ok(1) Ok(1) >>> Result.Err('Fail!') Err('Fail!') """ __slots__ = ('_val', '_is_ok', '_type') def __init__(self, val: Union[T, E], is_ok: bool, *, _force=False) -> None: if not _force: raise TypeError( 'Cannot directly initialize, ' 'please use one of the factory functions instead.' ) self._val = val self._is_ok = is_ok self._type = type(self) @classmethod def Ok(cls, val: T) -> 'Result[T, Any]': """ Contains the success value. Args: val: The success value. Returns: The :class:`Result` containing the success value. Examples: >>> res = Result.Ok(1) >>> res Ok(1) >>> res.is_ok True """ return cls(val, True, _force=True) @classmethod def Err(cls, err: E) -> 'Result[Any, E]': """ Contains the error value. Args: err: The error value. Returns: The :class:`Result` containing the error value. Examples: >>> res = Result.Err('Oh No') >>> res Err('Oh No') >>> res.is_err True """ return cls(err, False, _force=True) def __bool__(self): return self._is_ok @property def is_ok(self) -> bool: """ Returns `True` if the result is :meth:`Result.Ok`. Examples: >>> Ok(1).is_ok True >>> Err(1).is_ok False """ return self._is_ok @property def is_err(self) -> bool: """ Returns `True` if the result is :meth:`Result.Err`. Examples: >>> Ok(1).is_err False >>> Err(1).is_err True """ return not self._is_ok def ok(self) -> Union[Option[T], Option[None]]: """ Converts from :class:`Result` [T, E] to :class:`option.option_.Option` [T]. Returns: :class:`Option` containing the success value if `self` is :meth:`Result.Ok`, otherwise :data:`option.option_.NONE`. Examples: >>> Ok(1).ok() Some(1) >>> Err(1).ok() NONE """ if self._is_ok: return Option.Some(cast(T, self._val)) return NONE def err(self) -> Union[Option[E], Option[None]]: """ Converts from :class:`Result` [T, E] to :class:`option.option_.Option` [E]. Returns: :class:`Option` containing the error value if `self` is :meth:`Result.Err`, otherwise :data:`option.option_.NONE`. Examples: >>> Ok(1).err() NONE >>> Err(1).err() Some(1) """ if self._is_ok: return NONE return Option.Some(cast(E, self._val)) def map(self, op: Callable[[T], U]) -> 'Union[Result[U, E], Result[T, E]]': """ Applies a function to the contained :meth:`Result.Ok` value. Args: op: The function to apply to the :meth:`Result.Ok` value. Returns: A :class:`Result` with its success value as the function result if `self` is an :meth:`Result.Ok` value, otherwise returns `self`. Examples: >>> Ok(1).map(lambda x: x * 2) Ok(2) >>> Err(1).map(lambda x: x * 2) Err(1) """ if self._is_ok: return self._type.Ok(op(cast(T, self._val))) return self def map_err(self, op: Callable[[E], F]) -> 'Union[Result[T, F], Result[T, E]]': """ Applies a function to the contained :meth:`Result.Err` value. Args: op: The function to apply to the :meth:`Result.Err` value. Returns: A :class:`Result` with its error value as the function result if `self` is a :meth:`Result.Err` value, otherwise returns `self`. Examples: >>> Ok(1).map_err(lambda x: x * 2) Ok(1) >>> Err(1).map_err(lambda x: x * 2) Err(2) """ if self._is_ok: return self return self._type.Err(op(cast(E, self._val))) def unwrap(self) -> T: """ Returns the success value in the :class:`Result`. Returns: The success value in the :class:`Result`. Raises: ``ValueError`` with the message provided by the error value if the :class:`Result` is a :meth:`Result.Err` value. Examples: >>> Ok(1).unwrap() 1 >>> try: ... Err(1).unwrap() ... except ValueError as e: ... print(e) 1 """ if self._is_ok: return cast(T, self._val) raise ValueError(self._val) def unwrap_or(self, optb: T) -> T: """ Returns the success value in the :class:`Result` or ``optb``. Args: optb: The default return value. Returns: The success value in the :class:`Result` if it is a :meth:`Result.Ok` value, otherwise ``optb``. Notes: If you wish to use a result of a function call as the default, it is recommnded to use :meth:`unwrap_or_else` instead. Examples: >>> Ok(1).unwrap_or(2) 1 >>> Err(1).unwrap_or(2) 2 """ return cast(T, self._val) if self._is_ok else optb def unwrap_or_else(self, op: Callable[[E], U]) -> Union[T, U]: """ Returns the sucess value in the :class:`Result` or computes a default from the error value. Args: op: The function to computes default with. Returns: The success value in the :class:`Result` if it is a :meth:`Result.Ok` value, otherwise ``op(E)``. Examples: >>> Ok(1).unwrap_or_else(lambda e: e * 10) 1 >>> Err(1).unwrap_or_else(lambda e: e * 10) 10 """ return cast(T, self._val) if self._is_ok else op(cast(E, self._val)) def expect(self, msg) -> T: """ Returns the success value in the :class:`Result` or raises a ``ValueError`` with a provided message. Args: msg: The error message. Returns: The success value in the :class:`Result` if it is a :meth:`Result.Ok` value. Raises: ``ValueError`` with ``msg`` as the message if the :class:`Result` is a :meth:`Result.Err` value. Examples: >>> Ok(1).expect('no') 1 >>> try: ... Err(1).expect('no') ... except ValueError as e: ... print(e) no """ if self._is_ok: return cast(T, self._val) raise ValueError(msg) def unwrap_err(self) -> E: """ Returns the error value in a :class:`Result`. Returns: The error value in the :class:`Result` if it is a :meth:`Result.Err` value. Raises: ``ValueError`` with the message provided by the success value if the :class:`Result` is a :meth:`Result.Ok` value. Examples: >>> try: ... Ok(1).unwrap_err() ... except ValueError as e: ... print(e) 1 >>> Err('Oh No').unwrap_err() 'Oh No' """ if self._is_ok: raise ValueError(self._val) return cast(E, self._val) def expect_err(self, msg) -> E: """ Returns the error value in a :class:`Result`, or raises a ``ValueError`` with the provided message. Args: msg: The error message. Returns: The error value in the :class:`Result` if it is a :meth:`Result.Err` value. Raises: ``ValueError`` with the message provided by ``msg`` if the :class:`Result` is a :meth:`Result.Ok` value. Examples: >>> try: ... Ok(1).expect_err('Oh No') ... except ValueError as e: ... print(e) Oh No >>> Err(1).expect_err('Yes') 1 """ if self._is_ok: raise ValueError(msg) return cast(E, self._val) def __repr__(self): return f'Ok({self._val!r})' if self._is_ok else f'Err({self._val!r})' def __hash__(self): return hash((self._type, self._is_ok, self._val)) def __eq__(self, other): return (isinstance(other, self._type) and self._is_ok == other._is_ok and self._val == other._val) def __ne__(self, other): return (not isinstance(other, self._type) or self._is_ok != other._is_ok or self._val != other._val) def __lt__(self, other): if isinstance(other, self._type): if self._is_ok == other._is_ok: return self._val < other._val return self._is_ok return NotImplemented def __le__(self, other): if isinstance(other, self._type): if self._is_ok == other._is_ok: return self._val <= other._val return self._is_ok return NotImplemented def __gt__(self, other): if isinstance(other, self._type): if self._is_ok == other._is_ok: return self._val > other._val return other._is_ok return NotImplemented def __ge__(self, other): if isinstance(other, self._type): if self._is_ok == other._is_ok: return self._val >= other._val return other._is_ok return NotImplemented def Ok(val: T) -> Result[T, Any]: """Shortcut function for :meth:`Result.Ok`.""" return Result.Ok(val) def Err(err: E) -> Result[Any, E]: """Shortcut function for :meth:`Result.Err`.""" return Result.Err(err) if __name__ == '__main__': import doctest doctest.testmod() PK!8//option/result.py# MIT License # Copyright (c) 2018 Peijun Ma # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. """This module contains the Result type.""" from typing import Any, Callable, Generic, Union, cast from option.option_ import NONE, Option from option.types_ import E, F, T, U class Result(Generic[T, E]): """ :class:`Result` is a type that either success (:meth:`Result.Ok`) or failure (:meth:`Result.Err`). To create an Ok value, use :meth:`Result.Ok` or :func:`Ok`. To create a Err value, use :meth:`Result.Err` or :func:`Err`. Calling the :class:`Result` constructor directly will raise a ``TypeError``. Examples: >>> Result.Ok(1) Ok(1) >>> Result.Err('Fail!') Err('Fail!') """ __slots__ = ('_val', '_is_ok', '_type') def __init__(self, val: Union[T, E], is_ok: bool, *, _force=False) -> None: if not _force: raise TypeError( 'Cannot directly initialize, ' 'please use one of the factory functions instead.' ) self._val = val self._is_ok = is_ok self._type = type(self) @classmethod def Ok(cls, val: T) -> 'Result[T, Any]': """ Contains the success value. Args: val: The success value. Returns: The :class:`Result` containing the success value. Examples: >>> res = Result.Ok(1) >>> res Ok(1) >>> res.is_ok True """ return cls(val, True, _force=True) @classmethod def Err(cls, err: E) -> 'Result[Any, E]': """ Contains the error value. Args: err: The error value. Returns: The :class:`Result` containing the error value. Examples: >>> res = Result.Err('Oh No') >>> res Err('Oh No') >>> res.is_err True """ return cls(err, False, _force=True) def __bool__(self): return self._is_ok @property def is_ok(self) -> bool: """ Returns `True` if the result is :meth:`Result.Ok`. Examples: >>> Ok(1).is_ok True >>> Err(1).is_ok False """ return self._is_ok @property def is_err(self) -> bool: """ Returns `True` if the result is :meth:`Result.Err`. Examples: >>> Ok(1).is_err False >>> Err(1).is_err True """ return not self._is_ok def ok(self) -> Union[Option[T], Option[None]]: """ Converts from :class:`Result` [T, E] to :class:`option.option_.Option` [T]. Returns: :class:`Option` containing the success value if `self` is :meth:`Result.Ok`, otherwise :data:`option.option_.NONE`. Examples: >>> Ok(1).ok() Some(1) >>> Err(1).ok() NONE """ if self._is_ok: return Option.Some(cast(T, self._val)) return NONE def err(self) -> Union[Option[E], Option[None]]: """ Converts from :class:`Result` [T, E] to :class:`option.option_.Option` [E]. Returns: :class:`Option` containing the error value if `self` is :meth:`Result.Err`, otherwise :data:`option.option_.NONE`. Examples: >>> Ok(1).err() NONE >>> Err(1).err() Some(1) """ if self._is_ok: return NONE return Option.Some(cast(E, self._val)) def map(self, op: Callable[[T], U]) -> 'Union[Result[U, E], Result[T, E]]': """ Applies a function to the contained :meth:`Result.Ok` value. Args: op: The function to apply to the :meth:`Result.Ok` value. Returns: A :class:`Result` with its success value as the function result if `self` is an :meth:`Result.Ok` value, otherwise returns `self`. Examples: >>> Ok(1).map(lambda x: x * 2) Ok(2) >>> Err(1).map(lambda x: x * 2) Err(1) """ if self._is_ok: return self._type.Ok(op(cast(T, self._val))) return self def map_err(self, op: Callable[[E], F]) -> 'Union[Result[T, F], Result[T, E]]': """ Applies a function to the contained :meth:`Result.Err` value. Args: op: The function to apply to the :meth:`Result.Err` value. Returns: A :class:`Result` with its error value as the function result if `self` is a :meth:`Result.Err` value, otherwise returns `self`. Examples: >>> Ok(1).map_err(lambda x: x * 2) Ok(1) >>> Err(1).map_err(lambda x: x * 2) Err(2) """ if self._is_ok: return self return self._type.Err(op(cast(E, self._val))) def unwrap(self) -> T: """ Returns the success value in the :class:`Result`. Returns: The success value in the :class:`Result`. Raises: ``ValueError`` with the message provided by the error value if the :class:`Result` is a :meth:`Result.Err` value. Examples: >>> Ok(1).unwrap() 1 >>> try: ... Err(1).unwrap() ... except ValueError as e: ... print(e) 1 """ if self._is_ok: return cast(T, self._val) raise ValueError(self._val) def unwrap_or(self, optb: T) -> T: """ Returns the success value in the :class:`Result` or ``optb``. Args: optb: The default return value. Returns: The success value in the :class:`Result` if it is a :meth:`Result.Ok` value, otherwise ``optb``. Notes: If you wish to use a result of a function call as the default, it is recommnded to use :meth:`unwrap_or_else` instead. Examples: >>> Ok(1).unwrap_or(2) 1 >>> Err(1).unwrap_or(2) 2 """ return cast(T, self._val) if self._is_ok else optb def unwrap_or_else(self, op: Callable[[E], U]) -> Union[T, U]: """ Returns the sucess value in the :class:`Result` or computes a default from the error value. Args: op: The function to computes default with. Returns: The success value in the :class:`Result` if it is a :meth:`Result.Ok` value, otherwise ``op(E)``. Examples: >>> Ok(1).unwrap_or_else(lambda e: e * 10) 1 >>> Err(1).unwrap_or_else(lambda e: e * 10) 10 """ return cast(T, self._val) if self._is_ok else op(cast(E, self._val)) def expect(self, msg) -> T: """ Returns the success value in the :class:`Result` or raises a ``ValueError`` with a provided message. Args: msg: The error message. Returns: The success value in the :class:`Result` if it is a :meth:`Result.Ok` value. Raises: ``ValueError`` with ``msg`` as the message if the :class:`Result` is a :meth:`Result.Err` value. Examples: >>> Ok(1).expect('no') 1 >>> try: ... Err(1).expect('no') ... except ValueError as e: ... print(e) no """ if self._is_ok: return cast(T, self._val) raise ValueError(msg) def unwrap_err(self) -> E: """ Returns the error value in a :class:`Result`. Returns: The error value in the :class:`Result` if it is a :meth:`Result.Err` value. Raises: ``ValueError`` with the message provided by the success value if the :class:`Result` is a :meth:`Result.Ok` value. Examples: >>> try: ... Ok(1).unwrap_err() ... except ValueError as e: ... print(e) 1 >>> Err('Oh No').unwrap_err() 'Oh No' """ if self._is_ok: raise ValueError(self._val) return cast(E, self._val) def expect_err(self, msg) -> E: """ Returns the error value in a :class:`Result`, or raises a ``ValueError`` with the provided message. Args: msg: The error message. Returns: The error value in the :class:`Result` if it is a :meth:`Result.Err` value. Raises: ``ValueError`` with the message provided by ``msg`` if the :class:`Result` is a :meth:`Result.Ok` value. Examples: >>> try: ... Ok(1).expect_err('Oh No') ... except ValueError as e: ... print(e) Oh No >>> Err(1).expect_err('Yes') 1 """ if self._is_ok: raise ValueError(msg) return cast(E, self._val) def __repr__(self): return f'Ok({self._val!r})' if self._is_ok else f'Err({self._val!r})' def __hash__(self): return hash((self._type, self._is_ok, self._val)) def __eq__(self, other): return (isinstance(other, self._type) and self._is_ok == other._is_ok and self._val == other._val) def __ne__(self, other): return (not isinstance(other, self._type) or self._is_ok != other._is_ok or self._val != other._val) def __lt__(self, other): if isinstance(other, self._type): if self._is_ok == other._is_ok: return self._val < other._val return self._is_ok return NotImplemented def __le__(self, other): if isinstance(other, self._type): if self._is_ok == other._is_ok: return self._val <= other._val return self._is_ok return NotImplemented def __gt__(self, other): if isinstance(other, self._type): if self._is_ok == other._is_ok: return self._val > other._val return other._is_ok return NotImplemented def __ge__(self, other): if isinstance(other, self._type): if self._is_ok == other._is_ok: return self._val >= other._val return other._is_ok return NotImplemented def Ok(val: T) -> Result[T, Any]: """Shortcut function for :meth:`Result.Ok`.""" return Result.Ok(val) def Err(err: E) -> Result[Any, E]: """Shortcut function for :meth:`Result.Err`.""" return Result.Err(err) if __name__ == '__main__': import doctest doctest.testmod() PK!.>Poption/types_.py# MIT License # Copyright (c) 2018 Peijun Ma # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. # pylint: skip-file from typing import TypeVar T = TypeVar('T') U = TypeVar('U') A = TypeVar('A') K = TypeVar('K') V = TypeVar('V') E = TypeVar('E') F = TypeVar('F') PK!.>Poption/types_.py# MIT License # Copyright (c) 2018 Peijun Ma # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # The above copyright notice and this permission notice shall be included in all # copies or substantial portions of the Software. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. # pylint: skip-file from typing import TypeVar T = TypeVar('T') U = TypeVar('U') A = TypeVar('A') K = TypeVar('K') V = TypeVar('V') E = TypeVar('E') F = TypeVar('F') PK!RU**option-0.2.3.dist-info/LICENSEMIT License Copyright (c) 2018 Peijun Ma Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. PK!HW"TToption-0.2.3.dist-info/WHEEL A н#J."jm)Afb~ ڡ5 G7hiޅF4+-3ڦ/̖?XPK!H9option-0.2.3.dist-info/METADATAUn7}WLHrl pZ76P!R.#.EP;$W眹y=IK8)޳a da'){]<(BM@ຆ{tAyH wߒƯiRm]9uܿoNmH߆E!,Rvzdl w( |LR'{{kZӱ{3HnC(i}R9HFe}pPp S8W}WڣPK#ta" { mM2=ޣYXuR7&P">dqhz)Ygnq`esa:aeGPK!Hoption-0.2.3.dist-info/RECORDr@} `pq 2&.AOsUnܙ}UiP5;BU] ǔ4D|q}IZCa|H$]) 9n2'$imAߚSQB$X`O؁Mߖy2>-۫JǸ^oPx γ;$~hO SE5a%[G?Wu|c8[{)xնV+l󰦥dWHZSX *aE%a Uϊq.{OrGzeǥ7dgb#ԮQdGXnτYV[ET ;ZO4 3n.+|[^qw9p361u}}GfȦlj]!an>e{A6JF))wuP)Qr;~Ktj,Q*(V~ :0PNoption/types_.pyPK!.>Psoption/types_.pyPK!RU**option-0.2.3.dist-info/LICENSEPK!HW"TToption-0.2.3.dist-info/WHEELPK!H9option-0.2.3.dist-info/METADATAPK!Hoption-0.2.3.dist-info/RECORDPK}