gea-program 0.64.0__tar.gz → 0.65.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.64.0/gea_program.egg-info → gea_program-0.65.0}/PKG-INFO +29 -2
- {gea_program-0.64.0 → gea_program-0.65.0}/README.md +28 -1
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/__init__.py +1 -1
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/__main__.py +19 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/acceptance_tests.py +332 -1
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/IT_SECURITY.md +25 -1
- gea_program-0.65.0/gea/help/install.md +21 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/start.md +1 -1
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/helplib.py +1 -0
- gea_program-0.65.0/gea/icon.py +126 -0
- gea_program-0.65.0/gea/launcher.py +418 -0
- gea_program-0.65.0/gea/tray.py +381 -0
- {gea_program-0.64.0 → gea_program-0.65.0/gea_program.egg-info}/PKG-INFO +29 -2
- {gea_program-0.64.0 → gea_program-0.65.0}/gea_program.egg-info/SOURCES.txt +4 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/pyproject.toml +1 -1
- {gea_program-0.64.0 → gea_program-0.65.0}/LICENSE +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/BENCH_TEST_PROTOCOL.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/accuracy_statement.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/alarm_engine.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/alerts.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/backup.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/bench.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/blind_harness.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/casing_design.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/acex_lomonosov_age_depth_model.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/acex_lomonosov_age_depth_model.txt +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/agassiz77_canada_temperature.csv +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/agassiz77_canada_temperature.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/barbados_110_consolidation.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/barbados_110_consolidation.txt +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/bengal_u1452_grain_size.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/bengal_u1452_grain_size.txt +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/blake_164_methane_isotopes.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/blake_164_methane_isotopes.txt +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/chicxulub_m0077a_pwave_velocity.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/chicxulub_m0077a_pwave_velocity.txt +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/collingwood_1_28_ks_complete.las +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/collingwood_1_28_ks_complete.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/costa_rica_odp_friction_envelope.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/costa_rica_odp_friction_envelope.txt +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/dead_sea_5017_debrite_xrf_ms.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/dead_sea_5017_debrite_xrf_ms.txt +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/dsdp_504b_physical_properties.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/dsdp_504b_physical_properties.txt +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/dsdp_504b_sound_velocity.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/dsdp_504b_sound_velocity.txt +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/elgygytgyn_5011_turbidites.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/elgygytgyn_5011_turbidites.txt +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/epica_domec_co2_800kyr.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/epica_domec_co2_800kyr.txt +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/fram_909_organic_petrography.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/fram_909_organic_petrography.txt +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/gbr_325_coral_uth_ages.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/gbr_325_coral_uth_ages.txt +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/gisp2_greenland_temperature.csv +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/gisp2_greenland_temperature.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/gom_308_t2p_insitu.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/gom_308_t2p_insitu.txt +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/guaymas_385_dom_d13c.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/guaymas_385_dom_d13c.txt +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/hikurangi_u1520_friction_insitu.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/hikurangi_u1520_friction_insitu.txt +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/hydrate_ridge_204_ncr_hydrate.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/hydrate_ridge_204_ncr_hydrate.txt +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/iodp_u1324_pore_pressure.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/iodp_u1324_pore_pressure.txt +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/jfast_c0019_slow_slip_events.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/jfast_c0019_slow_slip_events.txt +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/kennetcook_2_p129_excerpt.las +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/kennetcook_2_p129_excerpt.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/ktb_hb_bhgm_density.dat +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/ktb_hb_bhgm_density.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/ktb_hb_complog_6020_excerpt.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/ktb_hb_complog_6020_excerpt.txt +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/ktb_hb_hlog246_temperature.dat +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/ktb_hb_hlog246_temperature.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/ktb_hb_rockmech_compress.dat +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/ktb_hb_rockmech_compress.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/ktb_hb_tvd_0_9080_excerpt.dat +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/ktb_hb_tvd_0_9080_excerpt.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/ktb_vb_rockmech_compress.dat +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/ktb_vb_rockmech_compress.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/ktb_vb_vlog251_temperature.dat +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/ktb_vb_vlog251_temperature.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/l06_06_nl_survey.csv +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/l06_06_nl_survey.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/l07_01_nl_excerpt.las +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/l07_01_nl_excerpt.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/mariana_1200_serpentinite_geochem.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/mariana_1200_serpentinite_geochem.txt +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/med_160_sapropels.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/med_160_sapropels.txt +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/nankai_megasplay_shear_strength.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/nankai_megasplay_shear_strength.txt +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/odp_1027b_thermal_conductivity.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/odp_1027b_thermal_conductivity.txt +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/odp_1027c_cork_temperature.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/odp_1027c_cork_temperature.txt +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/odp_1165b_thermal_conductivity.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/odp_1165b_thermal_conductivity.txt +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/odp_1274a_mantle_peridotite_mad.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/odp_1274a_mantle_peridotite_mad.txt +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/odp_504b_dike_elastic_moduli.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/odp_504b_dike_elastic_moduli.txt +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/odp_504b_leg137_borehole_fluids.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/odp_504b_leg137_borehole_fluids.txt +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/odp_735b_gabbro_elastic_moduli.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/odp_735b_gabbro_elastic_moduli.txt +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/peru_201_sulfate_reduction.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/peru_201_sulfate_reduction.txt +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/scorpio_e1_sa_excerpt.las +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/scorpio_e1_sa_excerpt.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/sumatra_362_cohesion.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/sumatra_362_cohesion.txt +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/university_6_17_no1_tx_excerpt.las +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/university_6_17_no1_tx_excerpt.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/ursa_308_xrd_mineralogy.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/ursa_308_xrd_mineralogy.txt +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/volve_15_9_19_sr_excerpt.las +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/volve_15_9_19_sr_excerpt.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/volve_15_9_19a_core_excerpt.csv +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/volve_15_9_19a_core_excerpt.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/volve_f12_f14_production_excerpt.csv +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/volve_f12_f14_production_excerpt.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/walvis_208_petm_carbonate.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/walvis_208_petm_carbonate.txt +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/woodlark_1109_rock_eval.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog/woodlark_1109_rock_eval.txt +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog_map.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/catalog_register.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/certificates.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/cli.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/client_reports.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/collision.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/config_versioning.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/conformance.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/control_room.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/correlation.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/dashboard.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/declarations.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/decline.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/deviation.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/dlis.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/dnp3.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/doctor.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/dossier.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/dossier_verify.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/downhole_engine.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/drift_monitor.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/drill_string.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/earth_model.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/economics.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/ed25519.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/edr.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/elevation.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/etp.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/etp12_schemas.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/example_register_map.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/fat_sat.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/files.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/fixtures/README.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/fixtures/comcat_delaware_basin_2026-09.txt +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/fixtures/comcat_mahoning_1990-2026.txt +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/fixtures/comcat_youngstown_2011-2012.txt +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/fixtures/ne_110m_coastline.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/follower.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/forward_model.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/frac_hits.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/friction_priors.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/gamma.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/gauge_aging.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/gauge_specs.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/geodesy.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/geomag.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/gravity_reference.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/hartip.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/TESTER_GUIDE.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/alarms.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/alerts.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/audit-update.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/backup.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/casing.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/catalog.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/charts.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/collision.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/company-sign-in.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/conformance.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/control-room.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/data-in.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/declare.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/decline.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/dlis.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/doctor.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/dossier.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/drift.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/drillstring.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/economics.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/edr.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/etp.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/field-ports.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/files.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/frac-hits.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/historian.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/https.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/hydraulics.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/instruments.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/interval.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/invoice-check.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/map.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/month-end.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/notifications.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/opseis.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/osdu.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/pad-summary.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/patches.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/penetrator.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/plan.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/pore-pressure.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/ppdm.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/quakeml.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/quality.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/report-history.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/rig-time.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/seedlink.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/seismic.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/setup.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/simulation.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/site.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/sites.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/slip.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/soak.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/sra.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/structure.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/tools.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/torque-drag.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/transients.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/upkeep.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/vibration.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/well-report.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/well-tests.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/help/well3d.md +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/housekeeping.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/hydraulics.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/interval.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/inverse_engine.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/invoice_check.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/jobs.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/live_ports.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/loadtest.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/matplotlib_demo.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/modbus.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/modbus_rtu.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/model_card.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/month_end.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/mqtt_port.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/notify.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/oidc.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/oidc_mock.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/op_seismicity.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/opcua_port.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/operator_app.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/osdu.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/pad_summary.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/patches.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/pdf_report.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/penetrator.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/permits.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/piwebapi.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/pore_pressure.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/ports.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/ppdm.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/profile_catalog.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/project.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/qt6_downhole_app.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/quakeml.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/reconciler.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/reference/IU_ANMO_10_BHZ_response.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/reference/IU_ANMO_10_BHZ_response.xml +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/reference/WMM2025.COF +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/reference/eia_henry_hub_daily.csv.gz +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/reference/eia_prices.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/reference/eia_wti_daily.csv.gz +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/reference/iscwsa_rev4_example.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/reference/iscwsa_rev5_example.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/reference/l0701_sonic_gr.las.gz +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/reference/l0701_sonic_gr.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/reference/libmseed_steim.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/reference/libmseed_steim1_4096.mseed +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/reference/libmseed_steim2_4096.mseed +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/reference/libmseed_steim2_512.mseed +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/reference/mahoning_example.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/reference/mud_motor_specs.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/reference/owsg_tool_models.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/reference/penetrator_ratings.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/reference/seismicity_protocols.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/reference/tool_sources.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/reference/us_outline.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/reference/us_outline.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/reference/volve_3d.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/reference/volve_f4_interpretation.las.gz +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/reference/volve_f4_logs.provenance.json +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/reference/volve_f4_lwd.las.gz +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/reference/volve_surfaces.json.gz +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/reference/volve_traj_F-10.xml.gz +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/reference/volve_traj_F-4.xml.gz +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/reference/volve_traj_F-5_12.25in.xml.gz +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/reference/volve_traj_F-5_17.5in.xml.gz +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/reference/volve_traj_F-5_36in.xml.gz +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/reference/volve_traj_F-5_8.5in.xml.gz +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/reference/volve_well_picks.csv.gz +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/report_history.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/rig_state.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/rock_inventory.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/sample_record.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/sample_well_profile.csv +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/sbom.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/seedlink.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/segy.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/seismic.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/seismic_array.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/seismic_assoc.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/seismic_detect.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/seismic_film.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/seismic_harmonic.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/seismic_qc.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/seismic_response.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/seismic_signature.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/seismic_track.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/seismic_uncertainty.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/seismic_unlisted.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/seismic_watch.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/sensor_swap.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/series_cache.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/service.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/service_life.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/setup_checklist.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/shapefile.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/shell.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/shut_in.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/simulation.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/site_map.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/sla_report.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/slip.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/soak.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/sra.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/store_forward.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/strata_join.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/structure.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/supervisor.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/survey_cmd.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/survey_view.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/telemetry.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/timestamp.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/tls.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/tool_catalog.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/tool_library.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/tool_taxonomy.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/torque_drag.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/transient.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/vibration.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/web/app.html +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/well3d.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/well_assembler.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/well_report.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/well_test_validation.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/wellplan.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/wellpos.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/wits0.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/witsml.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/workspace.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea/xlsx_read.py +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea_program.egg-info/dependency_links.txt +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea_program.egg-info/entry_points.txt +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea_program.egg-info/requires.txt +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/gea_program.egg-info/top_level.txt +0 -0
- {gea_program-0.64.0 → gea_program-0.65.0}/setup.cfg +0 -0
- {gea_program-0.64.0 → gea_program-0.65.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.65.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
|
|
@@ -1424,6 +1424,33 @@ builds the Windows and Linux kits in CI (`build-installer.yml`), installs
|
|
|
1424
1424
|
them the way a client does, runs the gate from the installed kit, and
|
|
1425
1425
|
attaches the zips to the GitHub release of that tag.
|
|
1426
1426
|
|
|
1427
|
+
### The Windows installer
|
|
1428
|
+
|
|
1429
|
+
Every release also carries `GEA-Program-Setup-0.65.0.exe` (for 0.65.0): the
|
|
1430
|
+
same Windows kit installed like any Windows program, for the signed-in user
|
|
1431
|
+
alone and with no administrator rights (`%LOCALAPPDATA%\Programs\GEA-Program`).
|
|
1432
|
+
It asks for the site workspace (an existing one such as `C:\site` is used as
|
|
1433
|
+
it is), runs the kit's `install.cmd` with no network, and adds Start-menu and
|
|
1434
|
+
desktop shortcuts, an Add/Remove Programs entry and, when chosen, a start at
|
|
1435
|
+
sign-in. The shortcut **GEA-Program** starts the control panel when it is not
|
|
1436
|
+
running and opens it in Microsoft Edge's app window (its own window and
|
|
1437
|
+
taskbar button; Chrome's, else a browser tab, where Edge is missing); the
|
|
1438
|
+
program's icon in the notification area says whether the panel is running
|
|
1439
|
+
and opens, starts or stops it (`gea launch`, `gea tray`). A newer setup
|
|
1440
|
+
installs over the older one after stopping the panel; the uninstaller stops
|
|
1441
|
+
it, removes the program and leaves the workspace. Silent, for a site's
|
|
1442
|
+
software deployment:
|
|
1443
|
+
|
|
1444
|
+
```
|
|
1445
|
+
GEA-Program-Setup-0.65.0.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /WORKSPACE="C:\site" /TASKS="desktopicon"
|
|
1446
|
+
```
|
|
1447
|
+
|
|
1448
|
+
The setup is built by Inno Setup 6 from `tools/installer.iss` in the same
|
|
1449
|
+
workflow, signed with the publisher's certificate when one is configured
|
|
1450
|
+
(unsigned, with a notice, until then), attested, and installed, upgraded in
|
|
1451
|
+
place with the control panel running, and uninstalled on the build machine
|
|
1452
|
+
before it is attached. `gea help install`.
|
|
1453
|
+
|
|
1427
1454
|
## Layout
|
|
1428
1455
|
|
|
1429
1456
|
```
|
|
@@ -1435,7 +1462,7 @@ docs/report_samples/ one rendered example of every client report, from this bui
|
|
|
1435
1462
|
docs/ TESTER_GUIDE.md, REQUIREMENTS_MATRIX.md (the scope-of-work mirror that shaped the reports), examples/ (port configs),
|
|
1436
1463
|
SESSION_LOG.md (the working record, session by session),
|
|
1437
1464
|
commercial/ (pilot proposal, bench readiness, commercial use), HISTORY.md (the ship-by-ship record)
|
|
1438
|
-
tools/ standalone_check.py (the self-contained guard; run by ci and ship.ps1), build_installer.py (the kit),
|
|
1465
|
+
tools/ standalone_check.py (the self-contained guard; run by ci and ship.ps1), build_installer.py (the kit), installer.iss (the Windows setup),
|
|
1439
1466
|
render_report_samples.py (docs/report_samples), seismic_reader_check.py (the reader against libmseed)
|
|
1440
1467
|
CHANGELOG.md per-release summary (a tag ships only with its section); SHIP_LOG.md is written by ship.ps1
|
|
1441
1468
|
tests/ pytest wrapper around the acceptance suite and the standalone check
|
|
@@ -1385,6 +1385,33 @@ builds the Windows and Linux kits in CI (`build-installer.yml`), installs
|
|
|
1385
1385
|
them the way a client does, runs the gate from the installed kit, and
|
|
1386
1386
|
attaches the zips to the GitHub release of that tag.
|
|
1387
1387
|
|
|
1388
|
+
### The Windows installer
|
|
1389
|
+
|
|
1390
|
+
Every release also carries `GEA-Program-Setup-0.65.0.exe` (for 0.65.0): the
|
|
1391
|
+
same Windows kit installed like any Windows program, for the signed-in user
|
|
1392
|
+
alone and with no administrator rights (`%LOCALAPPDATA%\Programs\GEA-Program`).
|
|
1393
|
+
It asks for the site workspace (an existing one such as `C:\site` is used as
|
|
1394
|
+
it is), runs the kit's `install.cmd` with no network, and adds Start-menu and
|
|
1395
|
+
desktop shortcuts, an Add/Remove Programs entry and, when chosen, a start at
|
|
1396
|
+
sign-in. The shortcut **GEA-Program** starts the control panel when it is not
|
|
1397
|
+
running and opens it in Microsoft Edge's app window (its own window and
|
|
1398
|
+
taskbar button; Chrome's, else a browser tab, where Edge is missing); the
|
|
1399
|
+
program's icon in the notification area says whether the panel is running
|
|
1400
|
+
and opens, starts or stops it (`gea launch`, `gea tray`). A newer setup
|
|
1401
|
+
installs over the older one after stopping the panel; the uninstaller stops
|
|
1402
|
+
it, removes the program and leaves the workspace. Silent, for a site's
|
|
1403
|
+
software deployment:
|
|
1404
|
+
|
|
1405
|
+
```
|
|
1406
|
+
GEA-Program-Setup-0.65.0.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /WORKSPACE="C:\site" /TASKS="desktopicon"
|
|
1407
|
+
```
|
|
1408
|
+
|
|
1409
|
+
The setup is built by Inno Setup 6 from `tools/installer.iss` in the same
|
|
1410
|
+
workflow, signed with the publisher's certificate when one is configured
|
|
1411
|
+
(unsigned, with a notice, until then), attested, and installed, upgraded in
|
|
1412
|
+
place with the control panel running, and uninstalled on the build machine
|
|
1413
|
+
before it is attached. `gea help install`.
|
|
1414
|
+
|
|
1388
1415
|
## Layout
|
|
1389
1416
|
|
|
1390
1417
|
```
|
|
@@ -1396,7 +1423,7 @@ docs/report_samples/ one rendered example of every client report, from this bui
|
|
|
1396
1423
|
docs/ TESTER_GUIDE.md, REQUIREMENTS_MATRIX.md (the scope-of-work mirror that shaped the reports), examples/ (port configs),
|
|
1397
1424
|
SESSION_LOG.md (the working record, session by session),
|
|
1398
1425
|
commercial/ (pilot proposal, bench readiness, commercial use), HISTORY.md (the ship-by-ship record)
|
|
1399
|
-
tools/ standalone_check.py (the self-contained guard; run by ci and ship.ps1), build_installer.py (the kit),
|
|
1426
|
+
tools/ standalone_check.py (the self-contained guard; run by ci and ship.ps1), build_installer.py (the kit), installer.iss (the Windows setup),
|
|
1400
1427
|
render_report_samples.py (docs/report_samples), seismic_reader_check.py (the reader against libmseed)
|
|
1401
1428
|
CHANGELOG.md per-release summary (a tag ships only with its section); SHIP_LOG.md is written by ship.ps1
|
|
1402
1429
|
tests/ pytest wrapper around the acceptance suite and the standalone check
|
|
@@ -815,6 +815,19 @@ def main(argv=None) -> int:
|
|
|
815
815
|
p_sv.add_argument("--behind-proxy", action="store_true", help="a reverse proxy terminates TLS in front: trust X-Forwarded-For/-Proto, mark the cookie Secure (deploy/ has nginx and Caddy examples)")
|
|
816
816
|
p_sv.add_argument("--no-browser", action="store_true", help="do not open the control panel in a browser once the service is listening (a scheduled start, a restart, a server with no desktop)")
|
|
817
817
|
|
|
818
|
+
p_la = sub.add_parser("launch", help="the control panel as a desktop program: start it when it is not running, open it in a window of its own (Edge's app window, else Chrome's, else the browser), put its icon in the notification area")
|
|
819
|
+
p_la.add_argument("--workspace", type=str, default=None, help="the workspace folder (default: GEA_WORKSPACE, else the installer's choice, else %%LOCALAPPDATA%%\\GEA-Program\\site)")
|
|
820
|
+
p_la.add_argument("--port", type=int, default=8765)
|
|
821
|
+
p_la.add_argument("--background", action="store_true", help="start the control panel and its icon without opening a window (the logon task)")
|
|
822
|
+
p_la.add_argument("--no-tray", action="store_true", help="no notification-area icon")
|
|
823
|
+
p_la.add_argument("--selftest", action="store_true", help="say what a launch would do here (the kit, the workspace, the window, the command), start nothing")
|
|
824
|
+
p_la.add_argument("--json", action="store_true")
|
|
825
|
+
p_la.add_argument("--set-workspace", type=str, default=None, help="record the site workspace for this installation (the installer runs it; never a folder inside the program's own)")
|
|
826
|
+
p_ty = sub.add_parser("tray", help="the program's icon in the Windows notification area: running or stopped, and a menu to open, start or stop the control panel")
|
|
827
|
+
p_ty.add_argument("--workspace", type=str, default=None, help="the workspace folder (as gea launch finds it)")
|
|
828
|
+
p_ty.add_argument("--port", type=int, default=8765)
|
|
829
|
+
p_ty.add_argument("--selftest", action="store_true", help="make the icon and its menu, show it for a moment and take it away")
|
|
830
|
+
|
|
818
831
|
p_tl = sub.add_parser("tls", help="HTTPS for the dashboard: the site's own certificate, a self-signed one made here, or off; with no option, how it stands")
|
|
819
832
|
p_tl.add_argument("--workspace", type=str, required=True)
|
|
820
833
|
p_tl.add_argument("--site-cert", type=str, default=None, help="the site's certificate (PEM, the server's first, then any chain) - read from where it is at every start")
|
|
@@ -3211,6 +3224,12 @@ def main(argv=None) -> int:
|
|
|
3211
3224
|
if n.get(k):
|
|
3212
3225
|
print(f" {k}: {n[k]}")
|
|
3213
3226
|
return 0
|
|
3227
|
+
elif a.cmd == "launch":
|
|
3228
|
+
from .launcher import main as _launch
|
|
3229
|
+
return _launch(a)
|
|
3230
|
+
elif a.cmd == "tray":
|
|
3231
|
+
from .tray import main as _tray
|
|
3232
|
+
return _tray(a)
|
|
3214
3233
|
elif a.cmd == "serve":
|
|
3215
3234
|
from .service import Service
|
|
3216
3235
|
from .workspace import WorkspaceError
|
|
@@ -12768,7 +12768,7 @@ def section_cz_it_review(tmp: str) -> None:
|
|
|
12768
12768
|
not_kit = "accepted"
|
|
12769
12769
|
except SystemExit as e:
|
|
12770
12770
|
not_kit = str(e)
|
|
12771
|
-
readme = bi.README.format(version="9.9.9", target="Windows x64", pyline="p", install="i", start="s", verify="v", port="8765",
|
|
12771
|
+
readme = bi.README.format(desktop=bi.WIN_DESKTOP.format(version="9.9.9"), version="9.9.9", target="Windows x64", pyline="p", install="i", start="s", verify="v", port="8765",
|
|
12772
12772
|
service="sv", stop="st", uninstall="u", workspace="w", check=bi.WIN_CHECK.format(version="9.9.9"))
|
|
12773
12773
|
build_src = (pkg.parent / "tools" / "build_installer.py").read_text(encoding="utf-8")
|
|
12774
12774
|
c2 = {
|
|
@@ -14219,6 +14219,336 @@ def PR_read_ok(path) -> bool:
|
|
|
14219
14219
|
return False
|
|
14220
14220
|
|
|
14221
14221
|
|
|
14222
|
+
def _iss_sections(text: str) -> dict:
|
|
14223
|
+
"""An Inno Setup script by section: {name: [lines]}, comments and blank lines left out; [Code] kept whole."""
|
|
14224
|
+
out, cur = {}, None
|
|
14225
|
+
for ln in text.splitlines():
|
|
14226
|
+
st = ln.strip()
|
|
14227
|
+
if st.startswith("[") and st.endswith("]") and (cur != "Code" or st == "[Code]"):
|
|
14228
|
+
cur = st[1:-1]; out.setdefault(cur, []); continue
|
|
14229
|
+
if cur is None or (cur != "Code" and (not st or st.startswith(";"))):
|
|
14230
|
+
continue
|
|
14231
|
+
out[cur].append(ln)
|
|
14232
|
+
return out
|
|
14233
|
+
|
|
14234
|
+
|
|
14235
|
+
def _iss_entry(line: str) -> dict:
|
|
14236
|
+
"""`Name: "x"; Flags: a b` -> {'Name': 'x', 'Flags': 'a b'} - split on ';' outside double quotes, "" kept as "."""
|
|
14237
|
+
parts, buf, q = [], "", False
|
|
14238
|
+
for ch in line:
|
|
14239
|
+
if ch == '"':
|
|
14240
|
+
q = not q
|
|
14241
|
+
if ch == ";" and not q:
|
|
14242
|
+
parts.append(buf); buf = ""
|
|
14243
|
+
else:
|
|
14244
|
+
buf += ch
|
|
14245
|
+
parts.append(buf)
|
|
14246
|
+
out = {}
|
|
14247
|
+
for p in parts:
|
|
14248
|
+
if not p.strip():
|
|
14249
|
+
continue
|
|
14250
|
+
k, _, v = p.partition(":")
|
|
14251
|
+
v = v.strip()
|
|
14252
|
+
if v.startswith('"') and v.endswith('"') and len(v) >= 2:
|
|
14253
|
+
v = v[1:-1].replace('""', '"')
|
|
14254
|
+
out[k.strip()] = v
|
|
14255
|
+
return out
|
|
14256
|
+
|
|
14257
|
+
|
|
14258
|
+
def section_dh_windows_installer(tmp: str) -> None:
|
|
14259
|
+
"""Section DH - the Windows installer: the icon drawn in code and read back as an .ico; the launcher's choices (the
|
|
14260
|
+
kit, the workspace, the window, the command) and the workspace it records, never inside the program's folder; the
|
|
14261
|
+
notification-area icon's menu and notices; the kit's scripts (a stop that needs no wmic and stops the restart loop
|
|
14262
|
+
first, a logon start that returns); the Inno Setup script (per-user, nothing deleted outside the program's folder,
|
|
14263
|
+
the control panel stopped before an upgrade and an uninstall, a failed install says so) and the workflow that
|
|
14264
|
+
builds, signs, installs, upgrades and uninstalls it; the command line and the help."""
|
|
14265
|
+
import importlib.util
|
|
14266
|
+
import re as _re
|
|
14267
|
+
import socket as _socket
|
|
14268
|
+
import struct as _struct
|
|
14269
|
+
import zlib as _zlib
|
|
14270
|
+
from . import helplib as H
|
|
14271
|
+
from . import icon as IC
|
|
14272
|
+
from . import launcher as L
|
|
14273
|
+
from . import tray as TR
|
|
14274
|
+
from .doctor import kit_dir as _doctor_kit
|
|
14275
|
+
pkg = Path(__file__).parent
|
|
14276
|
+
d = Path(tmp, "windows_installer"); d.mkdir()
|
|
14277
|
+
checkout = (pkg.parent / "pyproject.toml").exists() and (pkg.parent / "tools" / "installer.iss").exists()
|
|
14278
|
+
|
|
14279
|
+
# -- DH1 the icon ---------------------------------------------------------------------------------------------------------------
|
|
14280
|
+
ico = IC.ico_bytes()
|
|
14281
|
+
imgs = IC.read_ico(ico)
|
|
14282
|
+
p256 = IC.png(256)
|
|
14283
|
+
w, h = _struct.unpack(">II", p256[16:24])
|
|
14284
|
+
idat_at = p256.index(b"IDAT")
|
|
14285
|
+
raw = _zlib.decompress(p256[idat_at + 4:idat_at + 4 + _struct.unpack(">I", p256[idat_at - 4:idat_at])[0]])
|
|
14286
|
+
run16, stop16 = IC.draw(16, True), IC.draw(16, False)
|
|
14287
|
+
dib32 = IC.dib(32)
|
|
14288
|
+
c1 = {
|
|
14289
|
+
"sizes": [(x[0], x[3]) for x in imgs] == [(16, "dib"), (20, "dib"), (24, "dib"), (32, "dib"), (40, "dib"), (48, "dib"), (64, "dib"), (256, "png")],
|
|
14290
|
+
"png": (w, h) == (256, 256) and len(raw) == 256 * (1 + 256 * 4),
|
|
14291
|
+
"dib": len(dib32) == 40 + 32 * 32 * 4 + 4 * 32 and _struct.unpack("<IiiHH", dib32[:16]) == (40, 32, 64, 1, 32),
|
|
14292
|
+
"shape": run16[0][0][3] == 0 and run16[8][3][3] == 255 and stop16[8][3][3] == 255,
|
|
14293
|
+
"states": run16[12][3][:3] != stop16[12][3][:3] and run16[12][3][2] > run16[12][3][0] and abs(stop16[12][3][0] - stop16[12][3][2]) < 20,
|
|
14294
|
+
"same_in_kit": True,
|
|
14295
|
+
}
|
|
14296
|
+
if checkout:
|
|
14297
|
+
spec = importlib.util.spec_from_file_location("dh_installer", str(pkg.parent / "tools" / "build_installer.py"))
|
|
14298
|
+
bi = importlib.util.module_from_spec(spec); spec.loader.exec_module(bi)
|
|
14299
|
+
c1["same_in_kit"] = bi.icon_module().ico_bytes() == ico and "(kit / 'gea.ico').write_bytes(icon_module().ico_bytes())" in (pkg.parent / "tools" / "build_installer.py").read_text(encoding="utf-8")
|
|
14300
|
+
else:
|
|
14301
|
+
kd = _doctor_kit()
|
|
14302
|
+
if kd and os.path.isfile(os.path.join(kd, "gea.ico")):
|
|
14303
|
+
c1["same_in_kit"] = open(os.path.join(kd, "gea.ico"), "rb").read() == ico
|
|
14304
|
+
failed1 = [k for k, v in c1.items() if not v]
|
|
14305
|
+
ok(not failed1,
|
|
14306
|
+
"DH1 the program's icon is drawn in code - a derrick and its crown block on a rounded square, teal while the control panel runs, grey "
|
|
14307
|
+
"while it does not - and read back as an .ico of eight sizes (16 to 64 px as 32-bit images with their masks, 256 px as a PNG); the kit "
|
|
14308
|
+
"carries the same icon for the installer and its shortcuts" + (f" [failed: {', '.join(failed1)}]" if failed1 else ""))
|
|
14309
|
+
|
|
14310
|
+
# -- DH2 the launcher -----------------------------------------------------------------------------------------------------------
|
|
14311
|
+
kit = d / "Programs" / "GEA-Program"; (kit / "python").mkdir(parents=True)
|
|
14312
|
+
(kit / "start-dashboard.cmd").write_text("@echo off\n", encoding="utf-8")
|
|
14313
|
+
for n in ("python.exe", "pythonw.exe"):
|
|
14314
|
+
(kit / "python" / n).write_bytes(b"MZ stand-in")
|
|
14315
|
+
env0 = {"LOCALAPPDATA": str(d / "LocalAppData")}
|
|
14316
|
+
ws_u = str(d / "Säntis site")
|
|
14317
|
+
refused = {}
|
|
14318
|
+
for why, path in (("inside", str(kit / "site")), ("contains", str(d / "Programs")), ("relative", "site"), ("root", os.path.abspath(os.sep)), ("empty", "")):
|
|
14319
|
+
try:
|
|
14320
|
+
L.set_workspace(kit, path); refused[why] = "accepted"
|
|
14321
|
+
except L.LaunchError as e:
|
|
14322
|
+
refused[why] = str(e)
|
|
14323
|
+
w_default = L.resolve_workspace(None, env0, kit)
|
|
14324
|
+
rec = L.set_workspace(kit, ws_u + os.sep)
|
|
14325
|
+
raw_rec = (kit / L.WORKSPACE_FILE).read_bytes()
|
|
14326
|
+
w_file = L.resolve_workspace(None, env0, kit)
|
|
14327
|
+
w_env = L.resolve_workspace(None, dict(env0, GEA_WORKSPACE=str(d / "env site")), kit)
|
|
14328
|
+
w_arg = L.resolve_workspace(str(d / "arg site"), dict(env0, GEA_WORKSPACE=str(d / "env site")), kit)
|
|
14329
|
+
pf86 = r"C:\Program Files (x86)"
|
|
14330
|
+
edge_known = os.path.join(pf86, r"Microsoft\Edge\Application", "msedge.exe")
|
|
14331
|
+
reg = {"msedge.exe": r"C:\Edge\msedge.exe", "chrome.exe": r"C:\Chrome\chrome.exe"}
|
|
14332
|
+
b_edge = L.find_app_browser(registry=reg.get, exists=lambda p: True, env={}, windows=True)
|
|
14333
|
+
b_chrome = L.find_app_browser(registry=lambda e: reg["chrome.exe"] if e == "chrome.exe" else None, exists=lambda p: p == reg["chrome.exe"], env={}, windows=True)
|
|
14334
|
+
b_known = L.find_app_browser(registry=lambda e: None, exists=lambda p: p == edge_known, env={"ProgramFiles(x86)": pf86}, windows=True)
|
|
14335
|
+
b_none = L.find_app_browser(registry=lambda e: None, exists=lambda p: False, env={"ProgramFiles(x86)": pf86}, windows=True)
|
|
14336
|
+
b_unix = L.find_app_browser(which=lambda e: "/usr/bin/chromium" if e == "chromium" else None, windows=False)
|
|
14337
|
+
calls = []
|
|
14338
|
+
def fake_popen(args, **kw):
|
|
14339
|
+
calls.append(args); return None
|
|
14340
|
+
def bad_popen(args, **kw):
|
|
14341
|
+
raise OSError("not here")
|
|
14342
|
+
opened = []
|
|
14343
|
+
how_app = L.open_window("https://localhost:8765/", browser=("Microsoft Edge", r"C:\Edge\msedge.exe"), popen=fake_popen)
|
|
14344
|
+
how_web = L.open_window("http://127.0.0.1:8765/", popen=fake_popen, web_open=lambda u, new=1: opened.append(u) or True, find=lambda: None)
|
|
14345
|
+
how_fallback = L.open_window("http://127.0.0.1:8765/", browser=("Microsoft Edge", "x"), popen=bad_popen, web_open=lambda u, new=1: True)
|
|
14346
|
+
wsr = d / "running site"; (wsr / "records").mkdir(parents=True)
|
|
14347
|
+
(wsr / "records" / "runlog.jsonl").write_text(json.dumps({"utc": "2026-10-01T00:00:00Z", "event": "start", "pid": 1, "url": "http://127.0.0.1:8765/"}) + "\n"
|
|
14348
|
+
+ json.dumps({"utc": "2026-10-02T00:00:00Z", "event": "start", "pid": 2, "url": "https://localhost:8765/"}) + "\n"
|
|
14349
|
+
+ json.dumps({"utc": "2026-10-02T00:00:01Z", "event": "stop", "pid": 2}) + "\n", encoding="utf-8")
|
|
14350
|
+
srv = _socket.socket(); srv.bind(("127.0.0.1", 0)); srv.listen(64); port = srv.getsockname()[1]
|
|
14351
|
+
up = L.port_open(port)
|
|
14352
|
+
started, windows_opened = [], []
|
|
14353
|
+
saved = (L.start_service, L.start_tray, L.open_window)
|
|
14354
|
+
try:
|
|
14355
|
+
L.start_service = lambda k, ws, p, popen=None: started.append((k, ws, p)) or ["start"]
|
|
14356
|
+
L.start_tray = lambda ws, p, popen=None: None
|
|
14357
|
+
L.open_window = lambda url, **kw: windows_opened.append(url) or "app window"
|
|
14358
|
+
rc_running = L.launch(str(wsr), port)
|
|
14359
|
+
n_after_running = len(started)
|
|
14360
|
+
srv.close()
|
|
14361
|
+
down = not L.port_open(port)
|
|
14362
|
+
rc_bg = L.launch(str(wsr), port, background=True)
|
|
14363
|
+
finally:
|
|
14364
|
+
L.start_service, L.start_tray, L.open_window = saved
|
|
14365
|
+
try:
|
|
14366
|
+
srv.close()
|
|
14367
|
+
except OSError:
|
|
14368
|
+
pass
|
|
14369
|
+
sc_kit = L.service_command(kit, ws_u, 8765)
|
|
14370
|
+
sc_pip = L.service_command(None, ws_u, 8766, executable=str(kit / "python" / "pythonw.exe"))
|
|
14371
|
+
c2 = {
|
|
14372
|
+
"kit": L.kit_dir(str(kit / "python" / "pythonw.exe")) == kit.resolve() and L.kit_dir(str(d / "elsewhere" / "python.exe")) is None,
|
|
14373
|
+
"default": w_default == (os.path.join(str(d / "LocalAppData"), "GEA-Program", "site"), "the default"),
|
|
14374
|
+
"recorded": rec == ws_u and raw_rec == ws_u.encode("utf-8") and w_file[0] == ws_u and "site-workspace.txt" in w_file[1],
|
|
14375
|
+
"order": w_env == (str(d / "env site"), "GEA_WORKSPACE") and w_arg == (os.path.abspath(str(d / "arg site")), "--workspace"),
|
|
14376
|
+
"refused": all(v != "accepted" for v in refused.values()) and "inside the program's own folder" in refused["inside"]
|
|
14377
|
+
and "is inside" in refused["contains"] and "not a full path" in refused["relative"] and "root of a drive" in refused["root"],
|
|
14378
|
+
"browsers": b_edge == ("Microsoft Edge", reg["msedge.exe"]) and b_chrome == ("Google Chrome", reg["chrome.exe"])
|
|
14379
|
+
and b_known == ("Microsoft Edge", edge_known) and b_none is None and b_unix == ("Chromium", "/usr/bin/chromium"),
|
|
14380
|
+
"app_window": how_app == "app window (Microsoft Edge)" and calls[0] == [r"C:\Edge\msedge.exe", "--app=https://localhost:8765/", "--window-size=1440,960"]
|
|
14381
|
+
and how_web == "the default browser" and opened == ["http://127.0.0.1:8765/"] and how_fallback == "the default browser",
|
|
14382
|
+
"url": L.dashboard_url(str(wsr), 8765) == "https://localhost:8765/" and L.dashboard_url(str(wsr), 8770) == "http://127.0.0.1:8770/"
|
|
14383
|
+
and L.dashboard_url(str(wsr), 8765, since_utc="2026-10-03T00:00:00Z") == "http://127.0.0.1:8765/",
|
|
14384
|
+
"commands": sc_kit[1:] == ["/c", str(kit / "start-dashboard.cmd"), "--no-browser"]
|
|
14385
|
+
and sc_pip == [str(kit / "python" / "python.exe"), "-m", "gea", "serve", "--workspace", ws_u, "--port", "8766", "--no-browser"]
|
|
14386
|
+
and L.tray_command(ws_u, 8765, executable=str(kit / "python" / "python.exe"))[0] == str(kit / "python" / "pythonw.exe"),
|
|
14387
|
+
"launch": up and rc_running == 0 and n_after_running == 0 and windows_opened == [L.dashboard_url(str(wsr), port)] and down
|
|
14388
|
+
and rc_bg == 0 and started == [(None if L.kit_dir() is None else L.kit_dir(), str(wsr), port)] and len(windows_opened) == 1,
|
|
14389
|
+
}
|
|
14390
|
+
failed2 = [k for k, v in c2.items() if not v]
|
|
14391
|
+
ok(not failed2,
|
|
14392
|
+
"DH2 the launcher: the kit found from its own Python; the workspace from --workspace, else GEA_WORKSPACE, else the installer's choice "
|
|
14393
|
+
"(recorded as UTF-8, a name with an accent whole), else %LOCALAPPDATA%\\GEA-Program\\site - and a folder inside the program's own, one "
|
|
14394
|
+
"holding it, a relative path or a drive's root not taken; Edge's app window (from App Paths or where Edge installs), else Chrome's, else the "
|
|
14395
|
+
"default browser; the address the running service wrote in its run log; a control panel already answering is opened, not started "
|
|
14396
|
+
"again, and a stopped one is started in the kit's own window" + (f" [failed: {', '.join(failed2)}]" if failed2 else ""))
|
|
14397
|
+
|
|
14398
|
+
# -- DH3 the icon in the notification area ----------------------------------------------------------------------------------------
|
|
14399
|
+
m_run, m_stop, m_nokit = TR.menu_items(True, str(kit)), TR.menu_items(False, str(kit)), TR.menu_items(True, None)
|
|
14400
|
+
ids = lambda m: [x[0] for x in m if x]
|
|
14401
|
+
tip = TR.tooltip(True, 8765, "C:\\" + "very long site name " * 10)
|
|
14402
|
+
st_ok, st_lines = TR.selftest(str(wsr), 8765, str(kit), show=False)
|
|
14403
|
+
c3 = {
|
|
14404
|
+
"menu_running": ids(m_run) == [TR.CMD_STATUS, TR.CMD_OPEN, TR.CMD_STOP, TR.CMD_FOLDER, TR.CMD_HELP, TR.CMD_CLOSE] and m_run[0][2] is False
|
|
14405
|
+
and all(x[2] for x in m_run[2:] if x) and "keeps running" in m_run[-1][1],
|
|
14406
|
+
"menu_stopped": ids(m_stop) == [TR.CMD_STATUS, TR.CMD_OPEN, TR.CMD_START, TR.CMD_FOLDER, TR.CMD_HELP, TR.CMD_CLOSE] and "Start and open" in m_stop[2][1],
|
|
14407
|
+
"no_kit_no_stop": [x for x in m_nokit if x and x[0] == TR.CMD_STOP][0][2] is False,
|
|
14408
|
+
"tooltip": len(tip) <= TR.TIP_MAX and "running (port 8765)" in tip,
|
|
14409
|
+
"notices": TR.notice(None, True, False) is None and TR.notice(True, True, False) is None and TR.notice(True, False, True) is None
|
|
14410
|
+
and TR.notice(True, False, False)[2] is True and "stopped" in TR.notice(True, False, False)[1] and TR.notice(False, True, False)[2] is False,
|
|
14411
|
+
"help": TR.help_url("https://localhost:8765/") == "https://localhost:8765/#/help/install" and "install" in [t[0] for t in H.INDEX],
|
|
14412
|
+
"selftest": st_ok and any(x.startswith("icon: 2 images") for x in st_lines) and (L.is_windows() or any("Windows'" in x for x in st_lines))
|
|
14413
|
+
and (not L.is_windows() or any(x.startswith("window: made") for x in st_lines)),
|
|
14414
|
+
}
|
|
14415
|
+
failed3 = [k for k, v in c3.items() if not v]
|
|
14416
|
+
ok(not failed3,
|
|
14417
|
+
"DH3 the notification-area icon: its menu as the control panel stands (open, or start and open; stop - greyed where there is no kit to "
|
|
14418
|
+
"stop it with - or start without a window; the workspace folder, help, close), a tooltip inside Windows' 127 characters, a notification "
|
|
14419
|
+
"when the panel stops without being asked to from the icon and none when it was; on Windows the window, both icon images and the menu "
|
|
14420
|
+
"made for real" + (f" [failed: {', '.join(failed3)}]" if failed3 else ""))
|
|
14421
|
+
|
|
14422
|
+
# -- DH4 the kit's scripts ----------------------------------------------------------------------------------------------------------
|
|
14423
|
+
scripts = {}
|
|
14424
|
+
if checkout:
|
|
14425
|
+
scripts = dict(bi.WIN_SCRIPTS); where4 = "the checkout's templates"
|
|
14426
|
+
else:
|
|
14427
|
+
kd = _doctor_kit(); where4 = f"the installed kit at {kd}"
|
|
14428
|
+
for n in ("start-dashboard.cmd", "stop-dashboard.cmd", "register-service.cmd", "open-dashboard.cmd", "uninstall.cmd"):
|
|
14429
|
+
if kd and os.path.isfile(os.path.join(kd, n)):
|
|
14430
|
+
scripts[n] = open(os.path.join(kd, n), encoding="utf-8", errors="replace").read()
|
|
14431
|
+
if scripts.get("stop-dashboard.cmd"):
|
|
14432
|
+
stop, start = scripts["stop-dashboard.cmd"], scripts.get("start-dashboard.cmd", "")
|
|
14433
|
+
reg_, opn, unin = scripts.get("register-service.cmd", ""), scripts.get("open-dashboard.cmd", ""), scripts.get("uninstall.cmd", "")
|
|
14434
|
+
ps = [ln for ln in stop.splitlines() if ln.lower().startswith("powershell")]
|
|
14435
|
+
c4 = {
|
|
14436
|
+
"no_wmic": "wmic " not in "\n".join(ln for ln in stop.splitlines() if not ln.strip().lower().startswith("rem ")).lower()
|
|
14437
|
+
and len(ps) == 1 and "Get-CimInstance Win32_Process" in ps[0] and "%" not in ps[0] and '"' not in ps[0].split('-Command "', 1)[1][:-1],
|
|
14438
|
+
"loop_first": ps and ps[0].index("start-dashboard.cmd") < ps[0].index("' gea serve'") and "ParentProcessId" in ps[0] and "taskkill.exe /pid $p.ProcessId /t /f" in ps[0],
|
|
14439
|
+
"own_kit": ps and "ExecutablePath.StartsWith($k, $ic)" in ps[0] and 'set "GEA_KIT=%~dp0"' in stop,
|
|
14440
|
+
"all": 'if /i "%~1"=="--all" set "GEA_ALL=1"' in stop and ps and "' gea (tray|launch)'" in ps[0],
|
|
14441
|
+
"workspace_file": "if not \"%GEA_WORKSPACE%\"==\"\" goto gea_ws_done" in start and 'set /p GEA_WORKSPACE=<"%~dp0site-workspace.txt"' in start
|
|
14442
|
+
and "chcp 65001" in start and start.index("gea_ws_done") < start.index("--action init"),
|
|
14443
|
+
"logon_returns": "python\\pythonw.exe\\\" -m gea launch --background" in reg_ and "start-dashboard.cmd" not in reg_.split("schtasks /create", 1)[1].splitlines()[0],
|
|
14444
|
+
"open": "python\\pythonw.exe\" -m gea launch" in opn,
|
|
14445
|
+
"uninstall_stops": unin.index('stop-dashboard.cmd" --all') < unin.index("rmdir /s /q") if 'stop-dashboard.cmd" --all' in unin and "rmdir" in unin else False,
|
|
14446
|
+
}
|
|
14447
|
+
else:
|
|
14448
|
+
c4 = {"no_kit": True}; where4 = "a pip-installed copy: the kit's scripts are checked in the checkout and in the kit"
|
|
14449
|
+
failed4 = [k for k, v in c4.items() if not v]
|
|
14450
|
+
ok(not failed4,
|
|
14451
|
+
f"DH4 ({where4}) the kit's scripts: stop-dashboard finds the processes with PowerShell's Get-CimInstance (Windows 11 24H2 has no wmic, "
|
|
14452
|
+
"and the stop before v0.65 found nothing there), stops the window running start-dashboard first so its restart loop cannot start the "
|
|
14453
|
+
"panel again, then this kit's own gea serve, and with --all its icon; start-dashboard reads the installer's workspace; the logon task "
|
|
14454
|
+
"runs the launcher, which returns (a task running start-dashboard itself met Task Scheduler's three-day limit); uninstall stops "
|
|
14455
|
+
"everything first" + (f" [failed: {', '.join(failed4)}]" if failed4 else ""))
|
|
14456
|
+
|
|
14457
|
+
# -- DH5 the Inno Setup script and the workflow -------------------------------------------------------------------------------------
|
|
14458
|
+
if checkout:
|
|
14459
|
+
iss = (pkg.parent / "tools" / "installer.iss").read_text(encoding="utf-8")
|
|
14460
|
+
sec = _iss_sections(iss)
|
|
14461
|
+
setup = dict(ln.strip().split("=", 1) for ln in sec.get("Setup", []))
|
|
14462
|
+
known = {"Tasks": {"Name", "Description", "GroupDescription", "Flags"},
|
|
14463
|
+
"InstallDelete": {"Type", "Name"}, "UninstallDelete": {"Type", "Name"},
|
|
14464
|
+
"Files": {"Source", "DestDir", "Flags"},
|
|
14465
|
+
"Icons": {"Name", "Filename", "Parameters", "WorkingDir", "IconFilename", "Comment", "Tasks"},
|
|
14466
|
+
"Run": {"Filename", "Parameters", "WorkingDir", "Description", "Flags"},
|
|
14467
|
+
"UninstallRun": {"Filename", "Parameters", "WorkingDir", "Flags", "RunOnceId"}}
|
|
14468
|
+
entries = {s: [_iss_entry(ln) for ln in sec.get(s, [])] for s in known}
|
|
14469
|
+
bad_keys = [(s, k) for s, es in entries.items() for e in es for k in e if k not in known[s]]
|
|
14470
|
+
code = "\n".join(sec.get("Code", []))
|
|
14471
|
+
code_nc = _re.sub(r"'[^']*'", "''", _re.sub(r"\{[^}]*\}", "", code))
|
|
14472
|
+
n_begin, n_end = len(_re.findall(r"\bbegin\b", code_nc, _re.I)), len(_re.findall(r"\bend\b", code_nc, _re.I))
|
|
14473
|
+
defined = set(_re.findall(r"^\s*function\s+(\w+)", code, _re.M | _re.I))
|
|
14474
|
+
used_code = set(_re.findall(r"\{code:(\w+)", iss))
|
|
14475
|
+
deletes = [e["Name"] for s in ("InstallDelete", "UninstallDelete") for e in entries[s]]
|
|
14476
|
+
icons = {e["Name"]: e for e in entries["Icons"]}
|
|
14477
|
+
wf = (pkg.parent / ".github" / "workflows" / "build-installer.yml").read_text(encoding="utf-8")
|
|
14478
|
+
win = wf[wf.index("windows-kit:"):wf.index("linux-kit:")]
|
|
14479
|
+
guid = setup.get("AppId", "").strip("{}")
|
|
14480
|
+
order = [win.index(s) for s in ("Attach the kit to the release", "ISCC", "files: ${{ env.SETUP }}", "/d \"GEA-Program setup\" $env:SETUP",
|
|
14481
|
+
"Get-AuthenticodeSignature $env:SETUP", "/VERYSILENT", "subject-path: dist/GEA-Program-Setup-*.exe",
|
|
14482
|
+
'attach-kit.sh "${{ inputs.release_tag }}" "dist/GEA-Program-Setup-*.exe"')]
|
|
14483
|
+
c5 = {
|
|
14484
|
+
"per_user": setup.get("PrivilegesRequired") == "lowest" and setup.get("DefaultDirName") == "{userpf}\\GEA-Program" and "PrivilegesRequiredOverridesAllowed" not in setup
|
|
14485
|
+
and not _re.search(r"\{(pf|pf32|pf64|commonpf|commonprograms|commondesktop|commonstartup|sys|win)\}|HKLM|HKEY_LOCAL_MACHINE|\[Registry\]", iss),
|
|
14486
|
+
"identity": _re.fullmatch(r"\{\{[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}\}", setup.get("AppId", "")) is not None
|
|
14487
|
+
and guid.strip("{") in win and setup.get("AppVersion") == "{#AppVersion}" and setup.get("OutputBaseFilename") == "GEA-Program-Setup-{#AppVersion}"
|
|
14488
|
+
and setup.get("UsePreviousAppDir") == "yes" and setup.get("ArchitecturesInstallIn64BitMode") == "x64compatible",
|
|
14489
|
+
"parsed": not bad_keys and all(e.get("Name") or e.get("Filename") or e.get("Source") for es in entries.values() for e in es)
|
|
14490
|
+
and n_begin == n_end and used_code <= defined and {"NextButtonClick", "PrepareToInstall", "GetCustomSetupExitCode", "UpdateReadyMemo"} <= defined,
|
|
14491
|
+
"deletes_inside": bool(deletes) and all(n.startswith("{app}\\") or (n == "{app}" and e["Type"] == "dirifempty") for s in ("InstallDelete", "UninstallDelete")
|
|
14492
|
+
for e in entries[s] for n in [e["Name"]]) and "{code:" not in " ".join(deletes),
|
|
14493
|
+
"workspace_page": "CreateInputDirPage(wpSelectDir" in code and "{param:WORKSPACE|}" in code and "GetPreviousData('Workspace'" in code
|
|
14494
|
+
and "SetPreviousData(PreviousDataKey, 'Workspace'" in code and "IsInside(Ws, App)" in code and "IsInside(App, Ws)" in code
|
|
14495
|
+
and code.count("WorkspaceProblem(") == 3,
|
|
14496
|
+
"stops_first": "stop-dashboard.cmd" in code.split("function PrepareToInstall", 1)[1].split("end;\n\nprocedure", 1)[0] and '--all"' in code
|
|
14497
|
+
and any("stop-dashboard.cmd" in e.get("Parameters", "") and "--all" in e.get("Parameters", "") and "runhidden" in e.get("Flags", "") for e in entries["UninstallRun"]),
|
|
14498
|
+
"installs": "install.cmd" in code and "InstallFailed := True" in code and "if InstallFailed then Result := 8" in code
|
|
14499
|
+
and "-m gea launch --set-workspace" in code and "ssPostInstall" in code,
|
|
14500
|
+
"shortcuts": icons.get("{autoprograms}\\GEA-Program\\GEA-Program", {}).get("Parameters") == "-m gea launch"
|
|
14501
|
+
and icons["{autoprograms}\\GEA-Program\\GEA-Program"]["Filename"] == "{app}\\python\\pythonw.exe"
|
|
14502
|
+
and icons.get("{userstartup}\\GEA-Program", {}).get("Parameters") == "-m gea launch --background"
|
|
14503
|
+
and icons["{userstartup}\\GEA-Program"].get("Tasks") == "startlogon" and icons.get("{autodesktop}\\GEA-Program", {}).get("Tasks") == "desktopicon"
|
|
14504
|
+
and any(e.get("Filename") == "{uninstallexe}" for e in entries["Icons"])
|
|
14505
|
+
and [e["Name"] for e in entries["Tasks"]] == ["desktopicon", "startlogon"] and "unchecked" in entries["Tasks"][1].get("Flags", ""),
|
|
14506
|
+
"upgrade_clean": [e["Name"] for e in entries["InstallDelete"]][:2] == ["{app}\\python", "{app}\\wheels"],
|
|
14507
|
+
"workflow_order": order == sorted(order) and "if: env.ARTIFACT_SIGNING_ACCOUNT != ''" in win.split("ISCC", 1)[1]
|
|
14508
|
+
and "INSTALLED.txt')) { throw 'the installer source is not the clean kit'" in win,
|
|
14509
|
+
"workflow_test": all(x in win for x in ("InstallOnce 'install'", "InstallOnce 'upgrade'", "the upgrade did not stop the running control panel first",
|
|
14510
|
+
"unins000.exe", "the site workspace was touched by the uninstall", "ci-marker.txt",
|
|
14511
|
+
"gea launch --selftest", "gea tray --selftest", "the Add/Remove Programs entry is still there",
|
|
14512
|
+
"ships unsigned")),
|
|
14513
|
+
}
|
|
14514
|
+
where5 = "the checkout's installer script and workflow"
|
|
14515
|
+
else:
|
|
14516
|
+
c5 = {"installed": True}; where5 = "an installed copy: the installer script is checked in the checkout"
|
|
14517
|
+
failed5 = [k for k, v in c5.items() if not v]
|
|
14518
|
+
ok(not failed5,
|
|
14519
|
+
f"DH5 ({where5}) the installer installs for the signed-in user alone (no elevation, the user's own program folder, nothing in the "
|
|
14520
|
+
"machine's folders or registry), under one identity in every version; every entry reads as Inno Setup's; what it deletes is inside the "
|
|
14521
|
+
"program's folder and never the workspace, which it asks for, remembers, and never takes inside the program's folder; it stops the control "
|
|
14522
|
+
"panel and its icon before an upgrade and an uninstall, says when install.cmd failed (exit code 8), and its shortcuts open the app "
|
|
14523
|
+
"window; the workflow builds it from the clean kit after the kit is attached, signs it only with a configured certificate, installs, "
|
|
14524
|
+
"upgrades and uninstalls it silently with the panel running, then attests and attaches it" + (f" [failed: {', '.join(failed5)}]" if failed5 else ""))
|
|
14525
|
+
|
|
14526
|
+
# -- DH6 the command line and the help ----------------------------------------------------------------------------------------------
|
|
14527
|
+
env_ws = dict(os.environ, GEA_WORKSPACE=str(wsr))
|
|
14528
|
+
pkg_root = str(Path(__file__).resolve().parent.parent)
|
|
14529
|
+
env_ws["PYTHONPATH"] = pkg_root + os.pathsep + env_ws.get("PYTHONPATH", "")
|
|
14530
|
+
r1 = subprocess.run([sys.executable, "-m", "gea", "launch", "--selftest", "--port", "1"], capture_output=True, text=True, cwd=tmp, env=env_ws)
|
|
14531
|
+
r2 = subprocess.run([sys.executable, "-m", "gea", "launch", "--help"], capture_output=True, text=True, cwd=tmp, env=env_ws)
|
|
14532
|
+
r3 = subprocess.run([sys.executable, "-m", "gea", "tray", "--help"], capture_output=True, text=True, cwd=tmp, env=env_ws)
|
|
14533
|
+
page = H.page("install") or ""
|
|
14534
|
+
sec_txt = H.security_text()
|
|
14535
|
+
c6 = {
|
|
14536
|
+
"selftest": r1.returncode == 0 and f"workspace: {wsr} (from GEA_WORKSPACE" in r1.stdout and "nothing is listening: it would be started" in r1.stdout
|
|
14537
|
+
and "start:" in r1.stdout and "window:" in r1.stdout,
|
|
14538
|
+
"help_cli": r2.returncode == 0 and "--background" in r2.stdout and "--set-workspace" in r2.stdout and r3.returncode == 0 and "--selftest" in r3.stdout,
|
|
14539
|
+
"page": all(x in page for x in ("**The command**", "**What it writes**", "**The number to check**", "**What this page will not call a measurement**",
|
|
14540
|
+
"/VERYSILENT", "msedge --app=", "notification area", "never delete", "Startup folder", "gh attestation verify GEA-Program-Setup"))
|
|
14541
|
+
and ("never move it and never delete it" in page),
|
|
14542
|
+
"security": "PrivilegesRequired=lowest" in sec_txt and "Shell_NotifyIconW" in sec_txt and "unins000.exe" in sec_txt,
|
|
14543
|
+
}
|
|
14544
|
+
failed6 = [k for k, v in c6.items() if not v]
|
|
14545
|
+
ok(not failed6,
|
|
14546
|
+
"DH6 `gea launch --selftest` says what a launch would do here (the kit, the workspace and where it came from, whether the control panel "
|
|
14547
|
+
"answers, the window, the command) and starts nothing; `gea launch` and `gea tray` answer --help; the help page Install on Windows and "
|
|
14548
|
+
"the IT overview say what the setup installs, where, what it never touches and how its signature and provenance are checked"
|
|
14549
|
+
+ (f" [failed: {', '.join(failed6)}]" if failed6 else ""))
|
|
14550
|
+
|
|
14551
|
+
|
|
14222
14552
|
def main() -> int:
|
|
14223
14553
|
print("GEA-Program - ACCEPTANCE SUITE (the product gate)")
|
|
14224
14554
|
# a handle a job subprocess still holds at the end must not turn a finished gate into a traceback on Windows:
|
|
@@ -14333,6 +14663,7 @@ def main() -> int:
|
|
|
14333
14663
|
section_de_real_gas(tmp)
|
|
14334
14664
|
section_df_trusted_timestamp(tmp)
|
|
14335
14665
|
section_dg_casing_program(tmp)
|
|
14666
|
+
section_dh_windows_installer(tmp)
|
|
14336
14667
|
if _FAILS:
|
|
14337
14668
|
print(f"[ACCEPTANCE] {len(_FAILS)} FAILURES ({_PASS} passed):")
|
|
14338
14669
|
for f in _FAILS:
|
|
@@ -17,6 +17,21 @@ outside that folder and the site's workspace folder, adds no driver, no
|
|
|
17
17
|
system service (a per-user scheduled task only if the site runs
|
|
18
18
|
`register-service.cmd`), and no registry keys.
|
|
19
19
|
|
|
20
|
+
**The Windows installer** (on each GitHub release since 0.65.0:
|
|
21
|
+
`GEA-Program-Setup-0.65.0.exe` for 0.65.0) installs that same kit for the signed-in user alone:
|
|
22
|
+
`PrivilegesRequired=lowest` (no elevation prompt), the program under
|
|
23
|
+
`%LOCALAPPDATA%\Programs\GEA-Program`, shortcuts in the user's Start menu
|
|
24
|
+
and desktop, an optional shortcut in the user's Startup folder, and the
|
|
25
|
+
user's own Add/Remove Programs entry (`HKCU`, the only registry key it
|
|
26
|
+
writes, removed by its uninstaller). Silent install for a software
|
|
27
|
+
deployment: `/VERYSILENT /SUPPRESSMSGBOXES /NORESTART /WORKSPACE="C:\site"`.
|
|
28
|
+
The setup never writes into the site workspace and will not take one inside the
|
|
29
|
+
program's own folder; the uninstaller stops the control panel, removes the
|
|
30
|
+
program and leaves the workspace. The program's window is Microsoft Edge's
|
|
31
|
+
app window (`msedge --app=` on the local address); its notification-area
|
|
32
|
+
icon (standard library `ctypes`, `Shell_NotifyIconW`) reads only whether the
|
|
33
|
+
control panel's port answers on this computer.
|
|
34
|
+
|
|
20
35
|
`tools/standalone_check.py` (run by the acceptance gate) fails the build if
|
|
21
36
|
any module imports anything outside the standard library, numpy and the
|
|
22
37
|
declared extras.
|
|
@@ -119,8 +134,17 @@ since it was signed.
|
|
|
119
134
|
catalog. Until the certificate is in place the catalog ships unsigned and
|
|
120
135
|
the build says so. The embeddable Python's own executables are signed by
|
|
121
136
|
the Python Software Foundation.
|
|
137
|
+
- **The setup's signature**: when the certificate is in place the setup
|
|
138
|
+
executable is Authenticode-signed and timestamped by the same build
|
|
139
|
+
(`Get-AuthenticodeSignature .\GEA-Program-Setup-0.65.0.exe`), and it is
|
|
140
|
+
attested like the kit (`gh attestation verify GEA-Program-Setup-0.65.0.exe
|
|
141
|
+
-R Daniel8Murphy0007/GEA-Program`). Before each release the build installs
|
|
142
|
+
it silently, upgrades it in place with the control panel running, starts
|
|
143
|
+
it and uninstalls it, and checks the workspace untouched. The uninstaller
|
|
144
|
+
it writes (`unins000.exe`, Inno Setup's) is not signed separately.
|
|
122
145
|
- **Updates**: a new kit is installed beside the old one; the workspace is
|
|
123
|
-
found and opened as it is.
|
|
146
|
+
found and opened as it is. A newer setup installs over the older one in
|
|
147
|
+
place, after stopping the control panel. Nothing updates itself: on a pip installation,
|
|
124
148
|
`gea update` upgrades from PyPI only when a person runs it.
|
|
125
149
|
- **The acceptance gate**: `verify.cmd` runs every check of the program's
|
|
126
150
|
acceptance suite from the installed kit - the site's own evidence that
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Install on Windows
|
|
2
|
+
|
|
3
|
+
> GEA-Program-Setup: the program installed for you like any Windows program - a window of its own, an icon in the notification area, Start-menu and desktop shortcuts, an Add/Remove Programs entry, upgrades in place - with no administrator rights and the site's data left where it is.
|
|
4
|
+
|
|
5
|
+
**The command**: download the setup from the release on GitHub (`GEA-Program-Setup-0.65.0.exe` for this version) and run it. It installs for you alone, under `%LOCALAPPDATA%\Programs\GEA-Program`, and asks for one thing: the site workspace - the folder that holds the wells, reports, records, accounts and keys (an existing one such as `C:\site` is used as it is; otherwise `%LOCALAPPDATA%\GEA-Program\site`, made at the first start). Then the Start menu's **GEA-Program** (and the desktop shortcut) starts the control panel when it is not running and opens it in a window of its own. A newer setup installs over the older one: it stops the control panel, replaces the program, keeps the workspace and the choices made before. For a site's software deployment: `GEA-Program-Setup-0.65.0.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /WORKSPACE="C:\site" /TASKS="desktopicon"`. From a terminal: `gea launch` does what the shortcut does, `gea launch --selftest` says what it would do, `gea tray --selftest` checks the icon.
|
|
6
|
+
|
|
7
|
+
**The window**: Microsoft Edge's app window (`msedge --app=`: the control panel with no tabs and no address bar, its own button on the taskbar, signed in as the browser is), else Google Chrome's, else a tab in the default browser. The control panel itself runs in the window titled "GEA - Operations Control Panel", minimised on the taskbar: the window that starts it again when the panel asks for a restart and says why it stopped when it stops. Closing that window stops the panel.
|
|
8
|
+
|
|
9
|
+
**The icon**: in the notification area, teal while the control panel runs and grey while it does not; its tooltip says which and on what port, and a notification says so when the panel stops without being asked to from the icon. Its menu: Open the control panel (or a double click; when the panel is stopped, it is started first), Start it without a window, Stop it, Open the site workspace folder, Help (this page), Close this icon.
|
|
10
|
+
|
|
11
|
+
**Starting at sign-in**: the setup's "Start the control panel when I sign in to Windows" puts a GEA-Program shortcut in the Startup folder: the control panel starts in the background with its icon, and no window opens until you open one. The install kit's `register-service.cmd` (a scheduled task) does the same for a kit that was not installed by the setup.
|
|
12
|
+
|
|
13
|
+
**What it writes**: the program under `%LOCALAPPDATA%\Programs\GEA-Program` (the install kit, and the package installed into the kit's own Python by its `install.cmd`, from its own wheels, with no network); `site-workspace.txt` there, the workspace you chose; the shortcuts; the Add/Remove Programs entry under the current user. Setup and uninstall never write into the workspace, never move it and never delete it, and will not take a workspace inside the program's own folder (which an upgrade replaces and the uninstaller removes). Uninstalling stops the control panel and its icon, then removes the program and what `install.cmd` added to it.
|
|
14
|
+
|
|
15
|
+
**The number to check**: Add/Remove Programs lists GEA-Program with the version you installed; `gea doctor --workspace C:\site` ends with `nothing blocks serving`; the Start menu's **Verify GEA-Program** runs the acceptance gate from the installation and ends with `[ACCEPTANCE] OK - N checks passed`. The release's build installs, upgrades and uninstalls the setup silently before it is published, with the control panel running, and checks the workspace untouched afterwards.
|
|
16
|
+
|
|
17
|
+
**Signed**: when the publisher's code-signing certificate is configured for the build, the setup is signed with it (Authenticode, timestamped) and Windows names the publisher; until then it ships unsigned and Windows SmartScreen says "unknown publisher" (More info, then Run anyway). The build's provenance holds either way: `gh attestation verify GEA-Program-Setup-0.65.0.exe -R Daniel8Murphy0007/GEA-Program`. The uninstaller the setup leaves behind is Inno Setup's own and is not signed separately.
|
|
18
|
+
|
|
19
|
+
**What this page will not call a measurement**: the icon's running or stopped is whether the control panel's port answers on this computer, read every three seconds - not whether every patch, job or report behind it is healthy (Home and the Verification page say that).
|
|
20
|
+
|
|
21
|
+
Related: `gea help start`, `gea help site`, `gea help https`, `gea help doctor`, `gea security`.
|
|
@@ -10,4 +10,4 @@
|
|
|
10
10
|
|
|
11
11
|
**What this page will not call a measurement**: nothing the program computes is a gauge measurement. It reports the data it was given, the rules it applied and the numbers those rules produced, with the rule printed beside each number. The gauge aging band is a model band with no field validation on record, and every report that uses it says so.
|
|
12
12
|
|
|
13
|
-
Related: `gea help site`, `gea help data-in`, `gea guide` (the click-by-click tester guide), `gea doctor`.
|
|
13
|
+
Related: `gea help install` (the Windows setup), `gea help site`, `gea help data-in`, `gea guide` (the click-by-click tester guide), `gea doctor`.
|
|
@@ -25,6 +25,7 @@ HELP_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'help')
|
|
|
25
25
|
# the index order: by the job a reader arrives with, never by module
|
|
26
26
|
INDEX: List[tuple] = [
|
|
27
27
|
('start', 'Start', 'install, the first run, what the program will not claim'),
|
|
28
|
+
('install', 'Install on Windows', 'GEA-Program-Setup: a per-user install with no administrator rights, the control panel in a window of its own, its icon in the notification area, shortcuts, upgrades in place, the site workspace left where it is'),
|
|
28
29
|
('data-in', 'Bring data in', 'CSV, LAS, SEG-Y, operator tables, WITS0, WITSML, OPC UA, MQTT, Modbus, the patch panel'),
|
|
29
30
|
('quality', 'Quality rules', 'RANGE, ROC, FLATLINE, SPIKE, STALE, GAP, each with the limit that fired'),
|
|
30
31
|
('drift', 'Drift', 'the datasheet aging rate, the labels, and the line NONE ON RECORD'),
|