"""base classes and interfaces"""importabcimporttypingastfromitertoolsimportstarmapfromtypesimportGeneratorTypefrom.utilsimportCallableAsMethod__all__=["Generable","GeneratorCallable","ReusableGenerator",]T_yield=t.TypeVar("T_yield")T_send=t.TypeVar("T_send")T_return=t.TypeVar("T_return")
[docs]classGenerable(t.Generic[T_yield,T_send,T_return],t.Iterable[T_yield]):"""ABC for generable objects. Any object where :meth:`~object.__iter__` returns a generator implements it. """
[docs]@abc.abstractmethoddef__iter__(self):""" Returns ------- ~typing.Generator[T_yield, T_send, T_return] the generator iterator """raiseNotImplementedError()
Generable.register(GeneratorType)
[docs]classGeneratorCallable(t.Generic[T_yield,T_send,T_return]):"""ABC for callables which return a generator. Note that :term:`generator functions <generator>` already implement this. """
[docs]def__call__(self,*args,**kwargs):""" Returns ------- ~typing.Generator[T_yield, T_send, T_return] the resulting generator """raiseNotImplementedError()
[docs]classReusableGenerator(Generable[T_yield,T_send,T_return],metaclass=ReusableGeneratorMeta):"""base class for reusable generator functions Warning ------- * Do not subclass directly. Subclasses are created with the :func:`~gentools.core.reusable` decorator. """
[docs]defreplace(self,**kwargs):"""create a new instance with certain fields replaced Parameters ---------- **kwargs fields to replace Returns ------- ReusableGenerator a copy with replaced fields """copied=self.__signature__.bind(*self._bound_args.args,**self._bound_args.kwargs)copied.arguments.update(**kwargs)returnself.__class__(*copied.args,**copied.kwargs)