gea-program 0.30.0__tar.gz → 0.31.0__tar.gz
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.
- {gea_program-0.30.0/gea_program.egg-info → gea_program-0.31.0}/PKG-INFO +30 -6
- {gea_program-0.30.0 → gea_program-0.31.0}/README.md +29 -5
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/__init__.py +1 -1
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/__main__.py +76 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/acceptance_tests.py +188 -3
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/edr.py +370 -82
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/help/edr.md +4 -2
- gea_program-0.31.0/gea/help/tools.md +11 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/helplib.py +1 -1
- gea_program-0.31.0/gea/reference/tool_sources.json +3046 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/service.py +31 -0
- gea_program-0.31.0/gea/tool_taxonomy.py +905 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/web/app.html +105 -2
- {gea_program-0.30.0 → gea_program-0.31.0/gea_program.egg-info}/PKG-INFO +30 -6
- {gea_program-0.30.0 → gea_program-0.31.0}/gea_program.egg-info/SOURCES.txt +2 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/pyproject.toml +1 -1
- gea_program-0.30.0/gea/help/tools.md +0 -11
- {gea_program-0.30.0 → gea_program-0.31.0}/LICENSE +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/BENCH_TEST_PROTOCOL.md +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/accuracy_statement.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/alarm_engine.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/backup.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/bench.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/blind_harness.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/acex_lomonosov_age_depth_model.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/acex_lomonosov_age_depth_model.txt +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/agassiz77_canada_temperature.csv +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/agassiz77_canada_temperature.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/barbados_110_consolidation.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/barbados_110_consolidation.txt +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/bengal_u1452_grain_size.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/bengal_u1452_grain_size.txt +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/blake_164_methane_isotopes.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/blake_164_methane_isotopes.txt +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/chicxulub_m0077a_pwave_velocity.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/chicxulub_m0077a_pwave_velocity.txt +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/collingwood_1_28_ks_complete.las +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/collingwood_1_28_ks_complete.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/costa_rica_odp_friction_envelope.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/costa_rica_odp_friction_envelope.txt +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/dead_sea_5017_debrite_xrf_ms.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/dead_sea_5017_debrite_xrf_ms.txt +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/dsdp_504b_physical_properties.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/dsdp_504b_physical_properties.txt +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/dsdp_504b_sound_velocity.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/dsdp_504b_sound_velocity.txt +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/elgygytgyn_5011_turbidites.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/elgygytgyn_5011_turbidites.txt +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/epica_domec_co2_800kyr.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/epica_domec_co2_800kyr.txt +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/fram_909_organic_petrography.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/fram_909_organic_petrography.txt +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/gbr_325_coral_uth_ages.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/gbr_325_coral_uth_ages.txt +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/gisp2_greenland_temperature.csv +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/gisp2_greenland_temperature.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/gom_308_t2p_insitu.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/gom_308_t2p_insitu.txt +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/guaymas_385_dom_d13c.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/guaymas_385_dom_d13c.txt +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/hikurangi_u1520_friction_insitu.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/hikurangi_u1520_friction_insitu.txt +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/hydrate_ridge_204_ncr_hydrate.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/hydrate_ridge_204_ncr_hydrate.txt +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/iodp_u1324_pore_pressure.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/iodp_u1324_pore_pressure.txt +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/jfast_c0019_slow_slip_events.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/jfast_c0019_slow_slip_events.txt +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/kennetcook_2_p129_excerpt.las +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/kennetcook_2_p129_excerpt.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/ktb_hb_bhgm_density.dat +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/ktb_hb_bhgm_density.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/ktb_hb_complog_6020_excerpt.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/ktb_hb_complog_6020_excerpt.txt +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/ktb_hb_hlog246_temperature.dat +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/ktb_hb_hlog246_temperature.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/ktb_hb_rockmech_compress.dat +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/ktb_hb_rockmech_compress.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/ktb_hb_tvd_0_9080_excerpt.dat +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/ktb_hb_tvd_0_9080_excerpt.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/ktb_vb_rockmech_compress.dat +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/ktb_vb_rockmech_compress.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/ktb_vb_vlog251_temperature.dat +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/ktb_vb_vlog251_temperature.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/l06_06_nl_survey.csv +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/l06_06_nl_survey.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/l07_01_nl_excerpt.las +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/l07_01_nl_excerpt.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/mariana_1200_serpentinite_geochem.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/mariana_1200_serpentinite_geochem.txt +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/med_160_sapropels.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/med_160_sapropels.txt +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/nankai_megasplay_shear_strength.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/nankai_megasplay_shear_strength.txt +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/odp_1027b_thermal_conductivity.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/odp_1027b_thermal_conductivity.txt +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/odp_1027c_cork_temperature.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/odp_1027c_cork_temperature.txt +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/odp_1165b_thermal_conductivity.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/odp_1165b_thermal_conductivity.txt +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/odp_1274a_mantle_peridotite_mad.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/odp_1274a_mantle_peridotite_mad.txt +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/odp_504b_dike_elastic_moduli.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/odp_504b_dike_elastic_moduli.txt +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/odp_504b_leg137_borehole_fluids.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/odp_504b_leg137_borehole_fluids.txt +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/odp_735b_gabbro_elastic_moduli.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/odp_735b_gabbro_elastic_moduli.txt +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/peru_201_sulfate_reduction.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/peru_201_sulfate_reduction.txt +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/scorpio_e1_sa_excerpt.las +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/scorpio_e1_sa_excerpt.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/sumatra_362_cohesion.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/sumatra_362_cohesion.txt +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/university_6_17_no1_tx_excerpt.las +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/university_6_17_no1_tx_excerpt.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/ursa_308_xrd_mineralogy.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/ursa_308_xrd_mineralogy.txt +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/volve_15_9_19_sr_excerpt.las +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/volve_15_9_19_sr_excerpt.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/volve_15_9_19a_core_excerpt.csv +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/volve_15_9_19a_core_excerpt.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/volve_f12_f14_production_excerpt.csv +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/volve_f12_f14_production_excerpt.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/walvis_208_petm_carbonate.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/walvis_208_petm_carbonate.txt +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/woodlark_1109_rock_eval.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog/woodlark_1109_rock_eval.txt +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog_map.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/catalog_register.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/certificates.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/cli.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/client_reports.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/config_versioning.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/conformance.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/correlation.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/dashboard.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/deviation.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/dlis.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/dnp3.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/doctor.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/downhole_engine.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/drift_monitor.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/earth_model.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/elevation.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/etp.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/etp12_schemas.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/example_register_map.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/fat_sat.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/files.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/fixtures/README.md +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/fixtures/comcat_delaware_basin_2026-09.txt +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/fixtures/comcat_youngstown_2011-2012.txt +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/fixtures/ne_110m_coastline.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/follower.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/forward_model.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/friction_priors.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/gamma.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/gauge_aging.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/gauge_specs.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/geodesy.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/gravity_reference.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/hartip.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/help/TESTER_GUIDE.md +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/help/alarms.md +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/help/audit-update.md +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/help/backup.md +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/help/catalog.md +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/help/conformance.md +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/help/data-in.md +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/help/dlis.md +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/help/doctor.md +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/help/drift.md +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/help/etp.md +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/help/field-ports.md +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/help/files.md +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/help/historian.md +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/help/instruments.md +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/help/interval.md +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/help/month-end.md +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/help/notifications.md +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/help/osdu.md +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/help/patches.md +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/help/ppdm.md +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/help/quakeml.md +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/help/quality.md +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/help/seedlink.md +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/help/seismic.md +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/help/site.md +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/help/sites.md +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/help/slip.md +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/help/soak.md +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/help/sra.md +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/help/start.md +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/help/structure.md +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/help/transients.md +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/help/upkeep.md +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/help/vibration.md +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/help/well-tests.md +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/housekeeping.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/interval.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/inverse_engine.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/jobs.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/live_ports.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/loadtest.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/matplotlib_demo.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/modbus.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/modbus_rtu.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/model_card.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/month_end.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/mqtt_port.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/notify.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/opcua_port.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/operator_app.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/osdu.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/patches.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/permits.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/piwebapi.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/ports.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/ppdm.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/profile_catalog.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/project.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/qt6_downhole_app.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/quakeml.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/reconciler.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/reference/IU_ANMO_10_BHZ_response.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/reference/IU_ANMO_10_BHZ_response.xml +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/reference/libmseed_steim.provenance.json +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/reference/libmseed_steim1_4096.mseed +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/reference/libmseed_steim2_4096.mseed +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/reference/libmseed_steim2_512.mseed +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/rock_inventory.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/sample_record.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/sample_well_profile.csv +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/sbom.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/seedlink.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/segy.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/seismic.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/seismic_array.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/seismic_assoc.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/seismic_detect.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/seismic_film.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/seismic_harmonic.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/seismic_qc.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/seismic_response.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/seismic_signature.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/seismic_track.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/seismic_uncertainty.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/seismic_unlisted.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/sensor_swap.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/service_life.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/shapefile.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/shell.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/shut_in.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/sla_report.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/slip.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/soak.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/sra.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/store_forward.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/strata_join.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/structure.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/supervisor.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/survey_cmd.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/survey_view.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/telemetry.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/tool_catalog.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/tool_library.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/transient.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/vibration.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/well_assembler.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/well_test_validation.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/wits0.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/witsml.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea/workspace.py +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea_program.egg-info/dependency_links.txt +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea_program.egg-info/entry_points.txt +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea_program.egg-info/requires.txt +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/gea_program.egg-info/top_level.txt +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/setup.cfg +0 -0
- {gea_program-0.30.0 → gea_program-0.31.0}/tests/test_acceptance.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gea-program
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.31.0
|
|
4
4
|
Summary: GEA-Program: downhole gauge monitoring - canonical measurement records, quality rules, drift evaluation with a re-fit change log, well-test validation, alarm management, model cards, store-and-forward, monthly SLA measurement, FAT/SAT protocols and a dashboard, generated from live objects in the client's reporting outline.
|
|
5
5
|
Author: Daniel T. Murphy
|
|
6
6
|
License: MPL-2.0
|
|
@@ -125,7 +125,7 @@ gea dashboard --catalog-well volve_f12_f14_production_excerpt:15/9-F-12:10000 --
|
|
|
125
125
|
gea client-report --report accuracy --out client_report
|
|
126
126
|
gea model-cards --out model_cards
|
|
127
127
|
gea sbom --out sbom
|
|
128
|
-
gea accept # the product gate (
|
|
128
|
+
gea accept # the product gate (380 checks)
|
|
129
129
|
gea help drift # the help library, by the job (16 pages; the same text is on every dashboard page)
|
|
130
130
|
gea guide # the click-by-click tester guide (docs/TESTER_GUIDE.md)
|
|
131
131
|
gea gui # the desktop window (pip install "gea-program[desktop]")
|
|
@@ -650,8 +650,26 @@ itself; `gea help seedlink`. A TexNet station is served by EarthScope at
|
|
|
650
650
|
|
|
651
651
|
### Tools and ports
|
|
652
652
|
|
|
653
|
-
The Tools & ports tab (`#/tools`, `gea tools`)
|
|
654
|
-
|
|
653
|
+
The Tools & ports tab (`#/tools`, `gea tools`) opens on the **downhole tool
|
|
654
|
+
library**: every class of downhole tool in use across the industry - bits
|
|
655
|
+
and hole openers, motors and rotary steerable systems, MWD and LWD, the drill
|
|
656
|
+
string and its subs, casing and cementing equipment, completion and
|
|
657
|
+
artificial lift, wireline and cased-hole tools, fishing and milling, test
|
|
658
|
+
tools - ninety-six classes in nine categories. Point at a tool, or Tab to
|
|
659
|
+
it, for a one-line description; click, tap or press Enter for its tutorial:
|
|
660
|
+
what it is, where it runs, how it works, what it shows in the data, what to
|
|
661
|
+
watch, and what this program does with it, with the published figures
|
|
662
|
+
quoted from the pages they cite and the pages themselves. The tutorials
|
|
663
|
+
carry no numbers of their own; a figure on a tool's card is the cited page's
|
|
664
|
+
words, most often one maker's product, never a limit for the class. Your
|
|
665
|
+
**fleet** - the tools you actually run - goes in beside the classes, each
|
|
666
|
+
with its maker, model, serial and the datasheet that rates it
|
|
667
|
+
(`gea tools --action fleet-add --workspace C:\site --class pdm_motor
|
|
668
|
+
--maker ... --model ... --datasheet ...`, or from the tutorial), kept in the
|
|
669
|
+
workspace and audited. `gea tools --action classes`, `--action tutorial
|
|
670
|
+
--class drilling_jar`.
|
|
671
|
+
|
|
672
|
+
Below it are the program's two registers: the gauge library - every gauge
|
|
655
673
|
with its source citation, ratings, what it measures, the telemetry interface
|
|
656
674
|
it declares and its datasheet aging rate where the vendor published one -
|
|
657
675
|
and the ports, the file formats read and the eleven live protocols spoken,
|
|
@@ -730,8 +748,14 @@ on bottom and rotating, the rate of penetration on bottom, the connections,
|
|
|
730
748
|
the peaks; for the well, total depth and when the bit was first on bottom
|
|
731
749
|
there, the recorder's TVD at it; per channel what was missing and how
|
|
732
750
|
often; and the **MD-TVD table**, hole depth against the recorder's
|
|
733
|
-
interpolated TVD, labelled an interpolation and not a survey.
|
|
734
|
-
|
|
751
|
+
interpolated TVD, labelled an interpolation and not a survey. Before any
|
|
752
|
+
footage is counted the hole depth is read for what it can be trusted for:
|
|
753
|
+
a depth carried over from the last well, a depth set back and counted up
|
|
754
|
+
again by running pipe, a sidetrack, an overstated or understated depth
|
|
755
|
+
corrected - each named as a depth event in the record and on the well
|
|
756
|
+
page, and handled so that total depth is the final borehole's and the
|
|
757
|
+
footage adds up. The recorder's gamma is written as a LAS log by bit
|
|
758
|
+
depth. `gea edr
|
|
735
759
|
--file C:\site\_incoming\30636033.csv`; `gea workspace --action add-file`
|
|
736
760
|
then `refresh` for the record beside the well's other reports. `gea help
|
|
737
761
|
edr`.
|
|
@@ -86,7 +86,7 @@ gea dashboard --catalog-well volve_f12_f14_production_excerpt:15/9-F-12:10000 --
|
|
|
86
86
|
gea client-report --report accuracy --out client_report
|
|
87
87
|
gea model-cards --out model_cards
|
|
88
88
|
gea sbom --out sbom
|
|
89
|
-
gea accept # the product gate (
|
|
89
|
+
gea accept # the product gate (380 checks)
|
|
90
90
|
gea help drift # the help library, by the job (16 pages; the same text is on every dashboard page)
|
|
91
91
|
gea guide # the click-by-click tester guide (docs/TESTER_GUIDE.md)
|
|
92
92
|
gea gui # the desktop window (pip install "gea-program[desktop]")
|
|
@@ -611,8 +611,26 @@ itself; `gea help seedlink`. A TexNet station is served by EarthScope at
|
|
|
611
611
|
|
|
612
612
|
### Tools and ports
|
|
613
613
|
|
|
614
|
-
The Tools & ports tab (`#/tools`, `gea tools`)
|
|
615
|
-
|
|
614
|
+
The Tools & ports tab (`#/tools`, `gea tools`) opens on the **downhole tool
|
|
615
|
+
library**: every class of downhole tool in use across the industry - bits
|
|
616
|
+
and hole openers, motors and rotary steerable systems, MWD and LWD, the drill
|
|
617
|
+
string and its subs, casing and cementing equipment, completion and
|
|
618
|
+
artificial lift, wireline and cased-hole tools, fishing and milling, test
|
|
619
|
+
tools - ninety-six classes in nine categories. Point at a tool, or Tab to
|
|
620
|
+
it, for a one-line description; click, tap or press Enter for its tutorial:
|
|
621
|
+
what it is, where it runs, how it works, what it shows in the data, what to
|
|
622
|
+
watch, and what this program does with it, with the published figures
|
|
623
|
+
quoted from the pages they cite and the pages themselves. The tutorials
|
|
624
|
+
carry no numbers of their own; a figure on a tool's card is the cited page's
|
|
625
|
+
words, most often one maker's product, never a limit for the class. Your
|
|
626
|
+
**fleet** - the tools you actually run - goes in beside the classes, each
|
|
627
|
+
with its maker, model, serial and the datasheet that rates it
|
|
628
|
+
(`gea tools --action fleet-add --workspace C:\site --class pdm_motor
|
|
629
|
+
--maker ... --model ... --datasheet ...`, or from the tutorial), kept in the
|
|
630
|
+
workspace and audited. `gea tools --action classes`, `--action tutorial
|
|
631
|
+
--class drilling_jar`.
|
|
632
|
+
|
|
633
|
+
Below it are the program's two registers: the gauge library - every gauge
|
|
616
634
|
with its source citation, ratings, what it measures, the telemetry interface
|
|
617
635
|
it declares and its datasheet aging rate where the vendor published one -
|
|
618
636
|
and the ports, the file formats read and the eleven live protocols spoken,
|
|
@@ -691,8 +709,14 @@ on bottom and rotating, the rate of penetration on bottom, the connections,
|
|
|
691
709
|
the peaks; for the well, total depth and when the bit was first on bottom
|
|
692
710
|
there, the recorder's TVD at it; per channel what was missing and how
|
|
693
711
|
often; and the **MD-TVD table**, hole depth against the recorder's
|
|
694
|
-
interpolated TVD, labelled an interpolation and not a survey.
|
|
695
|
-
|
|
712
|
+
interpolated TVD, labelled an interpolation and not a survey. Before any
|
|
713
|
+
footage is counted the hole depth is read for what it can be trusted for:
|
|
714
|
+
a depth carried over from the last well, a depth set back and counted up
|
|
715
|
+
again by running pipe, a sidetrack, an overstated or understated depth
|
|
716
|
+
corrected - each named as a depth event in the record and on the well
|
|
717
|
+
page, and handled so that total depth is the final borehole's and the
|
|
718
|
+
footage adds up. The recorder's gamma is written as a LAS log by bit
|
|
719
|
+
depth. `gea edr
|
|
696
720
|
--file C:\site\_incoming\30636033.csv`; `gea workspace --action add-file`
|
|
697
721
|
then `refresh` for the record beside the well's other reports. `gea help
|
|
698
722
|
edr`.
|
|
@@ -285,6 +285,17 @@ def main(argv=None) -> int:
|
|
|
285
285
|
p_tl.add_argument("--station", type=str, action="append", default=None, help="a station as DEPTH_FT:TOOL, e.g. 9850:quartz_pt_geoq177_16k")
|
|
286
286
|
p_tl.add_argument("--surface-temp-f", type=float, default=75.0); p_tl.add_argument("--temp-gradient-f-ft", type=float, default=0.018)
|
|
287
287
|
p_tl.add_argument("--surface-pressure-psi", type=float, default=14.7); p_tl.add_argument("--pressure-gradient-psi-ft", type=float, default=0.465)
|
|
288
|
+
p_tl.add_argument("--action", choices=["classes", "tutorial", "fleet", "fleet-add", "fleet-remove"], default=None,
|
|
289
|
+
help="the downhole tool classes in use across the industry: classes (--category, --find), tutorial --class ID, and the workspace's own fleet (fleet, fleet-add, fleet-remove)")
|
|
290
|
+
p_tl.add_argument("--category", type=str, default=None, help="classes: one category (bits, drive, measure, bha, casing, completion, logging, fishing, testing)")
|
|
291
|
+
p_tl.add_argument("--find", type=str, default="", help="classes: words to look for in the name and description")
|
|
292
|
+
p_tl.add_argument("--class", dest="class_id", type=str, default=None, help="tutorial / fleet-add: the tool class id, e.g. pdm_motor")
|
|
293
|
+
p_tl.add_argument("--workspace", type=str, default=None, help="fleet actions: the workspace folder")
|
|
294
|
+
p_tl.add_argument("--maker", type=str, default=""); p_tl.add_argument("--model", type=str, default="")
|
|
295
|
+
p_tl.add_argument("--datasheet", type=str, default="", help="fleet-add: the datasheet that rates the tool - title and revision, or its URL (required)")
|
|
296
|
+
p_tl.add_argument("--serial", type=str, default=""); p_tl.add_argument("--od-in", type=float, default=None); p_tl.add_argument("--note", type=str, default="")
|
|
297
|
+
p_tl.add_argument("--id", type=str, default=None, help="fleet-remove: the fleet tool id (gea tools --action fleet lists them)")
|
|
298
|
+
p_tl.add_argument("--actor", type=str, default="cli")
|
|
288
299
|
p_cc = sub.add_parser("comcat", help="USGS ComCat / any FDSN event service: --lat --lon --radius-km --start --end prints the text-format query to open; --file reads the export it returns")
|
|
289
300
|
p_cc.add_argument("--lat", type=float, default=None); p_cc.add_argument("--lon", type=float, default=None); p_cc.add_argument("--radius-km", type=float, default=25.0)
|
|
290
301
|
p_cc.add_argument("--start", type=str, default=None); p_cc.add_argument("--end", type=str, default=None); p_cc.add_argument("--min-mag", type=float, default=1.0)
|
|
@@ -2374,6 +2385,71 @@ def main(argv=None) -> int:
|
|
|
2374
2385
|
elif a.cmd == "tools":
|
|
2375
2386
|
import json as _json
|
|
2376
2387
|
from . import tool_catalog as _TC
|
|
2388
|
+
if a.action:
|
|
2389
|
+
from . import tool_taxonomy as _TX
|
|
2390
|
+
from .cli import _safe_stdout
|
|
2391
|
+
_safe_stdout() # the cited figures carry fractions and degree signs
|
|
2392
|
+
if a.action == "classes":
|
|
2393
|
+
cs = _TX.classes(a.category, a.find)
|
|
2394
|
+
if a.category and a.category not in _TX.CATEGORY_NAMES:
|
|
2395
|
+
raise SystemExit(f"tools: no category {a.category!r}; one of {', '.join(_TX.CATEGORY_NAMES)}")
|
|
2396
|
+
if a.json:
|
|
2397
|
+
print(_json.dumps(cs, indent=1)); return 0
|
|
2398
|
+
sm = _TX.summary()
|
|
2399
|
+
print(f"{len(cs)} of {sm['classes']} tool classes; {sm['sources']} pages checked (fetched {sm['sources_fetched']}); {sm['figures']} published figures, each quoted from its page")
|
|
2400
|
+
last = None
|
|
2401
|
+
for t in cs:
|
|
2402
|
+
if t["category"] != last:
|
|
2403
|
+
print(f"\n{t['category_name']}"); last = t["category"]
|
|
2404
|
+
print(f" {t['id']:<24s} {t['name']}")
|
|
2405
|
+
print(f" {t['one_line']}")
|
|
2406
|
+
print("\n`gea tools --action tutorial --class ID` opens one.")
|
|
2407
|
+
return 0
|
|
2408
|
+
if a.action == "tutorial":
|
|
2409
|
+
if not a.class_id:
|
|
2410
|
+
raise SystemExit("tools: tutorial needs --class, e.g. --class pdm_motor (gea tools --action classes lists them)")
|
|
2411
|
+
try:
|
|
2412
|
+
if a.json:
|
|
2413
|
+
print(_json.dumps(_TX.tool_class(a.class_id), indent=1)); return 0
|
|
2414
|
+
print(_TX.tutorial_text(a.class_id))
|
|
2415
|
+
except KeyError as e:
|
|
2416
|
+
raise SystemExit(f"tools: {e.args[0]}")
|
|
2417
|
+
return 0
|
|
2418
|
+
if not a.workspace:
|
|
2419
|
+
raise SystemExit(f"tools: --action {a.action} needs --workspace, e.g. --workspace C:\\site")
|
|
2420
|
+
from .workspace import Workspace, WorkspaceError
|
|
2421
|
+
try:
|
|
2422
|
+
ws = Workspace(a.workspace)
|
|
2423
|
+
except WorkspaceError as e:
|
|
2424
|
+
raise SystemExit(f"tools: {e}")
|
|
2425
|
+
if a.action == "fleet":
|
|
2426
|
+
fl = _TX.fleet_list(ws.path)
|
|
2427
|
+
if a.json:
|
|
2428
|
+
print(_json.dumps(fl, indent=1)); return 0
|
|
2429
|
+
if not fl:
|
|
2430
|
+
print("the fleet is empty: gea tools --action fleet-add --workspace ... --class pdm_motor --maker ... --model ... --datasheet ...")
|
|
2431
|
+
for t in fl:
|
|
2432
|
+
print(f"{t['id']:<32s} {t['class_name']} - {t['maker']} {t['model']}" + (f" s/n {t['serial']}" if t['serial'] else '') + (f", {t['od_in']:g} in OD" if t['od_in'] else ''))
|
|
2433
|
+
print(f" datasheet: {t['datasheet']}")
|
|
2434
|
+
return 0
|
|
2435
|
+
if a.action == "fleet-add":
|
|
2436
|
+
try:
|
|
2437
|
+
rec = _TX.fleet_add(ws.path, a.class_id or "", a.maker, a.model, a.datasheet, serial=a.serial, od_in=a.od_in, note=a.note, actor=a.actor)
|
|
2438
|
+
except ValueError as e:
|
|
2439
|
+
raise SystemExit(f"tools: {e}")
|
|
2440
|
+
ws.audit(a.actor, 'fleet.add', {'id': rec['id'], 'class': rec['class_id'], 'datasheet': rec['datasheet']})
|
|
2441
|
+
print(f"added {rec['id']}: {rec['maker']} {rec['model']} ({rec['class_name']}); datasheet {rec['datasheet']}")
|
|
2442
|
+
return 0
|
|
2443
|
+
if a.action == "fleet-remove":
|
|
2444
|
+
if not a.id:
|
|
2445
|
+
raise SystemExit("tools: fleet-remove needs --id (gea tools --action fleet lists them)")
|
|
2446
|
+
try:
|
|
2447
|
+
rec = _TX.fleet_remove(ws.path, a.id)
|
|
2448
|
+
except ValueError as e:
|
|
2449
|
+
raise SystemExit(f"tools: {e}")
|
|
2450
|
+
ws.audit(a.actor, 'fleet.remove', {'id': rec['id'], 'class': rec['class_id']})
|
|
2451
|
+
print(f"removed {rec['id']}")
|
|
2452
|
+
return 0
|
|
2377
2453
|
if a.rating or a.station:
|
|
2378
2454
|
stations = []
|
|
2379
2455
|
for spec in (a.station or []):
|
|
@@ -7697,10 +7697,11 @@ def section_by_edr(tmp: str) -> None:
|
|
|
7697
7697
|
"sections": rec["n_sections"] == 3 and all(x["rows"] == 3000 and x["hours"] == 0.83 for x in secs) and secs[0]["gap_before_hours"] is None
|
|
7698
7698
|
and secs[1]["gap_before_hours"] == 48.0 and secs[2]["gap_before_hours"] == 48.0 and all(x["connections"] == 25 for x in secs)
|
|
7699
7699
|
and all(x["rop_on_bottom_mean_ft_h"] == 600.0 and x["on_bottom_hours"] == 0.69 and x["rotating_hours"] == 0.69 for x in secs)
|
|
7700
|
-
and secs[0]["hole_depth_at_start_ft"] == 1500.2 and abs(secs[0]["feet_drilled"] - 416.5) < 0.2 and
|
|
7701
|
-
and "
|
|
7700
|
+
and secs[0]["hole_depth_at_start_ft"] == 1500.2 and abs(secs[0]["feet_drilled"] - 416.5) < 0.2 and "depth_events" not in secs[0]
|
|
7701
|
+
and secs[1]["hole_depth_at_start_ft"] == 1916.7 and secs[0]["wob_max_klbf"] == 20.0 and secs[0]["rpm_max"] == 60.0,
|
|
7702
7702
|
"well": rec["total_depth_md_ft"] == 2750.0 and rec["tvd_at_td_ft"] == 2015.0 and rec["on_bottom_hours"] == 2.08 and abs(rec["feet_drilled"] - 1249.8) < 0.2
|
|
7703
|
-
and rec["
|
|
7703
|
+
and rec["depth_events"] == [] and rec["excluded_hours"] == 0.0 and rec["flag_idle_hours"] == 0.0 and not rec["notes"]
|
|
7704
|
+
and rec["first_hole_depth_ft"] == 1500.2 and [b["status"] for b in rec["boreholes"]] == ["FINAL"]
|
|
7704
7705
|
and abs(rec["feet_per_on_bottom_hour"] - 600.9) < 0.2 and rec["hours_recorded"] == 2.5 and rec["span_days"] == 4.1 and rec["reached_td"].startswith("2026-06-05T02:29"),
|
|
7705
7706
|
"md_tvd": rec["md_tvd"]["status"] == "OK" and rec["md_tvd"]["n"] == 13 and rec["md_tvd"]["tvd_decreasing_steps"] == 0 and rec["md_tvd"]["samples_without_tvd"] == 900
|
|
7706
7707
|
and "not a survey" in rec["md_tvd"]["source"] and rec["lateral"]["lateral_start_md_ft"] == 1999.8 and abs(rec["lateral"]["lateral_length_ft"] - 750.2) < 0.2
|
|
@@ -7716,6 +7717,27 @@ def section_by_edr(tmp: str) -> None:
|
|
|
7716
7717
|
"registry": PORT_REGISTRY["edr"].status == "IMPLEMENTED" and read_any(r["path"]).source_format == "edr"
|
|
7717
7718
|
and any(p["name"] == "edr" and p["status"] == "IMPLEMENTED" for p in TC.catalog()["ports"]["files"]),
|
|
7718
7719
|
}
|
|
7720
|
+
# the depth events: a stale opening, a re-reference, a sidetrack and a correction, each named and handled
|
|
7721
|
+
ev = E.selftest_events(str(d)); er = ev["record"]
|
|
7722
|
+
types = [(e["type"], e["from_ft"], e["to_ft"]) for e in er["depth_events"]]
|
|
7723
|
+
bh = er["boreholes"]
|
|
7724
|
+
c4 = {}
|
|
7725
|
+
c4["events"] = (types == [("STALE OPENING", 9999.0, 5200.2), ("RE-REFERENCE", 5400.0, 2000.0), ("SIDETRACK", 5500.0, 4800.0), ("CORRECTION", 5700.0, 5650.2)]
|
|
7726
|
+
and er["total_depth_md_ft"] == 5750.0 and abs(er["feet_drilled"] - 1449.8) < 0.2 and er["first_hole_depth_ft"] == 5000.2
|
|
7727
|
+
and len(bh) == 2 and bh[0]["status"].startswith("ABANDONED") and bh[0]["deepest_ft"] == 5500.0 and bh[1]["status"] == "FINAL" and bh[1]["from_ft"] == 4800.0
|
|
7728
|
+
and er["on_bottom_hours"] == 8.45 and er["on_bottom_flag_hours"] == 9.39 and er["excluded_hours"] == 1.03
|
|
7729
|
+
and any("largest value is 9,999.0 ft" in x for x in er["notes"])
|
|
7730
|
+
and er["gamma"]["status"] == "OK" and er["gamma"]["bins"] == 951 and er["gamma"]["depth_from_ft"] == 4800.0 and er["gamma"]["depth_to_ft"] == 5750.0
|
|
7731
|
+
and len(ev["gamma"].index) == 951 and bool(np.all(ev["gamma"].channels["GR"].values == 110.0))
|
|
7732
|
+
and er["md_tvd"]["n"] == 10 and any(l.startswith("Depth event, SIDETRACK") and "abandoned" in l for l in er["lines"])
|
|
7733
|
+
and any(l.startswith("Boreholes:") for l in er["lines"]))
|
|
7734
|
+
fl = E.selftest_flag(str(d))["record"]
|
|
7735
|
+
c4["flag_and_corrections"] = ([(e["type"], e["from_ft"], e["to_ft"]) for e in fl["depth_events"]] == [("CORRECTION", 1060.0, 1080.0), ("CORRECTION", 1140.0, 1128.0), ("CORRECTION", 1128.0, 1140.0),
|
|
7736
|
+
("STALE OPENING", 9999.0, None), ("STALE OPENING", 9999.0, None), ("STALE OPENING", 9999.0, 1200.1)]
|
|
7737
|
+
and fl["total_depth_md_ft"] == 1230.0 and fl["first_hole_depth_ft"] == 1000.1 and abs(fl["feet_drilled"] - 229.9) < 0.05
|
|
7738
|
+
and fl["on_bottom_hours"] == 0.58 and fl["flag_idle_hours"] == 0.56 and fl["excluded_hours"] == 0.18 and fl["on_bottom_flag_hours"] == 1.14
|
|
7739
|
+
and [x.get("hole_depth_at_start_ft") for x in fl["sections"]] == [1000.1, 1128.0, None, None, 1200.0] and len(fl["boreholes"]) == 1
|
|
7740
|
+
and any("nothing drilled" in l for l in fl["lines"]))
|
|
7719
7741
|
odd = str(d / "odd.csv")
|
|
7720
7742
|
with open(r["path"], encoding="utf-8") as f, open(odd, "w", encoding="utf-8") as g:
|
|
7721
7743
|
for i, line in enumerate(f):
|
|
@@ -7820,6 +7842,168 @@ def section_by_edr(tmp: str) -> None:
|
|
|
7820
7842
|
"written gamma LAS converts its feet once, says so, recognizes the gamma and says what it lacks; the help page and its index entry"
|
|
7821
7843
|
+ (f" [failed: {', '.join(failed3)}]" if failed3 else ""))
|
|
7822
7844
|
|
|
7845
|
+
c4["help"] = all(t in help_md for t in ("STALE OPENING", "RE-REFERENCE", "SIDETRACK", "CORRECTION", "UNRESOLVED")) and "daily drilling report" in help_md \
|
|
7846
|
+
and "nothing drilled" in help_md and "total depth less the first depth" in help_md
|
|
7847
|
+
failed4 = [k for k, v in c4.items() if not v]
|
|
7848
|
+
ok(not failed4,
|
|
7849
|
+
"BY4 the depth events: a section opening on another well's depth (STALE OPENING, excluded), a depth set back and regained by counting pipe at 3,600 "
|
|
7850
|
+
"ft/h (RE-REFERENCE, excluded), a 700 ft set-back time-drilled at 5 ft/h (SIDETRACK: total depth 5,750 ft from the final borehole, 1,449.8 ft drilled "
|
|
7851
|
+
"counting the abandoned 4,800-5,500 ft, the gamma log and TVD table kept off the abandoned hole) and a 50 ft overstated depth (CORRECTION) each named; "
|
|
7852
|
+
"a 20 ft set-forward off bottom added, a 12 ft fall regained only in the next section a correction and never a re-reference, the next section drilling "
|
|
7853
|
+
"on from its opening depth not a stale opening, three restarts on another well's depth each a stale opening (judged against the last depth the file can "
|
|
7854
|
+
"be trusted for), and 2,000 s of on-bottom flag with nothing drilled kept out of the drilling hours - footage exactly total depth less the first depth "
|
|
7855
|
+
"(229.9 ft); the help page names every event"
|
|
7856
|
+
+ (f" [failed: {', '.join(failed4)}]" if failed4 else ""))
|
|
7857
|
+
|
|
7858
|
+
|
|
7859
|
+
|
|
7860
|
+
def section_bz_tool_library(tmp: str) -> None:
|
|
7861
|
+
"""Section BZ - the downhole tool library: every class of downhole tool in use across the industry, a one-line
|
|
7862
|
+
description on hover and a tutorial that opens on a click, the published figures quoted from the pages they cite and
|
|
7863
|
+
nothing more, and the operator's own fleet tied to the classes and to the datasheets that rate them."""
|
|
7864
|
+
import http.cookiejar
|
|
7865
|
+
import re as _re
|
|
7866
|
+
import subprocess as _sp
|
|
7867
|
+
import urllib.request
|
|
7868
|
+
import urllib.error
|
|
7869
|
+
from urllib.parse import urlparse
|
|
7870
|
+
from . import tool_taxonomy as TX
|
|
7871
|
+
from . import helplib as H
|
|
7872
|
+
from .client_reports import FORBIDDEN_TERMS
|
|
7873
|
+
from .tool_library import TOOL_LIBRARY
|
|
7874
|
+
from .workspace import Workspace
|
|
7875
|
+
from .service import Service, Users
|
|
7876
|
+
pkg = Path(__file__).parent
|
|
7877
|
+
d = Path(tmp, "bz"); d.mkdir()
|
|
7878
|
+
|
|
7879
|
+
def _raises(fn, exc, words=""):
|
|
7880
|
+
try:
|
|
7881
|
+
fn()
|
|
7882
|
+
except exc as e:
|
|
7883
|
+
return words in str(e)
|
|
7884
|
+
return False
|
|
7885
|
+
|
|
7886
|
+
sm = TX.summary()
|
|
7887
|
+
cls = list(TX.TAXONOMY.values())
|
|
7888
|
+
prose = lambda t: " ".join([t["one_line"]] + [t["tutorial"][p] for p in TX.PARTS])
|
|
7889
|
+
lowtier = _re.compile(r"(wikipedia\.org|rigzone\.com|drillingmanual\.com|petroleumacronyms|turbodrill\.com)$")
|
|
7890
|
+
figs = [f for t in cls for f in t["figures"]]
|
|
7891
|
+
c1 = {
|
|
7892
|
+
"breadth": sm["classes"] >= 90 and len(sm["categories"]) == 9 and all(c["classes"] >= 1 for c in sm["categories"])
|
|
7893
|
+
and {"pdm_motor", "rss_push", "mwd_mud_pulse", "lwd_gamma", "drilling_jar", "production_packer", "esp", "perforating_gun",
|
|
7894
|
+
"pdg", "wl_formation_tester", "cbl", "overshot", "dst"} <= set(TX.TAXONOMY),
|
|
7895
|
+
"hover": all(0 < len(t["one_line"]) <= 140 for t in cls),
|
|
7896
|
+
"tutorial": all(all(len(t["tutorial"][p]) > 20 for p in TX.PARTS) for t in cls) and TX.PARTS == ("what", "where", "how", "reads", "watch", "program"),
|
|
7897
|
+
"no_numbers_in_prose": not any(_re.search(r"\d", prose(t)) for t in cls),
|
|
7898
|
+
"words": not any(w in (t["name"] + " " + prose(t)).lower() for t in cls for w in FORBIDDEN_TERMS),
|
|
7899
|
+
"sources": all(t["sources"] for t in cls) and all(urlparse(x["url"]).scheme == "https" and x.get("publisher") for t in cls for x in t["sources"])
|
|
7900
|
+
and not any(lowtier.search(urlparse(x["url"]).netloc.lower()) for t in cls for x in t["sources"])
|
|
7901
|
+
and (pkg / "reference" / "tool_sources.json").is_file() and sm["sources"] >= 150 and sm["sources_fetched"] == "2026-10-14",
|
|
7902
|
+
"figures": len(figs) == sm["figures"] and len(figs) >= 150 and all(f.get("quote") and f.get("url") and f.get("publisher") and f.get("what") for f in figs)
|
|
7903
|
+
and not any("..." in f["quote"] for f in figs)
|
|
7904
|
+
and all(("not a limit for the class" in t["figures_note"]) if t["figures"] else ("supply your model's datasheet" in t["figures_note"]) for t in cls),
|
|
7905
|
+
"lookup": [t["id"] for t in TX.classes("drive")][:1] == ["pdm_motor"] and {t["id"] for t in TX.classes(None, "packer")} >= {"production_packer"}
|
|
7906
|
+
and TX.classes(None, "no such tool zzz") == [],
|
|
7907
|
+
"unknown": _raises(lambda: TX.tool_class("no_such_tool"), KeyError),
|
|
7908
|
+
"text": all(TX.PART_TITLES[p] + ": " in TX.tutorial_text("pdm_motor") for p in TX.PARTS) and "Sources (fetched 2026-10-14)" in TX.tutorial_text("pdm_motor")
|
|
7909
|
+
and "Published figures (" in TX.tutorial_text("agitator") and "8-12 Hz" in TX.tutorial_text("agitator"),
|
|
7910
|
+
"gauges": all(TX.GAUGE_CLASS_TO_TAXONOMY.get(t.tool_class) in TX.TAXONOMY for t in TOOL_LIBRARY.values()),
|
|
7911
|
+
}
|
|
7912
|
+
failed1 = [k for k, v in c1.items() if not v]
|
|
7913
|
+
ok(not failed1,
|
|
7914
|
+
"BZ1 the downhole tool library: at least ninety classes in nine categories from bits to test tools, each with a one-line description for the hover "
|
|
7915
|
+
"and a six-part tutorial for the pop-open; the prose carries no number at all and none of the words a client report may not; every class checked "
|
|
7916
|
+
"against at least one public page (none of them an encyclopaedia or a re-publisher); every published figure is the cited page's own words with its "
|
|
7917
|
+
"unit and page, never a limit for the class, and a class with none says to supply the datasheet; the classes searchable; an unknown class named; "
|
|
7918
|
+
"every gauge in the gauge library opens its class's tutorial"
|
|
7919
|
+
+ (f" [failed: {', '.join(failed1)}]" if failed1 else ""))
|
|
7920
|
+
|
|
7921
|
+
wsp = str(d / "ws"); Workspace.create(wsp, "Pad 3", actor="tester")
|
|
7922
|
+
e_ds = _raises(lambda: TX.fleet_add(wsp, "pdm_motor", "Acme", "M1", ""), ValueError, "datasheet")
|
|
7923
|
+
e_cls = _raises(lambda: TX.fleet_add(wsp, "warp_drive", "Acme", "M1", "sheet"), ValueError, "no tool class")
|
|
7924
|
+
r1 = TX.fleet_add(wsp, "pdm_motor", "Acme", "M1", "Acme M1 datasheet rev B", serial="A100", od_in=6.75)
|
|
7925
|
+
e_dup = _raises(lambda: TX.fleet_add(wsp, "pdm_motor", "Acme", "M1", "Acme M1 datasheet rev B", serial="A100"), ValueError, "already")
|
|
7926
|
+
users = Users(str(Path(wsp, "users.json"))); users.add("op", "operator-pass-1", "operator"); users.add("v", "viewer-pass-1", "viewer")
|
|
7927
|
+
svc = Service(wsp, port=0, scheduler=False).start()
|
|
7928
|
+
base_url = svc.url.rstrip("/")
|
|
7929
|
+
|
|
7930
|
+
def session():
|
|
7931
|
+
o = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(http.cookiejar.CookieJar()))
|
|
7932
|
+
|
|
7933
|
+
def call(method, path, body=None):
|
|
7934
|
+
req = urllib.request.Request(base_url + path, method=method, data=(json.dumps(body).encode() if body is not None else None))
|
|
7935
|
+
req.add_header("Content-Type", "application/json"); req.add_header("X-GEA-Action", "1")
|
|
7936
|
+
try:
|
|
7937
|
+
with o.open(req, timeout=60) as rr_:
|
|
7938
|
+
return rr_.status, json.loads(rr_.read())
|
|
7939
|
+
except urllib.error.HTTPError as e:
|
|
7940
|
+
return e.code, json.loads(e.read())
|
|
7941
|
+
return call
|
|
7942
|
+
try:
|
|
7943
|
+
view, op = session(), session()
|
|
7944
|
+
view("POST", "/api/login", {"name": "v", "password": "viewer-pass-1"}); op("POST", "/api/login", {"name": "op", "password": "operator-pass-1"})
|
|
7945
|
+
st_t, tx = view("GET", "/api/tools/taxonomy")
|
|
7946
|
+
st_q, txq = view("GET", "/api/tools/taxonomy?q=jar")
|
|
7947
|
+
st_v, _ = view("POST", "/api/tools/fleet", {"class_id": "esp", "maker": "Acme", "model": "P2", "datasheet": "Acme P2 sheet"})
|
|
7948
|
+
st_nods, nods = op("POST", "/api/tools/fleet", {"class_id": "esp", "maker": "Acme", "model": "P2", "datasheet": ""})
|
|
7949
|
+
st_add, added = op("POST", "/api/tools/fleet", {"class_id": "esp", "maker": "Acme", "model": "P2", "datasheet": "Acme P2 sheet rev A", "od_in": "5.38"})
|
|
7950
|
+
st_fl, fl = view("GET", "/api/tools/fleet")
|
|
7951
|
+
st_rm, _ = op("POST", f"/api/tools/fleet/{r1['id']}/remove", {})
|
|
7952
|
+
st_rm2, _ = op("POST", "/api/tools/fleet/nothing-here/remove", {})
|
|
7953
|
+
finally:
|
|
7954
|
+
svc.stop()
|
|
7955
|
+
audit = Path(wsp, "records", "audit.jsonl").read_text(encoding="utf-8")
|
|
7956
|
+
c2 = {
|
|
7957
|
+
"fleet_rules": e_ds and e_cls and e_dup and r1["id"] == "acme-m1-a100" and r1["class_name"] == TX.TAXONOMY["pdm_motor"]["name"] and r1["od_in"] == 6.75
|
|
7958
|
+
and Path(wsp, "config", "fleet.json").is_file(),
|
|
7959
|
+
"api": st_t == 200 and len(tx["classes"]) == sm["classes"] and [p[0] for p in tx["parts"]] == list(TX.PARTS) and tx["summary"]["figures"] == sm["figures"]
|
|
7960
|
+
and st_q == 200 and {c["id"] for c in txq["classes"]} >= {"drilling_jar", "jar_accelerator"} and len(txq["classes"]) < 10
|
|
7961
|
+
and tx["fleet"] and tx["fleet"][0]["id"] == "acme-m1-a100",
|
|
7962
|
+
"roles": st_v == 403 and st_nods == 400 and "datasheet" in nods.get("error", "") and st_add == 200 and added["od_in"] == 5.38
|
|
7963
|
+
and st_fl == 200 and {t["id"] for t in fl["tools"]} == {"acme-m1-a100", "acme-p2"} and st_rm == 200 and st_rm2 == 404
|
|
7964
|
+
and [t["id"] for t in TX.fleet_list(wsp)] == ["acme-p2"],
|
|
7965
|
+
"audit": '"fleet.add"' in audit and '"fleet.remove"' in audit and "Acme P2 sheet rev A" in audit,
|
|
7966
|
+
}
|
|
7967
|
+
failed2 = [k for k, v in c2.items() if not v]
|
|
7968
|
+
ok(not failed2,
|
|
7969
|
+
"BZ2 the fleet: a tool of yours needs its class and its datasheet citation, and is not added twice; it is kept in the workspace's config; the API "
|
|
7970
|
+
"serves the classes, the tutorial parts and the fleet to any signed-in user, adds and removes for an operator and not a viewer, says why an "
|
|
7971
|
+
"addition without a datasheet is turned away, and every addition and removal is in the audit log"
|
|
7972
|
+
+ (f" [failed: {', '.join(failed2)}]" if failed2 else ""))
|
|
7973
|
+
|
|
7974
|
+
page_src = (pkg / "web" / "app.html").read_text(encoding="utf-8")
|
|
7975
|
+
help_md = (pkg / "help" / "tools.md").read_text(encoding="utf-8")
|
|
7976
|
+
r_cls = _sp.run([sys.executable, "-m", "gea", "tools", "--action", "classes"], capture_output=True, text=True)
|
|
7977
|
+
r_cat = _sp.run([sys.executable, "-m", "gea", "tools", "--action", "classes", "--category", "fishing"], capture_output=True, text=True)
|
|
7978
|
+
r_tut = _sp.run([sys.executable, "-m", "gea", "tools", "--action", "tutorial", "--class", "drilling_jar"], capture_output=True, text=True)
|
|
7979
|
+
r_none = _sp.run([sys.executable, "-m", "gea", "tools", "--action", "tutorial"], capture_output=True, text=True)
|
|
7980
|
+
r_bad = _sp.run([sys.executable, "-m", "gea", "tools", "--action", "tutorial", "--class", "warp_drive"], capture_output=True, text=True)
|
|
7981
|
+
r_add = _sp.run([sys.executable, "-m", "gea", "tools", "--action", "fleet-add", "--workspace", wsp, "--class", "drilling_jar", "--maker", "Acme",
|
|
7982
|
+
"--model", "J9", "--datasheet", "Acme J9 sheet rev C"], capture_output=True, text=True)
|
|
7983
|
+
r_nods = _sp.run([sys.executable, "-m", "gea", "tools", "--action", "fleet-add", "--workspace", wsp, "--class", "drilling_jar", "--maker", "Acme",
|
|
7984
|
+
"--model", "J10"], capture_output=True, text=True)
|
|
7985
|
+
r_list = _sp.run([sys.executable, "-m", "gea", "tools", "--action", "fleet", "--workspace", wsp], capture_output=True, text=True)
|
|
7986
|
+
r_nows = _sp.run([sys.executable, "-m", "gea", "tools", "--action", "fleet"], capture_output=True, text=True)
|
|
7987
|
+
c3 = {
|
|
7988
|
+
"page": all(x in page_src for x in ("Downhole tool library", "class=\"tl-chip\"", 'role="tooltip"', "aria-haspopup=\"dialog\"", ".tl-chip:focus-visible .tl-tip",
|
|
7989
|
+
"@media (hover:none)", "showModal()", "dialog.tl-dlg::backdrop", "/api/tools/taxonomy", "/api/tools/fleet", "Add one of yours",
|
|
7990
|
+
"Your fleet", "tl-open", "Esc closes it")),
|
|
7991
|
+
"cli": r_cls.returncode == 0 and f"{sm['classes']} of {sm['classes']} tool classes" in r_cls.stdout and "Fishing, milling and intervention" in r_cls.stdout
|
|
7992
|
+
and r_cat.returncode == 0 and "overshot" in r_cat.stdout and "pdm_motor" not in r_cat.stdout
|
|
7993
|
+
and r_tut.returncode == 0 and "What it is: " in r_tut.stdout and "In this program: " in r_tut.stdout
|
|
7994
|
+
and r_none.returncode != 0 and "--class pdm_motor" in (r_none.stderr + r_none.stdout) and "<" not in (r_none.stderr + r_none.stdout)
|
|
7995
|
+
and r_bad.returncode != 0 and "no tool class 'warp_drive'" in (r_bad.stderr + r_bad.stdout),
|
|
7996
|
+
"cli_fleet": r_add.returncode == 0 and "added acme-j9" in r_add.stdout and r_nods.returncode != 0 and "datasheet" in (r_nods.stderr + r_nods.stdout)
|
|
7997
|
+
and r_list.returncode == 0 and "Acme J9 sheet rev C" in r_list.stdout and r_nows.returncode != 0 and "needs --workspace" in (r_nows.stderr + r_nows.stdout),
|
|
7998
|
+
"help": not H.check("tools") and "tutorial" in help_md and "fleet" in help_md and "the tutorials carry no numbers at all" in help_md.split("will not call a measurement")[1],
|
|
7999
|
+
}
|
|
8000
|
+
failed3 = [k for k, v in c3.items() if not v]
|
|
8001
|
+
ok(not failed3,
|
|
8002
|
+
"BZ3 the page and the command line: a chip per class that shows its description on hover and on keyboard focus (not on a touch screen, where a tap "
|
|
8003
|
+
"opens it), a tutorial dialog that opens on click, tap or Enter and closes on Esc or the backdrop, a find box and a category filter, the fleet card, "
|
|
8004
|
+
"the gauge library's Tutorial buttons; `gea tools --action classes | tutorial | fleet | fleet-add`, each refusing a missing argument by name without "
|
|
8005
|
+
"a placeholder; the help page"
|
|
8006
|
+
+ (f" [failed: {', '.join(failed3)}]" if failed3 else ""))
|
|
7823
8007
|
|
|
7824
8008
|
def main() -> int:
|
|
7825
8009
|
print("GEA-Program - ACCEPTANCE SUITE (the product gate)")
|
|
@@ -7901,6 +8085,7 @@ def main() -> int:
|
|
|
7901
8085
|
section_bw_catalog_map(tmp)
|
|
7902
8086
|
section_bx_pasteable(tmp)
|
|
7903
8087
|
section_by_edr(tmp)
|
|
8088
|
+
section_bz_tool_library(tmp)
|
|
7904
8089
|
if _FAILS:
|
|
7905
8090
|
print(f"[ACCEPTANCE] {len(_FAILS)} FAILURES ({_PASS} passed):")
|
|
7906
8091
|
for f in _FAILS:
|