From b514a444b0f408206a795e5f9f0f572839e61df3 Mon Sep 17 00:00:00 2001 From: Laurent Courty Date: Fri, 26 Jun 2026 11:24:53 -0600 Subject: [PATCH 1/3] remove duplicate messages. Make logging handler idempotent. --- src/itzi/messenger.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/itzi/messenger.py b/src/itzi/messenger.py index 8521789..599137b 100644 --- a/src/itzi/messenger.py +++ b/src/itzi/messenger.py @@ -45,11 +45,19 @@ def __init__(self): def _setup_handlers(self): """Configure console and optional file handlers""" + self.logger.setLevel(logging.DEBUG) + self.logger.propagate = False + + if any( + getattr(handler, "_itzi_console_handler", False) for handler in self.logger.handlers + ): + return + # Console handler (stderr) console_handler = logging.StreamHandler(sys.stderr) + console_handler._itzi_console_handler = True console_handler.setFormatter(logging.Formatter("%(message)s")) self.logger.addHandler(console_handler) - self.logger.setLevel(logging.DEBUG) def add_file_handler(self, filepath, level=logging.DEBUG): """Add file logging capability""" From 6826ee5b17c900744bf107e6f91f9c7aa2d989e5 Mon Sep 17 00:00:00 2001 From: Laurent Courty Date: Fri, 26 Jun 2026 11:45:23 -0600 Subject: [PATCH 2/3] fix tests for new log catch --- tests/cli/test_configreader.py | 7 +- tests/core/test_hotstart_timed_inputs.py | 7 +- .../b/test8b_drainage_ponding_mod.inp | 205 ++++++++++++++++++ .../nc_itzi_tutorial_drainage.csv | 8 + .../tutorial_files/tutorial_drainage.ini | 26 +++ 5 files changed, 251 insertions(+), 2 deletions(-) create mode 100644 tests/test_data/EA_test_8/b/test8b_drainage_ponding_mod.inp create mode 100644 tests/test_data/tutorial_files/nc_itzi_tutorial_drainage.csv create mode 100644 tests/test_data/tutorial_files/tutorial_drainage.ini diff --git a/tests/cli/test_configreader.py b/tests/cli/test_configreader.py index c019c32..b3c28ca 100644 --- a/tests/cli/test_configreader.py +++ b/tests/cli/test_configreader.py @@ -94,8 +94,13 @@ def test_reader_normalizes_deprecated_aliases(tmp_path, caplog): ), ) + itzi_logger = logging.getLogger("itzi") with caplog.at_level(logging.WARNING, logger="itzi"): - sim_config = ConfigReader(config_file).get_sim_params() + itzi_logger.addHandler(caplog.handler) + try: + sim_config = ConfigReader(config_file).get_sim_params() + finally: + itzi_logger.removeHandler(caplog.handler) assert sim_config.input_map_names["water_depth"] == "legacy_depth" assert sim_config.input_map_names["losses"] == "legacy_losses" diff --git a/tests/core/test_hotstart_timed_inputs.py b/tests/core/test_hotstart_timed_inputs.py index 5998f31..a28b1a5 100644 --- a/tests/core/test_hotstart_timed_inputs.py +++ b/tests/core/test_hotstart_timed_inputs.py @@ -298,8 +298,13 @@ def test_build_warns_when_non_dem_input_has_only_nan_cells(domain_5by5, caplog) temporal_type=TemporalType.ABSOLUTE, ) + itzi_logger = logging.getLogger("itzi") with caplog.at_level(logging.WARNING, logger="itzi"): - simulation = _build_provider_simulation(sim_config, domain_5by5, dataset) + itzi_logger.addHandler(caplog.handler) + try: + simulation = _build_provider_simulation(sim_config, domain_5by5, dataset) + finally: + itzi_logger.removeHandler(caplog.handler) warning_messages = [record.message for record in caplog.records] assert any( diff --git a/tests/test_data/EA_test_8/b/test8b_drainage_ponding_mod.inp b/tests/test_data/EA_test_8/b/test8b_drainage_ponding_mod.inp new file mode 100644 index 0000000..e9656bc --- /dev/null +++ b/tests/test_data/EA_test_8/b/test8b_drainage_ponding_mod.inp @@ -0,0 +1,205 @@ +[TITLE] +'UK EA 2D test case #8b' + +[OPTIONS] +FLOW_UNITS CMS +INFILTRATION HORTON +FLOW_ROUTING DYNWAVE +START_DATE 01/01/2007 +START_TIME 01:40:00 +REPORT_START_DATE 01/01/2007 +REPORT_START_TIME 01:40:00 +END_DATE 01/01/2007 +END_TIME 05:00:00 +SWEEP_START 01/01 +SWEEP_END 12/31 +DRY_DAYS 0 +REPORT_STEP 00:00:30 +WET_STEP 00:00:05 +DRY_STEP 01:00:00 +ROUTING_STEP 1 +ALLOW_PONDING YES +INERTIAL_DAMPING NONE +VARIABLE_STEP .5 +LENGTHENING_STEP 0 +MIN_SURFAREA 1 +NORMAL_FLOW_LIMITED FROUDE +SKIP_STEADY_STATE NO +FORCE_MAIN_EQUATION D-W +LINK_OFFSETS DEPTH +MIN_SLOPE 0 + +[REPORT] +INPUT YES +CONTROLS YES +NODES ALL +LINKS ALL + +[JUNCTIONS] +;; Invert Max. Init. Surcharge Ponded +;;Name Elev. Depth Depth Depth Area +;;-------------- ---------- ---------- ---------- ---------- ---------- +J0 39.17 2.0 0 100 0 +J1 29.46 2.0 0 100 1 +J2 27.70 2.0 0 100 0 +J3 26.37 2.0 0 100 0 +J4 25.70 2.0 0 100 0 +J5 24.64 2.0 0 100 0 +J6 24.29 2.0 0 100 0 + +[OUTFALL] +O7 23.49 FREE + +[COORDINATES] +;;Node X-Coord Y-Coord +;;-------------- -------------- -------- +J1 264895 664747 + +[CONDUITS] +;; Inlet Outlet Manning Inlet Outlet Init. Max. +;;Name Node Node Length N Offset Offset Flow Flow +;;------------ ---------- ----------- ---------- ---------- ---------- ---------- ---------- ---------- +C0 J0 J1 467 0.017 0 0 0 +C1 J1 J2 104 0.017 0 0 0 +C2 J2 J3 106 0.017 0 0 0 +C3 J3 J4 200 0.017 0 0 0 +C4 J4 J5 114 0.017 0 0 0 +C5 J5 J6 154 0.017 0 0 0 +C6 J6 O7 195 0.017 0 0 0 + +[XSECTIONS] +;;Link Shape Geom1 Geom2 Geom3 Geom4 Barrels +;;-------------- ------------ ---------------- ---------- ---------- ---------- ---------- +C0 CIRCULAR 1.4 0 0 0 1 +C1 CIRCULAR 1.4 0 0 0 1 +C2 CIRCULAR 1.4 0 0 0 1 +C3 CIRCULAR 1.4 0 0 0 1 +C4 CIRCULAR 1.4 0 0 0 1 +C5 CIRCULAR 1.4 0 0 0 1 +C6 CIRCULAR 1.4 0 0 0 1 + +[INFLOWS] +J0 FLOW inq + +[TIMESERIES] +inq 0 1.6 +inq 0.033 1.6 +inq 0.067 1.6 +inq 0.1 1.6 +inq 0.133 1.61644 +inq 0.167 1.6336 +inq 0.2 1.65472 +inq 0.233 1.67188 +inq 0.267 1.68904 +inq 0.3 1.70488 +inq 0.333 1.71808 +inq 0.367 1.71808 +inq 0.4 1.7392 +inq 0.433 1.75636 +inq 0.467 1.77352 +inq 0.5 1.7986 +inq 0.533 1.82764 +inq 0.567 1.8448 +inq 0.6 1.88704 +inq 0.633 1.92136 +inq 0.667 1.95436 +inq 0.7 1.98868 +inq 0.733 2.02168 +inq 0.767 2.056 +inq 0.8 2.09824 +inq 0.833 2.1484 +inq 0.867 2.19988 +inq 0.9 2.25928 +inq 0.933 2.32264 +inq 0.967 2.3728 +inq 1 2.4784 +inq 1.033 2.56288 +inq 1.067 2.66056 +inq 1.1 2.77012 +inq 1.133 2.8876 +inq 1.167 3.0064 +inq 1.2 3.17536 +inq 1.233 3.29416 +inq 1.267 3.44992 +inq 1.3 3.61888 +inq 1.333 3.78784 +inq 1.367 3.9568 +inq 1.4 4.168 +inq 1.433 4.33696 +inq 1.467 4.50592 +inq 1.5 4.67488 +inq 1.533 4.83988 +inq 1.567 4.99168 +inq 1.6 5.16064 +inq 1.633 5.27944 +inq 1.667 5.41012 +inq 1.7 5.54476 +inq 1.733 5.67148 +inq 1.767 5.77312 +inq 1.8 5.89984 +inq 1.833 6.00148 +inq 1.867 6.10312 +inq 1.9 6.1876 +inq 1.933 6.24096 +inq 1.967 6.28111 +inq 2 6.28111 +inq 2.033 6.24096 +inq 2.067 6.1876 +inq 2.1 6.10312 +inq 2.133 6.00148 +inq 2.167 5.89984 +inq 2.2 5.77312 +inq 2.233 5.67148 +inq 2.267 5.54476 +inq 2.3 5.41012 +inq 2.333 5.27944 +inq 2.367 5.16064 +inq 2.4 4.99168 +inq 2.433 4.83988 +inq 2.467 4.67488 +inq 2.5 4.50592 +inq 2.533 4.33696 +inq 2.567 4.168 +inq 2.6 3.9568 +inq 2.633 3.78784 +inq 2.667 3.61888 +inq 2.7 3.44992 +inq 2.733 3.29416 +inq 2.767 3.17536 +inq 2.8 3.0064 +inq 2.833 2.8876 +inq 2.867 2.77012 +inq 2.9 2.66056 +inq 2.933 2.56288 +inq 2.967 2.4784 +inq 3 2.3728 +inq 3.033 2.32264 +inq 3.067 2.25928 +inq 3.1 2.19988 +inq 3.133 2.1484 +inq 3.167 2.09824 +inq 3.2 2.056 +inq 3.233 2.02168 +inq 3.267 1.98868 +inq 3.3 1.95436 +inq 3.333 1.92136 +inq 3.367 1.88704 +inq 3.4 1.8448 +inq 3.433 1.82764 +inq 3.467 1.7986 +inq 3.5 1.77352 +inq 3.533 1.75636 +inq 3.567 1.7392 +inq 3.6 1.71808 +inq 3.633 1.71808 +inq 3.667 1.70488 +inq 3.7 1.68904 +inq 3.733 1.67188 +inq 3.767 1.65472 +inq 3.8 1.6336 +inq 3.833 1.61644 +inq 3.867 1.6 +inq 3.9 1.6 +inq 3.933 1.6 +inq 3.967 1.6 +inq 5 1.6 diff --git a/tests/test_data/tutorial_files/nc_itzi_tutorial_drainage.csv b/tests/test_data/tutorial_files/nc_itzi_tutorial_drainage.csv new file mode 100644 index 0000000..c4cbead --- /dev/null +++ b/tests/test_data/tutorial_files/nc_itzi_tutorial_drainage.csv @@ -0,0 +1,8 @@ +simulation_time,average_timestep,timesteps,boundary_volume,rainfall_volume,infiltration_volume,inflow_volume,losses_volume,drainage_network_volume,domain_volume,volume_change,volume_error,percent_error +0:00:00,-,0,0.000,0.000,-0.000,0.000,-0.000,0.000,0.000,0.000,0.000,0.00% +0:05:00,0.500,600,-6.408,4374.482,-0.000,0.000,-0.000,-5.671,4362.951,4362.951,0.000,0.00% +0:10:00,0.500,600,-109.524,4374.482,-0.000,0.000,-0.000,-17.825,8610.655,4247.705,0.000,0.00% +0:15:00,0.500,600,-322.998,4374.482,-0.000,0.000,-0.000,-18.876,12643.927,4033.271,0.000,0.00% +0:20:00,0.500,600,-1525.654,4374.482,-0.000,0.000,-0.000,-3.066,15490.193,2846.267,0.000,0.00% +0:25:00,0.500,600,-1920.266,4374.482,-0.000,0.000,-0.000,-0.456,17944.461,2454.268,0.000,0.00% +0:30:00,0.500,600,-1954.510,4374.482,-0.000,0.000,-0.000,-0.154,20364.799,2420.338,0.000,0.00% diff --git a/tests/test_data/tutorial_files/tutorial_drainage.ini b/tests/test_data/tutorial_files/tutorial_drainage.ini new file mode 100644 index 0000000..8c2f506 --- /dev/null +++ b/tests/test_data/tutorial_files/tutorial_drainage.ini @@ -0,0 +1,26 @@ +[time] +duration = 00:30:00 +record_step = 00:05:00 + +[input] +dem = elev_lid792_5m +friction = n +rain = rain +bctype = bctype +bcvalue = bcvalue + +[output] +prefix = nc_itzi_tutorial_drainage +values = water_depth, v, vdir + +[statistics] +stats_file = nc_itzi_tutorial_drainage.csv + +[options] +cfl = 0.7 +theta = 0.9 +dtmax = 0.5 + +[drainage] +swmm_inp = /home/laurent/software/itzi/tests/test_data/tutorial_files/tutorial_drainage.inp +; output = nc_itzi_tutorial_drainage From 8d171fca934d63e0ecba10f253faf0707e839cee Mon Sep 17 00:00:00 2001 From: Laurent Courty Date: Fri, 26 Jun 2026 11:45:55 -0600 Subject: [PATCH 3/3] add CLI tests to CI --- .github/workflows/tests.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index da69bae..e2c3fa6 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -30,6 +30,7 @@ jobs: - name: Pytest run: | $HOME/.local/bin/uv run --all-extras --python ${{ matrix.python-version }} pytest --cov=src --junitxml=junit/test-core-results.xml --cov-report=xml --cov-report=html tests/core + $HOME/.local/bin/uv run --all-extras --python ${{ matrix.python-version }} pytest --cov=src --junitxml=junit/test-core-results.xml --cov-report=xml --cov-report=html tests/cli $HOME/.local/bin/uv run --all-extras --python ${{ matrix.python-version }} pytest --cov=src --junitxml=junit/test-itzi-results.xml --cov-report=xml --cov-report=html tests/grass/test_itzi.py $HOME/.local/bin/uv run --all-extras --python ${{ matrix.python-version }} pytest --cov=src --junitxml=junit/test-bmi-results.xml --cov-report=xml --cov-report=html tests/grass/test_bmi.py $HOME/.local/bin/uv run --all-extras --python ${{ matrix.python-version }} pytest --cov=src --junitxml=junit/test-tutorial-results.xml --cov-report=xml --cov-report=html tests/grass/test_tutorial.py