Skip to content

Instantly share code, notes, and snippets.

@surenkov
Last active October 7, 2019 17:07
Show Gist options
  • Save surenkov/ed84f25d24e1b66bf316143aaed83568 to your computer and use it in GitHub Desktop.
Save surenkov/ed84f25d24e1b66bf316143aaed83568 to your computer and use it in GitHub Desktop.
Some minimal service abstraction
from abc import ABC, abstractmethod
from functools import reduce
from typing import Tuple, TypeVar, Union, Iterable, Mapping
TInstance = TypeVar("TInstance")
class AbstractFactory(Iterable[TInstance], ABC):
pass
class AbstractService(ABC):
__slots__ = ()
def __call__(self, **kwargs):
return self.apply(**kwargs)
@abstractmethod
def apply(self, **kwargs):
pass
def then(self, service: "AbstractService"):
return flow(self, service)
class ServiceFlow(AbstractService):
__slots__ = ("services",)
def __init__(self, services: Tuple[AbstractService] = ()):
self.services = services
def then(self, *services: AbstractService) -> "ServiceFlow":
return ServiceFlow(self.services + services)
def apply(self, **kwargs):
def chain_call(prev_result, service):
if not isinstance(prev_result, Mapping):
prev_result = dict()
return service(**dict(kwargs, **prev_result))
return reduce(chain_call, self.services, dict())
def flow(*services: Union[AbstractService, Iterable[AbstractService]]):
def flatten_flow(prev_flow: ServiceFlow, service):
return prev_flow.then(service if callable(service) else flow(*service))
return reduce(flatten_flow, services, ServiceFlow())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment