mostlyright-data 0.9.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mostlyright/data_harness/__init__.py +158 -0
- mostlyright/data_harness/acquisition/__init__.py +55 -0
- mostlyright/data_harness/acquisition/http.py +2773 -0
- mostlyright/data_harness/acquisition/parsing.py +809 -0
- mostlyright/data_harness/acquisition/ranges.py +495 -0
- mostlyright/data_harness/acquisition/result_download.py +360 -0
- mostlyright/data_harness/acquisition/retention_admission.py +248 -0
- mostlyright/data_harness/acquisition/sandbox.py +4888 -0
- mostlyright/data_harness/acquisition/url_policy.py +530 -0
- mostlyright/data_harness/agent_runtime.py +2743 -0
- mostlyright/data_harness/assets/logo-ink.svg +31 -0
- mostlyright/data_harness/backends/__init__.py +28 -0
- mostlyright/data_harness/backends/pandas_backend.py +350 -0
- mostlyright/data_harness/backends/polars_backend.py +366 -0
- mostlyright/data_harness/backends/protocol.py +124 -0
- mostlyright/data_harness/backends/reference.py +83 -0
- mostlyright/data_harness/backends/registry.py +55 -0
- mostlyright/data_harness/backends/restrictions.py +126 -0
- mostlyright/data_harness/canonical.py +333 -0
- mostlyright/data_harness/catalog_job.py +625 -0
- mostlyright/data_harness/cli.py +5398 -0
- mostlyright/data_harness/contracts.py +53 -0
- mostlyright/data_harness/coordinator.py +1307 -0
- mostlyright/data_harness/deploy.py +924 -0
- mostlyright/data_harness/deploy_target.py +312 -0
- mostlyright/data_harness/deployment_evidence.py +1067 -0
- mostlyright/data_harness/event_presentation.py +576 -0
- mostlyright/data_harness/events.py +2152 -0
- mostlyright/data_harness/fast_delimited.py +239 -0
- mostlyright/data_harness/fleet.py +237 -0
- mostlyright/data_harness/formats.py +236 -0
- mostlyright/data_harness/governors.py +1163 -0
- mostlyright/data_harness/hosted_bootstrap.py +972 -0
- mostlyright/data_harness/hosted_crawler.py +1115 -0
- mostlyright/data_harness/hosted_crawler_container_smoke.py +351 -0
- mostlyright/data_harness/hosted_crawler_fetch.py +423 -0
- mostlyright/data_harness/hosted_crawler_job.py +1277 -0
- mostlyright/data_harness/hosted_crawler_protocol.py +676 -0
- mostlyright/data_harness/hosted_dataset.py +1500 -0
- mostlyright/data_harness/hosted_deploy.py +3037 -0
- mostlyright/data_harness/hosted_handoff.py +62 -0
- mostlyright/data_harness/hosted_ingestion_contract.py +504 -0
- mostlyright/data_harness/hosted_ingestion_job.py +356 -0
- mostlyright/data_harness/hosted_ingestion_job_smoke.py +40 -0
- mostlyright/data_harness/hosted_session_container_smoke.py +194 -0
- mostlyright/data_harness/hosted_session_worker.py +3554 -0
- mostlyright/data_harness/hosted_session_worker_job_smoke.py +46 -0
- mostlyright/data_harness/hosted_worker.py +6784 -0
- mostlyright/data_harness/ingestion/__init__.py +56 -0
- mostlyright/data_harness/ingestion/contracts.py +461 -0
- mostlyright/data_harness/ingestion/faults.py +42 -0
- mostlyright/data_harness/ingestion/gcs_store.py +1162 -0
- mostlyright/data_harness/ingestion/spool.py +130 -0
- mostlyright/data_harness/ingestion/store.py +885 -0
- mostlyright/data_harness/key_seam.py +434 -0
- mostlyright/data_harness/linux_process_boundary.py +262 -0
- mostlyright/data_harness/local_contracts.py +2880 -0
- mostlyright/data_harness/local_search/__init__.py +5 -0
- mostlyright/data_harness/local_search/build_index.py +1087 -0
- mostlyright/data_harness/local_search/contracts.py +920 -0
- mostlyright/data_harness/local_search/query_trace.py +266 -0
- mostlyright/data_harness/local_search/retrieval.py +700 -0
- mostlyright/data_harness/local_search/sealed.py +474 -0
- mostlyright/data_harness/local_search/service.py +784 -0
- mostlyright/data_harness/nbrender/CONTRACT.md +212 -0
- mostlyright/data_harness/nbrender/__init__.py +12 -0
- mostlyright/data_harness/nbrender/chrome.py +359 -0
- mostlyright/data_harness/nbrender/code_body.py +266 -0
- mostlyright/data_harness/nbrender/document.py +407 -0
- mostlyright/data_harness/nbrender/frame.py +275 -0
- mostlyright/data_harness/nbrender/interactive.py +337 -0
- mostlyright/data_harness/nbrender/markdown_body.py +477 -0
- mostlyright/data_harness/nbrender/mr_components.py +134 -0
- mostlyright/data_harness/nbrender/outputs_data.py +595 -0
- mostlyright/data_harness/nbrender/outputs_rich.py +906 -0
- mostlyright/data_harness/nbrender/outputs_source.py +260 -0
- mostlyright/data_harness/nbrender/outputs_stage.py +176 -0
- mostlyright/data_harness/nbrender/outputs_text.py +400 -0
- mostlyright/data_harness/nbrender/parse.py +394 -0
- mostlyright/data_harness/nbrender/status.py +40 -0
- mostlyright/data_harness/nbrender/tokens.py +1295 -0
- mostlyright/data_harness/notebook.py +1710 -0
- mostlyright/data_harness/offline.py +2049 -0
- mostlyright/data_harness/operation_registry.py +1007 -0
- mostlyright/data_harness/operator_setup.py +239 -0
- mostlyright/data_harness/pipeline.py +6428 -0
- mostlyright/data_harness/plan_graph.py +2026 -0
- mostlyright/data_harness/preparation/__init__.py +104 -0
- mostlyright/data_harness/preparation/contracts.py +1017 -0
- mostlyright/data_harness/preparation/engine.py +221 -0
- mostlyright/data_harness/preparation/errors.py +14 -0
- mostlyright/data_harness/preparation/gates.py +751 -0
- mostlyright/data_harness/preparation/joins.py +574 -0
- mostlyright/data_harness/preparation/profile.py +384 -0
- mostlyright/data_harness/preparation/table.py +217 -0
- mostlyright/data_harness/preparation/transforms.py +568 -0
- mostlyright/data_harness/progress_events.py +534 -0
- mostlyright/data_harness/readers/__init__.py +46 -0
- mostlyright/data_harness/readers/containers.py +963 -0
- mostlyright/data_harness/readers/contracts.py +542 -0
- mostlyright/data_harness/readers/delimited.py +257 -0
- mostlyright/data_harness/readers/grib2/__init__.py +33 -0
- mostlyright/data_harness/readers/grib2/admission.py +722 -0
- mostlyright/data_harness/readers/grib2/decode.py +1009 -0
- mostlyright/data_harness/readers/grib2/geometry.py +1133 -0
- mostlyright/data_harness/readers/grib2/portable_math.py +501 -0
- mostlyright/data_harness/readers/json_tabular.py +485 -0
- mostlyright/data_harness/readers/registry.py +514 -0
- mostlyright/data_harness/readers/samples/README.md +110 -0
- mostlyright/data_harness/readers/samples/archive.gzip/1.0.0/cities_one_stream/cities.csv.gz +0 -0
- mostlyright/data_harness/readers/samples/archive.gzip/1.0.0/cities_one_stream/expected.json +24 -0
- mostlyright/data_harness/readers/samples/archive.gzip/1.1.0/cities_one_stream/cities.csv.gz +0 -0
- mostlyright/data_harness/readers/samples/archive.gzip/1.1.0/cities_one_stream/expected.json +24 -0
- mostlyright/data_harness/readers/samples/archive.tar/1.0.0/cities_beside_a_directory_entry/cities.tar +0 -0
- mostlyright/data_harness/readers/samples/archive.tar/1.0.0/cities_beside_a_directory_entry/expected.json +24 -0
- mostlyright/data_harness/readers/samples/archive.tar/1.1.0/cities_beside_a_directory_entry/cities.tar +0 -0
- mostlyright/data_harness/readers/samples/archive.tar/1.1.0/cities_beside_a_directory_entry/expected.json +24 -0
- mostlyright/data_harness/readers/samples/archive.zip/1.0.0/cities_beside_a_second_member/cities.zip +0 -0
- mostlyright/data_harness/readers/samples/archive.zip/1.0.0/cities_beside_a_second_member/expected.json +25 -0
- mostlyright/data_harness/readers/samples/archive.zip/1.1.0/dwd_semicolon_station_member/dwd-station.zip +0 -0
- mostlyright/data_harness/readers/samples/archive.zip/1.1.0/dwd_semicolon_station_member/expected.json +25 -0
- mostlyright/data_harness/readers/samples/archive.zip/1.2.0/dwd_semicolon_station_member/dwd-station.zip +0 -0
- mostlyright/data_harness/readers/samples/archive.zip/1.2.0/dwd_semicolon_station_member/expected.json +25 -0
- mostlyright/data_harness/readers/samples/delimited_text/1.0.0/an_ordinary_comma_separated_table/cities.csv +3 -0
- mostlyright/data_harness/readers/samples/delimited_text/1.0.0/an_ordinary_comma_separated_table/expected.json +23 -0
- mostlyright/data_harness/readers/samples/delimited_text/1.0.0/quoted_fields_holding_the_delimiter/cities.tsv +5 -0
- mostlyright/data_harness/readers/samples/delimited_text/1.0.0/quoted_fields_holding_the_delimiter/expected.json +25 -0
- mostlyright/data_harness/readers/samples/delimited_text/1.1.0/an_hourly_observation_table_served_as_plain_text/expected.json +30 -0
- mostlyright/data_harness/readers/samples/delimited_text/1.1.0/an_hourly_observation_table_served_as_plain_text/observations.csv +5 -0
- mostlyright/data_harness/readers/samples/json.tabular/1.0.0/nested_hourly_observations/expected.json +44 -0
- mostlyright/data_harness/readers/samples/json.tabular/1.0.0/nested_hourly_observations/stations.json +1 -0
- mostlyright/data_harness/readers/samples/json.tabular/1.1.0/an_observation_stream_served_as_plain_text/expected.json +48 -0
- mostlyright/data_harness/readers/samples/json.tabular/1.1.0/an_observation_stream_served_as_plain_text/observations.ndjson +4 -0
- mostlyright/data_harness/readers/samples/spreadsheet.xlsx/1.0.0/an_ordinary_table_beside_a_second_sheet/cities.xlsx +0 -0
- mostlyright/data_harness/readers/samples/spreadsheet.xlsx/1.0.0/an_ordinary_table_beside_a_second_sheet/expected.json +24 -0
- mostlyright/data_harness/readers/samples/spreadsheet.xlsx/1.0.0/shares_the_workbook_had_already_computed/expected.json +27 -0
- mostlyright/data_harness/readers/samples/spreadsheet.xlsx/1.0.0/shares_the_workbook_had_already_computed/shares.xlsx +0 -0
- mostlyright/data_harness/readers/samples/spreadsheet.xlsx/1.1.0/shares_the_workbook_had_already_computed/expected.json +27 -0
- mostlyright/data_harness/readers/samples/spreadsheet.xlsx/1.1.0/shares_the_workbook_had_already_computed/shares.xlsx +0 -0
- mostlyright/data_harness/readers/samples/weather.grib2/1.0.0/README.md +20 -0
- mostlyright/data_harness/readers/samples/weather.grib2/1.0.0/gfs_2m_temperature/expected.json +55 -0
- mostlyright/data_harness/readers/samples/weather.grib2/1.0.0/gfs_2m_temperature/gfs-2m-temperature.grib2 +0 -0
- mostlyright/data_harness/readers/samples/weather.grib2/1.0.0/hrrr_2m_temperature/expected.json +54 -0
- mostlyright/data_harness/readers/samples/weather.grib2/1.0.0/hrrr_2m_temperature/hrrr-2m-temperature.grib2 +0 -0
- mostlyright/data_harness/readers/samples/weather.grib2/1.0.0/hrrr_categorical_rain/expected.json +54 -0
- mostlyright/data_harness/readers/samples/weather.grib2/1.0.0/hrrr_categorical_rain/hrrr-categorical-rain.grib2 +0 -0
- mostlyright/data_harness/readers/samples/weather.grib2/2.0.0/hrrr_2m_temperature/expected.json +54 -0
- mostlyright/data_harness/readers/samples/weather.grib2/2.0.0/hrrr_2m_temperature/hrrr-2m-temperature.grib2 +0 -0
- mostlyright/data_harness/readers/samples.py +582 -0
- mostlyright/data_harness/readers/spreadsheet.py +803 -0
- mostlyright/data_harness/readers/tabular.py +510 -0
- mostlyright/data_harness/recipe.py +5321 -0
- mostlyright/data_harness/repair/__init__.py +78 -0
- mostlyright/data_harness/repair/adapters.py +274 -0
- mostlyright/data_harness/repair/contracts.py +872 -0
- mostlyright/data_harness/repair/coordinator.py +1099 -0
- mostlyright/data_harness/repair/errors.py +16 -0
- mostlyright/data_harness/review.py +2533 -0
- mostlyright/data_harness/rowset.py +283 -0
- mostlyright/data_harness/serving.py +1975 -0
- mostlyright/data_harness/serving_edge.py +590 -0
- mostlyright/data_harness/serving_http.py +1031 -0
- mostlyright/data_harness/session_probes.py +759 -0
- mostlyright/data_harness/signing.py +101 -0
- mostlyright/data_harness/source_discovery.py +898 -0
- mostlyright/data_harness/sources/__init__.py +209 -0
- mostlyright/data_harness/sources/_adapter_steps.py +213 -0
- mostlyright/data_harness/sources/adapters.py +1214 -0
- mostlyright/data_harness/sources/cadence.py +1428 -0
- mostlyright/data_harness/sources/cadence_emission.py +453 -0
- mostlyright/data_harness/sources/cadence_history.py +546 -0
- mostlyright/data_harness/sources/catalog/__init__.py +17 -0
- mostlyright/data_harness/sources/catalog/admission.py +477 -0
- mostlyright/data_harness/sources/catalog/authoring.py +1701 -0
- mostlyright/data_harness/sources/catalog/authoring_policy.py +701 -0
- mostlyright/data_harness/sources/catalog/authoring_shards.py +1217 -0
- mostlyright/data_harness/sources/catalog/bounded_io.py +231 -0
- mostlyright/data_harness/sources/catalog/channel.py +523 -0
- mostlyright/data_harness/sources/catalog/channel_client.py +296 -0
- mostlyright/data_harness/sources/catalog/contracts.py +825 -0
- mostlyright/data_harness/sources/catalog/coverage.py +137 -0
- mostlyright/data_harness/sources/catalog/delta.py +1340 -0
- mostlyright/data_harness/sources/catalog/embedding.py +532 -0
- mostlyright/data_harness/sources/catalog/entry_v2.py +1182 -0
- mostlyright/data_harness/sources/catalog/fill.py +3889 -0
- mostlyright/data_harness/sources/catalog/fill_partitions.py +459 -0
- mostlyright/data_harness/sources/catalog/fill_staging.py +1105 -0
- mostlyright/data_harness/sources/catalog/gating.py +374 -0
- mostlyright/data_harness/sources/catalog/generation_receipt.py +1607 -0
- mostlyright/data_harness/sources/catalog/harvest/__init__.py +7 -0
- mostlyright/data_harness/sources/catalog/harvest/ckan.py +384 -0
- mostlyright/data_harness/sources/catalog/harvest/datagov_v4.py +798 -0
- mostlyright/data_harness/sources/catalog/harvest/protocol.py +964 -0
- mostlyright/data_harness/sources/catalog/harvest/sdmx.py +445 -0
- mostlyright/data_harness/sources/catalog/harvest/stac.py +384 -0
- mostlyright/data_harness/sources/catalog/health.py +447 -0
- mostlyright/data_harness/sources/catalog/hosted_catalog.py +105 -0
- mostlyright/data_harness/sources/catalog/identity_history.py +1549 -0
- mostlyright/data_harness/sources/catalog/neural.py +1618 -0
- mostlyright/data_harness/sources/catalog/packed_catalog.py +2345 -0
- mostlyright/data_harness/sources/catalog/packed_retrieval.py +1517 -0
- mostlyright/data_harness/sources/catalog/packed_writer.py +2802 -0
- mostlyright/data_harness/sources/catalog/query_trace.py +1037 -0
- mostlyright/data_harness/sources/catalog/recommend.py +171 -0
- mostlyright/data_harness/sources/catalog/retrieval.py +230 -0
- mostlyright/data_harness/sources/catalog/retrieval_manifest.py +995 -0
- mostlyright/data_harness/sources/catalog/rights_decisions.py +254 -0
- mostlyright/data_harness/sources/catalog/sealed.py +560 -0
- mostlyright/data_harness/sources/catalog/search.py +230 -0
- mostlyright/data_harness/sources/catalog/streaming_delta.py +1097 -0
- mostlyright/data_harness/sources/catalog/update.py +891 -0
- mostlyright/data_harness/sources/collections.py +815 -0
- mostlyright/data_harness/sources/contracts.py +2223 -0
- mostlyright/data_harness/sources/deletion.py +761 -0
- mostlyright/data_harness/sources/fitness.py +162 -0
- mostlyright/data_harness/sources/governance.py +163 -0
- mostlyright/data_harness/sources/hosted.py +173 -0
- mostlyright/data_harness/sources/integration.py +218 -0
- mostlyright/data_harness/sources/range_reader.py +418 -0
- mostlyright/data_harness/sources/registry.py +514 -0
- mostlyright/data_harness/sources/rights_rule.py +59 -0
- mostlyright/data_harness/sources/source_cadence_vectors.v1.json +1 -0
- mostlyright/data_harness/sources/sports.py +521 -0
- mostlyright/data_harness/sources/stream.py +524 -0
- mostlyright/data_harness/sources/stream_connector.py +418 -0
- mostlyright/data_harness/sources/stream_recorder.py +1404 -0
- mostlyright/data_harness/studio_boundary.py +2019 -0
- mostlyright/data_harness/thin/__init__.py +37 -0
- mostlyright/data_harness/thin/acquire.py +1137 -0
- mostlyright/data_harness/thin/acquire_cancel.py +579 -0
- mostlyright/data_harness/thin/approvals.py +617 -0
- mostlyright/data_harness/thin/commands.py +406 -0
- mostlyright/data_harness/thin/download.py +194 -0
- mostlyright/data_harness/thin/narrative.py +589 -0
- mostlyright/data_harness/thin/parity.py +1070 -0
- mostlyright/data_harness/thin/propose.py +2759 -0
- mostlyright/data_harness/thin/research.py +1663 -0
- mostlyright/data_harness/thin/router.py +924 -0
- mostlyright/data_harness/thin/runs.py +519 -0
- mostlyright/data_harness/thin/session.py +281 -0
- mostlyright/data_harness/thin/stream.py +501 -0
- mostlyright/data_harness/thin/transport.py +187 -0
- mostlyright/data_harness/thin/vocabulary.py +368 -0
- mostlyright/data_harness/thin/workers.py +164 -0
- mostlyright/data_harness/ucum/TABLE-PIN.json +40 -0
- mostlyright/data_harness/ucum/ucum-subset.v1.json +632 -0
- mostlyright/data_harness/unit_flow.py +927 -0
- mostlyright/data_harness/units.py +572 -0
- mostlyright/data_harness/ux/__init__.py +9 -0
- mostlyright/data_harness/ux/approve.py +485 -0
- mostlyright/data_harness/ux/author_yaml.py +597 -0
- mostlyright/data_harness/ux/cloud_auth.py +447 -0
- mostlyright/data_harness/ux/commands/__init__.py +260 -0
- mostlyright/data_harness/ux/commands/approve.py +136 -0
- mostlyright/data_harness/ux/commands/auth.py +744 -0
- mostlyright/data_harness/ux/commands/author.py +79 -0
- mostlyright/data_harness/ux/commands/catalog_author.py +403 -0
- mostlyright/data_harness/ux/commands/catalog_fill.py +523 -0
- mostlyright/data_harness/ux/commands/catalog_harvest.py +545 -0
- mostlyright/data_harness/ux/commands/catalog_publish.py +1838 -0
- mostlyright/data_harness/ux/commands/catalog_search.py +71 -0
- mostlyright/data_harness/ux/commands/catalog_update.py +437 -0
- mostlyright/data_harness/ux/commands/deploy.py +134 -0
- mostlyright/data_harness/ux/commands/deploy_dataset.py +98 -0
- mostlyright/data_harness/ux/commands/deploy_plan.py +105 -0
- mostlyright/data_harness/ux/commands/deploy_status.py +104 -0
- mostlyright/data_harness/ux/commands/diff.py +74 -0
- mostlyright/data_harness/ux/commands/index.py +84 -0
- mostlyright/data_harness/ux/commands/inventory.py +47 -0
- mostlyright/data_harness/ux/commands/list_builds.py +143 -0
- mostlyright/data_harness/ux/commands/login.py +63 -0
- mostlyright/data_harness/ux/commands/peek.py +236 -0
- mostlyright/data_harness/ux/commands/plan_check.py +90 -0
- mostlyright/data_harness/ux/commands/preflight.py +97 -0
- mostlyright/data_harness/ux/commands/record.py +107 -0
- mostlyright/data_harness/ux/commands/review_setup.py +47 -0
- mostlyright/data_harness/ux/commands/search.py +440 -0
- mostlyright/data_harness/ux/commands/show.py +61 -0
- mostlyright/data_harness/ux/commands/whoami.py +37 -0
- mostlyright/data_harness/ux/credential_native.py +551 -0
- mostlyright/data_harness/ux/credential_store.py +1055 -0
- mostlyright/data_harness/ux/credentials.py +631 -0
- mostlyright/data_harness/ux/diffing.py +444 -0
- mostlyright/data_harness/ux/headline.py +671 -0
- mostlyright/data_harness/ux/hosted_acquisition.py +974 -0
- mostlyright/data_harness/ux/hosted_run_status.py +619 -0
- mostlyright/data_harness/ux/inventory.py +427 -0
- mostlyright/data_harness/ux/local_review.py +375 -0
- mostlyright/data_harness/ux/login.py +691 -0
- mostlyright/data_harness/ux/path_kind.py +147 -0
- mostlyright/data_harness/ux/peek.py +1000 -0
- mostlyright/data_harness/ux/plain_file.py +178 -0
- mostlyright/data_harness/ux/plan_check.py +311 -0
- mostlyright/data_harness/ux/preflight.py +918 -0
- mostlyright/data_harness/ux/readers.py +1124 -0
- mostlyright/data_harness/ux/remediation.py +2195 -0
- mostlyright/data_harness/ux/render.py +657 -0
- mostlyright/data_harness/ux/workload.py +1077 -0
- mostlyright/data_harness/viewer.py +3713 -0
- mostlyright/data_harness/visual_run/__init__.py +83 -0
- mostlyright/data_harness/visual_run/authoring.py +235 -0
- mostlyright/data_harness/visual_run/contracts.py +673 -0
- mostlyright/data_harness/visual_run/materialize.py +486 -0
- mostlyright/data_harness/visual_run/observations.py +874 -0
- mostlyright/data_harness/visual_run/query.py +259 -0
- mostlyright/data_harness/visual_run/reducer.py +280 -0
- mostlyright/data_harness/visual_run/sdk.py +892 -0
- mostlyright/data_harness/visual_run/store.py +584 -0
- mostlyright/data_harness/visual_run/transport.py +239 -0
- mostlyright/data_harness/watch.py +2999 -0
- mostlyright_data-0.9.0.dist-info/METADATA +607 -0
- mostlyright_data-0.9.0.dist-info/RECORD +314 -0
- mostlyright_data-0.9.0.dist-info/WHEEL +4 -0
- mostlyright_data-0.9.0.dist-info/entry_points.txt +12 -0
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
"""The single closed table of data formats the harness accepts.
|
|
2
|
+
|
|
3
|
+
Every layer that admits, refuses, or describes a data format reads its membership from
|
|
4
|
+
this module. No other module re-declares the list. A test walks the package and fails
|
|
5
|
+
if one does, because a format accepted by one layer and refused by another is a bug in
|
|
6
|
+
its own right rather than a cosmetic inconsistency.
|
|
7
|
+
|
|
8
|
+
The table is closed. There is no plugin discovery, no import-by-name, and no
|
|
9
|
+
environment override: membership is exactly the values written below. Add a Reader family here
|
|
10
|
+
before implementing its decoder.
|
|
11
|
+
|
|
12
|
+
Two vocabularies, not one
|
|
13
|
+
-------------------------
|
|
14
|
+
The harness has two format-shaped sets and they are deliberately different.
|
|
15
|
+
|
|
16
|
+
``DATA_FORMATS`` is the wire-format set: the payload encodings a source adapter can hand
|
|
17
|
+
back as bytes. ``PLAN_DATA_FORMATS`` is the plan-contract set, which additionally
|
|
18
|
+
carries ``api`` and ``stream``. Those two are acquisition modes -- how bytes are
|
|
19
|
+
reached -- not encodings of bytes. They are modelled as two named tables so the
|
|
20
|
+
distinction stays visible and typed, and they must never be collapsed into one set.
|
|
21
|
+
|
|
22
|
+
This module imports nothing from the rest of the package. It is a leaf, so every layer
|
|
23
|
+
including ``acquisition`` and ``backends`` can read it without creating an import cycle.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
from __future__ import annotations
|
|
27
|
+
|
|
28
|
+
from collections.abc import Mapping
|
|
29
|
+
from types import MappingProxyType
|
|
30
|
+
|
|
31
|
+
__all__ = [
|
|
32
|
+
"ARCHIVE_OR_EXECUTABLE_MAGICS",
|
|
33
|
+
"DATA_FORMATS",
|
|
34
|
+
"DIRECT_FETCH_MEDIA_TYPES",
|
|
35
|
+
"FORMAT_MEDIA_TYPES",
|
|
36
|
+
"FORMAT_SUFFIXES",
|
|
37
|
+
"PARSER_FORMATS_BY_OPERATION",
|
|
38
|
+
"PARSER_FORMAT_ORDER",
|
|
39
|
+
"PLAN_DATA_FORMATS",
|
|
40
|
+
"READER_CONTRACT_VERSION",
|
|
41
|
+
"READER_OUTPUT_FORMATS",
|
|
42
|
+
"READER_WORKER_MEMORY_BYTES",
|
|
43
|
+
"SLICE_SNAPSHOT_SUFFIX",
|
|
44
|
+
"SNAPSHOT_SUFFIXES",
|
|
45
|
+
"SNAPSHOT_SUFFIX_PATTERN",
|
|
46
|
+
"WEAK_TEXT_MEDIA_TYPES",
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
# The label of the Reader contract a recipe pins itself to. A Reader family is the code
|
|
50
|
+
# that turns fetched bytes into rows; this label versions the shape of that pin -- the
|
|
51
|
+
# family identifier, its version, and its decode options -- not any individual family.
|
|
52
|
+
# Bumping this label invalidates recipes that name the previous contract.
|
|
53
|
+
READER_CONTRACT_VERSION = "harness-reader-contract.v1"
|
|
54
|
+
|
|
55
|
+
# The one process-memory ceiling shared by Reader admission and the operating-system sandbox.
|
|
56
|
+
# It lives in this dependency-free leaf because acquisition consumes Readers and Readers must not
|
|
57
|
+
# import acquisition back. A family-level worst-case proof is required to stay below this value.
|
|
58
|
+
READER_WORKER_MEMORY_BYTES = 512 * 1024 * 1024
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
# Encodings a Reader family may emit. Reader output is canonical CSV regardless of source format.
|
|
62
|
+
#
|
|
63
|
+
# This is a different question from ``DATA_FORMATS``. That table answers "what encoding may
|
|
64
|
+
# arrive on the wire"; this one answers "what encoding may a decoder produce". A wire format
|
|
65
|
+
# with no Reader that emits it is normal, and so is the reverse, so neither is derived from
|
|
66
|
+
# the other. Zip, gzip, tar, xlsx, tsv, and grib2 appear in neither: they are Reader
|
|
67
|
+
# families, not encodings a parser is ever handed.
|
|
68
|
+
READER_OUTPUT_FORMATS: tuple[str, ...] = ("csv",)
|
|
69
|
+
|
|
70
|
+
# The ordered parser table. Order is digest-load-bearing: this exact sequence is
|
|
71
|
+
# embedded in the sandbox policy document built by
|
|
72
|
+
# ``acquisition.sandbox._policy_digest``, and the attestation a coordinator supplies is
|
|
73
|
+
# compared against the digest of that document. Reordering these names rotates the
|
|
74
|
+
# attestation for every operation that parses bytes, so treat the order as part of the
|
|
75
|
+
# contract and not as an implementation detail.
|
|
76
|
+
PARSER_FORMAT_ORDER: tuple[str, ...] = ("csv", "json", "ndjson", "parquet")
|
|
77
|
+
|
|
78
|
+
# The wire-format set: payload encodings an adapter emits and a parser admits.
|
|
79
|
+
DATA_FORMATS: frozenset[str] = frozenset(PARSER_FORMAT_ORDER)
|
|
80
|
+
|
|
81
|
+
# The plan-contract set. ``api`` and ``stream`` are acquisition modes, not wire
|
|
82
|
+
# formats: they describe how bytes are reached rather than how bytes are encoded. A
|
|
83
|
+
# plan may name them; a parser may never be handed them. See the vocabulary map in
|
|
84
|
+
# ``sources/contracts.py``.
|
|
85
|
+
PLAN_DATA_FORMATS: frozenset[str] = frozenset({"csv", "parquet", "json", "api", "stream"})
|
|
86
|
+
|
|
87
|
+
# Media types accepted for each wire format, used to admit or refuse a response by its
|
|
88
|
+
# declared content type.
|
|
89
|
+
FORMAT_MEDIA_TYPES: Mapping[str, frozenset[str]] = MappingProxyType(
|
|
90
|
+
{
|
|
91
|
+
"csv": frozenset({"text/csv"}),
|
|
92
|
+
"json": frozenset({"application/json"}),
|
|
93
|
+
"ndjson": frozenset({"application/x-ndjson"}),
|
|
94
|
+
"parquet": frozenset({"application/vnd.apache.parquet"}),
|
|
95
|
+
}
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
# The weak *text* label: what a server sends when it declines to describe a text file at all.
|
|
99
|
+
# It is NOT a member of the table above and must never become one -- ``FORMAT_MEDIA_TYPES``
|
|
100
|
+
# answers "what encoding may be sealed", and its members are what a recipe may name and what
|
|
101
|
+
# the sandbox policy pins. ``text/plain`` names no encoding; it is the absence of a claim.
|
|
102
|
+
#
|
|
103
|
+
# Named for text on purpose. ``application/octet-stream`` is the other weak label this
|
|
104
|
+
# codebase knows -- it is what ``SIDECAR_MEDIA_TYPES`` admits and what the widened archive and
|
|
105
|
+
# spreadsheet coordinates admit -- and it does not belong here. Adding it would admit an
|
|
106
|
+
# opaque binary download as csv, json or ndjson at both the fetch and the parse, for every
|
|
107
|
+
# direct source, with no certified coordinate having approved it; the archive-magic guard in
|
|
108
|
+
# ``parsing`` catches a container but not a binary whose first bytes match no known prefix.
|
|
109
|
+
# Widening to that label is a separate change with its own evidence.
|
|
110
|
+
WEAK_TEXT_MEDIA_TYPES: frozenset[str] = frozenset({"text/plain"})
|
|
111
|
+
|
|
112
|
+
# The formats whose bytes are text, and so the only ones a weak text label can plausibly carry.
|
|
113
|
+
# ``parquet`` is excluded because a Parquet file is never plain text: admitting the label there
|
|
114
|
+
# would widen a refusal without ever matching something a publisher actually sends.
|
|
115
|
+
_TEXT_SHAPED_FORMATS: frozenset[str] = frozenset({"csv", "json", "ndjson"})
|
|
116
|
+
|
|
117
|
+
# What a *direct* fetch -- a source with no Reader pin -- admits, and what its parse admits.
|
|
118
|
+
#
|
|
119
|
+
# Kept separate from ``FORMAT_MEDIA_TYPES`` rather than folded into it, because the two answer
|
|
120
|
+
# different questions and only one of them is the sealing vocabulary. A Reader-pinned fetch
|
|
121
|
+
# consults neither: it takes its admitted set from the pinned family, where
|
|
122
|
+
# ``delimited_text@1.1.0`` and ``json.tabular@1.1.0`` carry the weak label and their ``1.0.0``
|
|
123
|
+
# siblings deliberately do not. A direct fetch has no recipe to protect and no coordinate to
|
|
124
|
+
# pin, so its widening lives here or it does not exist.
|
|
125
|
+
#
|
|
126
|
+
# This is the one clause of the slice-vocabulary invariant that this map changes, and it is
|
|
127
|
+
# changed on purpose: a parser now admits ``text/plain`` for a text-shaped format. The other
|
|
128
|
+
# clauses hold unchanged -- no recipe may name it (``PLAN_DATA_FORMATS`` is format names), and
|
|
129
|
+
# no deletion sweep tracks it (the sweep is suffix-driven). The residual risk is the one
|
|
130
|
+
# already recorded for the widened Reader coordinates: a plain-text error body can parse as a
|
|
131
|
+
# one-column table with no rows, which is visible at review before anything is sealed.
|
|
132
|
+
DIRECT_FETCH_MEDIA_TYPES: Mapping[str, frozenset[str]] = MappingProxyType(
|
|
133
|
+
{
|
|
134
|
+
data_format: (
|
|
135
|
+
accepted | WEAK_TEXT_MEDIA_TYPES if data_format in _TEXT_SHAPED_FORMATS else accepted
|
|
136
|
+
)
|
|
137
|
+
for data_format, accepted in FORMAT_MEDIA_TYPES.items()
|
|
138
|
+
}
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
# Filename suffixes accepted for each wire format. A format may carry more than one.
|
|
142
|
+
FORMAT_SUFFIXES: Mapping[str, frozenset[str]] = MappingProxyType(
|
|
143
|
+
{
|
|
144
|
+
"csv": frozenset({".csv"}),
|
|
145
|
+
"json": frozenset({".json"}),
|
|
146
|
+
"ndjson": frozenset({".jsonl", ".ndjson"}),
|
|
147
|
+
"parquet": frozenset({".parquet"}),
|
|
148
|
+
}
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
# What an archive, an executable, or a rich document looks like from its first bytes. Not a
|
|
152
|
+
# format table: these are the things that are never a table, listed by the prefix that gives
|
|
153
|
+
# them away.
|
|
154
|
+
#
|
|
155
|
+
# It lives in the leaf because two layers refuse on it and they must agree. The tabular
|
|
156
|
+
# parser refuses these bytes outright, so an archive is never parsed as data. The container
|
|
157
|
+
# Readers refuse a member whose own first bytes match, so an archive one layer inside an
|
|
158
|
+
# archive is never opened. Those are two layers of one invariant; a second copy of the list
|
|
159
|
+
# would let them drift into disagreeing about what an archive is, which is a security-
|
|
160
|
+
# relevant disagreement and not a cosmetic one. ``readers/`` cannot import ``acquisition/``
|
|
161
|
+
# -- that back-edge closes an import cycle -- so the one statement lives here, where both
|
|
162
|
+
# sides can read it.
|
|
163
|
+
#
|
|
164
|
+
# The table is public for the same reason: a cross-package import of another module's private
|
|
165
|
+
# name is not a contract. Adding or removing a prefix changes what the harness refuses and is
|
|
166
|
+
# a reviewed edit, never a tidy-up.
|
|
167
|
+
ARCHIVE_OR_EXECUTABLE_MAGICS: tuple[bytes, ...] = (
|
|
168
|
+
b"PK\x03\x04",
|
|
169
|
+
b"PK\x05\x06",
|
|
170
|
+
b"PK\x07\x08",
|
|
171
|
+
b"\x1f\x8b",
|
|
172
|
+
b"BZh",
|
|
173
|
+
b"\xfd7zXZ\x00",
|
|
174
|
+
b"7z\xbc\xaf'\x1c",
|
|
175
|
+
b"Rar!\x1a\x07",
|
|
176
|
+
b"\x7fELF",
|
|
177
|
+
b"MZ",
|
|
178
|
+
b"\xca\xfe\xba\xbe",
|
|
179
|
+
b"%PDF-",
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
# Which formats each sandbox operation may hand to a parser. This is enforced, not merely
|
|
183
|
+
# declared: ``acquisition.sandbox._execute_worker_request`` refuses a request whose
|
|
184
|
+
# ``data_format`` is outside its operation's entry, and refuses outright when the operation
|
|
185
|
+
# has no entry. The same mapping is embedded in the operation's policy document, so the
|
|
186
|
+
# attestation a coordinator binds and the rule the worker applies are the one table.
|
|
187
|
+
#
|
|
188
|
+
# Presence in this mapping is also what makes an operation rotatable by a format addition; an
|
|
189
|
+
# operation that is absent from it never rotates on one, because its policy document carries
|
|
190
|
+
# no format list at all.
|
|
191
|
+
#
|
|
192
|
+
# ``probe`` is deliberately absent: it returns from the sandbox worker before the request's
|
|
193
|
+
# data format is ever read, so it hands nothing to a parser.
|
|
194
|
+
#
|
|
195
|
+
# Values are the shared ``PARSER_FORMAT_ORDER`` by reference rather than re-spelled
|
|
196
|
+
# literals, because the order is digest-load-bearing and because a re-spelled list here
|
|
197
|
+
# would trip the anti-duplication gate -- which would be that gate working correctly.
|
|
198
|
+
# Add Reader families here so attestation changes remain scoped to decode operations.
|
|
199
|
+
# The decode operation is scoped to what a Reader may emit rather than to the wire table, and
|
|
200
|
+
# that separation is the consequence worth stating: adding a **wire** format rotates ``parse``
|
|
201
|
+
# and ``retrieve_and_parse`` and leaves the decode operation exactly where it was, while
|
|
202
|
+
# adding a **Reader output** encoding rotates the decode operation alone. Neither event
|
|
203
|
+
# touches the other's attestation, which is what the per-operation scoping was built for.
|
|
204
|
+
PARSER_FORMATS_BY_OPERATION: Mapping[str, tuple[str, ...]] = MappingProxyType(
|
|
205
|
+
{
|
|
206
|
+
"parse": PARSER_FORMAT_ORDER,
|
|
207
|
+
"retrieve_and_parse": PARSER_FORMAT_ORDER,
|
|
208
|
+
"decode_and_parse": READER_OUTPUT_FORMATS,
|
|
209
|
+
"retrieve_decode_and_parse": READER_OUTPUT_FORMATS,
|
|
210
|
+
}
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
# The one sealed-snapshot suffix that is deliberately not a data format. A fetched slice
|
|
214
|
+
# is a byte range of an object, not a parseable document: no parser in this build reads it,
|
|
215
|
+
# and putting it in ``DATA_FORMATS`` would claim a parser that does not exist and would
|
|
216
|
+
# rotate every format-table digest to say so.
|
|
217
|
+
#
|
|
218
|
+
# It lives here rather than beside the sealing function because sealing and deletion have to
|
|
219
|
+
# agree about it. A suffix that could be written but not matched for removal would strand
|
|
220
|
+
# snapshots no retention sweep can find -- the exact hazard the derivation below exists to
|
|
221
|
+
# prevent -- and that is what happened when this suffix was declared at the sealing site and
|
|
222
|
+
# unioned in there alone.
|
|
223
|
+
SLICE_SNAPSHOT_SUFFIX: str = "slice"
|
|
224
|
+
|
|
225
|
+
# Every suffix a sealed content-addressed snapshot may carry: the wire formats, plus the one
|
|
226
|
+
# non-format above. This is the set both halves read. ``_is_allowlisted_snapshot_suffix``
|
|
227
|
+
# admits exactly this set when writing, and ``SNAPSHOT_SUFFIX_PATTERN`` below is the
|
|
228
|
+
# alternation the deletion regex matches with -- so what can be sealed and what can be
|
|
229
|
+
# removed are one derived set rather than two lists that drift.
|
|
230
|
+
SNAPSHOT_SUFFIXES: frozenset[str] = DATA_FORMATS | frozenset({SLICE_SNAPSHOT_SUFFIX})
|
|
231
|
+
|
|
232
|
+
# The alternation fragment the sealed-snapshot filename regex is built from, derived
|
|
233
|
+
# from the set above rather than spelled out. Deriving it is what stops a suffix from
|
|
234
|
+
# becoming admissible for sealing while staying unmatchable for deletion, which would
|
|
235
|
+
# strand snapshots that no retention sweep can find.
|
|
236
|
+
SNAPSHOT_SUFFIX_PATTERN: str = "|".join(sorted(SNAPSHOT_SUFFIXES))
|