import abc from typing import Iterable from funcy import curry, identity class Transformer(abc.ABC): @abc.abstractmethod def transform(self, obj): raise NotImplementedError def __call__(self, obj): return self._apply(self.transform, obj) @staticmethod def _must_be_mapped_over(obj): return isinstance(obj, Iterable) and not isinstance(obj, dict) def _apply(self, func, obj): return (curry(map) if self._must_be_mapped_over(obj) else identity)(func)(obj)