Source code for jivago.lang.nullable

import inspect
from typing import Generic, TypeVar, Optional, Callable, Union

T = TypeVar('T')
S = TypeVar('S')


[docs] class Nullable(Generic[T]): """Nullable class which wraps Optional types. Args: nullable (Optional) : Item which can be None. """ def __init__(self, nullable: Optional[T]): self._item = nullable
[docs] def isPresent(self) -> bool: """Returns True if item is not None.""" return self._item is not None
[docs] def get(self) -> T: """Gets the item if present. Raises: EmptyNullableException : Attempting to get a missing item. """ if self.isPresent(): return self._item raise EmptyNullableException()
[docs] def orElse(self, default_value: T) -> T: """Returns the item if present, else return the supplied default value. Args: default_value : Value to return instead of a None value. """ return self._item if self.isPresent() else default_value
[docs] def orElseThrow(self, exception: Union[Exception, Callable[[], Exception]]) -> T: """Returns if present, raises exception if missing. Args: exception : Either an exception, or a callable which returns an exception. """ if self.isPresent(): return self._item if isinstance(exception, Exception): raise exception raise exception()
[docs] def orElseFetch(self, supplier: Callable[[], T]) -> T: """Returns if present, invoke callable if missing. Args: supplier (Callable) : Supplied return value will be return in place of a None value. Should not require parameters. """ if self.isPresent(): return self._item return supplier()
[docs] def ifPresent(self, consumer: Union[Callable[[T], None], Callable[..., None]]) -> "Nullable[T]": """Invoke function if value is present; otherwise does nothing. Args: consumer (Callable) : Function to be invoked with a non-nil parameter. """ if self.isPresent(): if self.__should_expand(consumer): consumer(*self._item) else: consumer(self._item) return self
[docs] def filter(self, predicate: Union[Callable[[T], bool], Callable[..., bool]]) -> "Nullable[T]": """Filters item given a criterion. Args: predicate (Callable) : Invoked with a non-nil parameter. Should return a boolean. """ if self.isPresent(): if self.__should_expand(predicate): return self if predicate(*self._item) else Nullable.empty() return self if predicate(self._item) else Nullable.empty() return Nullable.empty()
[docs] def map(self, callable: Union[Callable[[T], S], Callable[..., S]]) -> "Nullable[S]": """Maps the item when present. Args: callable (Callable) : Invoked with a non-nil parameter. """ if self.isPresent(): if self.__should_expand(callable): return Nullable(callable(*self._item)) return Nullable(callable(self._item)) return Nullable.empty()
def __bool__(self) -> bool: return self.isPresent() def __should_expand(self, fun: Callable) -> bool: if inspect.isbuiltin(fun): return False if inspect.isclass(fun): return len(inspect.signature(fun.__init__).parameters) > 2 sig = inspect.signature(fun) return len(sig.parameters) > 1
[docs] @staticmethod def empty() -> "Nullable": return _empty
_empty = Nullable(None)
[docs] class EmptyNullableException(Exception): pass