|
6 | 6 | from __future__ import annotations |
7 | 7 |
|
8 | 8 | from abc import ABC, abstractmethod |
9 | | -from typing import Any, Union, overload |
| 9 | +from typing import Any, FrozenSet, Union, overload |
10 | 10 |
|
11 | 11 | from typeguard import check_type, typechecked |
12 | 12 |
|
|
18 | 18 | class Transformation(ABC): |
19 | 19 | """Abstract base class for transformations.""" |
20 | 20 |
|
| 21 | + _FORMAT_EXCLUDED_ATTRS: FrozenSet[str] = frozenset( |
| 22 | + {"input_domain", "input_metric", "output_domain", "output_metric"} |
| 23 | + ) |
| 24 | + """Fields hidden from output when formatting this transformation.""" |
| 25 | + |
21 | 26 | @typechecked |
22 | 27 | def __init__( |
23 | 28 | self, |
@@ -125,3 +130,33 @@ def __or__(self, other: Any) -> Union[Measurement, Transformation]: |
125 | 130 | @abstractmethod |
126 | 131 | def __call__(self, data: Any) -> Any: |
127 | 132 | """Perform transformation.""" |
| 133 | + |
| 134 | + def format(self) -> str: |
| 135 | + """Return a human-readable multi-line description of this transformation. |
| 136 | +
|
| 137 | + The default implementation assembles :meth:`_format_head` and |
| 138 | + :meth:`_format_children`; subclasses can override either of these |
| 139 | + hooks (or :meth:`format` itself) to customize the rendering. |
| 140 | + """ |
| 141 | + head = self._format_head() |
| 142 | + children = self._format_children() |
| 143 | + if not children: |
| 144 | + return head |
| 145 | + return f"{head}\n{children}" |
| 146 | + |
| 147 | + def _format_head(self) -> str: |
| 148 | + """Render this component's head line: class name followed by its attrs.""" |
| 149 | + from tmlt.core.utils.format import default_format_attrs # noqa: PLC0415 |
| 150 | + |
| 151 | + parts = [type(self).__name__] |
| 152 | + parts.extend( |
| 153 | + f"{name}={value}" |
| 154 | + for name, value in default_format_attrs(self, self._FORMAT_EXCLUDED_ATTRS) |
| 155 | + ) |
| 156 | + return " ".join(parts) |
| 157 | + |
| 158 | + def _format_children(self) -> str: |
| 159 | + """Return the rendered block for nested transformations.""" |
| 160 | + from tmlt.core.utils.format import default_format_children # noqa: PLC0415 |
| 161 | + |
| 162 | + return default_format_children(self) |
0 commit comments