from __future__ import annotations import unittest from govoplan_core.core.datasources import ( DatasourceDescriptor, DatasourceReadRequest, DatasourceReadResult, ) from govoplan_core.core.modules import ModuleContext, ModuleManifest from govoplan_core.core.registry import PlatformRegistry from govoplan_core.core.tabular_sources import ( CAPABILITY_CONNECTORS_TABULAR_SNAPSHOT_WRITER, CAPABILITY_CONNECTORS_TABULAR_SOURCES, TabularColumn, TabularPreviewDiagnostic, TabularPushdown, TabularReadRequest, TabularReadResult, TabularSnapshotInput, TabularSnapshotWriter, TabularSource, TabularSourceHealth, TabularSourceProvider, TabularSourceValidationError, parse_tabular_csv, tabular_snapshot_writer, tabular_source_provider, ) class _TabularProvider: source = TabularSource( ref="snapshot:source-1", provider="snapshot", source_name="monthly_cases", name="Monthly cases", schema=(TabularColumn(name="case_id", data_type="string", nullable=False),), fingerprint="abc123", row_count=1, source_mode="cached", pushdown=TabularPushdown(projections=True, pagination=True), health=TabularSourceHealth( status="healthy", code="snapshot.ready", summary="Immutable snapshot is ready.", ), ) def list_sources(self, session, principal, *, query="", limit=100): del session, principal if query and query.casefold() not in self.source.name.casefold(): return () return (self.source,)[:limit] def get_source(self, session, principal, *, source_ref): del session, principal return self.source if source_ref == self.source.ref else None def read_source(self, session, principal, *, request): del session, principal rows = ({"case_id": "A-1"},) selected = rows[request.offset : request.offset + request.limit] return TabularReadResult( source=self.source, rows=selected, total_rows=len(rows), truncated=len(selected) < len(rows), returned_bytes=18, elapsed_ms=1, effective_row_limit=request.limit, effective_byte_limit=request.max_bytes, effective_timeout_ms=request.timeout_ms, diagnostics=( TabularPreviewDiagnostic( severity="info", code="preview.bounded", message="The preview used explicit budgets.", ), ), ) def create_snapshot(self, session, principal, *, snapshot): del session, principal, snapshot return self.source class TabularSourceContractTests(unittest.TestCase): def test_provider_and_snapshot_writer_are_runtime_checkable(self) -> None: provider = _TabularProvider() self.assertIsInstance(provider, TabularSourceProvider) self.assertIsInstance(provider, TabularSnapshotWriter) def test_capabilities_resolve_without_importing_connectors(self) -> None: provider = _TabularProvider() registry = PlatformRegistry() registry.register( ModuleManifest( id="tabular_contract_test", name="Tabular contract test", version="test", capability_factories={ CAPABILITY_CONNECTORS_TABULAR_SOURCES: lambda context: provider, CAPABILITY_CONNECTORS_TABULAR_SNAPSHOT_WRITER: lambda context: provider, }, ) ) registry.configure_capability_context(ModuleContext(registry=registry, settings=object())) self.assertIs(provider, tabular_source_provider(registry)) self.assertIs(provider, tabular_snapshot_writer(registry)) self.assertIsNone(tabular_source_provider(PlatformRegistry())) def test_read_and_snapshot_dtos_are_immutable_and_bounded_by_callers(self) -> None: provider = _TabularProvider() request = TabularReadRequest(source_ref=provider.source.ref, limit=1) result = provider.read_source(object(), object(), request=request) snapshot = TabularSnapshotInput( name="Monthly cases", source_name="monthly_cases", rows=({"case_id": "A-1"},), ) self.assertEqual(({"case_id": "A-1"},), result.rows) self.assertEqual("cached", result.source.source_mode) self.assertTrue(result.source.pushdown.projections) self.assertEqual("healthy", result.source.health.status) self.assertEqual("preview.bounded", result.diagnostics[0].code) self.assertEqual(1_000_000, request.max_bytes) self.assertEqual(2_000, request.timeout_ms) self.assertEqual(provider.source, provider.create_snapshot(object(), object(), snapshot=snapshot)) def test_datasource_read_contract_preserves_live_preview_evidence(self) -> None: request = DatasourceReadRequest(datasource_ref="datasource:monthly-cases") result = DatasourceReadResult( datasource=DatasourceDescriptor( ref=request.datasource_ref, source_name="monthly_cases", name="Monthly cases", kind="database", mode="live", shape="tabular", ), rows=(), total_rows=0, truncated=False, returned_bytes=2, elapsed_ms=3, effective_row_limit=request.limit, effective_byte_limit=request.max_bytes, effective_timeout_ms=request.timeout_ms, diagnostics=( TabularPreviewDiagnostic( severity="info", code="preview.complete", message="The bounded preview completed.", ), ), ) self.assertEqual(1_000_000, request.max_bytes) self.assertEqual(2_000, request.timeout_ms) self.assertEqual(2, result.returned_bytes) self.assertEqual("preview.complete", result.diagnostics[0].code) def test_shared_csv_parser_preserves_identifier_zeroes_and_rejects_extra_values(self) -> None: rows = parse_tabular_csv( "case_id;amount;active\n0012;7.5;true\n\n", delimiter=";", max_rows=2, ) self.assertEqual( ({"case_id": "0012", "amount": 7.5, "active": True},), rows, ) with self.assertRaises(TabularSourceValidationError): parse_tabular_csv("id,name\n1,Ada,extra\n") def test_text_csv_mode_preserves_lexical_values_and_explicit_empty_records(self) -> None: source = 'id,value\r\n9007199254740993," keep me "\r\ntrue,0.123456789012345678901234567890\r\n" ",""\r\n' self.assertEqual( ( {"id": "9007199254740993", "value": " keep me "}, {"id": "true", "value": "0.123456789012345678901234567890"}, {"id": " ", "value": ""}, ), parse_tabular_csv(source, value_mode="text"), ) self.assertEqual(({"value": " "},), parse_tabular_csv('value\n" "\n', value_mode="text")) def test_text_csv_mode_rejects_shape_loss_and_applies_input_and_row_bounds(self) -> None: for source in ('id,name\n1\n', 'id,name\n1,Ada,\n'): with self.subTest(source=source), self.assertRaises(TabularSourceValidationError): parse_tabular_csv(source, value_mode="text") with self.assertRaises(TabularSourceValidationError): parse_tabular_csv('value\n""\n""\n', value_mode="text", max_rows=1) with self.assertRaises(TabularSourceValidationError): parse_tabular_csv('value\nä\n', value_mode="text", max_bytes=8) with self.assertRaises(TabularSourceValidationError): parse_tabular_csv('value\nx\n', value_mode="unknown") if __name__ == "__main__": unittest.main()