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.
Files changed (314) hide show
  1. mostlyright/data_harness/__init__.py +158 -0
  2. mostlyright/data_harness/acquisition/__init__.py +55 -0
  3. mostlyright/data_harness/acquisition/http.py +2773 -0
  4. mostlyright/data_harness/acquisition/parsing.py +809 -0
  5. mostlyright/data_harness/acquisition/ranges.py +495 -0
  6. mostlyright/data_harness/acquisition/result_download.py +360 -0
  7. mostlyright/data_harness/acquisition/retention_admission.py +248 -0
  8. mostlyright/data_harness/acquisition/sandbox.py +4888 -0
  9. mostlyright/data_harness/acquisition/url_policy.py +530 -0
  10. mostlyright/data_harness/agent_runtime.py +2743 -0
  11. mostlyright/data_harness/assets/logo-ink.svg +31 -0
  12. mostlyright/data_harness/backends/__init__.py +28 -0
  13. mostlyright/data_harness/backends/pandas_backend.py +350 -0
  14. mostlyright/data_harness/backends/polars_backend.py +366 -0
  15. mostlyright/data_harness/backends/protocol.py +124 -0
  16. mostlyright/data_harness/backends/reference.py +83 -0
  17. mostlyright/data_harness/backends/registry.py +55 -0
  18. mostlyright/data_harness/backends/restrictions.py +126 -0
  19. mostlyright/data_harness/canonical.py +333 -0
  20. mostlyright/data_harness/catalog_job.py +625 -0
  21. mostlyright/data_harness/cli.py +5398 -0
  22. mostlyright/data_harness/contracts.py +53 -0
  23. mostlyright/data_harness/coordinator.py +1307 -0
  24. mostlyright/data_harness/deploy.py +924 -0
  25. mostlyright/data_harness/deploy_target.py +312 -0
  26. mostlyright/data_harness/deployment_evidence.py +1067 -0
  27. mostlyright/data_harness/event_presentation.py +576 -0
  28. mostlyright/data_harness/events.py +2152 -0
  29. mostlyright/data_harness/fast_delimited.py +239 -0
  30. mostlyright/data_harness/fleet.py +237 -0
  31. mostlyright/data_harness/formats.py +236 -0
  32. mostlyright/data_harness/governors.py +1163 -0
  33. mostlyright/data_harness/hosted_bootstrap.py +972 -0
  34. mostlyright/data_harness/hosted_crawler.py +1115 -0
  35. mostlyright/data_harness/hosted_crawler_container_smoke.py +351 -0
  36. mostlyright/data_harness/hosted_crawler_fetch.py +423 -0
  37. mostlyright/data_harness/hosted_crawler_job.py +1277 -0
  38. mostlyright/data_harness/hosted_crawler_protocol.py +676 -0
  39. mostlyright/data_harness/hosted_dataset.py +1500 -0
  40. mostlyright/data_harness/hosted_deploy.py +3037 -0
  41. mostlyright/data_harness/hosted_handoff.py +62 -0
  42. mostlyright/data_harness/hosted_ingestion_contract.py +504 -0
  43. mostlyright/data_harness/hosted_ingestion_job.py +356 -0
  44. mostlyright/data_harness/hosted_ingestion_job_smoke.py +40 -0
  45. mostlyright/data_harness/hosted_session_container_smoke.py +194 -0
  46. mostlyright/data_harness/hosted_session_worker.py +3554 -0
  47. mostlyright/data_harness/hosted_session_worker_job_smoke.py +46 -0
  48. mostlyright/data_harness/hosted_worker.py +6784 -0
  49. mostlyright/data_harness/ingestion/__init__.py +56 -0
  50. mostlyright/data_harness/ingestion/contracts.py +461 -0
  51. mostlyright/data_harness/ingestion/faults.py +42 -0
  52. mostlyright/data_harness/ingestion/gcs_store.py +1162 -0
  53. mostlyright/data_harness/ingestion/spool.py +130 -0
  54. mostlyright/data_harness/ingestion/store.py +885 -0
  55. mostlyright/data_harness/key_seam.py +434 -0
  56. mostlyright/data_harness/linux_process_boundary.py +262 -0
  57. mostlyright/data_harness/local_contracts.py +2880 -0
  58. mostlyright/data_harness/local_search/__init__.py +5 -0
  59. mostlyright/data_harness/local_search/build_index.py +1087 -0
  60. mostlyright/data_harness/local_search/contracts.py +920 -0
  61. mostlyright/data_harness/local_search/query_trace.py +266 -0
  62. mostlyright/data_harness/local_search/retrieval.py +700 -0
  63. mostlyright/data_harness/local_search/sealed.py +474 -0
  64. mostlyright/data_harness/local_search/service.py +784 -0
  65. mostlyright/data_harness/nbrender/CONTRACT.md +212 -0
  66. mostlyright/data_harness/nbrender/__init__.py +12 -0
  67. mostlyright/data_harness/nbrender/chrome.py +359 -0
  68. mostlyright/data_harness/nbrender/code_body.py +266 -0
  69. mostlyright/data_harness/nbrender/document.py +407 -0
  70. mostlyright/data_harness/nbrender/frame.py +275 -0
  71. mostlyright/data_harness/nbrender/interactive.py +337 -0
  72. mostlyright/data_harness/nbrender/markdown_body.py +477 -0
  73. mostlyright/data_harness/nbrender/mr_components.py +134 -0
  74. mostlyright/data_harness/nbrender/outputs_data.py +595 -0
  75. mostlyright/data_harness/nbrender/outputs_rich.py +906 -0
  76. mostlyright/data_harness/nbrender/outputs_source.py +260 -0
  77. mostlyright/data_harness/nbrender/outputs_stage.py +176 -0
  78. mostlyright/data_harness/nbrender/outputs_text.py +400 -0
  79. mostlyright/data_harness/nbrender/parse.py +394 -0
  80. mostlyright/data_harness/nbrender/status.py +40 -0
  81. mostlyright/data_harness/nbrender/tokens.py +1295 -0
  82. mostlyright/data_harness/notebook.py +1710 -0
  83. mostlyright/data_harness/offline.py +2049 -0
  84. mostlyright/data_harness/operation_registry.py +1007 -0
  85. mostlyright/data_harness/operator_setup.py +239 -0
  86. mostlyright/data_harness/pipeline.py +6428 -0
  87. mostlyright/data_harness/plan_graph.py +2026 -0
  88. mostlyright/data_harness/preparation/__init__.py +104 -0
  89. mostlyright/data_harness/preparation/contracts.py +1017 -0
  90. mostlyright/data_harness/preparation/engine.py +221 -0
  91. mostlyright/data_harness/preparation/errors.py +14 -0
  92. mostlyright/data_harness/preparation/gates.py +751 -0
  93. mostlyright/data_harness/preparation/joins.py +574 -0
  94. mostlyright/data_harness/preparation/profile.py +384 -0
  95. mostlyright/data_harness/preparation/table.py +217 -0
  96. mostlyright/data_harness/preparation/transforms.py +568 -0
  97. mostlyright/data_harness/progress_events.py +534 -0
  98. mostlyright/data_harness/readers/__init__.py +46 -0
  99. mostlyright/data_harness/readers/containers.py +963 -0
  100. mostlyright/data_harness/readers/contracts.py +542 -0
  101. mostlyright/data_harness/readers/delimited.py +257 -0
  102. mostlyright/data_harness/readers/grib2/__init__.py +33 -0
  103. mostlyright/data_harness/readers/grib2/admission.py +722 -0
  104. mostlyright/data_harness/readers/grib2/decode.py +1009 -0
  105. mostlyright/data_harness/readers/grib2/geometry.py +1133 -0
  106. mostlyright/data_harness/readers/grib2/portable_math.py +501 -0
  107. mostlyright/data_harness/readers/json_tabular.py +485 -0
  108. mostlyright/data_harness/readers/registry.py +514 -0
  109. mostlyright/data_harness/readers/samples/README.md +110 -0
  110. mostlyright/data_harness/readers/samples/archive.gzip/1.0.0/cities_one_stream/cities.csv.gz +0 -0
  111. mostlyright/data_harness/readers/samples/archive.gzip/1.0.0/cities_one_stream/expected.json +24 -0
  112. mostlyright/data_harness/readers/samples/archive.gzip/1.1.0/cities_one_stream/cities.csv.gz +0 -0
  113. mostlyright/data_harness/readers/samples/archive.gzip/1.1.0/cities_one_stream/expected.json +24 -0
  114. mostlyright/data_harness/readers/samples/archive.tar/1.0.0/cities_beside_a_directory_entry/cities.tar +0 -0
  115. mostlyright/data_harness/readers/samples/archive.tar/1.0.0/cities_beside_a_directory_entry/expected.json +24 -0
  116. mostlyright/data_harness/readers/samples/archive.tar/1.1.0/cities_beside_a_directory_entry/cities.tar +0 -0
  117. mostlyright/data_harness/readers/samples/archive.tar/1.1.0/cities_beside_a_directory_entry/expected.json +24 -0
  118. mostlyright/data_harness/readers/samples/archive.zip/1.0.0/cities_beside_a_second_member/cities.zip +0 -0
  119. mostlyright/data_harness/readers/samples/archive.zip/1.0.0/cities_beside_a_second_member/expected.json +25 -0
  120. mostlyright/data_harness/readers/samples/archive.zip/1.1.0/dwd_semicolon_station_member/dwd-station.zip +0 -0
  121. mostlyright/data_harness/readers/samples/archive.zip/1.1.0/dwd_semicolon_station_member/expected.json +25 -0
  122. mostlyright/data_harness/readers/samples/archive.zip/1.2.0/dwd_semicolon_station_member/dwd-station.zip +0 -0
  123. mostlyright/data_harness/readers/samples/archive.zip/1.2.0/dwd_semicolon_station_member/expected.json +25 -0
  124. mostlyright/data_harness/readers/samples/delimited_text/1.0.0/an_ordinary_comma_separated_table/cities.csv +3 -0
  125. mostlyright/data_harness/readers/samples/delimited_text/1.0.0/an_ordinary_comma_separated_table/expected.json +23 -0
  126. mostlyright/data_harness/readers/samples/delimited_text/1.0.0/quoted_fields_holding_the_delimiter/cities.tsv +5 -0
  127. mostlyright/data_harness/readers/samples/delimited_text/1.0.0/quoted_fields_holding_the_delimiter/expected.json +25 -0
  128. mostlyright/data_harness/readers/samples/delimited_text/1.1.0/an_hourly_observation_table_served_as_plain_text/expected.json +30 -0
  129. mostlyright/data_harness/readers/samples/delimited_text/1.1.0/an_hourly_observation_table_served_as_plain_text/observations.csv +5 -0
  130. mostlyright/data_harness/readers/samples/json.tabular/1.0.0/nested_hourly_observations/expected.json +44 -0
  131. mostlyright/data_harness/readers/samples/json.tabular/1.0.0/nested_hourly_observations/stations.json +1 -0
  132. mostlyright/data_harness/readers/samples/json.tabular/1.1.0/an_observation_stream_served_as_plain_text/expected.json +48 -0
  133. mostlyright/data_harness/readers/samples/json.tabular/1.1.0/an_observation_stream_served_as_plain_text/observations.ndjson +4 -0
  134. mostlyright/data_harness/readers/samples/spreadsheet.xlsx/1.0.0/an_ordinary_table_beside_a_second_sheet/cities.xlsx +0 -0
  135. mostlyright/data_harness/readers/samples/spreadsheet.xlsx/1.0.0/an_ordinary_table_beside_a_second_sheet/expected.json +24 -0
  136. mostlyright/data_harness/readers/samples/spreadsheet.xlsx/1.0.0/shares_the_workbook_had_already_computed/expected.json +27 -0
  137. mostlyright/data_harness/readers/samples/spreadsheet.xlsx/1.0.0/shares_the_workbook_had_already_computed/shares.xlsx +0 -0
  138. mostlyright/data_harness/readers/samples/spreadsheet.xlsx/1.1.0/shares_the_workbook_had_already_computed/expected.json +27 -0
  139. mostlyright/data_harness/readers/samples/spreadsheet.xlsx/1.1.0/shares_the_workbook_had_already_computed/shares.xlsx +0 -0
  140. mostlyright/data_harness/readers/samples/weather.grib2/1.0.0/README.md +20 -0
  141. mostlyright/data_harness/readers/samples/weather.grib2/1.0.0/gfs_2m_temperature/expected.json +55 -0
  142. mostlyright/data_harness/readers/samples/weather.grib2/1.0.0/gfs_2m_temperature/gfs-2m-temperature.grib2 +0 -0
  143. mostlyright/data_harness/readers/samples/weather.grib2/1.0.0/hrrr_2m_temperature/expected.json +54 -0
  144. mostlyright/data_harness/readers/samples/weather.grib2/1.0.0/hrrr_2m_temperature/hrrr-2m-temperature.grib2 +0 -0
  145. mostlyright/data_harness/readers/samples/weather.grib2/1.0.0/hrrr_categorical_rain/expected.json +54 -0
  146. mostlyright/data_harness/readers/samples/weather.grib2/1.0.0/hrrr_categorical_rain/hrrr-categorical-rain.grib2 +0 -0
  147. mostlyright/data_harness/readers/samples/weather.grib2/2.0.0/hrrr_2m_temperature/expected.json +54 -0
  148. mostlyright/data_harness/readers/samples/weather.grib2/2.0.0/hrrr_2m_temperature/hrrr-2m-temperature.grib2 +0 -0
  149. mostlyright/data_harness/readers/samples.py +582 -0
  150. mostlyright/data_harness/readers/spreadsheet.py +803 -0
  151. mostlyright/data_harness/readers/tabular.py +510 -0
  152. mostlyright/data_harness/recipe.py +5321 -0
  153. mostlyright/data_harness/repair/__init__.py +78 -0
  154. mostlyright/data_harness/repair/adapters.py +274 -0
  155. mostlyright/data_harness/repair/contracts.py +872 -0
  156. mostlyright/data_harness/repair/coordinator.py +1099 -0
  157. mostlyright/data_harness/repair/errors.py +16 -0
  158. mostlyright/data_harness/review.py +2533 -0
  159. mostlyright/data_harness/rowset.py +283 -0
  160. mostlyright/data_harness/serving.py +1975 -0
  161. mostlyright/data_harness/serving_edge.py +590 -0
  162. mostlyright/data_harness/serving_http.py +1031 -0
  163. mostlyright/data_harness/session_probes.py +759 -0
  164. mostlyright/data_harness/signing.py +101 -0
  165. mostlyright/data_harness/source_discovery.py +898 -0
  166. mostlyright/data_harness/sources/__init__.py +209 -0
  167. mostlyright/data_harness/sources/_adapter_steps.py +213 -0
  168. mostlyright/data_harness/sources/adapters.py +1214 -0
  169. mostlyright/data_harness/sources/cadence.py +1428 -0
  170. mostlyright/data_harness/sources/cadence_emission.py +453 -0
  171. mostlyright/data_harness/sources/cadence_history.py +546 -0
  172. mostlyright/data_harness/sources/catalog/__init__.py +17 -0
  173. mostlyright/data_harness/sources/catalog/admission.py +477 -0
  174. mostlyright/data_harness/sources/catalog/authoring.py +1701 -0
  175. mostlyright/data_harness/sources/catalog/authoring_policy.py +701 -0
  176. mostlyright/data_harness/sources/catalog/authoring_shards.py +1217 -0
  177. mostlyright/data_harness/sources/catalog/bounded_io.py +231 -0
  178. mostlyright/data_harness/sources/catalog/channel.py +523 -0
  179. mostlyright/data_harness/sources/catalog/channel_client.py +296 -0
  180. mostlyright/data_harness/sources/catalog/contracts.py +825 -0
  181. mostlyright/data_harness/sources/catalog/coverage.py +137 -0
  182. mostlyright/data_harness/sources/catalog/delta.py +1340 -0
  183. mostlyright/data_harness/sources/catalog/embedding.py +532 -0
  184. mostlyright/data_harness/sources/catalog/entry_v2.py +1182 -0
  185. mostlyright/data_harness/sources/catalog/fill.py +3889 -0
  186. mostlyright/data_harness/sources/catalog/fill_partitions.py +459 -0
  187. mostlyright/data_harness/sources/catalog/fill_staging.py +1105 -0
  188. mostlyright/data_harness/sources/catalog/gating.py +374 -0
  189. mostlyright/data_harness/sources/catalog/generation_receipt.py +1607 -0
  190. mostlyright/data_harness/sources/catalog/harvest/__init__.py +7 -0
  191. mostlyright/data_harness/sources/catalog/harvest/ckan.py +384 -0
  192. mostlyright/data_harness/sources/catalog/harvest/datagov_v4.py +798 -0
  193. mostlyright/data_harness/sources/catalog/harvest/protocol.py +964 -0
  194. mostlyright/data_harness/sources/catalog/harvest/sdmx.py +445 -0
  195. mostlyright/data_harness/sources/catalog/harvest/stac.py +384 -0
  196. mostlyright/data_harness/sources/catalog/health.py +447 -0
  197. mostlyright/data_harness/sources/catalog/hosted_catalog.py +105 -0
  198. mostlyright/data_harness/sources/catalog/identity_history.py +1549 -0
  199. mostlyright/data_harness/sources/catalog/neural.py +1618 -0
  200. mostlyright/data_harness/sources/catalog/packed_catalog.py +2345 -0
  201. mostlyright/data_harness/sources/catalog/packed_retrieval.py +1517 -0
  202. mostlyright/data_harness/sources/catalog/packed_writer.py +2802 -0
  203. mostlyright/data_harness/sources/catalog/query_trace.py +1037 -0
  204. mostlyright/data_harness/sources/catalog/recommend.py +171 -0
  205. mostlyright/data_harness/sources/catalog/retrieval.py +230 -0
  206. mostlyright/data_harness/sources/catalog/retrieval_manifest.py +995 -0
  207. mostlyright/data_harness/sources/catalog/rights_decisions.py +254 -0
  208. mostlyright/data_harness/sources/catalog/sealed.py +560 -0
  209. mostlyright/data_harness/sources/catalog/search.py +230 -0
  210. mostlyright/data_harness/sources/catalog/streaming_delta.py +1097 -0
  211. mostlyright/data_harness/sources/catalog/update.py +891 -0
  212. mostlyright/data_harness/sources/collections.py +815 -0
  213. mostlyright/data_harness/sources/contracts.py +2223 -0
  214. mostlyright/data_harness/sources/deletion.py +761 -0
  215. mostlyright/data_harness/sources/fitness.py +162 -0
  216. mostlyright/data_harness/sources/governance.py +163 -0
  217. mostlyright/data_harness/sources/hosted.py +173 -0
  218. mostlyright/data_harness/sources/integration.py +218 -0
  219. mostlyright/data_harness/sources/range_reader.py +418 -0
  220. mostlyright/data_harness/sources/registry.py +514 -0
  221. mostlyright/data_harness/sources/rights_rule.py +59 -0
  222. mostlyright/data_harness/sources/source_cadence_vectors.v1.json +1 -0
  223. mostlyright/data_harness/sources/sports.py +521 -0
  224. mostlyright/data_harness/sources/stream.py +524 -0
  225. mostlyright/data_harness/sources/stream_connector.py +418 -0
  226. mostlyright/data_harness/sources/stream_recorder.py +1404 -0
  227. mostlyright/data_harness/studio_boundary.py +2019 -0
  228. mostlyright/data_harness/thin/__init__.py +37 -0
  229. mostlyright/data_harness/thin/acquire.py +1137 -0
  230. mostlyright/data_harness/thin/acquire_cancel.py +579 -0
  231. mostlyright/data_harness/thin/approvals.py +617 -0
  232. mostlyright/data_harness/thin/commands.py +406 -0
  233. mostlyright/data_harness/thin/download.py +194 -0
  234. mostlyright/data_harness/thin/narrative.py +589 -0
  235. mostlyright/data_harness/thin/parity.py +1070 -0
  236. mostlyright/data_harness/thin/propose.py +2759 -0
  237. mostlyright/data_harness/thin/research.py +1663 -0
  238. mostlyright/data_harness/thin/router.py +924 -0
  239. mostlyright/data_harness/thin/runs.py +519 -0
  240. mostlyright/data_harness/thin/session.py +281 -0
  241. mostlyright/data_harness/thin/stream.py +501 -0
  242. mostlyright/data_harness/thin/transport.py +187 -0
  243. mostlyright/data_harness/thin/vocabulary.py +368 -0
  244. mostlyright/data_harness/thin/workers.py +164 -0
  245. mostlyright/data_harness/ucum/TABLE-PIN.json +40 -0
  246. mostlyright/data_harness/ucum/ucum-subset.v1.json +632 -0
  247. mostlyright/data_harness/unit_flow.py +927 -0
  248. mostlyright/data_harness/units.py +572 -0
  249. mostlyright/data_harness/ux/__init__.py +9 -0
  250. mostlyright/data_harness/ux/approve.py +485 -0
  251. mostlyright/data_harness/ux/author_yaml.py +597 -0
  252. mostlyright/data_harness/ux/cloud_auth.py +447 -0
  253. mostlyright/data_harness/ux/commands/__init__.py +260 -0
  254. mostlyright/data_harness/ux/commands/approve.py +136 -0
  255. mostlyright/data_harness/ux/commands/auth.py +744 -0
  256. mostlyright/data_harness/ux/commands/author.py +79 -0
  257. mostlyright/data_harness/ux/commands/catalog_author.py +403 -0
  258. mostlyright/data_harness/ux/commands/catalog_fill.py +523 -0
  259. mostlyright/data_harness/ux/commands/catalog_harvest.py +545 -0
  260. mostlyright/data_harness/ux/commands/catalog_publish.py +1838 -0
  261. mostlyright/data_harness/ux/commands/catalog_search.py +71 -0
  262. mostlyright/data_harness/ux/commands/catalog_update.py +437 -0
  263. mostlyright/data_harness/ux/commands/deploy.py +134 -0
  264. mostlyright/data_harness/ux/commands/deploy_dataset.py +98 -0
  265. mostlyright/data_harness/ux/commands/deploy_plan.py +105 -0
  266. mostlyright/data_harness/ux/commands/deploy_status.py +104 -0
  267. mostlyright/data_harness/ux/commands/diff.py +74 -0
  268. mostlyright/data_harness/ux/commands/index.py +84 -0
  269. mostlyright/data_harness/ux/commands/inventory.py +47 -0
  270. mostlyright/data_harness/ux/commands/list_builds.py +143 -0
  271. mostlyright/data_harness/ux/commands/login.py +63 -0
  272. mostlyright/data_harness/ux/commands/peek.py +236 -0
  273. mostlyright/data_harness/ux/commands/plan_check.py +90 -0
  274. mostlyright/data_harness/ux/commands/preflight.py +97 -0
  275. mostlyright/data_harness/ux/commands/record.py +107 -0
  276. mostlyright/data_harness/ux/commands/review_setup.py +47 -0
  277. mostlyright/data_harness/ux/commands/search.py +440 -0
  278. mostlyright/data_harness/ux/commands/show.py +61 -0
  279. mostlyright/data_harness/ux/commands/whoami.py +37 -0
  280. mostlyright/data_harness/ux/credential_native.py +551 -0
  281. mostlyright/data_harness/ux/credential_store.py +1055 -0
  282. mostlyright/data_harness/ux/credentials.py +631 -0
  283. mostlyright/data_harness/ux/diffing.py +444 -0
  284. mostlyright/data_harness/ux/headline.py +671 -0
  285. mostlyright/data_harness/ux/hosted_acquisition.py +974 -0
  286. mostlyright/data_harness/ux/hosted_run_status.py +619 -0
  287. mostlyright/data_harness/ux/inventory.py +427 -0
  288. mostlyright/data_harness/ux/local_review.py +375 -0
  289. mostlyright/data_harness/ux/login.py +691 -0
  290. mostlyright/data_harness/ux/path_kind.py +147 -0
  291. mostlyright/data_harness/ux/peek.py +1000 -0
  292. mostlyright/data_harness/ux/plain_file.py +178 -0
  293. mostlyright/data_harness/ux/plan_check.py +311 -0
  294. mostlyright/data_harness/ux/preflight.py +918 -0
  295. mostlyright/data_harness/ux/readers.py +1124 -0
  296. mostlyright/data_harness/ux/remediation.py +2195 -0
  297. mostlyright/data_harness/ux/render.py +657 -0
  298. mostlyright/data_harness/ux/workload.py +1077 -0
  299. mostlyright/data_harness/viewer.py +3713 -0
  300. mostlyright/data_harness/visual_run/__init__.py +83 -0
  301. mostlyright/data_harness/visual_run/authoring.py +235 -0
  302. mostlyright/data_harness/visual_run/contracts.py +673 -0
  303. mostlyright/data_harness/visual_run/materialize.py +486 -0
  304. mostlyright/data_harness/visual_run/observations.py +874 -0
  305. mostlyright/data_harness/visual_run/query.py +259 -0
  306. mostlyright/data_harness/visual_run/reducer.py +280 -0
  307. mostlyright/data_harness/visual_run/sdk.py +892 -0
  308. mostlyright/data_harness/visual_run/store.py +584 -0
  309. mostlyright/data_harness/visual_run/transport.py +239 -0
  310. mostlyright/data_harness/watch.py +2999 -0
  311. mostlyright_data-0.9.0.dist-info/METADATA +607 -0
  312. mostlyright_data-0.9.0.dist-info/RECORD +314 -0
  313. mostlyright_data-0.9.0.dist-info/WHEEL +4 -0
  314. mostlyright_data-0.9.0.dist-info/entry_points.txt +12 -0
@@ -0,0 +1,427 @@
1
+ """What this build can actually do, derived from the sets the code itself is held to.
2
+
3
+ Until now the only way to find out which cleaning steps exist, which types a cast may target, or
4
+ which engines this build has was to read the source. An agent driving this harness had no way at
5
+ all, so it guessed, and a guess about capability becomes a plan that cannot be built.
6
+
7
+ **Every list here is imported, never re-typed.** The frozensets below are the same objects the
8
+ contract checker measures a Recipe against. ``tests/test_ux_inventory.py`` asserts each rendered
9
+ list equals the sorted frozenset, so an inventory that has drifted from what the code does fails a
10
+ test rather than misleading somebody.
11
+
12
+ Three sentences in this file are the reason it is worth shipping at all, and each of them is a lie
13
+ the obvious version tells:
14
+
15
+ **Six operations.** Four cleaning steps a Recipe may name, plus joining and choosing which columns
16
+ to keep. The last two are operations in every sense that matters -- they are what an engine
17
+ restriction would key on -- and an inventory that prints only four undercounts what this build does.
18
+
19
+ **The restriction table is empty, and that is said out loud.** No operation is restricted on any
20
+ engine. Omitting the section would read as "unknown"; the answer is "none", and those are different
21
+ answers to the question an agent is asking.
22
+
23
+ **Five source formats, one sealed table format.** ``_DATA_FORMATS`` is the vocabulary a source
24
+ option may declare. The build path consumes canonical CSV directly or as normalized output from a
25
+ certified Reader. Printing five formats without that sentence beside them is the single most
26
+ likely way this command causes harm, so the two facts are in one section and a test holds them
27
+ there.
28
+
29
+ **Six column types, all executable.** Recipe declarations and local plan casts share one
30
+ authoritative vocabulary. ``timestamp_utc`` includes the timezone in the name because the Recipe
31
+ requires UTC; nothing here calls a naive timestamp UTC.
32
+
33
+ The checks are the ones the shipping build path records (``MIN_ROWS``, ``NOT_NULL_<column>``,
34
+ ``UNIQUE_GRAIN``), not ``repair.contracts.ALL_QUALITY_CHECK_IDS``. Those nine gates belong to a part
35
+ of the tree that is imported only by ``repair/`` and reachable from no command; a test asserts the
36
+ two sets do not overlap, and that inequality is the correct outcome rather than a bug.
37
+
38
+ Nothing here reads the filesystem, and nothing here prints. :meth:`Inventory.to_dict` returns the
39
+ one payload both renderings are built from.
40
+ """
41
+
42
+ from __future__ import annotations
43
+
44
+ from dataclasses import dataclass
45
+ from typing import Any
46
+
47
+ from mostlyright.data_harness.backends.restrictions import _ENGINE_RESTRICTED_OPS
48
+ from mostlyright.data_harness.local_contracts import (
49
+ _ACQUISITION_METHODS,
50
+ _CAST_TYPES,
51
+ _CLEANING_OPERATIONS,
52
+ _DATA_FORMATS,
53
+ _FEASIBILITY_DECISIONS,
54
+ _FITNESS_DECISIONS,
55
+ _JOIN_CARDINALITIES,
56
+ _LIVE_ENDPOINTS,
57
+ _LOCATOR_KINDS,
58
+ _OUTPUT_INTENTS,
59
+ _PERMISSIONS,
60
+ _PROPOSAL_RIGHTS,
61
+ _RIGHTS_STATUSES,
62
+ _TARGET_POLICIES,
63
+ )
64
+ from mostlyright.data_harness.operation_registry import (
65
+ OPERATION_REGISTRY,
66
+ RETIRED_OPERATIONS,
67
+ )
68
+ from mostlyright.data_harness.pipeline import _VERIFY_ALLOWLISTED_ENGINES
69
+ from mostlyright.data_harness.readers.registry import TOOLBOX
70
+ from mostlyright.data_harness.recipe import LOGICAL_TYPES
71
+ from mostlyright.data_harness.ux.render import render_human
72
+
73
+ # Every Recipe logical type is a target of the local plan's deterministic cast step. This text is
74
+ # derived from the compatibility alias so inventory cannot drift from plan validation.
75
+ _CASTABLE = ", ".join(sorted(_CAST_TYPES))
76
+
77
+ # The one status this command reports.
78
+ INVENTORY_STATUS = "inventory_listed"
79
+
80
+ # The sections, by the name a person reads and types after ``--section``. They are keys in the
81
+ # payload as well as values, because a section name is a name this command chose rather than one
82
+ # taken from the data, so relabelling it would not invent a name the data does not have.
83
+ CLEANING_STEPS = "cleaning steps"
84
+ COLUMN_TYPES = "column types"
85
+ JOINS = "joins"
86
+ ENGINES = "engines"
87
+ ENGINE_RESTRICTIONS = "engine restrictions"
88
+ CHECKS = "checks"
89
+ SOURCE_FORMATS = "source formats"
90
+ READERS = "Reader coordinates"
91
+ SOURCE_LOCATIONS = "source locations"
92
+ ARRIVAL = "how a source arrives"
93
+ RIGHTS_STATUSES = "rights statuses"
94
+ RIGHTS_CLAIMS = "rights claims"
95
+ RIGHTS_ALLOW = "what the rights allow"
96
+ BUILD_INTENT = "what a build is for"
97
+ SOURCE_FIT = "source fit"
98
+ ADDRESS_HEALTH = "address health"
99
+ TARGETS = "requirement targets"
100
+ FEASIBILITY = "feasibility"
101
+ DATASET_GRAPH = "dataset graph operations"
102
+
103
+ # The sentence the empty restriction table is reported with. A constant because a test pins it: the
104
+ # difference between this sentence and an absent section is the difference between "none" and
105
+ # "unknown".
106
+ NO_RESTRICTIONS = "no operation is restricted on any engine"
107
+
108
+ # The two operation identities that are not cleaning steps. Named here rather than counted from a
109
+ # plan, because this is the surface `backends/restrictions.py` keys on, and it says so in its own
110
+ # docstring: each cleaning step's operation name, plus joining and choosing columns.
111
+ _OPERATION_IDENTITIES = frozenset({"join", "select"})
112
+
113
+ # The checks the shipping build path records, in the order `pipeline._validate_output` records
114
+ # them. The middle one is written with its column placeholder because there is one per column that
115
+ # may not be empty, and a list of the columns of somebody else's Recipe would be no answer at all.
116
+ _SHIPPING_CHECKS: tuple[str, ...] = ("MIN_ROWS", "NOT_NULL_<column>", "UNIQUE_GRAIN")
117
+
118
+
119
+ @dataclass(frozen=True)
120
+ class InventorySection:
121
+ """One closed set, and the sentence a reader needs in order not to misread it.
122
+
123
+ ``note`` is never optional. A list of words with no sentence beside it is where an agent
124
+ invents capability: five source formats read as five readable formats unless something on the
125
+ same screen says otherwise.
126
+ """
127
+
128
+ name: str
129
+ names: tuple[str, ...]
130
+ note: str
131
+
132
+ def to_dict(self) -> dict[str, Any]:
133
+ return {"count": len(self.names), "names": list(self.names), "note": self.note}
134
+
135
+
136
+ @dataclass(frozen=True)
137
+ class Inventory:
138
+ """Every closed set this build is held to, in the order a person reads them."""
139
+
140
+ sections: tuple[InventorySection, ...]
141
+
142
+ def section(self, name: str) -> InventorySection:
143
+ for section in self.sections:
144
+ if section.name == name:
145
+ return section
146
+ raise KeyError(name)
147
+
148
+ def to_dict(self, *, section: str | None = None) -> dict[str, Any]:
149
+ """The one payload both renderings are built from, filtered to one section on request."""
150
+
151
+ chosen = self.sections if section is None else (self.section(section),)
152
+ return {
153
+ "status": INVENTORY_STATUS,
154
+ "sections": {item.name: item.to_dict() for item in chosen},
155
+ }
156
+
157
+ def lines(self, *, section: str | None = None) -> list[str]:
158
+ """Exactly the plain lines the command line prints, from exactly the same payload."""
159
+
160
+ return render_human(self.to_dict(section=section)).splitlines()
161
+
162
+
163
+ def _retired_sentence() -> str:
164
+ """Say which listed operations are retired, in the same words for however many there are.
165
+
166
+ Derived from the live table: a name that stops being retired stops being named here, and one
167
+ that starts being retired starts being named, without this sentence being edited.
168
+ """
169
+
170
+ retired = tuple(name for name in OPERATION_REGISTRY if name in RETIRED_OPERATIONS)
171
+ if not retired:
172
+ return "Every one of them may be named by a new plan."
173
+ if len(retired) == 1:
174
+ subject, pronoun = f"{retired[0]} is retired", "it"
175
+ else:
176
+ subject = f"{', '.join(retired[:-1])} and {retired[-1]} are retired"
177
+ pronoun = "one of them"
178
+ return (
179
+ f"{subject}: still executed when replaying a Build that was sealed with {pronoun}, and "
180
+ "refused in any newly authored plan. Every other one may be named by a new plan."
181
+ )
182
+
183
+
184
+ def build_inventory() -> Inventory:
185
+ """Read every closed set out of the live code and describe it.
186
+
187
+ Called fresh each time rather than computed once at import, so a test may put an entry in the
188
+ restriction table and see the sentence about it change.
189
+ """
190
+
191
+ return Inventory(
192
+ sections=(
193
+ InventorySection(
194
+ name=DATASET_GRAPH,
195
+ names=tuple(OPERATION_REGISTRY),
196
+ note=(
197
+ "The closed local-graph-table-plan.v1 graph operations executed by the shared "
198
+ "deterministic kernel; order is contract-significant and every node emits "
199
+ "sealed operation evidence. " + _retired_sentence()
200
+ # Read off the live table rather than written out, so a name cannot be
201
+ # retired in the registry and stay advertised as available here. This list
202
+ # is what an agent reads before proposing operations, so a retired name
203
+ # listed with no sentence beside it is exactly where one gets written into a
204
+ # new plan.
205
+ ),
206
+ ),
207
+ InventorySection(
208
+ name=CLEANING_STEPS,
209
+ names=tuple(sorted(set(_CLEANING_OPERATIONS) | set(_OPERATION_IDENTITIES))),
210
+ note=(
211
+ "There are six, and these are all of them: four steps a Recipe may name over "
212
+ "a column, plus joining two sources and choosing which columns to keep."
213
+ ),
214
+ ),
215
+ InventorySection(
216
+ name=COLUMN_TYPES,
217
+ names=tuple(sorted(LOGICAL_TYPES)),
218
+ note=(
219
+ "The types a column may be declared as. A value that will not hold exactly in "
220
+ "the type you asked for stops the build; it is never rounded or blanked. "
221
+ f"A cast step inside a plan may target every type: {_CASTABLE}. "
222
+ "timestamp_utc means "
223
+ "microseconds at UTC and nothing else -- a column at another offset, or with "
224
+ "no zone at all, is not that type."
225
+ ),
226
+ ),
227
+ InventorySection(
228
+ name=JOINS,
229
+ names=tuple(sorted(_JOIN_CARDINALITIES)),
230
+ note=(
231
+ "The relationship a Recipe declares between two sources. Every row on the "
232
+ "left must find its match, and one row in must give one row out."
233
+ ),
234
+ ),
235
+ InventorySection(
236
+ name=ENGINES,
237
+ names=tuple(sorted(_VERIFY_ALLOWLISTED_ENGINES)),
238
+ note=(
239
+ "Which engine does the work is chosen when you build, not written into a "
240
+ "Recipe. All three produce the same derived data members; execution evidence "
241
+ "records the chosen engine, so the complete Build digest intentionally "
242
+ "differs. The sealed known-good samples check that narrower data-byte parity."
243
+ ),
244
+ ),
245
+ _restriction_section(),
246
+ InventorySection(
247
+ name=CHECKS,
248
+ names=_SHIPPING_CHECKS,
249
+ note=(
250
+ "Every build must pass these before it is sealed: the fewest rows you will "
251
+ "accept, one check per column that may not be empty, and that no two rows "
252
+ "describe the same thing."
253
+ ),
254
+ ),
255
+ InventorySection(
256
+ name=SOURCE_FORMATS,
257
+ names=tuple(sorted(_DATA_FORMATS)),
258
+ note=(
259
+ "A source option may declare any of these five. The build consumes canonical "
260
+ "CSV directly or as normalized output from a certified Reader; the Reader "
261
+ "coordinates section is the executable source-format authority. Executable "
262
+ "support is limited to the certified Reader coordinates listed below."
263
+ ),
264
+ ),
265
+ InventorySection(
266
+ name=READERS,
267
+ names=tuple(f"{family_id}@{version}" for family_id, version in TOOLBOX.families()),
268
+ note=(
269
+ "These are certified Toolbox coordinates. On validated Ubuntu both the "
270
+ "stock user.file path and the generic public-HTTPS path route every "
271
+ "coordinate; coordinate-specific optional dependencies, settings, and "
272
+ "budgets still apply. Every other host reports typed Reader "
273
+ "unavailability, macOS included since ADR 0021, because it has no "
274
+ "enforceable Reader memory boundary."
275
+ ),
276
+ ),
277
+ InventorySection(
278
+ name=SOURCE_LOCATIONS,
279
+ names=tuple(sorted(_LOCATOR_KINDS)),
280
+ note=(
281
+ "Where a source option says its data is. This build reads a file at a path "
282
+ "under the input folder you name; the rest are what a source option may "
283
+ "declare."
284
+ ),
285
+ ),
286
+ InventorySection(
287
+ name=ARRIVAL,
288
+ names=tuple(sorted(_ACQUISITION_METHODS)),
289
+ note=(
290
+ "How the bytes reached your input folder. It is recorded with the Build and "
291
+ "sealed into its Receipt; adapter and Reader acquisition evidence is reported "
292
+ "separately when the public local-file Reader path is used."
293
+ ),
294
+ ),
295
+ InventorySection(
296
+ name=RIGHTS_STATUSES,
297
+ names=tuple(sorted(_RIGHTS_STATUSES)),
298
+ note=(
299
+ "What a Recipe records about its right to read one file. A build refuses "
300
+ "outright on unknown and on prohibited."
301
+ ),
302
+ ),
303
+ InventorySection(
304
+ name=RIGHTS_CLAIMS,
305
+ names=tuple(sorted(_PROPOSAL_RIGHTS)),
306
+ note=(
307
+ "What a source option claims about its own rights, before anything is built. "
308
+ "This is a claim being weighed, not the basis a build reads under."
309
+ ),
310
+ ),
311
+ InventorySection(
312
+ name=RIGHTS_ALLOW,
313
+ names=tuple(sorted(_PERMISSIONS)),
314
+ note=(
315
+ "What the recorded rights permit doing with the data: using it on your own "
316
+ "machine, passing it on, or running it as a live dataset."
317
+ ),
318
+ ),
319
+ InventorySection(
320
+ name=BUILD_INTENT,
321
+ names=tuple(sorted(_OUTPUT_INTENTS)),
322
+ note=(
323
+ "What a Recipe says its Build is for. It is checked against what every "
324
+ "source's rights allow, and the narrower of the two wins."
325
+ ),
326
+ ),
327
+ InventorySection(
328
+ name=SOURCE_FIT,
329
+ names=tuple(sorted(_FITNESS_DECISIONS)),
330
+ note=(
331
+ "Whether a source option was taken, kept as a fallback, or turned down. Only "
332
+ "a chosen one reaches a Recipe."
333
+ ),
334
+ ),
335
+ InventorySection(
336
+ name=ADDRESS_HEALTH,
337
+ names=tuple(sorted(_LIVE_ENDPOINTS)),
338
+ note=(
339
+ "What a source option records about the address it names. It is a recorded "
340
+ "observation, not something this build goes and re-checks for you."
341
+ ),
342
+ ),
343
+ InventorySection(
344
+ name=TARGETS,
345
+ names=tuple(sorted(_TARGET_POLICIES)),
346
+ note=(
347
+ "Whether a requirement's target has to be met once it turns out to be "
348
+ "reachable at all. A newly authored Recipe can only use none: the one "
349
+ "operation that ever built a target is retired, and asking for a target "
350
+ "that has to be met leaves a Recipe nothing to meet it with."
351
+ ),
352
+ ),
353
+ InventorySection(
354
+ name=FEASIBILITY,
355
+ names=tuple(sorted(_FEASIBILITY_DECISIONS)),
356
+ note=(
357
+ "The verdict recorded against the question itself, before any source is "
358
+ "chosen. A question recorded as unsupported is not built."
359
+ ),
360
+ ),
361
+ )
362
+ )
363
+
364
+
365
+ def _restriction_section() -> InventorySection:
366
+ """The per-operation, per-engine restriction table, whether it holds anything or not.
367
+
368
+ Today it holds nothing: every operation reaches the same bytes on all three engines, and the
369
+ sealed known-good samples are what establishes that. The sentence is derived from the table
370
+ rather than written under it, so the day an entry is added the section stops saying none.
371
+ """
372
+
373
+ if not _ENGINE_RESTRICTED_OPS:
374
+ return InventorySection(
375
+ name=ENGINE_RESTRICTIONS,
376
+ names=(),
377
+ note=(
378
+ f"There is a table of operations some engine may not run, and it is empty: "
379
+ f"{NO_RESTRICTIONS}. This section is printed empty on purpose, because a section "
380
+ f"that was left out would read as unknown and the answer is none."
381
+ ),
382
+ )
383
+ return InventorySection(
384
+ name=ENGINE_RESTRICTIONS,
385
+ names=tuple(
386
+ f"{operation}: not on {', '.join(sorted(engines))}"
387
+ for operation, engines in sorted(_ENGINE_RESTRICTED_OPS.items())
388
+ ),
389
+ note=(
390
+ "These operations cannot reach the same bytes on the engines named beside them, so "
391
+ "asking for that pairing is refused rather than built."
392
+ ),
393
+ )
394
+
395
+
396
+ # The sections that exist, derived from the inventory itself so the command line's list of what you
397
+ # may ask for cannot fall behind what there is to ask for.
398
+ SECTION_NAMES: tuple[str, ...] = tuple(section.name for section in build_inventory().sections)
399
+
400
+
401
+ __all__ = [
402
+ "ADDRESS_HEALTH",
403
+ "ARRIVAL",
404
+ "BUILD_INTENT",
405
+ "CHECKS",
406
+ "CLEANING_STEPS",
407
+ "COLUMN_TYPES",
408
+ "DATASET_GRAPH",
409
+ "ENGINES",
410
+ "ENGINE_RESTRICTIONS",
411
+ "FEASIBILITY",
412
+ "INVENTORY_STATUS",
413
+ "JOINS",
414
+ "NO_RESTRICTIONS",
415
+ "READERS",
416
+ "RIGHTS_ALLOW",
417
+ "RIGHTS_CLAIMS",
418
+ "RIGHTS_STATUSES",
419
+ "SECTION_NAMES",
420
+ "SOURCE_FIT",
421
+ "SOURCE_FORMATS",
422
+ "SOURCE_LOCATIONS",
423
+ "TARGETS",
424
+ "Inventory",
425
+ "InventorySection",
426
+ "build_inventory",
427
+ ]