From dc8f658ac80c406485a90dee42f5ca4066e9389e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edouard=20Choini=C3=A8re?= <27212526+echoix@users.noreply.github.com> Date: Sat, 5 Sep 2026 20:52:28 +0000 Subject: [PATCH] temporal: Avoid PLY debug-mode overhead in raster algebra gunittest unittests_temporal_raster_algebra.py instantiates TemporalRasterAlgebraParser with debug=True in all 43 of its test methods (45 instantiations), far more than any sibling test file in this family (the next highest is 26). With debug=True, the vendored PLY yacc.yacc() (python/grass/temporal/ply/yacc.py) rebuilds and verbosely logs the full LALR table on every call, and opens a parser.out debug file that is never closed (confirmed by a "ResourceWarning: unclosed file ... 'parser.out'" in a macOS CI log), in addition to enabling extra "if self.debug: print(...)" statements throughout temporal_raster_base_algebra.py. None of this output is used by the tests or by CI. This matches a macOS-only CI failure where this file alone timed out at the gunittest per-file limit (FAILED ... Timeout >300.0s) after completing only a fraction of its tests, while the same file runs all 43 tests in about a minute on Linux CI. The production CLI tool (t.rast.algebra.py) already calls this parser with debug=False, and TemporalRasterBaseAlgebraParser's own default is debug=False; only this test file's parser subclass overrode it to True. Passing debug=False here removes avoidable per-test disk I/O and redundant LALR logging that a contended or slow-disk CI runner would feel most, without changing what is tested (no test inspects the debug output). Investigated by pulling recent macOS Actions runs on this fork, reading the gunittest and PLY yacc internals, and comparing timing across CI runs; see PR description for the full analysis. Co-Authored-By: Claude Sonnet 5 --- .../unittests_temporal_raster_algebra.py | 94 ++++++++++--------- 1 file changed, 49 insertions(+), 45 deletions(-) diff --git a/python/grass/temporal/testsuite/unittests_temporal_raster_algebra.py b/python/grass/temporal/testsuite/unittests_temporal_raster_algebra.py index bbc9b46bd7e..2be814d6b7c 100644 --- a/python/grass/temporal/testsuite/unittests_temporal_raster_algebra.py +++ b/python/grass/temporal/testsuite/unittests_temporal_raster_algebra.py @@ -127,7 +127,7 @@ def tearDownClass(cls) -> None: def test_temporal_extent1(self) -> None: """Testing the temporal extent operators.""" - ta = tgis.TemporalRasterAlgebraParser(run=True, debug=True) + ta = tgis.TemporalRasterAlgebraParser(run=True, debug=False) ta.parse(expression="R = A {:,during,r} C", basename="r", overwrite=True) D = tgis.open_old_stds("R", type="strds") @@ -141,7 +141,7 @@ def test_temporal_extent1(self) -> None: self.assertEqual(D.check_temporal_topology(), False) self.assertEqual(D.get_granularity(), "2 days") - ta = tgis.TemporalRasterAlgebraParser(run=True, debug=True, dry_run=True) + ta = tgis.TemporalRasterAlgebraParser(run=True, debug=False, dry_run=True) pc = ta.parse(expression="R = A {:,during,r} C", basename="r", overwrite=True) self.assertEqual(len(pc["register"]), 2) @@ -155,7 +155,7 @@ def test_temporal_conditional_time_dimension_bug(self) -> None: """Testing the conditional time dimension bug, that uses the time dimension of the conditional statement instead the time dimension of the then/else statement.""" - tra = tgis.TemporalRasterAlgebraParser(run=True, debug=True) + tra = tgis.TemporalRasterAlgebraParser(run=True, debug=False) tra.parse( expression="R = if({contains}, B == 5, A - 1, A + 1)", basename="r", @@ -189,7 +189,9 @@ def test_simple_arith_hash_1(self) -> None: r4 = a4 + 1 """ - tra = tgis.TemporalRasterAlgebraParser(run=True, debug=True, time_suffix="gran") + tra = tgis.TemporalRasterAlgebraParser( + run=True, debug=False, time_suffix="gran" + ) tra.parse(expression="R = A + (A {#, equal,l} A)", basename="r", overwrite=True) D = tgis.open_old_stds("R", type="strds") @@ -228,7 +230,9 @@ def test_simple_arith_td_1(self) -> None: r4 = a4 + 1 """ - tra = tgis.TemporalRasterAlgebraParser(run=True, debug=True, time_suffix="time") + tra = tgis.TemporalRasterAlgebraParser( + run=True, debug=False, time_suffix="time" + ) tra.parse(expression="R = A + td(A)", basename="r", overwrite=True) D = tgis.open_old_stds("R", type="strds") @@ -267,7 +271,7 @@ def test_simple_arith_td_2(self) -> None: r3 = a3 / 1 r4 = a4 / 1 """ - tra = tgis.TemporalRasterAlgebraParser(run=True, debug=True) + tra = tgis.TemporalRasterAlgebraParser(run=True, debug=False) tra.parse(expression="R = A / td(A)", basename="r", overwrite=True) D = tgis.open_old_stds("R", type="strds") @@ -294,7 +298,7 @@ def test_simple_arith_td_3(self) -> None: r4 = a4 + 1 """ - tra = tgis.TemporalRasterAlgebraParser(run=True, debug=True) + tra = tgis.TemporalRasterAlgebraParser(run=True, debug=False) tra.parse(expression="R = A {+,equal} td(A)", basename="r", overwrite=True) D = tgis.open_old_stds("R", type="strds") @@ -321,7 +325,7 @@ def test_simple_arith_td_4(self) -> None: r4 = a4 + 1 """ - tra = tgis.TemporalRasterAlgebraParser(run=True, debug=True) + tra = tgis.TemporalRasterAlgebraParser(run=True, debug=False) tra.parse(expression="R = A {/, equal} td(A)", basename="r", overwrite=True) D = tgis.open_old_stds("R", type="strds") @@ -345,7 +349,7 @@ def test_simple_arith_if_1(self) -> None: r4 = a4 + a4 """ - tra = tgis.TemporalRasterAlgebraParser(run=True, debug=True) + tra = tgis.TemporalRasterAlgebraParser(run=True, debug=False) tra.parse( expression='R = if({equal}, start_date(A) >= "2001-01-02", A + A)', basename="r", @@ -381,7 +385,7 @@ def test_simple_arith_if_2(self) -> None: r4 = a4 - a4 """ - tra = tgis.TemporalRasterAlgebraParser(run=True, debug=True) + tra = tgis.TemporalRasterAlgebraParser(run=True, debug=False) tra.parse( expression="R = if({equal}, A#A == 1, A - A)", basename="r", overwrite=True ) @@ -409,7 +413,7 @@ def test_complex_arith_if_1(self) -> None: will compute a3 + c1 """ - tra = tgis.TemporalRasterAlgebraParser(run=True, debug=True) + tra = tgis.TemporalRasterAlgebraParser(run=True, debug=False) tra.parse( expression='R = if(start_date(A) < "2001-01-03" && A#A == 1, A{+, starts,l}C, A{+, finishes,l}C)', basename="r", @@ -427,7 +431,7 @@ def test_complex_arith_if_1(self) -> None: def test_simple_arith_1(self) -> None: """Simple arithmetic test""" - tra = tgis.TemporalRasterAlgebraParser(run=True, debug=True) + tra = tgis.TemporalRasterAlgebraParser(run=True, debug=False) tra.parse( expression="R = A {*, equal} A {+, equal} A", basename="r", overwrite=True ) @@ -443,7 +447,7 @@ def test_simple_arith_1(self) -> None: def test_simple_arith_2(self) -> None: """Simple arithmetic test that creates an empty strds""" - tra = tgis.TemporalRasterAlgebraParser(run=True, debug=True) + tra = tgis.TemporalRasterAlgebraParser(run=True, debug=False) tra.parse( expression="R = A {*, during} A {+, during} A", basename="r", overwrite=True ) @@ -453,7 +457,7 @@ def test_simple_arith_2(self) -> None: def test_simple_arith_3(self) -> None: """Simple arithmetic test""" - tra = tgis.TemporalRasterAlgebraParser(run=True, debug=True) + tra = tgis.TemporalRasterAlgebraParser(run=True, debug=False) tra.parse(expression="R = A / A + A*A/A", basename="r", overwrite=True) D = tgis.open_old_stds("R", type="strds") @@ -467,7 +471,7 @@ def test_simple_arith_3(self) -> None: def test_temporal_intersection_1(self) -> None: """Simple temporal intersection test""" - tra = tgis.TemporalRasterAlgebraParser(run=True, debug=True) + tra = tgis.TemporalRasterAlgebraParser(run=True, debug=False) tra.parse(expression="R = A {+,equal,i} B", basename="r", overwrite=True) D = tgis.open_old_stds("R", type="strds") D.select() @@ -475,7 +479,7 @@ def test_temporal_intersection_1(self) -> None: def test_temporal_intersection_2(self) -> None: """Simple temporal intersection test""" - tra = tgis.TemporalRasterAlgebraParser(run=True, debug=True) + tra = tgis.TemporalRasterAlgebraParser(run=True, debug=False) tra.parse(expression="R = A {+,during,i} B", basename="r", overwrite=True) D = tgis.open_old_stds("R", type="strds") @@ -489,7 +493,7 @@ def test_temporal_intersection_2(self) -> None: def test_temporal_intersection_3(self) -> None: """Simple temporal intersection test""" - tra = tgis.TemporalRasterAlgebraParser(run=True, debug=True) + tra = tgis.TemporalRasterAlgebraParser(run=True, debug=False) tra.parse(expression="R = A {+,starts,i} B", basename="r", overwrite=True) D = tgis.open_old_stds("R", type="strds") @@ -503,7 +507,7 @@ def test_temporal_intersection_3(self) -> None: def test_temporal_intersection_4(self) -> None: """Simple temporal intersection test""" - tra = tgis.TemporalRasterAlgebraParser(run=True, debug=True) + tra = tgis.TemporalRasterAlgebraParser(run=True, debug=False) tra.parse( expression="R = A {+,finishes,intersect} B", basename="r", overwrite=True ) @@ -519,7 +523,7 @@ def test_temporal_intersection_4(self) -> None: def test_temporal_intersection_5(self) -> None: """Simple temporal intersection test""" - tra = tgis.TemporalRasterAlgebraParser(run=True, debug=True) + tra = tgis.TemporalRasterAlgebraParser(run=True, debug=False) tra.parse( expression="R = A {+,starts|finishes,i} B", basename="r", overwrite=True ) @@ -535,7 +539,7 @@ def test_temporal_intersection_5(self) -> None: def test_temporal_intersection_6(self) -> None: """Simple temporal intersection test""" - tra = tgis.TemporalRasterAlgebraParser(run=True, debug=True) + tra = tgis.TemporalRasterAlgebraParser(run=True, debug=False) tra.parse(expression="R = B {+,overlaps,u} C", basename="r", overwrite=True) D = tgis.open_old_stds("R", type="strds") @@ -549,7 +553,7 @@ def test_temporal_intersection_6(self) -> None: def test_temporal_intersection_7(self) -> None: """Simple temporal intersection test""" - tra = tgis.TemporalRasterAlgebraParser(run=True, debug=True) + tra = tgis.TemporalRasterAlgebraParser(run=True, debug=False) tra.parse(expression="R = B {+,overlapped,u} C", basename="r", overwrite=True) D = tgis.open_old_stds("R", type="strds") @@ -563,7 +567,7 @@ def test_temporal_intersection_7(self) -> None: def test_temporal_intersection_8(self) -> None: """Simple temporal intersection test""" - tra = tgis.TemporalRasterAlgebraParser(run=True, debug=True) + tra = tgis.TemporalRasterAlgebraParser(run=True, debug=False) tra.parse( expression='R = A {+,during,l} buff_t(C, "1 day") ', basename="r", @@ -581,7 +585,7 @@ def test_temporal_intersection_8(self) -> None: def test_temporal_neighbors_1(self) -> None: """Simple temporal neighborhood computation test""" - tra = tgis.TemporalRasterAlgebraParser(run=True, debug=True) + tra = tgis.TemporalRasterAlgebraParser(run=True, debug=False) tra.parse(expression="R = A[-1] + A[1]", basename="r", overwrite=True) D = tgis.open_old_stds("R", type="strds") @@ -595,7 +599,7 @@ def test_temporal_neighbors_1(self) -> None: def test_temporal_neighbors_2(self) -> None: """Simple temporal neighborhood computation test""" - tra = tgis.TemporalRasterAlgebraParser(run=True, debug=True) + tra = tgis.TemporalRasterAlgebraParser(run=True, debug=False) tra.parse(expression="R = A[0,0,-1] + A[0,0,1]", basename="r", overwrite=True) D = tgis.open_old_stds("R", type="strds") @@ -609,7 +613,7 @@ def test_temporal_neighbors_2(self) -> None: def test_tmap_function1(self) -> None: """Testing the tmap function.""" - tra = tgis.TemporalRasterAlgebraParser(run=True, debug=True) + tra = tgis.TemporalRasterAlgebraParser(run=True, debug=False) tra.parse(expression="R = tmap(singletmap)", basename="r", overwrite=True) D = tgis.open_old_stds("R", type="strds") @@ -626,7 +630,7 @@ def test_tmap_function1(self) -> None: def test_tmap_function2(self) -> None: """Testing the tmap function.""" - tra = tgis.TemporalRasterAlgebraParser(run=True, debug=True) + tra = tgis.TemporalRasterAlgebraParser(run=True, debug=False) tra.parse(expression="R = tmap(singletmap) + 1", basename="r", overwrite=True) D = tgis.open_old_stds("R", type="strds") @@ -643,7 +647,7 @@ def test_tmap_function2(self) -> None: def test_map_function1(self) -> None: """Testing the map function.""" - tra = tgis.TemporalRasterAlgebraParser(run=True, debug=True) + tra = tgis.TemporalRasterAlgebraParser(run=True, debug=False) tra.parse(expression="R = map(singlemap) + A", basename="r", overwrite=True) D = tgis.open_old_stds("R", type="strds") @@ -660,7 +664,7 @@ def test_map_function1(self) -> None: def test_map_function2(self) -> None: """Testing the map function.""" - tra = tgis.TemporalRasterAlgebraParser(run=True, debug=True) + tra = tgis.TemporalRasterAlgebraParser(run=True, debug=False) tra.parse(expression="R = A * map(singlemap)", basename="r", overwrite=True) D = tgis.open_old_stds("R", type="strds") @@ -677,7 +681,7 @@ def test_map_function2(self) -> None: def test_temporal_select_same_left_right(self) -> None: """Testing the temporal select operator with the same map for left and right.""" - tra = tgis.TemporalRasterAlgebraParser(run=True, debug=True) + tra = tgis.TemporalRasterAlgebraParser(run=True, debug=False) tra.parse(expression="R = A : A", basename="r", overwrite=True) D = tgis.open_old_stds("R", type="strds") @@ -693,7 +697,7 @@ def test_temporal_select_same_left_right(self) -> None: def test_temporal_select(self) -> None: """Testing the temporal select operator.""" - tra = tgis.TemporalRasterAlgebraParser(run=True, debug=True) + tra = tgis.TemporalRasterAlgebraParser(run=True, debug=False) tra.parse(expression="R = A : D", basename="r", overwrite=True) D = tgis.open_old_stds("R", type="strds") @@ -709,7 +713,7 @@ def test_temporal_select(self) -> None: def test_temporal_select_operators1(self) -> None: """Testing the temporal select operator. Including temporal relations.""" - tra = tgis.TemporalRasterAlgebraParser(run=True, debug=True) + tra = tgis.TemporalRasterAlgebraParser(run=True, debug=False) tra.parse(expression="R = A : D", basename="r", overwrite=True) D = tgis.open_old_stds("R", type="strds") @@ -725,7 +729,7 @@ def test_temporal_select_operators1(self) -> None: def test_temporal_select_operators2(self) -> None: """Testing the temporal select operator. Including temporal relations.""" - tra = tgis.TemporalRasterAlgebraParser(run=True, debug=True) + tra = tgis.TemporalRasterAlgebraParser(run=True, debug=False) tra.parse(expression="R = A {!:,during} C", basename="r", overwrite=True) D = tgis.open_old_stds("R", type="strds") @@ -742,7 +746,7 @@ def test_temporal_select_operators2(self) -> None: def test_temporal_select_operators3(self) -> None: """Testing the temporal select operator. Including temporal relations and different temporal operators (lr|+&)""" - tra = tgis.TemporalRasterAlgebraParser(run=True, debug=True) + tra = tgis.TemporalRasterAlgebraParser(run=True, debug=False) tra.parse(expression="R = A {:,during,d} B", basename="r", overwrite=True) D = tgis.open_old_stds("R", type="strds") @@ -759,7 +763,7 @@ def test_temporal_select_operators3(self) -> None: def test_temporal_select_operators4(self) -> None: """Testing the temporal select operator. Including temporal relations and different temporal operators (lr|+&)""" - tra = tgis.TemporalRasterAlgebraParser(run=True, debug=True) + tra = tgis.TemporalRasterAlgebraParser(run=True, debug=False) tra.parse(expression="R = A {:,equal|during,r} C", basename="r", overwrite=True) D = tgis.open_old_stds("R", type="strds") @@ -780,7 +784,7 @@ def test_temporal_select_operators4(self) -> None: def test_temporal_hash_operator1(self) -> None: """Testing the temporal hash operator in the raster algebra.""" - tra = tgis.TemporalRasterAlgebraParser(run=True, debug=True) + tra = tgis.TemporalRasterAlgebraParser(run=True, debug=False) tra.parse(expression="R = if(A # D == 1, A)", basename="r", overwrite=True) D = tgis.open_old_stds("R", type="strds") @@ -796,7 +800,7 @@ def test_temporal_hash_operator1(self) -> None: def test_temporal_hash_operator2(self) -> None: """Testing the temporal hash operator in the raster algebra.""" - tra = tgis.TemporalRasterAlgebraParser(run=True, debug=True) + tra = tgis.TemporalRasterAlgebraParser(run=True, debug=False) tra.parse(expression="R = A # D", basename="r", overwrite=True) D = tgis.open_old_stds("R", type="strds") @@ -812,7 +816,7 @@ def test_temporal_hash_operator2(self) -> None: def test_temporal_hash_operator3(self) -> None: """Testing the temporal hash operator in the raster algebra.""" - tra = tgis.TemporalRasterAlgebraParser(run=True, debug=True) + tra = tgis.TemporalRasterAlgebraParser(run=True, debug=False) tra.parse(expression="R = C {#,contains} A", basename="r", overwrite=True) D = tgis.open_old_stds("R", type="strds") @@ -828,7 +832,7 @@ def test_temporal_hash_operator3(self) -> None: def test_temporal_hash_operator4(self) -> None: """Testing the temporal hash operator in the raster algebra.""" - tra = tgis.TemporalRasterAlgebraParser(run=True, debug=True) + tra = tgis.TemporalRasterAlgebraParser(run=True, debug=False) tra.parse( expression="R = if({contains},A # D == 1, C {#,contains} A)", basename="r", @@ -848,7 +852,7 @@ def test_temporal_hash_operator4(self) -> None: def test_raster_arithmetic_relation_1(self) -> None: """Arithmetic test with temporal intersection""" - tra = tgis.TemporalRasterAlgebraParser(run=True, debug=True) + tra = tgis.TemporalRasterAlgebraParser(run=True, debug=False) tra.parse(expression="R = B {+,contains,l} A ", basename="r", overwrite=True) D = tgis.open_old_stds("R", type="strds") @@ -864,7 +868,7 @@ def test_raster_arithmetic_relation_1(self) -> None: def test_raster_arithmetic_relation_2(self) -> None: """Arithmetic test with temporal intersection""" - tra = tgis.TemporalRasterAlgebraParser(run=True, debug=True) + tra = tgis.TemporalRasterAlgebraParser(run=True, debug=False) tra.parse(expression="R = B {*,contains,l} A ", basename="r", overwrite=True) D = tgis.open_old_stds("R", type="strds") @@ -880,7 +884,7 @@ def test_raster_arithmetic_relation_2(self) -> None: def test_raster_arithmetic_relation_3(self) -> None: """Arithmetic test with temporal intersection""" - tra = tgis.TemporalRasterAlgebraParser(run=True, debug=True) + tra = tgis.TemporalRasterAlgebraParser(run=True, debug=False) tra.parse(expression="R = B {+,contains,l} A ", basename="r", overwrite=True) D = tgis.open_old_stds("R", type="strds") @@ -896,7 +900,7 @@ def test_raster_arithmetic_relation_3(self) -> None: def test_raster_arithmetic_relation_4(self) -> None: """Arithmetic test with temporal intersection""" - tra = tgis.TemporalRasterAlgebraParser(run=True, debug=True) + tra = tgis.TemporalRasterAlgebraParser(run=True, debug=False) tra.parse(expression="R = B {+,contains,r} A ", basename="r", overwrite=True) D = tgis.open_old_stds("R", type="strds") @@ -912,7 +916,7 @@ def test_raster_arithmetic_relation_4(self) -> None: def test_raster_arithmetic_relation_5(self) -> None: """Complex arithmetic test with temporal intersection""" - tra = tgis.TemporalRasterAlgebraParser(run=True, debug=True) + tra = tgis.TemporalRasterAlgebraParser(run=True, debug=False) tra.parse( expression="R = tmap(singletmap) {+,equal| precedes| follows,l} A + map(singlemap)", basename="r", @@ -932,7 +936,7 @@ def test_raster_arithmetic_relation_5(self) -> None: def test_capacity_1(self) -> None: """Arithmetic test with temporal intersection""" - tra = tgis.TemporalRasterAlgebraParser(run=True, debug=True) + tra = tgis.TemporalRasterAlgebraParser(run=True, debug=False) expr = "R = (((((((A + A) - A) * A) / A) % A) - td(A)) - (A # A))" tra.parse(expression=expr, basename="r", overwrite=True) @@ -947,7 +951,7 @@ def test_capacity_1(self) -> None: self.assertEqual(D.check_temporal_topology(), True) self.assertEqual(D.get_granularity(), "1 day") - tra = tgis.TemporalRasterAlgebraParser(run=True, debug=True, dry_run=True) + tra = tgis.TemporalRasterAlgebraParser(run=True, debug=False, dry_run=True) pc = tra.parse(expression=expr, basename="r", overwrite=True) self.assertEqual(len(pc["register"]), 4)