diff --git a/backend/source.py b/backend/source.py index 534f192..48619bc 100644 --- a/backend/source.py +++ b/backend/source.py @@ -69,18 +69,6 @@ def validate(self, record: dict) -> None: raise ValueError(f"Invalid record. Missing {k}") -class _SubclassValidatorShim(RecordValidator): - """Shim: delegates to source._validate_record() for subclasses that override it.""" - def __init__(self, source): - self._source = source - - def set_config(self, config) -> None: - pass # source._validate_record uses self.config directly - - def validate(self, record: dict) -> None: - self._source._validate_record(record) - - # ============================================================================= # Record summarization strategy # ============================================================================= @@ -192,10 +180,8 @@ def get_analyte_search_param(parameter: str, mapping: dict) -> str: class BaseSource: - transformer_klass = BaseTransformer # deprecated: pass transformer= to __init__ - def __init__(self, transformer: Optional[BaseTransformer] = None, http_client: httpx.Client | None = None): - self.transformer = transformer if transformer is not None else self.transformer_klass() + self.transformer = transformer if transformer is not None else BaseTransformer() self._http_client = http_client if http_client is not None else httpx.Client(timeout=900) _l = make_logger(self.__class__.__name__) self.log = _l.log @@ -228,7 +214,7 @@ def tag(self): def set_config(self, config): self.config = config self.transformer.set_config(config) - if hasattr(self, "_validator"): + if getattr(self, "_validator", None) is not None: self._validator.set_config(config) def check(self, *args, **kw): @@ -356,7 +342,7 @@ class BaseParameterSource(BaseSource): def __init__(self, transformer=None, validator: Optional[RecordValidator] = None, http_client: httpx.Client | None = None): super().__init__(transformer=transformer, http_client=http_client) - self._validator = validator if validator is not None else _SubclassValidatorShim(self) + self._validator = validator self._summarizer = RecordSummarizer(self) def _extract_earliest_record(self, records: list) -> dict: @@ -483,16 +469,13 @@ def _extract_source_parameter_results(self, records: list) -> list: def _extract_parameter(self, record: dict) -> dict: record = self._extract_parameter_record(record) - self._validator.validate(record) + if self._validator is not None: + self._validator.validate(record) return record def _sort_func(self, x): return x.date_measured - # deprecated: override via validator= __init__ arg instead - def _validate_record(self, record: dict) -> None: - raise NotImplementedError(f"{self.__class__.__name__} Must implement _validate_record") - class BaseAnalyteSource(BaseParameterSource): name = "analyte" diff --git a/docs/cleanup-todo.md b/docs/cleanup-todo.md index 01c5716..a282aef 100644 --- a/docs/cleanup-todo.md +++ b/docs/cleanup-todo.md @@ -62,7 +62,7 @@ registry). Tiers are ordered by safety — Tier 1 is batchable into one no-risk - **`config.validate()` `sys.exit(2)` → raise** — library code shouldn't exit the process; raise a `ConfigError` and let CLI translate to an exit code. (Affects callers; needs care.) - **Hoist connector `_extract_*` duplication** — `_extract_source_parameter_results/dates/units` repeat dict/list access across connectors; lift common shapes to a base. - **Spatial-filter precedence** — `bbox_bounding_points` (bbox first) vs `bounding_wkt` (wkt first) resolve multiple filters differently; #101 warns, but unify the precedence. Consider a small `Scope` value object and drop the `wkt=None`-means-statewide magic in `die_config`. -- **Remove deprecated shims** — `transformer_klass`, `_SubclassValidatorShim`, `_validate_record` (`backend/source.py`). Verify no connector still relies on the override path first. +- ✅ **Remove deprecated shims** (DONE) — removed `transformer_klass`, `_SubclassValidatorShim`, `_validate_record` (`backend/source.py`). Verified no connector overrides `_validate_record` or sets `transformer_klass`, and every concrete parameter source gets a real validator via `BaseAnalyteSource`/`BaseWaterLevelSource` (WQP through its mixin MRO). `transformer=None` now falls back to `BaseTransformer()` directly; `validator=None` is tolerated (validation skipped) for the test fake / mixin. ---