Source code for pysatl_cpd.data.providers.transformers.base

# -*- coding: ascii -*-
"""Data transformer interfaces."""

__author__ = "Mikhail Mikhailov"
__copyright__ = "Copyright (c) 2026 PySATL project"
__license__ = "SPDX-License-Identifier: MIT"

from abc import ABC, abstractmethod
from typing import Any

from pysatl_cpd.data.providers import DataProvider
from pysatl_cpd.typedefs import stable_hash


[docs] class IDataTransformer[DataProviderInT: DataProvider[Any, Any], DataProviderOutT: DataProvider[Any, Any]](ABC): """ Abstract source class for data transformers. Defines the interface for transforming data providers from one type to another through a transform operation. """
[docs] @abstractmethod def transform(self, provider: DataProviderInT) -> DataProviderOutT: """ Transform input data provider to output data provider. Parameters ---------- provider Input data provider to transform. Returns ------- result Transformed data provider. """
@property @abstractmethod def annotation(self) -> str: """ Transformer annotation. Returns ------- annotation Annotation string describing this transformer. """
[docs] def __and__[DataProviderFinalT: DataProvider[Any, Any]]( self, other: "IDataTransformer[DataProviderOutT, DataProviderFinalT]" ) -> "ComposedTransformer[DataProviderInT, DataProviderFinalT]": """Compose this transformer with another transformer. Parameters ---------- other Transformer applied after this transformer. Returns ------- transformer Composed transformer applying both transforms in order. """ return ComposedTransformer[DataProviderInT, DataProviderFinalT](self, other) # type: ignore[arg-type]
[docs] def __hash__(self) -> int: """Return a stable hash derived from the transformer annotation. Returns ------- hash Stable integer hash for the transformer instance. """ return stable_hash(self.annotation)
[docs] class ComposedTransformer[DataProviderInT: DataProvider[Any, Any], DataProviderOutT: DataProvider[Any, Any]]( IDataTransformer[DataProviderInT, DataProviderOutT] ): """ Transformer composed of multiple transformers applied in sequence. Applies each transformer to the result of the previous one, chaining transformations together. Parameters ---------- *transformers Variable-length list of transformers to apply in order. Raises ------ ValueError If no transformers are provided. """
[docs] def __init__( self, *transformers: IDataTransformer[DataProvider, DataProvider], ) -> None: if not transformers: raise ValueError("ComposedTransformer requires at least one transformer") self._transformers = list(transformers)
[docs] def transform(self, provider: DataProviderInT) -> DataProviderOutT: """ Apply all transformers in sequence to the input provider. Parameters ---------- provider Input data provider to transform. Returns ------- result Data provider after all transformations applied. """ result: DataProviderOutT = provider # type: ignore for transformer in self._transformers: result = transformer.transform(result) # type: ignore return result
[docs] def __and__[DataProviderFinalT: DataProvider[Any, Any]]( self, other: "IDataTransformer[DataProviderOutT, DataProviderFinalT]" ) -> "ComposedTransformer[DataProviderInT, DataProviderFinalT]": """Append another transformer to the composition. Parameters ---------- other Transformer applied after the current composition. Returns ------- transformer Extended composed transformer. """ return ComposedTransformer(*self._transformers, other) # type: ignore[arg-type]
@property def annotation(self) -> str: """ Composed transformer annotation. Returns ------- annotation Combined annotation from all composed transformers. """ filtered = [t.annotation.strip() for t in self._transformers if t.annotation.strip()] return "->".join(filtered) if len(filtered) >= 2 else (filtered[0] if filtered else "")