git.lucas.co / hou-control
SideFX Houdini customization package
git clone https://git.lucas.co/hou-control.git

commitba29f4bd79ccd3b86d178197be81154b466c35e0
parent3c95f98964
authorLucas Galante <[email protected]>
date2026-09-14 13:05
check: pin node_coloring inside the checks that exercise it

Four maintenance checks called updateNodeColors() and read whether it
would run from hc_settings.json, so switching the setting off in 3c95f98
failed them without anything being wrong. A nodeColoring(enabled)
context manager (also a decorator) patches HCSettings.nodeColoringEnabled
for the duration of each check; the switched-off check uses it both ways.

Co-Authored-By: Claude Fable 5.1 <[email protected]>

 tools/check.py | 39 +++++++++++++++++++++++++++++++++------
 1 file changed, 33 insertions(+), 6 deletions(-)

diff --git a/tools/check.py b/tools/check.py
index f8a7716..bca5834 100644
--- a/tools/check.py
+++ b/tools/check.py
@@ -64,6 +64,32 @@ def blank(cls):
     return cls.__new__(cls)
 
 
+class nodeColoring:
+    """Pin the node_coloring switch for one check.
+
+    The maintenance checks exercise what updateNodeColors() does when it
+    runs; whether it runs is the user's setting in hc_settings.json, which
+    ships off since 3c95f98. Reading the file made four checks fail on a
+    setting, not a bug. Use as a context manager or a decorator.
+    """
+
+    def __init__(self, enabled):
+        self.enabled = enabled
+
+    def __enter__(self):
+        self.original = HCSettings.nodeColoringEnabled
+        HCSettings.nodeColoringEnabled = lambda _self, enabled=self.enabled: enabled
+
+    def __exit__(self, *exc):
+        HCSettings.nodeColoringEnabled = self.original
+
+    def __call__(self, fn):
+        def wrapped():
+            with self:
+                return fn()
+        return wrapped
+
+
 def check_settings():
     print("settings")
     settings = HCSettings()
@@ -776,6 +802,7 @@ def check_node_colors():
     RED = hou.Color((1.0, 0.0, 0.0))
     GREEN = hou.Color((0.0, 1.0, 0.0))
 
+    @nodeColoring(True)
     def only_unchanged_nodes_are_recolored():
         default = settings.nodeColor()
         default_hex = settings.nodeColorHex()
@@ -811,6 +838,7 @@ def check_node_colors():
 
     check("updateNodeColors ownership", only_unchanged_nodes_are_recolored)
 
+    @nodeColoring(True)
     def second_pass_writes_nothing():
         """Every setColor marks the hip modified, and 456.py runs this on load."""
         geo = hou.node("/obj").createNode("geo")
@@ -829,6 +857,7 @@ def check_node_colors():
 
     check("updateNodeColors is idempotent", second_pass_writes_nothing)
 
+    @nodeColoring(True)
     def opting_out_is_reversible():
         """Set Node Colors / Reset Node Colors, minus the UI.
 
@@ -859,6 +888,7 @@ def check_node_colors():
 
     check("resetNodeColors round trip", opting_out_is_reversible)
 
+    @nodeColoring(True)
     def recolor_is_one_undo():
         """A scene-wide recolor must cost one ctrl-Z, not one per node."""
         if not hou.undos.areEnabled():
@@ -1047,16 +1077,13 @@ def check_disable_switches():
         node.setColor(hou.Color((1.0, 0.0, 0.0)))
 
         session = blank(HCSession)
-        original = HCSettings.nodeColoringEnabled
-        try:
-            HCSettings.nodeColoringEnabled = lambda self: False
+        with nodeColoring(False):
             assert session.updateNodeColors() == 0, "recolored while switched off"
             assert node.userData("hc_custom_color") == "1", "rewrote the tag while off"
-        finally:
-            HCSettings.nodeColoringEnabled = original
 
         # And the tag is still there, so turning it back on resumes.
-        assert session.updateNodeColors() >= 1, "did not resume when switched on"
+        with nodeColoring(True):
+            assert session.updateNodeColors() >= 1, "did not resume when switched on"
         geo.destroy()
         return "no writes while off, resumes after"