gea-program 0.58.0__tar.gz → 0.60.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.58.0 → gea_program-0.60.0}/PKG-INFO +25 -1
- {gea_program-0.58.0 → gea_program-0.60.0}/README.md +24 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/__init__.py +1 -1
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/__main__.py +17 -5
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/acceptance_tests.py +312 -2
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/dashboard.py +149 -128
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/declarations.py +371 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/files.py +2 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/catalog.md +1 -1
- gea_program-0.60.0/gea/help/declare.md +13 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/hydraulics.md +1 -1
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/month-end.md +1 -1
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/torque-drag.md +1 -1
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/hydraulics.py +50 -11
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/invoice_check.py +3 -1
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/month_end.py +20 -2
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/rig_state.py +4 -2
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/service.py +41 -9
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/tls.py +3 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/torque_drag.py +16 -6
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/web/app.html +22 -14
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/workspace.py +38 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea_program.egg-info/PKG-INFO +25 -1
- {gea_program-0.58.0 → gea_program-0.60.0}/pyproject.toml +1 -1
- gea_program-0.58.0/gea/help/declare.md +0 -13
- {gea_program-0.58.0 → gea_program-0.60.0}/LICENSE +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/BENCH_TEST_PROTOCOL.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/accuracy_statement.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/alarm_engine.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/alerts.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/backup.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/bench.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/blind_harness.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/acex_lomonosov_age_depth_model.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/acex_lomonosov_age_depth_model.txt +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/agassiz77_canada_temperature.csv +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/agassiz77_canada_temperature.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/barbados_110_consolidation.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/barbados_110_consolidation.txt +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/bengal_u1452_grain_size.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/bengal_u1452_grain_size.txt +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/blake_164_methane_isotopes.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/blake_164_methane_isotopes.txt +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/chicxulub_m0077a_pwave_velocity.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/chicxulub_m0077a_pwave_velocity.txt +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/collingwood_1_28_ks_complete.las +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/collingwood_1_28_ks_complete.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/costa_rica_odp_friction_envelope.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/costa_rica_odp_friction_envelope.txt +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/dead_sea_5017_debrite_xrf_ms.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/dead_sea_5017_debrite_xrf_ms.txt +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/dsdp_504b_physical_properties.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/dsdp_504b_physical_properties.txt +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/dsdp_504b_sound_velocity.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/dsdp_504b_sound_velocity.txt +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/elgygytgyn_5011_turbidites.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/elgygytgyn_5011_turbidites.txt +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/epica_domec_co2_800kyr.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/epica_domec_co2_800kyr.txt +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/fram_909_organic_petrography.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/fram_909_organic_petrography.txt +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/gbr_325_coral_uth_ages.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/gbr_325_coral_uth_ages.txt +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/gisp2_greenland_temperature.csv +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/gisp2_greenland_temperature.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/gom_308_t2p_insitu.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/gom_308_t2p_insitu.txt +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/guaymas_385_dom_d13c.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/guaymas_385_dom_d13c.txt +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/hikurangi_u1520_friction_insitu.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/hikurangi_u1520_friction_insitu.txt +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/hydrate_ridge_204_ncr_hydrate.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/hydrate_ridge_204_ncr_hydrate.txt +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/iodp_u1324_pore_pressure.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/iodp_u1324_pore_pressure.txt +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/jfast_c0019_slow_slip_events.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/jfast_c0019_slow_slip_events.txt +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/kennetcook_2_p129_excerpt.las +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/kennetcook_2_p129_excerpt.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/ktb_hb_bhgm_density.dat +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/ktb_hb_bhgm_density.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/ktb_hb_complog_6020_excerpt.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/ktb_hb_complog_6020_excerpt.txt +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/ktb_hb_hlog246_temperature.dat +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/ktb_hb_hlog246_temperature.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/ktb_hb_rockmech_compress.dat +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/ktb_hb_rockmech_compress.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/ktb_hb_tvd_0_9080_excerpt.dat +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/ktb_hb_tvd_0_9080_excerpt.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/ktb_vb_rockmech_compress.dat +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/ktb_vb_rockmech_compress.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/ktb_vb_vlog251_temperature.dat +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/ktb_vb_vlog251_temperature.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/l06_06_nl_survey.csv +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/l06_06_nl_survey.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/l07_01_nl_excerpt.las +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/l07_01_nl_excerpt.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/mariana_1200_serpentinite_geochem.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/mariana_1200_serpentinite_geochem.txt +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/med_160_sapropels.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/med_160_sapropels.txt +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/nankai_megasplay_shear_strength.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/nankai_megasplay_shear_strength.txt +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/odp_1027b_thermal_conductivity.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/odp_1027b_thermal_conductivity.txt +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/odp_1027c_cork_temperature.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/odp_1027c_cork_temperature.txt +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/odp_1165b_thermal_conductivity.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/odp_1165b_thermal_conductivity.txt +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/odp_1274a_mantle_peridotite_mad.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/odp_1274a_mantle_peridotite_mad.txt +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/odp_504b_dike_elastic_moduli.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/odp_504b_dike_elastic_moduli.txt +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/odp_504b_leg137_borehole_fluids.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/odp_504b_leg137_borehole_fluids.txt +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/odp_735b_gabbro_elastic_moduli.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/odp_735b_gabbro_elastic_moduli.txt +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/peru_201_sulfate_reduction.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/peru_201_sulfate_reduction.txt +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/scorpio_e1_sa_excerpt.las +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/scorpio_e1_sa_excerpt.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/sumatra_362_cohesion.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/sumatra_362_cohesion.txt +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/university_6_17_no1_tx_excerpt.las +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/university_6_17_no1_tx_excerpt.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/ursa_308_xrd_mineralogy.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/ursa_308_xrd_mineralogy.txt +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/volve_15_9_19_sr_excerpt.las +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/volve_15_9_19_sr_excerpt.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/volve_15_9_19a_core_excerpt.csv +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/volve_15_9_19a_core_excerpt.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/volve_f12_f14_production_excerpt.csv +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/volve_f12_f14_production_excerpt.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/walvis_208_petm_carbonate.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/walvis_208_petm_carbonate.txt +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/woodlark_1109_rock_eval.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog/woodlark_1109_rock_eval.txt +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog_map.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/catalog_register.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/certificates.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/cli.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/client_reports.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/collision.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/config_versioning.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/conformance.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/control_room.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/correlation.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/decline.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/deviation.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/dlis.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/dnp3.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/doctor.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/dossier.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/dossier_verify.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/downhole_engine.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/drift_monitor.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/drill_string.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/earth_model.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/economics.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/ed25519.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/edr.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/elevation.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/etp.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/etp12_schemas.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/example_register_map.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/fat_sat.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/fixtures/README.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/fixtures/comcat_delaware_basin_2026-09.txt +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/fixtures/comcat_mahoning_1990-2026.txt +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/fixtures/comcat_youngstown_2011-2012.txt +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/fixtures/ne_110m_coastline.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/follower.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/forward_model.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/frac_hits.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/friction_priors.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/gamma.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/gauge_aging.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/gauge_specs.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/geodesy.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/geomag.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/gravity_reference.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/hartip.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/IT_SECURITY.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/TESTER_GUIDE.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/alarms.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/alerts.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/audit-update.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/backup.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/charts.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/collision.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/company-sign-in.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/conformance.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/control-room.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/data-in.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/decline.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/dlis.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/doctor.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/dossier.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/drift.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/drillstring.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/economics.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/edr.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/etp.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/field-ports.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/files.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/frac-hits.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/historian.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/https.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/instruments.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/interval.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/invoice-check.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/map.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/notifications.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/opseis.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/osdu.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/pad-summary.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/patches.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/penetrator.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/plan.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/pore-pressure.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/ppdm.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/quakeml.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/quality.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/report-history.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/rig-time.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/seedlink.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/seismic.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/setup.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/simulation.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/site.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/sites.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/slip.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/soak.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/sra.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/start.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/structure.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/tools.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/transients.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/upkeep.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/vibration.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/well-report.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/well-tests.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/help/well3d.md +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/helplib.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/housekeeping.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/interval.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/inverse_engine.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/jobs.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/live_ports.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/loadtest.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/matplotlib_demo.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/modbus.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/modbus_rtu.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/model_card.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/mqtt_port.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/notify.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/oidc.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/oidc_mock.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/op_seismicity.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/opcua_port.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/operator_app.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/osdu.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/pad_summary.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/patches.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/pdf_report.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/penetrator.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/permits.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/piwebapi.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/pore_pressure.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/ports.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/ppdm.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/profile_catalog.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/project.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/qt6_downhole_app.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/quakeml.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/reconciler.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/reference/IU_ANMO_10_BHZ_response.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/reference/IU_ANMO_10_BHZ_response.xml +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/reference/WMM2025.COF +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/reference/eia_henry_hub_daily.csv.gz +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/reference/eia_prices.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/reference/eia_wti_daily.csv.gz +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/reference/iscwsa_rev4_example.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/reference/iscwsa_rev5_example.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/reference/l0701_sonic_gr.las.gz +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/reference/l0701_sonic_gr.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/reference/libmseed_steim.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/reference/libmseed_steim1_4096.mseed +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/reference/libmseed_steim2_4096.mseed +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/reference/libmseed_steim2_512.mseed +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/reference/mahoning_example.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/reference/mud_motor_specs.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/reference/owsg_tool_models.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/reference/penetrator_ratings.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/reference/seismicity_protocols.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/reference/tool_sources.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/reference/us_outline.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/reference/us_outline.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/reference/volve_3d.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/reference/volve_f4_interpretation.las.gz +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/reference/volve_f4_logs.provenance.json +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/reference/volve_f4_lwd.las.gz +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/reference/volve_surfaces.json.gz +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/reference/volve_traj_F-10.xml.gz +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/reference/volve_traj_F-4.xml.gz +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/reference/volve_traj_F-5_12.25in.xml.gz +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/reference/volve_traj_F-5_17.5in.xml.gz +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/reference/volve_traj_F-5_36in.xml.gz +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/reference/volve_traj_F-5_8.5in.xml.gz +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/reference/volve_well_picks.csv.gz +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/report_history.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/rock_inventory.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/sample_record.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/sample_well_profile.csv +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/sbom.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/seedlink.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/segy.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/seismic.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/seismic_array.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/seismic_assoc.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/seismic_detect.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/seismic_film.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/seismic_harmonic.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/seismic_qc.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/seismic_response.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/seismic_signature.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/seismic_track.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/seismic_uncertainty.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/seismic_unlisted.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/seismic_watch.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/sensor_swap.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/series_cache.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/service_life.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/setup_checklist.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/shapefile.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/shell.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/shut_in.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/simulation.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/site_map.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/sla_report.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/slip.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/soak.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/sra.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/store_forward.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/strata_join.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/structure.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/supervisor.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/survey_cmd.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/survey_view.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/telemetry.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/tool_catalog.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/tool_library.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/tool_taxonomy.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/transient.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/vibration.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/well3d.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/well_assembler.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/well_report.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/well_test_validation.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/wellplan.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/wellpos.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/wits0.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/witsml.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea/xlsx_read.py +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea_program.egg-info/SOURCES.txt +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea_program.egg-info/dependency_links.txt +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea_program.egg-info/entry_points.txt +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea_program.egg-info/requires.txt +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/gea_program.egg-info/top_level.txt +0 -0
- {gea_program-0.58.0 → gea_program-0.60.0}/setup.cfg +0 -0
- {gea_program-0.58.0 → gea_program-0.60.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.60.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
|
|
@@ -659,6 +659,30 @@ EIA) or a declared price, with the net revenue interest, severance tax and
|
|
|
659
659
|
operating cost declared. A forecast is not a reserves report, and the page
|
|
660
660
|
says so. The **Decline curves** tab, `gea decline`, `gea help decline`.
|
|
661
661
|
|
|
662
|
+
### The declarations workbook
|
|
663
|
+
|
|
664
|
+
Everything the operator declares about a pad goes in through one sheet -
|
|
665
|
+
`gea declare --workspace C:\site --template pad3.xlsx` writes it as an
|
|
666
|
+
Excel workbook already filled with what is declared; `gea declare
|
|
667
|
+
--workspace C:\site --file pad3.xlsx` checks it row by row and `--apply`
|
|
668
|
+
writes it. Beside the wells, rates, runs and casing, it carries the
|
|
669
|
+
engineering: the survey program and plans, pore pressure and measured
|
|
670
|
+
pressures, the torque-and-drag string, the hydraulics (string, hole, mud,
|
|
671
|
+
viscometer, nozzles), frac stage tables and monitored wells, production
|
|
672
|
+
and the decline terms. A well with no directional survey is read on the
|
|
673
|
+
drilling recorder's own Interpolated TVD where one is needed, labelled as
|
|
674
|
+
the recorder's interpolation. `gea help declare`.
|
|
675
|
+
|
|
676
|
+
### When one well cannot be reported
|
|
677
|
+
|
|
678
|
+
Refresh every report goes on past a well it cannot read: that well is
|
|
679
|
+
written down with why (`reports\wells\<well>\refresh_failed.json`), shown
|
|
680
|
+
NOT REPORTED on the overview and the printed dashboard, and named by the
|
|
681
|
+
refresh job and the month-end packet; every other well is reported. A
|
|
682
|
+
catalogue well is added only from an entry that carries a downhole gauge
|
|
683
|
+
series, with a well inside it and its gauge depth; a live seismic station
|
|
684
|
+
whose feed has written nothing yet is listed as having no recording yet.
|
|
685
|
+
|
|
662
686
|
### Hydraulics and ECD
|
|
663
687
|
|
|
664
688
|
The pressures the mud makes while it circulates, from the six-speed
|
|
@@ -620,6 +620,30 @@ EIA) or a declared price, with the net revenue interest, severance tax and
|
|
|
620
620
|
operating cost declared. A forecast is not a reserves report, and the page
|
|
621
621
|
says so. The **Decline curves** tab, `gea decline`, `gea help decline`.
|
|
622
622
|
|
|
623
|
+
### The declarations workbook
|
|
624
|
+
|
|
625
|
+
Everything the operator declares about a pad goes in through one sheet -
|
|
626
|
+
`gea declare --workspace C:\site --template pad3.xlsx` writes it as an
|
|
627
|
+
Excel workbook already filled with what is declared; `gea declare
|
|
628
|
+
--workspace C:\site --file pad3.xlsx` checks it row by row and `--apply`
|
|
629
|
+
writes it. Beside the wells, rates, runs and casing, it carries the
|
|
630
|
+
engineering: the survey program and plans, pore pressure and measured
|
|
631
|
+
pressures, the torque-and-drag string, the hydraulics (string, hole, mud,
|
|
632
|
+
viscometer, nozzles), frac stage tables and monitored wells, production
|
|
633
|
+
and the decline terms. A well with no directional survey is read on the
|
|
634
|
+
drilling recorder's own Interpolated TVD where one is needed, labelled as
|
|
635
|
+
the recorder's interpolation. `gea help declare`.
|
|
636
|
+
|
|
637
|
+
### When one well cannot be reported
|
|
638
|
+
|
|
639
|
+
Refresh every report goes on past a well it cannot read: that well is
|
|
640
|
+
written down with why (`reports\wells\<well>\refresh_failed.json`), shown
|
|
641
|
+
NOT REPORTED on the overview and the printed dashboard, and named by the
|
|
642
|
+
refresh job and the month-end packet; every other well is reported. A
|
|
643
|
+
catalogue well is added only from an entry that carries a downhole gauge
|
|
644
|
+
series, with a well inside it and its gauge depth; a live seismic station
|
|
645
|
+
whose feed has written nothing yet is listed as having no recording yet.
|
|
646
|
+
|
|
623
647
|
### Hydraulics and ECD
|
|
624
648
|
|
|
625
649
|
The pressures the mud makes while it circulates, from the six-speed
|
|
@@ -533,11 +533,11 @@ def main(argv=None) -> int:
|
|
|
533
533
|
p_ds.add_argument("--actor", type=str, default="cli")
|
|
534
534
|
p_ds.add_argument("--json", action="store_true")
|
|
535
535
|
|
|
536
|
-
p_dc = sub.add_parser("declare", help="the declarations sheet: wells' identity, position and elevation, surveys, rates, items and AFEs, fleet tools, drill-string runs, ESP penetrators and drives - one CSV, checked against the workspace before anything is written")
|
|
536
|
+
p_dc = sub.add_parser("declare", help="the declarations sheet: wells' identity, position and elevation, surveys, rates, items and AFEs, fleet tools, drill-string runs, ESP penetrators and drives, the survey program and plans, pore pressure, torque and drag, hydraulics, frac stages, production - one CSV or Excel workbook, checked against the workspace before anything is written")
|
|
537
537
|
p_dc.add_argument("--workspace", type=str, required=True)
|
|
538
538
|
p_dc.add_argument("--file", type=str, default=None, help="the sheet (CSV); every row is planned NEW, CHANGE or SAME and nothing is written without --apply")
|
|
539
539
|
p_dc.add_argument("--apply", action="store_true", help="write the NEW and CHANGE rows (only when the sheet has no error)")
|
|
540
|
-
p_dc.add_argument("--template", type=str, default=None, help="write the sheet for this workspace, filled with what is already declared, to this path")
|
|
540
|
+
p_dc.add_argument("--template", type=str, default=None, help="write the sheet for this workspace, filled with what is already declared, to this path (.xlsx: an Excel workbook; otherwise CSV)")
|
|
541
541
|
p_dc.add_argument("--actor", type=str, default="cli")
|
|
542
542
|
p_dc.add_argument("--json", action="store_true")
|
|
543
543
|
|
|
@@ -2352,8 +2352,11 @@ def main(argv=None) -> int:
|
|
|
2352
2352
|
except WorkspaceError as e:
|
|
2353
2353
|
raise SystemExit(f"declare: {e}")
|
|
2354
2354
|
if a.template:
|
|
2355
|
-
|
|
2356
|
-
|
|
2355
|
+
if a.template.lower().endswith(".xlsx"):
|
|
2356
|
+
_DC.template_xlsx(ws, a.template)
|
|
2357
|
+
else:
|
|
2358
|
+
with open(a.template, "w", encoding="utf-8", newline="") as f:
|
|
2359
|
+
f.write(_DC.template(ws))
|
|
2357
2360
|
print(f"wrote {a.template}: fill in the blanks, then gea declare --workspace {a.workspace} --file {a.template}")
|
|
2358
2361
|
return 0
|
|
2359
2362
|
if not a.file:
|
|
@@ -3223,7 +3226,16 @@ def main(argv=None) -> int:
|
|
|
3223
3226
|
print(_json.dumps(ws.migrate_out_dir(a.from_dir, actor=a.actor), indent=1)); return 0
|
|
3224
3227
|
elif a.action == "refresh":
|
|
3225
3228
|
r = ws.refresh_dashboard(actor=a.actor, outages=a.outage, month=a.month, run_sat=a.sat)
|
|
3226
|
-
print("dashboard:", r.get("index") if isinstance(r, dict) else r)
|
|
3229
|
+
print("dashboard:", r.get("index") if isinstance(r, dict) else r)
|
|
3230
|
+
for wname, kinds in sorted(((r.get("reports") or {}) if isinstance(r, dict) else {}).items()):
|
|
3231
|
+
if "refresh_failed" in kinds:
|
|
3232
|
+
try:
|
|
3233
|
+
with open(os.path.join(ws.reports_dir, "wells", wname, "refresh_failed.json"), encoding="utf-8") as fh:
|
|
3234
|
+
why = _json.load(fh).get("reason", "")
|
|
3235
|
+
except (OSError, ValueError):
|
|
3236
|
+
why = ""
|
|
3237
|
+
print(f"well {wname}: its reports could not be written - {why} (the other wells were reported)")
|
|
3238
|
+
return 0
|
|
3227
3239
|
elif a.action == "audit":
|
|
3228
3240
|
for row in ws.audit_log(limit=50):
|
|
3229
3241
|
print(row["utc"], row["actor"], row["action"], _json.dumps(row["detail"]))
|
|
@@ -10472,8 +10472,9 @@ def section_cn_four(tmp: str) -> None:
|
|
|
10472
10472
|
t0 = now.replace(hour=10, minute=59, second=0) if now.hour < 23 else now.replace(hour=10, minute=59, second=0)
|
|
10473
10473
|
due_before = PS.due_now(ws, t0)
|
|
10474
10474
|
s1 = PS.write(ws, __version__, "tester", nt, now + timedelta(minutes=2))
|
|
10475
|
-
|
|
10476
|
-
|
|
10475
|
+
w1 = now + timedelta(minutes=2) # the summary's own day: two minutes on may already be tomorrow (UTC)
|
|
10476
|
+
due_after = PS.due_now(ws, w1.replace(hour=23, minute=0))
|
|
10477
|
+
nxt = (w1 + timedelta(days=1)).replace(hour=11, minute=1, second=0)
|
|
10477
10478
|
due_next = PS.due_now(ws, nxt)
|
|
10478
10479
|
ws.audit("tester", "test.after", {})
|
|
10479
10480
|
s2 = PS.write(ws, __version__, "tester", nt, now + timedelta(minutes=5), send=False)
|
|
@@ -13002,6 +13003,313 @@ def section_da_hydraulics(tmp: str) -> None:
|
|
|
13002
13003
|
+ (f" [failed: {', '.join(failed4)}]" if failed4 else ""))
|
|
13003
13004
|
|
|
13004
13005
|
|
|
13006
|
+
def section_db_declarations_engineering(tmp: str) -> None:
|
|
13007
|
+
"""Section DB - the declarations sheet carries the engineering: the survey program, a plan, the pore-pressure
|
|
13008
|
+
settings and a measured pressure, the torque-and-drag string, the hydraulics, a frac stage table and its monitor,
|
|
13009
|
+
production and the decline terms - planned NEW, written, then SAME on a second import and from the template; every
|
|
13010
|
+
malformed row refused with nothing written; the sheet as an Excel workbook; a well with no survey read on the
|
|
13011
|
+
drilling recorder's own TVD, labelled so."""
|
|
13012
|
+
import csv as _csv
|
|
13013
|
+
import io as _io
|
|
13014
|
+
import shutil as _sh
|
|
13015
|
+
import subprocess as _sp
|
|
13016
|
+
from . import __version__ as _ver
|
|
13017
|
+
from . import declarations as DC
|
|
13018
|
+
from . import decline as DCA
|
|
13019
|
+
from . import edr as E
|
|
13020
|
+
from . import frac_hits as FH
|
|
13021
|
+
from . import helplib as H
|
|
13022
|
+
from . import hydraulics as HY
|
|
13023
|
+
from . import pore_pressure as PPF
|
|
13024
|
+
from . import torque_drag as TND
|
|
13025
|
+
from . import wellplan as WPL
|
|
13026
|
+
from . import xlsx_read as XR
|
|
13027
|
+
from .workspace import Workspace
|
|
13028
|
+
pkg = Path(__file__).parent
|
|
13029
|
+
d = Path(tmp, "declare_eng"); d.mkdir()
|
|
13030
|
+
hy = HY.selftest_files(str(d / "hy"))
|
|
13031
|
+
fh = FH.selftest_files(str(d / "fh"))
|
|
13032
|
+
dc = DCA.selftest_files(str(d / "dc"))
|
|
13033
|
+
wsp = str(d / "ws"); ws = Workspace.create(wsp, "Pad 3", actor="tester")
|
|
13034
|
+
w1 = ws.add_well_file(hy["record"], display="HY-1", actor="tester")["id"]
|
|
13035
|
+
w2 = ws.add_well_file(fh["gauge"], display="MON-1", actor="tester")["id"]
|
|
13036
|
+
sheet_dir = d / "sheet"; sheet_dir.mkdir()
|
|
13037
|
+
_sh.copy(hy["survey"], sheet_dir / "plan.csv"); _sh.copy(fh["stages"], sheet_dir / "stages.csv"); _sh.copy(dc["path"], sheet_dir / "production.csv")
|
|
13038
|
+
rows = [
|
|
13039
|
+
["[survey_program]", "well", "program", "source"], ["", "HY-1", "0-1000:MWD+SRGM, 1000-:MWD+IFR1", "survey program rev 1 (test)"],
|
|
13040
|
+
["[plans]", "well", "file", "azimuth_reference", "md_unit", "source"], ["", "HY-1", "plan.csv", "true", "ft", "well plan rev 2 (test)"],
|
|
13041
|
+
["[pore_pressure]", "well", "indicator", "bit_in", "nct_top_m", "nct_bottom_m", "source"], ["", "HY-1", "dexponent", "8.75", "1300", "2000", "drilling program (test)"],
|
|
13042
|
+
["[pressures]", "well", "depth_m", "depth_kind", "value", "unit", "kind", "source"], ["", "HY-1", "2100", "tvd", "13.5", "ppg", "lot", "LOT at the 9-5/8 shoe (test)"],
|
|
13043
|
+
["[torque_drag]", "well", "string", "mud_ppg", "mu_cased", "mu_open", "source"], ["", "HY-1", "BHA:350:6.75:95:6.75; drill pipe::5:22.6:6.625", "11", "0.2", "0.28", "BHA report (test)"],
|
|
13044
|
+
["[hydraulics]", "well", "string", "hole", "mw_ppg", "fann", "flow_gpm", "nozzles_32", "bit_in", "tools_psi", "pp_ppg", "fg_ppg", "source"],
|
|
13045
|
+
["", "HY-1", "BHA:350:6.75:2.875; drill pipe::5:4.276", "9-5/8 casing:3500:8.681; open hole::8.75", "11", "600=60 300=38 100=21 6=7 3=6", "500",
|
|
13046
|
+
"14 14 14 14 14", "8.75", "400", "9.5", "14.5", "mud report (test)"],
|
|
13047
|
+
["[frac_stages]", "well", "file", "depth_unit", "source"], ["", "HY-1", "stages.csv", "ft", "post-job report (test)"],
|
|
13048
|
+
["[frac_monitors]", "well", "channel"], ["", "MON-1", "P_gauge_psi"],
|
|
13049
|
+
["[production]", "well", "file", "source"], ["", "HY-1", "production.csv", "monthly report (test)"],
|
|
13050
|
+
["[decline_terms]", "well", "terminal_decline", "price_basis", "oil_price", "gas_price", "opex_month", "source"], ["", "HY-1", "0.08", "flat", "70", "3", "9000", "budget deck (test)"],
|
|
13051
|
+
]
|
|
13052
|
+
buf = _io.StringIO(); _csv.writer(buf, lineterminator="\n").writerows(rows); text = buf.getvalue()
|
|
13053
|
+
p1 = DC.apply(ws, text, "tester", str(sheet_dir))
|
|
13054
|
+
a1 = DC.apply(ws, text, "tester", str(sheet_dir), write=True)
|
|
13055
|
+
p2 = DC.apply(ws, text, "tester", str(sheet_dir))
|
|
13056
|
+
tpl = DC.template(ws)
|
|
13057
|
+
pt = DC.apply(ws, tpl, "tester", str(sheet_dir))
|
|
13058
|
+
hcfg, tcfg, pcfg = HY.well_config(ws, w1), TND.well_config(ws, w1), PPF.well_config(ws, w1)
|
|
13059
|
+
meas = (PPF._load(ws).get("measured") or {}).get(w1) or []
|
|
13060
|
+
c1 = {
|
|
13061
|
+
"planned": not p1["errors"] and p1["counts"]["NEW"] == 10 and p1["counts"]["CHANGE"] == 0 and sorted({s["table"] for s in p1["steps"]}) == sorted(DC.ENG_ORDER),
|
|
13062
|
+
"written": a1["applied"] and len(a1["written"]) == 10,
|
|
13063
|
+
"landed": WPL.well_settings(ws, w1)["program"] == [{"to_md_m": 1000.0, "model": "MWD+SRGM"}, {"to_md_m": None, "model": "MWD+IFR1"}]
|
|
13064
|
+
and bool(ws.well(w1).get("plan")) and pcfg["indicator"] == "dexponent" and pcfg["bit_in"] == 8.75
|
|
13065
|
+
and meas and meas[0]["kind"] == "lot" and meas[0]["unit"] == "ppg" and len(tcfg["string"]) == 2 and tcfg["mu_open"] == 0.28
|
|
13066
|
+
and hcfg["fann"] == {"600": 60.0, "300": 38.0, "100": 21.0, "6": 7.0, "3": 6.0} and hcfg["nozzles_32"] == [14.0] * 5 and len(hcfg["hole"]) == 2
|
|
13067
|
+
and FH.stages(ws).get(w1, {}).get("stages") == 6 and FH.settings(ws)["monitors"].get(w2, {}).get("channel") == "P_gauge_psi"
|
|
13068
|
+
and DCA.production(ws, w1) and DCA.well_config(ws, w1)["oil_price"] == 70.0,
|
|
13069
|
+
"again": not p2["errors"] and p2["counts"]["NEW"] == 0 and p2["counts"]["CHANGE"] == 0 and p2["counts"]["SAME"] == 10,
|
|
13070
|
+
"template": not pt["errors"] and pt["counts"]["NEW"] == 0 and pt["counts"]["CHANGE"] == 0 and all(f"[{t}]" in tpl for t in DC.ENG_ORDER),
|
|
13071
|
+
}
|
|
13072
|
+
failed1 = [k for k, v in c1.items() if not v]
|
|
13073
|
+
ok(not failed1,
|
|
13074
|
+
"DB1 one sheet carries the engineering - the survey program, a plan, the pore-pressure settings and a leak-off test, the torque-and-drag string, "
|
|
13075
|
+
"the hydraulics (string, hole, mud, viscometer, nozzles), a frac stage table and its monitored well, production and the decline terms: ten rows "
|
|
13076
|
+
"planned NEW, written through each tab's own function, SAME on a second import; the template lists every table and carries what is declared, "
|
|
13077
|
+
"so importing it writes nothing" + (f" [failed: {', '.join(failed1)}]" if failed1 else ""))
|
|
13078
|
+
|
|
13079
|
+
# -- DB2 every malformed row refused, nothing written ---------------------------------------------------------------------
|
|
13080
|
+
bad = {
|
|
13081
|
+
"survey_program": ["", "HY-1", "0-1000:NO-SUCH-TOOL", "x"], "plans": ["", "HY-1", "missing.csv", "true", "ft", "x"],
|
|
13082
|
+
"pore_pressure": ["", "HY-1", "dexponent", "99", "1300", "2000", "x"], "pressures": ["", "HY-1", "2100", "tvd", "13.5", "ppg", "guess", "x"],
|
|
13083
|
+
"torque_drag": ["", "HY-1", "BHA:350", "11", "0.2", "0.28", "x"],
|
|
13084
|
+
"hydraulics": ["", "HY-1", "", "", "11", "600:60", "500", "40 40", "8.75", "400", "9.5", "14.5", "x"],
|
|
13085
|
+
"frac_stages": ["", "HY-1", "stages.csv", "yards", "x"], "decline_terms": ["", "HY-1", "0.08", "spot", "70", "3", "9000", "x"],
|
|
13086
|
+
}
|
|
13087
|
+
errs = {}
|
|
13088
|
+
for t, r in bad.items():
|
|
13089
|
+
hdr = next(x for x in rows if x[0] == f"[{t}]")
|
|
13090
|
+
b_ = _io.StringIO(); _csv.writer(b_, lineterminator="\n").writerows([hdr, r]); bp = DC.apply(ws, b_.getvalue(), "tester", str(sheet_dir), write=True)
|
|
13091
|
+
errs[t] = (len(bp["errors"]) == 1 and not bp["written"] and not bp["applied"])
|
|
13092
|
+
mixed = rows[:2] + [["[pressures]", "well", "depth_m", "value", "kind", "source"], ["", "HY-1", "-5", "13", "pore", "x"]]
|
|
13093
|
+
b_ = _io.StringIO(); _csv.writer(b_, lineterminator="\n").writerows(mixed); mp = DC.apply(ws, b_.getvalue(), "tester", str(sheet_dir), write=True)
|
|
13094
|
+
ok(all(errs.values()) and len(mp["errors"]) == 1 and not mp["written"],
|
|
13095
|
+
"DB2 a tool model that does not exist, a plan file that is not there, a bit size out of range, a pressure of no known kind, a string section "
|
|
13096
|
+
"short of its figures, a viscometer pair without '=' and nozzles over 32/32, a depth unit of yards, a price basis of 'spot' - each refused with "
|
|
13097
|
+
"its row named; a sheet with one bad row writes none of its good rows"
|
|
13098
|
+
+ (f" [failed: {', '.join(k for k, v in errs.items() if not v)}]" if not all(errs.values()) else ""))
|
|
13099
|
+
|
|
13100
|
+
# -- DB3 the sheet as an Excel workbook --------------------------------------------------------------------------------
|
|
13101
|
+
xp = str(d / "declarations.xlsx")
|
|
13102
|
+
DC.template_xlsx(ws, xp)
|
|
13103
|
+
xb = Path(xp).read_bytes()
|
|
13104
|
+
px = DC.apply(ws, XR.text_of(xb), "tester", str(sheet_dir))
|
|
13105
|
+
cli_t = _sp.run([sys.executable, "-m", "gea", "declare", "--workspace", wsp, "--template", str(d / "t2.xlsx")], capture_output=True, text=True, cwd=str(pkg.parent))
|
|
13106
|
+
cli_p = _sp.run([sys.executable, "-m", "gea", "declare", "--workspace", wsp, "--file", str(d / "t2.xlsx")], capture_output=True, text=True, cwd=str(pkg.parent))
|
|
13107
|
+
ok(XR.is_xlsx(xb) and not px["errors"] and px["counts"]["NEW"] == 0 and px["counts"]["CHANGE"] == 0 and px["counts"]["SAME"] >= 10
|
|
13108
|
+
and cli_t.returncode == 0 and XR.is_xlsx(Path(d / "t2.xlsx").read_bytes()) and cli_p.returncode == 0 and "nothing to write" in cli_p.stdout,
|
|
13109
|
+
"DB3 the template as an Excel workbook (gea declare --template declarations.xlsx, and the Download on the Setup page): a workbook the import "
|
|
13110
|
+
"reads back to the same plan - nothing new to write")
|
|
13111
|
+
|
|
13112
|
+
# -- DB4 no survey: the recorder's own TVD -------------------------------------------------------------------------------
|
|
13113
|
+
st = E.read(hy["record"])
|
|
13114
|
+
out = Path(ws.reports_dir, "wells", w1); out.mkdir(parents=True, exist_ok=True)
|
|
13115
|
+
E.write_record(st, str(out), _ver)
|
|
13116
|
+
rp = HY.recorder_path(ws, w1)
|
|
13117
|
+
r_h = HY.page(ws, "workspace", w1)["result"]
|
|
13118
|
+
TND.set_well(ws, "tester", w1, "BHA report (test)", TND.parse_string("BHA:350:6.75:95:6.75; drill pipe::5:22.6:6.625"), 11)
|
|
13119
|
+
r_t = TND.page(ws, "workspace", w1)["result"]
|
|
13120
|
+
from . import well3d as W
|
|
13121
|
+
W.attach_trajectory(ws, w1, "s.csv", Path(hy["survey"]).read_bytes(), "tester", "true", "ft", None, None, None, "test survey")
|
|
13122
|
+
r_s = HY.page(ws, "workspace", w1)["result"]
|
|
13123
|
+
help_txt = H.page("declare") or ""
|
|
13124
|
+
page_src = (pkg / "web" / "app.html").read_text(encoding="utf-8")
|
|
13125
|
+
c4 = {
|
|
13126
|
+
"path": rp and rp["md_ft"][0] == 0.0 and abs(max(rp["tvd_ft"]) - 7480.0) < 30.0 and max(rp["inc_deg"]) <= 61.0 and "not a survey" in rp["source"],
|
|
13127
|
+
"hydraulics": r_h and r_h["path_from"] == "recorder" and "Interpolated TVD" in r_h["how"] and abs(r_h["record"]["median_difference_psi"] - hy["offset_psi"]) <= 10.0
|
|
13128
|
+
and abs(r_h["tvd_td_ft"] - r_s["tvd_td_ft"]) < 30.0,
|
|
13129
|
+
"torque_drag": r_t and r_t["path_from"] == "recorder" and "one vertical plane" in r_t["how"] and 55.0 <= r_t["max_inc_deg"] <= 61.0,
|
|
13130
|
+
"survey_first": r_s["path_from"] == "survey",
|
|
13131
|
+
"help": not H.check("declare") and all(f"[{t}]" in help_txt for t in DC.ENG_ORDER) and "Interpolated TVD" in (H.page("hydraulics") or "")
|
|
13132
|
+
and "/api/declare/template?format=xlsx" in page_src,
|
|
13133
|
+
}
|
|
13134
|
+
failed4 = [k for k, v in c4.items() if not v]
|
|
13135
|
+
ok(not failed4,
|
|
13136
|
+
"DB4 a well with no survey attached is read on the drilling recorder's own Interpolated TVD, labelled as the recorder's interpolation and not a "
|
|
13137
|
+
"survey: the hydraulics' TVDs within 30 ft of the survey's and the standpipe offset recovered the same; torque and drag on an inclination-only path "
|
|
13138
|
+
"in one vertical plane, said so; a survey, once attached, is used instead; the help names every table"
|
|
13139
|
+
+ (f" [failed: {', '.join(failed4)}]" if failed4 else ""))
|
|
13140
|
+
|
|
13141
|
+
|
|
13142
|
+
def section_dc_every_tab(tmp: str) -> None:
|
|
13143
|
+
"""Section DC - every tab and button answers: the Verification tab reads the site reports itself; the Rig time
|
|
13144
|
+
tab and the charts with a live well whose stream has not arrived; a catalogue well only from a gauge series, its
|
|
13145
|
+
well and its gauge depth; one well that cannot be read never stops the refresh or the month-end, and is shown
|
|
13146
|
+
with why; a live seismic station with no recording yet is a state, not a failure; a field left empty is answered
|
|
13147
|
+
in the form's words."""
|
|
13148
|
+
import http.cookiejar
|
|
13149
|
+
import urllib.error
|
|
13150
|
+
import urllib.request
|
|
13151
|
+
from . import dashboard as D
|
|
13152
|
+
from . import hydraulics as HY
|
|
13153
|
+
from . import month_end as ME
|
|
13154
|
+
from .service import Service, Users, friendly_error
|
|
13155
|
+
from .workspace import Workspace, WorkspaceError, catalog_gauge_wells, gauge_entries
|
|
13156
|
+
pkg = Path(__file__).parent
|
|
13157
|
+
page_src = (pkg / "web" / "app.html").read_text(encoding="utf-8")
|
|
13158
|
+
d = Path(tmp, "every_tab"); d.mkdir()
|
|
13159
|
+
hy = HY.selftest_files(str(d / "hy"))
|
|
13160
|
+
wsp = str(d / "ws"); ws = Workspace.create(wsp, "Pad 3", actor="tester")
|
|
13161
|
+
w_edr = ws.add_well_file(hy["record"], display="HY-1", actor="tester")["id"]
|
|
13162
|
+
w_cat = ws.add_well_catalog("volve_f12_f14_production_excerpt", "15/9-F-12", 10000.0, actor="tester")["id"]
|
|
13163
|
+
|
|
13164
|
+
# -- DC1 a catalogue well: a gauge series, a well inside it, a gauge depth -------------------------------------------
|
|
13165
|
+
def answer(*a):
|
|
13166
|
+
try:
|
|
13167
|
+
ws.add_well_catalog(*a, actor="tester")
|
|
13168
|
+
return ""
|
|
13169
|
+
except WorkspaceError as e:
|
|
13170
|
+
return str(e)
|
|
13171
|
+
other = next(k for k in __import__("gea").CATALOG if k not in gauge_entries())
|
|
13172
|
+
m_series, m_empty = answer(other, "", 10000.0), answer("volve_f12_f14_production_excerpt", "", 10000.0)
|
|
13173
|
+
m_wrong, m_md0 = answer("volve_f12_f14_production_excerpt", "15/9-F-99", 10000.0), answer("volve_f12_f14_production_excerpt", "15/9-F-14", 0)
|
|
13174
|
+
m_none = answer("volve_f12_f14_production_excerpt", "15/9-F-14", None)
|
|
13175
|
+
n_wells = len(ws.wells())
|
|
13176
|
+
c1 = {
|
|
13177
|
+
"gauges": gauge_entries() == ["volve_f12_f14_production_excerpt"] and catalog_gauge_wells("volve_f12_f14_production_excerpt") == ["15/9-F-12", "15/9-F-14"]
|
|
13178
|
+
and catalog_gauge_wells(other) == [],
|
|
13179
|
+
"answered": "is not a downhole gauge series" in m_series and "volve_f12_f14_production_excerpt" in m_series
|
|
13180
|
+
and "choose the well inside" in m_empty and "15/9-F-14" in m_empty and "has no well '15/9-F-99'" in m_wrong
|
|
13181
|
+
and "greater than zero" in m_md0 and "the station MD is needed" in m_none,
|
|
13182
|
+
"nothing_added": n_wells == 2,
|
|
13183
|
+
"form": "entries.filter(e => (e.gauge_wells || []).length)" in page_src and '<select id="cWell">' in page_src
|
|
13184
|
+
and "Enter the station MD in feet" in page_src,
|
|
13185
|
+
}
|
|
13186
|
+
failed1 = [k for k, v in c1.items() if not v]
|
|
13187
|
+
ok(not failed1,
|
|
13188
|
+
"DC1 a catalogue well is added only from an entry that carries a downhole gauge series, naming a well inside it and a gauge depth above zero: "
|
|
13189
|
+
"an entry that is not a series, a well left empty or not in the entry, and a depth of zero or none are each answered with what to choose, and "
|
|
13190
|
+
"nothing is added; the form lists only the series and their wells" + (f" [failed: {', '.join(failed1)}]" if failed1 else ""))
|
|
13191
|
+
|
|
13192
|
+
# -- DC2 one well that cannot be read: the refresh and the month-end go on, and say which and why ----------------------
|
|
13193
|
+
bad = ws._register({"id": "old_entry__", "display": "old entry", "kind": "catalog", "files": [],
|
|
13194
|
+
"source": {"entry": other, "well": ""}, "station_md_ft": 10000.0}, "tester")["id"] # as an older version could add it
|
|
13195
|
+
res = ws.refresh_dashboard(actor="tester")
|
|
13196
|
+
rep = res.get("reports") or {}
|
|
13197
|
+
data = D.collect(ws.reports_dir)
|
|
13198
|
+
failed_row = next((w for w in data["wells"] if w["slug"].startswith(other)), {})
|
|
13199
|
+
me = ME.assemble(ws, "2026-09", actor="tester")
|
|
13200
|
+
me_err = " | ".join(me.get("errors") or [])
|
|
13201
|
+
cat_name = f"volve_f12_f14_production_excerpt__15/9-F-12".replace("/", "-")
|
|
13202
|
+
c2 = {
|
|
13203
|
+
"others_reported": "drift" in rep.get(cat_name, []) and "drilling_record" in rep.get(w_edr, []),
|
|
13204
|
+
"failed_named": any("refresh_failed" in v for k, v in rep.items() if k.startswith(other))
|
|
13205
|
+
and os.path.isfile(os.path.join(ws.reports_dir, "wells", f"{other}__", "refresh_failed.json")),
|
|
13206
|
+
"shown": bool(failed_row.get("failed")) and D._drift_status(failed_row)[1].startswith("NOT REPORTED"),
|
|
13207
|
+
"month_end": me.get("included", 0) > 0 and f"well {other}__" in me_err and "dashboard refresh" not in me_err,
|
|
13208
|
+
"page": "w.failed ? statusPill('serious', 'not reported')" in page_src,
|
|
13209
|
+
}
|
|
13210
|
+
ws.remove_well(bad, actor="tester")
|
|
13211
|
+
failed2 = [k for k, v in c2.items() if not v]
|
|
13212
|
+
ok(not failed2,
|
|
13213
|
+
"DC2 a well that cannot be read (a catalogue entry an older version accepted) never stops the refresh: every other well is reported, the "
|
|
13214
|
+
"failed one is written down with why and shown NOT REPORTED on the overview; the month-end packet is assembled and names that one well"
|
|
13215
|
+
+ (f" [failed: {', '.join(failed2)}]" if failed2 else ""))
|
|
13216
|
+
|
|
13217
|
+
# -- DC3 a live well with no stream yet, a live station with no recording yet ------------------------------------------
|
|
13218
|
+
from .wits0 import EXAMPLE_CONFIG as _WITS
|
|
13219
|
+
wits_cfg = d / "wits0.json"
|
|
13220
|
+
wits_cfg.write_text(json.dumps(_WITS), encoding="utf-8")
|
|
13221
|
+
w_live = ws.add_well_live("Rig feed", "wits0", str(wits_cfg), actor="tester")["id"]
|
|
13222
|
+
st = ws.add_live_station("Pad 3 seismometer", {"host": "127.0.0.1", "port": 18000, "streams": [{"network": "XX", "station": "PAD3"}]}, actor="tester")
|
|
13223
|
+
try:
|
|
13224
|
+
ws.refresh_seismic(st["id"], actor="tester")
|
|
13225
|
+
m_seis = ""
|
|
13226
|
+
except WorkspaceError as e:
|
|
13227
|
+
m_seis = str(e)
|
|
13228
|
+
me2 = ME.assemble(ws, "2026-09", actor="tester", refresh=True)
|
|
13229
|
+
with open(os.path.splitext(me2["index"])[0] + ".json", encoding="utf-8") as fh_:
|
|
13230
|
+
me2_items = json.load(fh_).get("items") or []
|
|
13231
|
+
seis_item = next((i for i in me2_items if i["kind"] == "seismic" and i["id"] == st["id"]), {})
|
|
13232
|
+
|
|
13233
|
+
Users(str(Path(wsp, "users.json"))).add("op", "op-pass-123", "operator")
|
|
13234
|
+
svc = Service(wsp, port=0, scheduler=False).start()
|
|
13235
|
+
base_url = svc.url.rstrip("/")
|
|
13236
|
+
o = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(http.cookiejar.CookieJar()))
|
|
13237
|
+
|
|
13238
|
+
def call(method, path, body=None):
|
|
13239
|
+
rq = urllib.request.Request(base_url + path, method=method, data=(json.dumps(body).encode() if body is not None else None))
|
|
13240
|
+
rq.add_header("Content-Type", "application/json"); rq.add_header("X-GEA-Action", "1")
|
|
13241
|
+
try:
|
|
13242
|
+
with o.open(rq, timeout=120) as rr_:
|
|
13243
|
+
return rr_.status, json.loads(rr_.read())
|
|
13244
|
+
except urllib.error.HTTPError as e:
|
|
13245
|
+
return e.code, json.loads(e.read())
|
|
13246
|
+
try:
|
|
13247
|
+
call("POST", "/api/login", {"name": "op", "password": "op-pass-123"})
|
|
13248
|
+
st_rig, rig = call("GET", "/api/rig-time")
|
|
13249
|
+
st_cm, cm = call("GET", f"/api/wells/{w_live}/chart/meta")
|
|
13250
|
+
st_cx, _ = call("GET", "/api/wells/no-such-well/chart/meta")
|
|
13251
|
+
st_cat, cat = call("GET", "/api/catalog")
|
|
13252
|
+
st_add, add = call("POST", "/api/wells/catalog", {"entry": other, "well": "", "station_md": 10000})
|
|
13253
|
+
st_pp, pp = call("POST", "/api/pore-pressure/measure", {"well_id": w_edr, "depth_m": "", "value": "", "unit": "psi", "kind": "pore", "source": "x"})
|
|
13254
|
+
st_cf, cf = call("GET", "/api/config/")
|
|
13255
|
+
st_cd, cd = call("GET", "/api/config/defaults/")
|
|
13256
|
+
st_fw, fw = call("POST", "/api/files/watch", {"root": ""})
|
|
13257
|
+
st_sl, sl = call("GET", "/api/seismic")
|
|
13258
|
+
st_tp, tp = call("POST", f"/api/wells/{w_edr}/transient-params", {"params": {"mu_cp": 0.8}})
|
|
13259
|
+
st_tp0, tp0 = call("POST", f"/api/wells/{w_edr}/transient-params", {"params": {}})
|
|
13260
|
+
finally:
|
|
13261
|
+
svc.stop()
|
|
13262
|
+
gauges_api = {e["entry"]: e["gauge_wells"] for e in cat.get("entries", []) if e.get("gauge_wells")}
|
|
13263
|
+
c3 = {
|
|
13264
|
+
"seismic": "has no recording yet" in m_seis and seis_item.get("status") == "NOT AVAILABLE" and "no recording yet" in seis_item.get("reason", "")
|
|
13265
|
+
and not any(st["id"] in e for e in me2.get("errors") or []),
|
|
13266
|
+
"rig_time": st_rig == 200 and isinstance(rig, dict),
|
|
13267
|
+
"chart": st_cm == 200 and cm.get("available") is False and bool(cm.get("reason")) and st_cx == 404
|
|
13268
|
+
and "meta.available === false" in page_src,
|
|
13269
|
+
"catalog_api": st_cat == 200 and gauges_api == {"volve_f12_f14_production_excerpt": ["15/9-F-12", "15/9-F-14"]}
|
|
13270
|
+
and st_add == 400 and "is not a downhole gauge series" in add.get("error", ""),
|
|
13271
|
+
"site_reports": st_sl == 200 and "site_reports" in sl,
|
|
13272
|
+
}
|
|
13273
|
+
failed3 = [k for k, v in c3.items() if not v]
|
|
13274
|
+
ok(not failed3,
|
|
13275
|
+
"DC3 a live seismic station whose feed has written nothing is answered as having no recording yet and is NOT AVAILABLE in the month-end, not "
|
|
13276
|
+
"a failure; the Rig time tab answers with a live well whose stream has not arrived; that well's chart says there is nothing to chart yet "
|
|
13277
|
+
"(an unknown well is still not found); the catalogue API names each series' wells and answers a well that is not one with what to choose"
|
|
13278
|
+
+ (f" [failed: {', '.join(failed3)}]" if failed3 else ""))
|
|
13279
|
+
|
|
13280
|
+
# -- DC4 the form's words, and the Verification tab's own data -------------------------------------------------------------
|
|
13281
|
+
def _tls_msg():
|
|
13282
|
+
from . import tls as TLS
|
|
13283
|
+
try:
|
|
13284
|
+
TLS.use_site_certificate(ws, "tester", "", "")
|
|
13285
|
+
return ""
|
|
13286
|
+
except ValueError as e:
|
|
13287
|
+
return str(e)
|
|
13288
|
+
verify = page_src[page_src.index("VIEWS.verify = async"):]
|
|
13289
|
+
verify = verify[:verify.index("\nVIEWS.", 10)] if "\nVIEWS." in verify[10:] else verify
|
|
13290
|
+
c4 = {
|
|
13291
|
+
"words": friendly_error("could not convert string to float: ''") == "a number is needed: a field was left empty"
|
|
13292
|
+
and friendly_error("could not convert string to float: 'abc'") == "'abc' is not a number"
|
|
13293
|
+
and friendly_error("no such well") == "no such well",
|
|
13294
|
+
"pore": st_pp == 400 and pp.get("error") == "a number is needed: a field was left empty",
|
|
13295
|
+
"config": st_cf == 404 and "choose a configuration by name first" in cf.get("error", "")
|
|
13296
|
+
and st_cd == 404 and "choose a configuration by name first" in cd.get("error", "")
|
|
13297
|
+
and page_src.count("if (!$('#cfgName').value.trim()) return toast('Choose a configuration by name first', 'err');") == 3,
|
|
13298
|
+
"watch": st_fw == 400 and "add an import root under Administration first" in fw.get("error", "")
|
|
13299
|
+
and "w.title = 'Add an import root under Administration first'" in page_src,
|
|
13300
|
+
"params": st_tp == 200 and st_tp0 == 200 and "unknown parameter" not in json.dumps(tp0),
|
|
13301
|
+
"tls_path": _tls_msg().startswith("give the certificate file's full path"),
|
|
13302
|
+
"verify": "let siteReports = {}; try { siteReports = (await get('/api/seismic')).site_reports || {}; }" in verify
|
|
13303
|
+
and verify.index("let siteReports") < verify.index("siteReports.seismic_dataset_report"),
|
|
13304
|
+
}
|
|
13305
|
+
failed4 = [k for k, v in c4.items() if not v]
|
|
13306
|
+
ok(not failed4,
|
|
13307
|
+
"DC4 a field left empty, or text where a number goes, is answered in the form's words rather than the program's; a configuration button with "
|
|
13308
|
+
"no name chosen, a folder watch with no import root and the site's certificate with no path given say what to do first; a well's transient "
|
|
13309
|
+
"parameters saved empty are cleared; the Verification tab reads the site reports itself"
|
|
13310
|
+
+ (f" [failed: {', '.join(failed4)}]" if failed4 else ""))
|
|
13311
|
+
|
|
13312
|
+
|
|
13005
13313
|
def PR_read_ok(path) -> bool:
|
|
13006
13314
|
from . import pdf_report as PR
|
|
13007
13315
|
try:
|
|
@@ -13118,6 +13426,8 @@ def main() -> int:
|
|
|
13118
13426
|
section_cy_company_sign_in(tmp)
|
|
13119
13427
|
section_cz_it_review(tmp)
|
|
13120
13428
|
section_da_hydraulics(tmp)
|
|
13429
|
+
section_db_declarations_engineering(tmp)
|
|
13430
|
+
section_dc_every_tab(tmp)
|
|
13121
13431
|
if _FAILS:
|
|
13122
13432
|
print(f"[ACCEPTANCE] {len(_FAILS)} FAILURES ({_PASS} passed):")
|
|
13123
13433
|
for f in _FAILS:
|