== Custom Steps via dotted path (ohne zentrale Änderungen)

Du kannst projektspezifische Transformationen hinzufügen, ohne das zentrale Repository zu verändern.
Schreibe einfach eine Factory-Funktion in ein eigenes Modul/Repo und referenziere sie per *dotted path* in der Pipeline.

=== 1) Eigene Factory schreiben

[source,python]
----
# my_project/steps.py
from spreadsheet_handling.pipeline import BoundStep
import pandas as pd

def make_extract_subset_step(*, table: str, columns: list[str], name: str = "extract_subset") -> BoundStep:
    """Return a BoundStep that keeps only a subset of columns for a given sheet."""
    Frames = dict[str, pd.DataFrame]
    cfg = {"table": table, "columns": columns}

    def run(frames: Frames) -> Frames:
        df = frames.get(table)
        if df is None:
            return frames
        out = dict(frames)
        keep = [c for c in columns if c in df.columns]
        out[table] = df.loc[:, keep]
        return out

    return BoundStep(name=name, config=cfg, fn=run)
----

=== 2) In YAML referenzieren (dotted path)

[source,yaml]
----
pipeline:
  - step: my_project.steps:make_extract_subset_step
    table: Orders
    columns: [id, date, total]
  - step: validate
    mode_duplicate_ids: warn
    mode_missing_fk: warn
    defaults: { id_field: id, label_field: name, detect_fk: true, helper_prefix: "_" }
----

*Hinweise:*
- Die Form ist `<module>:<factory_function>`.
- Die Factory muss einen `BoundStep` zurückgeben (Signatur: `frames -> frames`).
- Optional kann die Factory ein `name`-Argument akzeptieren (wird für Logging angezeigt).

=== 3) Wo liegt das Modul?

Es reicht, wenn dein Modul im `PYTHONPATH` ist. Typische Varianten:
- In deinem Projekt installiert (z. B. `pip install -e .`)
- Ein einfacher Ordner, der per `PYTHONPATH=. python -m ...` erreichbar ist
- Ein eigenes Repo (z. B. Firmen-spezifisch), das du separat installierst

=== 4) Zusammenspiel mit Profilen & Overrides

Du kannst weiterhin `--profile` (I/O-Presets) nutzen und über `--in-path`/`--out-path` Pfade überschreiben.
Die Pipeline-Definition (mit dotted path) bleibt davon unabhängig.

=== 5) Fehlersuche

- *"Unknown step '...'"*: Modul nicht importierbar oder Factory-Name falsch.
- *"Factory 'X' not found in module 'Y'"*: Schreibfehler oder Factory nicht exportiert.
- Mit `-vv` starten, um mehr Logging zu erhalten.
