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,400 @@
|
|
|
1
|
+
"""Group D · text outputs (D16, D17, D18, D23, D24): stdout, stderr, result, traceback, progress.
|
|
2
|
+
|
|
3
|
+
Routed to from ``document._render_output``. ANSI escapes are stripped via :func:`parse.strip_ansi`
|
|
4
|
+
and never honored — only its SGR-bold flag maps to weight 600 (D17/D23). Tracebacks are
|
|
5
|
+
re-tokenized here, not passed through: strip the ANSI, then color frames/arrows/source ourselves,
|
|
6
|
+
and collapse site-packages frames behind a static bar. Progress (D24) re-derives its fraction from
|
|
7
|
+
:func:`parse.detect_tqdm` over the output text. Every string that reaches HTML passes through
|
|
8
|
+
:func:`parse.esc`; no literal color is emitted here — all styling resolves to a rule in
|
|
9
|
+
``tokens.build_css``, including the three ``.nb-tb-*`` classes of the D23 source mini-theme.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import re
|
|
15
|
+
|
|
16
|
+
from mostlyright.data_harness.nbrender.parse import (
|
|
17
|
+
Output,
|
|
18
|
+
RenderContext,
|
|
19
|
+
detect_tqdm,
|
|
20
|
+
esc,
|
|
21
|
+
strip_ansi,
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
# Long-output trigger for the D24 scrolled box. The design fires at more than 8 lines or 96px;
|
|
25
|
+
# pixel height is not measurable at render time, so the logical line count carries the trigger.
|
|
26
|
+
_SCROLL_LINE_THRESHOLD = 8
|
|
27
|
+
|
|
28
|
+
# --- D23 traceback re-tokenizer ---------------------------------------------------------------
|
|
29
|
+
# Python keywords for the traceback source mini-theme. Hardcoded as data rather than importing the
|
|
30
|
+
# stdlib ``keyword`` module, which is outside the sanctioned stdlib subset.
|
|
31
|
+
_PY_KEYWORDS = frozenset(
|
|
32
|
+
{
|
|
33
|
+
"False",
|
|
34
|
+
"None",
|
|
35
|
+
"True",
|
|
36
|
+
"and",
|
|
37
|
+
"as",
|
|
38
|
+
"assert",
|
|
39
|
+
"async",
|
|
40
|
+
"await",
|
|
41
|
+
"break",
|
|
42
|
+
"class",
|
|
43
|
+
"continue",
|
|
44
|
+
"def",
|
|
45
|
+
"del",
|
|
46
|
+
"elif",
|
|
47
|
+
"else",
|
|
48
|
+
"except",
|
|
49
|
+
"finally",
|
|
50
|
+
"for",
|
|
51
|
+
"from",
|
|
52
|
+
"global",
|
|
53
|
+
"if",
|
|
54
|
+
"import",
|
|
55
|
+
"in",
|
|
56
|
+
"is",
|
|
57
|
+
"lambda",
|
|
58
|
+
"nonlocal",
|
|
59
|
+
"not",
|
|
60
|
+
"or",
|
|
61
|
+
"pass",
|
|
62
|
+
"raise",
|
|
63
|
+
"return",
|
|
64
|
+
"try",
|
|
65
|
+
"while",
|
|
66
|
+
"with",
|
|
67
|
+
"yield",
|
|
68
|
+
"match",
|
|
69
|
+
"case",
|
|
70
|
+
}
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
# One-physical-line source lexer. Traceback source arrives as individual dedented lines, which the
|
|
74
|
+
# stdlib ``tokenize`` module rejects; a regex lexer is robust to fragments. Only three token
|
|
75
|
+
# classes are colored (keyword / string / comment); everything else keeps the body color. The
|
|
76
|
+
# trailing ``any`` alternative guarantees every character is consumed (so an unterminated quote is
|
|
77
|
+
# never silently dropped).
|
|
78
|
+
_PY_TOK_RE = re.compile(
|
|
79
|
+
r"(?P<com>\#[^\n]*)"
|
|
80
|
+
r"|(?P<str>\"(?:\\.|[^\"\\\n])*\"|'(?:\\.|[^'\\\n])*')"
|
|
81
|
+
r"|(?P<word>[A-Za-z_][A-Za-z0-9_]*)"
|
|
82
|
+
r"|(?P<ws>\s+)"
|
|
83
|
+
r"|(?P<other>[^\sA-Za-z_\"'#]+)"
|
|
84
|
+
r"|(?P<any>.)"
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
# `----> 3 code` (current frame) and `--> 118 code` (nested) — arrow, line number, source.
|
|
88
|
+
_ARROW_RE = re.compile(r"^(?P<lead>\s*)(?P<arrow>-+>)(?P<sp>\s+)(?P<num>\d+)(?P<rest>.*)$")
|
|
89
|
+
# ` 118 code` — bare line-numbered source.
|
|
90
|
+
_NUM_RE = re.compile(r"^(?P<lead>\s*)(?P<num>\d+)(?P<rest>\s.*)?$")
|
|
91
|
+
# The ipython banner rule of dashes above the exception name.
|
|
92
|
+
_DASH_RE = re.compile(r"^\s*-{3,}\s*$")
|
|
93
|
+
# Frame location headers.
|
|
94
|
+
_LOC_RE = re.compile(r"^\s*(Cell|File|Input) ")
|
|
95
|
+
_TB_LABEL = "Traceback (most recent call last)"
|
|
96
|
+
_CARET = "▸" # ▸ · sanctioned B09 collapse glyph
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def _plural(count: int, word: str) -> str:
|
|
100
|
+
"""`3 frame` -> `3 frames`; `1 frame` -> `1 frame`. Terse, no locale handling."""
|
|
101
|
+
return f"{count} {word}" + ("s" if count != 1 else "")
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
# --- D16 · stdout -----------------------------------------------------------------------------
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def render_stdout(out: Output, ctx: RenderContext) -> str:
|
|
108
|
+
"""D16 · stdout stream — labeled well, pre-wrap; long runs scroll (D24 box).
|
|
109
|
+
|
|
110
|
+
Consecutive stdout merging is an upstream concern (one :class:`Output` per stream record
|
|
111
|
+
reaches here); this renders one well per record. ANSI is stripped, not honored — a stray SGR
|
|
112
|
+
escape never reaches the page as a control byte. Over :data:`_SCROLL_LINE_THRESHOLD` lines the
|
|
113
|
+
body moves into the D24 scrolled box with an "output scrolled" note.
|
|
114
|
+
"""
|
|
115
|
+
text = strip_ansi(out.text).text
|
|
116
|
+
label = '<div class="nb-out-label">stdout</div>'
|
|
117
|
+
lines = text.splitlines()
|
|
118
|
+
if len(lines) > _SCROLL_LINE_THRESHOLD:
|
|
119
|
+
hidden = len(lines) - _SCROLL_LINE_THRESHOLD
|
|
120
|
+
note = "output scrolled · " + _plural(hidden, "more line")
|
|
121
|
+
body = (
|
|
122
|
+
'<div class="nb-scrolled"><pre>' + esc(text) + "</pre></div>"
|
|
123
|
+
'<div class="nb-scrolled-note">' + esc(note) + "</div>"
|
|
124
|
+
)
|
|
125
|
+
else:
|
|
126
|
+
body = "<pre>" + esc(text) + "</pre>"
|
|
127
|
+
return '<div class="nb-well nb-stdout">' + label + body + "</div>"
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
# --- D17 · stderr / warnings ------------------------------------------------------------------
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def render_stderr(out: Output, ctx: RenderContext) -> str:
|
|
134
|
+
"""D17 · stderr / warnings — rust text; ANSI stripped, SGR bold maps to weight 600.
|
|
135
|
+
|
|
136
|
+
The dashed top separator that connects stderr to a preceding stdout well lives in the shared
|
|
137
|
+
``.nb-stderr`` rule. The dispatch signature carries no predecessor, so the separator renders on
|
|
138
|
+
every stderr well rather than only when it follows stdout. Per-span bold is not available from
|
|
139
|
+
the shared helper — a single bold flag bolds the whole block.
|
|
140
|
+
"""
|
|
141
|
+
stripped = strip_ansi(out.text)
|
|
142
|
+
content = esc(stripped.text)
|
|
143
|
+
if stripped.bold:
|
|
144
|
+
content = '<span class="nb-sgr-bold">' + content + "</span>"
|
|
145
|
+
return (
|
|
146
|
+
'<div class="nb-well nb-stderr">'
|
|
147
|
+
'<div class="nb-out-label">stderr</div>'
|
|
148
|
+
"<pre>" + content + "</pre>"
|
|
149
|
+
"</div>"
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
# --- D18 · execute_result (plain text) --------------------------------------------------------
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def render_result_text(out: Output, ctx: RenderContext) -> str:
|
|
157
|
+
"""D18 · execute_result plain text — bare pre, no well, in the Out[n] content column.
|
|
158
|
+
|
|
159
|
+
Faithful to the object repr: escaped, not ANSI-stripped, so a repr that legitimately contains
|
|
160
|
+
escape-like text is preserved verbatim.
|
|
161
|
+
"""
|
|
162
|
+
text = out.text_of("text/plain") or out.text
|
|
163
|
+
return '<pre class="nb-result-plain">' + esc(text) + "</pre>"
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
# --- D24 · progress ---------------------------------------------------------------------------
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def _fmt_pct(fraction: float) -> str:
|
|
170
|
+
"""Fraction (0..1) to a bare CSS percentage number, no trailing zero noise."""
|
|
171
|
+
return f"{fraction * 100:g}"
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def _indeterminate_label(text: str) -> str:
|
|
175
|
+
"""Best-effort description label from an indeterminate tqdm frame (`desc: |...`)."""
|
|
176
|
+
last = text.rsplit("\r", 1)[-1].strip()
|
|
177
|
+
match = re.match(r"\s*([^|:%]+?)\s*[:|]", last)
|
|
178
|
+
return match.group(1).strip() if match else ""
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def render_progress(out: Output, ctx: RenderContext) -> str:
|
|
182
|
+
"""D24 · progress — determinate tqdm track/fill/stat, else an indeterminate yellow bar.
|
|
183
|
+
|
|
184
|
+
``document`` routes here only when :func:`parse.detect_tqdm` matched (a determinate frame with
|
|
185
|
+
n/total); the indeterminate branch renders a fixed 30% yellow bar for direct callers. The
|
|
186
|
+
scrolled long-output box (also D24) is reached through :func:`render_stdout`, since long
|
|
187
|
+
non-tqdm stdout dispatches to D16, not here.
|
|
188
|
+
"""
|
|
189
|
+
text = out.text if out.text else out.text_of("text/plain")
|
|
190
|
+
prog = detect_tqdm(text)
|
|
191
|
+
if prog is not None:
|
|
192
|
+
width = _fmt_pct(prog.fraction)
|
|
193
|
+
return (
|
|
194
|
+
'<div class="nb-progress">'
|
|
195
|
+
'<span class="nb-progress-label">' + esc(prog.label) + "</span>"
|
|
196
|
+
'<div class="nb-progress-track">'
|
|
197
|
+
'<div class="nb-progress-fill" style="width: ' + width + '%"></div>'
|
|
198
|
+
"</div>"
|
|
199
|
+
'<span class="nb-progress-stat">' + esc(prog.stat) + "</span>"
|
|
200
|
+
"</div>"
|
|
201
|
+
)
|
|
202
|
+
label = _indeterminate_label(text)
|
|
203
|
+
return (
|
|
204
|
+
'<div class="nb-progress">'
|
|
205
|
+
'<span class="nb-progress-label">' + esc(label) + "</span>"
|
|
206
|
+
'<div class="nb-progress-track">'
|
|
207
|
+
'<div class="nb-progress-fill nb-progress-fill--indeterminate"></div>'
|
|
208
|
+
"</div>"
|
|
209
|
+
'<span class="nb-progress-stat"></span>'
|
|
210
|
+
"</div>"
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
# --- D23 · traceback --------------------------------------------------------------------------
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
def _tokenize_code(code: str) -> str:
|
|
218
|
+
"""Colorize one source fragment with the three-class traceback theme; escape every piece."""
|
|
219
|
+
parts: list[str] = []
|
|
220
|
+
for match in _PY_TOK_RE.finditer(code):
|
|
221
|
+
kind = match.lastgroup
|
|
222
|
+
value = match.group()
|
|
223
|
+
if kind == "com":
|
|
224
|
+
parts.append('<span class="nb-tb-com">' + esc(value) + "</span>")
|
|
225
|
+
elif kind == "str":
|
|
226
|
+
parts.append('<span class="nb-tb-str">' + esc(value) + "</span>")
|
|
227
|
+
elif kind == "word" and value in _PY_KEYWORDS:
|
|
228
|
+
parts.append('<span class="nb-tb-kw">' + esc(value) + "</span>")
|
|
229
|
+
else:
|
|
230
|
+
parts.append(esc(value))
|
|
231
|
+
return "".join(parts)
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
def _render_source_line(line: str) -> str:
|
|
235
|
+
"""Render a numbered (optionally arrowed) source line: arrow span + line number + tokens."""
|
|
236
|
+
match = _ARROW_RE.match(line)
|
|
237
|
+
if match:
|
|
238
|
+
return (
|
|
239
|
+
esc(match.group("lead"))
|
|
240
|
+
+ '<span class="nb-tb-arrow">'
|
|
241
|
+
+ esc(match.group("arrow"))
|
|
242
|
+
+ "</span>"
|
|
243
|
+
+ esc(match.group("sp"))
|
|
244
|
+
+ esc(match.group("num"))
|
|
245
|
+
+ _tokenize_code(match.group("rest"))
|
|
246
|
+
)
|
|
247
|
+
match = _NUM_RE.match(line)
|
|
248
|
+
if match:
|
|
249
|
+
return (
|
|
250
|
+
esc(match.group("lead"))
|
|
251
|
+
+ esc(match.group("num"))
|
|
252
|
+
+ _tokenize_code(match.group("rest") or "")
|
|
253
|
+
)
|
|
254
|
+
return _tokenize_code(line)
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
def _render_tb_line(line: str, is_final: bool) -> str:
|
|
258
|
+
"""One body line: final exception (weight 600), frame location, blank, or source."""
|
|
259
|
+
if is_final:
|
|
260
|
+
return '<span class="nb-tb-final">' + esc(line) + "</span>"
|
|
261
|
+
if line.strip() == "":
|
|
262
|
+
return ""
|
|
263
|
+
if _LOC_RE.match(line):
|
|
264
|
+
return '<span class="nb-tb-loc">' + esc(line) + "</span>"
|
|
265
|
+
return _render_source_line(line)
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
def _collapse_bar(count: int) -> str:
|
|
269
|
+
"""B09-style static bar standing in for a run of collapsed site-packages frames."""
|
|
270
|
+
return (
|
|
271
|
+
'<div class="nb-collapse">'
|
|
272
|
+
'<span class="nb-collapse-caret">'
|
|
273
|
+
+ _CARET
|
|
274
|
+
+ "</span>"
|
|
275
|
+
+ esc(_plural(count, "library frame"))
|
|
276
|
+
+ '<span class="nb-collapse-spacer"></span>'
|
|
277
|
+
"</div>"
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
def _trim_blank_edges(
|
|
282
|
+
payload: list[tuple[str, bool]],
|
|
283
|
+
) -> list[tuple[str, bool]]:
|
|
284
|
+
"""Drop leading/trailing blank non-final lines so a pre never renders empty edge rows."""
|
|
285
|
+
start, end = 0, len(payload)
|
|
286
|
+
while start < end and not payload[start][1] and payload[start][0].strip() == "":
|
|
287
|
+
start += 1
|
|
288
|
+
while end > start and not payload[end - 1][1] and payload[end - 1][0].strip() == "":
|
|
289
|
+
end -= 1
|
|
290
|
+
return payload[start:end]
|
|
291
|
+
|
|
292
|
+
|
|
293
|
+
def _render_tb_body(out: Output) -> str:
|
|
294
|
+
"""Re-tokenize the ANSI-laden traceback into user-frame pres and collapsed library-frame bars.
|
|
295
|
+
|
|
296
|
+
Steps: strip ANSI; drop the dashes banner and the "…Traceback (most recent call last)" header
|
|
297
|
+
(both hoisted into the header bar); split off the final exception line; group the rest into
|
|
298
|
+
frames by location header; render user frames as pre blocks and each run of site-packages
|
|
299
|
+
frames as a single B09 count bar; append the final exception line in weight 600.
|
|
300
|
+
"""
|
|
301
|
+
lines = [strip_ansi(raw).text for raw in (out.traceback or [])]
|
|
302
|
+
cleaned = [
|
|
303
|
+
line for line in lines if not _DASH_RE.match(line) and not line.rstrip().endswith(_TB_LABEL)
|
|
304
|
+
]
|
|
305
|
+
|
|
306
|
+
# Final exception line: prefer the model's ename/evalue; drop the matching trailing body line so
|
|
307
|
+
# it is not rendered twice. With no ename, fall back to the last non-empty body line.
|
|
308
|
+
final_text: str | None = None
|
|
309
|
+
if out.ename:
|
|
310
|
+
final_text = f"{out.ename}: {out.evalue}" if out.evalue else str(out.ename)
|
|
311
|
+
last_index = next((i for i in range(len(cleaned) - 1, -1, -1) if cleaned[i].strip()), None)
|
|
312
|
+
if last_index is not None:
|
|
313
|
+
if final_text is not None and cleaned[last_index].strip().startswith(str(out.ename)):
|
|
314
|
+
cleaned.pop(last_index)
|
|
315
|
+
elif final_text is None:
|
|
316
|
+
final_text = cleaned[last_index].strip()
|
|
317
|
+
cleaned.pop(last_index)
|
|
318
|
+
|
|
319
|
+
# Group into frames by location header; lines before the first header are preamble.
|
|
320
|
+
frames: list[tuple[bool, list[str]]] = []
|
|
321
|
+
preamble: list[str] = []
|
|
322
|
+
current: tuple[bool, list[str]] | None = None
|
|
323
|
+
for line in cleaned:
|
|
324
|
+
if _LOC_RE.match(line):
|
|
325
|
+
if current is not None:
|
|
326
|
+
frames.append(current)
|
|
327
|
+
is_lib = "site-packages" in line or "dist-packages" in line
|
|
328
|
+
current = (is_lib, [line])
|
|
329
|
+
elif current is None:
|
|
330
|
+
preamble.append(line)
|
|
331
|
+
else:
|
|
332
|
+
current[1].append(line)
|
|
333
|
+
if current is not None:
|
|
334
|
+
frames.append(current)
|
|
335
|
+
|
|
336
|
+
# Ordered render blocks: shown ('pre') vs collapsed library run ('lib').
|
|
337
|
+
blocks: list[list] = []
|
|
338
|
+
|
|
339
|
+
def push_lines(more: list[str]) -> None:
|
|
340
|
+
entries = [(line, False) for line in more]
|
|
341
|
+
if blocks and blocks[-1][0] == "pre":
|
|
342
|
+
blocks[-1][1].extend(entries)
|
|
343
|
+
else:
|
|
344
|
+
blocks.append(["pre", entries])
|
|
345
|
+
|
|
346
|
+
def push_lib() -> None:
|
|
347
|
+
if blocks and blocks[-1][0] == "lib":
|
|
348
|
+
blocks[-1][1] += 1
|
|
349
|
+
else:
|
|
350
|
+
blocks.append(["lib", 1])
|
|
351
|
+
|
|
352
|
+
if preamble:
|
|
353
|
+
push_lines(preamble)
|
|
354
|
+
for is_lib, frame_lines in frames:
|
|
355
|
+
if is_lib:
|
|
356
|
+
push_lib()
|
|
357
|
+
else:
|
|
358
|
+
push_lines(frame_lines)
|
|
359
|
+
|
|
360
|
+
if final_text is not None:
|
|
361
|
+
if blocks and blocks[-1][0] == "pre":
|
|
362
|
+
blocks[-1][1].append((final_text, True))
|
|
363
|
+
else:
|
|
364
|
+
blocks.append(["pre", [(final_text, True)]])
|
|
365
|
+
|
|
366
|
+
parts: list[str] = []
|
|
367
|
+
for kind, payload in blocks:
|
|
368
|
+
if kind == "lib":
|
|
369
|
+
parts.append(_collapse_bar(payload))
|
|
370
|
+
continue
|
|
371
|
+
trimmed = _trim_blank_edges(payload)
|
|
372
|
+
if not trimmed:
|
|
373
|
+
continue
|
|
374
|
+
rendered = "\n".join(_render_tb_line(line, is_final) for line, is_final in trimmed)
|
|
375
|
+
parts.append('<pre class="nb-tb-body">' + rendered + "</pre>")
|
|
376
|
+
|
|
377
|
+
if not parts:
|
|
378
|
+
fallback = final_text or (str(out.evalue) if out.evalue else "")
|
|
379
|
+
parts.append(
|
|
380
|
+
'<pre class="nb-tb-body"><span class="nb-tb-final">' + esc(fallback) + "</span></pre>"
|
|
381
|
+
)
|
|
382
|
+
return "".join(parts)
|
|
383
|
+
|
|
384
|
+
|
|
385
|
+
def render_traceback(out: Output, ctx: RenderContext) -> str:
|
|
386
|
+
"""D23 · traceback — native error output, re-tokenized body, library frames collapsed.
|
|
387
|
+
|
|
388
|
+
The exception name and the "Traceback (most recent call last)" caption are hoisted into the
|
|
389
|
+
header bar; the body carries frames, arrows, source, and the final exception line. ``role`` is
|
|
390
|
+
``alert`` only in connected mode, where the error is new; a static export is silent.
|
|
391
|
+
"""
|
|
392
|
+
head_name = esc(out.ename) if out.ename else "Traceback"
|
|
393
|
+
head = (
|
|
394
|
+
'<div class="nb-tb-head">'
|
|
395
|
+
'<span class="nb-tb-name">' + head_name + "</span>"
|
|
396
|
+
'<span class="nb-tb-label">' + esc(_TB_LABEL) + "</span>"
|
|
397
|
+
"</div>"
|
|
398
|
+
)
|
|
399
|
+
role = ' role="alert"' if ctx.mode == "connected" else ""
|
|
400
|
+
return '<div class="nb-tb"' + role + ">" + head + _render_tb_body(out) + "</div>"
|