[Lldb-commits] [lldb] [SBProgress] Add swig support for `with` statement in Python (PR #133527)

Jacob Lalonde via lldb-commits lldb-commits at lists.llvm.org
Fri Mar 28 15:24:33 PDT 2025


https://github.com/Jlalond created https://github.com/llvm/llvm-project/pull/133527

We recently added an explicit finalize to SBProgress, #128966. I realized while adding some additional implementations of SBProgress that we should to add `with` support for ease of use. This patch addresses adding and `__enter()__` method (which a no-op) and an `__exit()__` to swig. I also refactor the emitter for the test to leverage `with` instead of explicitly calling finalize, and I've updated the docstrings.

>From ec90252f34b358e1eba65f4b430d267833fa9ec8 Mon Sep 17 00:00:00 2001
From: Jacob Lalonde <jalalonde at fb.com>
Date: Fri, 28 Mar 2025 15:01:31 -0700
Subject: [PATCH 1/3] Implement methods for 'with' in python

---
 .../bindings/interface/SBProgressExtensions.i |  0
 .../lldb-dap/progress/Progress_emitter.py     | 38 ++++++++++---------
 2 files changed, 20 insertions(+), 18 deletions(-)
 create mode 100644 lldb/bindings/interface/SBProgressExtensions.i

diff --git a/lldb/bindings/interface/SBProgressExtensions.i b/lldb/bindings/interface/SBProgressExtensions.i
new file mode 100644
index 0000000000000..e69de29bb2d1d
diff --git a/lldb/test/API/tools/lldb-dap/progress/Progress_emitter.py b/lldb/test/API/tools/lldb-dap/progress/Progress_emitter.py
index e94a09676e067..140a6fce99b48 100644
--- a/lldb/test/API/tools/lldb-dap/progress/Progress_emitter.py
+++ b/lldb/test/API/tools/lldb-dap/progress/Progress_emitter.py
@@ -67,6 +67,16 @@ def get_short_help(self):
     def get_long_help(self):
         return self.help_string
 
+    def __get__progress(self, debugger, total):
+        if total is None:
+            progress = lldb.SBProgress(
+                "Progress tester", "Initial Indeterminate Detail", debugger
+            )
+        else:
+            progress = lldb.SBProgress(
+                "Progress tester", "Initial Detail", total, debugger
+            )
+
     def __init__(self, debugger, unused):
         self.parser = self.create_options()
         self.help_string = self.parser.format_help()
@@ -80,26 +90,18 @@ def __call__(self, debugger, command, exe_ctx, result):
             return
 
         total = cmd_options.total
-        if total is None:
-            progress = lldb.SBProgress(
-                "Progress tester", "Initial Indeterminate Detail", debugger
-            )
-        else:
-            progress = lldb.SBProgress(
-                "Progress tester", "Initial Detail", total, debugger
-            )
-
         # Check to see if total is set to None to indicate an indeterminate progress
         # then default to 10 steps.
-        if total is None:
-            total = 10
-
-        for i in range(1, total):
-            if cmd_options.no_details:
-                progress.Increment(1)
-            else:
-                progress.Increment(1, f"Step {i}")
-            time.sleep(cmd_options.seconds)
+        with self.__get_progress(debugger, total) as progress:
+            if total is None:
+                total = 10
+
+            for i in range(1, total):
+                if cmd_options.no_details:
+                    progress.Increment(1)
+                else:
+                    progress.Increment(1, f"Step {i}")
+                time.sleep(cmd_options.seconds)
 
         # Not required for deterministic progress, but required for indeterminate progress.
         progress.Finalize()

>From 353aac719f3223683eab21b113d22043c5ad9575 Mon Sep 17 00:00:00 2001
From: Jacob Lalonde <jalalonde at fb.com>
Date: Fri, 28 Mar 2025 15:19:29 -0700
Subject: [PATCH 2/3] Fix swig interfaces, and the emitter class

---
 .../bindings/interface/SBProgressExtensions.i | 13 +++++++++++
 lldb/bindings/interfaces.swig                 |  1 +
 .../lldb-dap/progress/Progress_emitter.py     | 23 ++++++++-----------
 3 files changed, 23 insertions(+), 14 deletions(-)

diff --git a/lldb/bindings/interface/SBProgressExtensions.i b/lldb/bindings/interface/SBProgressExtensions.i
index e69de29bb2d1d..6ecf3a1af93b7 100644
--- a/lldb/bindings/interface/SBProgressExtensions.i
+++ b/lldb/bindings/interface/SBProgressExtensions.i
@@ -0,0 +1,13 @@
+%extend lldb::SBProgress {
+#ifdef SWIGPYTHON
+    %pythoncode %{
+        def __enter__(self):
+            '''No-op for with statement'''
+            pass
+
+        def __exit__(self, exc_type, exc_value, traceback):
+            '''Finalize the progress object'''
+            self.Finalize()
+    %}
+#endif
+}
\ No newline at end of file
diff --git a/lldb/bindings/interfaces.swig b/lldb/bindings/interfaces.swig
index 08df9a1a8d539..6da56e4e0fa52 100644
--- a/lldb/bindings/interfaces.swig
+++ b/lldb/bindings/interfaces.swig
@@ -200,6 +200,7 @@
 %include "./interface/SBModuleSpecExtensions.i"
 %include "./interface/SBModuleSpecListExtensions.i"
 %include "./interface/SBProcessExtensions.i"
+%include "./interface/SBProgressExtensions.i"
 %include "./interface/SBProcessInfoListExtensions.i"
 %include "./interface/SBQueueItemExtensions.i"
 %include "./interface/SBScriptObjectExtensions.i"
diff --git a/lldb/test/API/tools/lldb-dap/progress/Progress_emitter.py b/lldb/test/API/tools/lldb-dap/progress/Progress_emitter.py
index 140a6fce99b48..445d1bdf4e496 100644
--- a/lldb/test/API/tools/lldb-dap/progress/Progress_emitter.py
+++ b/lldb/test/API/tools/lldb-dap/progress/Progress_emitter.py
@@ -67,16 +67,6 @@ def get_short_help(self):
     def get_long_help(self):
         return self.help_string
 
-    def __get__progress(self, debugger, total):
-        if total is None:
-            progress = lldb.SBProgress(
-                "Progress tester", "Initial Indeterminate Detail", debugger
-            )
-        else:
-            progress = lldb.SBProgress(
-                "Progress tester", "Initial Detail", total, debugger
-            )
-
     def __init__(self, debugger, unused):
         self.parser = self.create_options()
         self.help_string = self.parser.format_help()
@@ -90,9 +80,17 @@ def __call__(self, debugger, command, exe_ctx, result):
             return
 
         total = cmd_options.total
+        if total is None:
+            progress = lldb.SBProgress(
+                "Progress tester", "Initial Indeterminate Detail", debugger
+            )
+        else:
+            progress = lldb.SBProgress(
+                "Progress tester", "Initial Detail", total, debugger
+            )
         # Check to see if total is set to None to indicate an indeterminate progress
         # then default to 10 steps.
-        with self.__get_progress(debugger, total) as progress:
+        with progress:
             if total is None:
                 total = 10
 
@@ -103,9 +101,6 @@ def __call__(self, debugger, command, exe_ctx, result):
                     progress.Increment(1, f"Step {i}")
                 time.sleep(cmd_options.seconds)
 
-        # Not required for deterministic progress, but required for indeterminate progress.
-        progress.Finalize()
-
 
 def __lldb_init_module(debugger, dict):
     # Register all classes that have a register_lldb_command method

>From 4a188565db3fee49564df270813eb79f47adf933 Mon Sep 17 00:00:00 2001
From: Jacob Lalonde <jalalonde at fb.com>
Date: Fri, 28 Mar 2025 15:23:49 -0700
Subject: [PATCH 3/3] Add documentation on the new support

---
 lldb/bindings/interface/SBProgressDocstrings.i | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/lldb/bindings/interface/SBProgressDocstrings.i b/lldb/bindings/interface/SBProgressDocstrings.i
index 8d252ef1f370c..0aff4c502f3a4 100644
--- a/lldb/bindings/interface/SBProgressDocstrings.i
+++ b/lldb/bindings/interface/SBProgressDocstrings.i
@@ -52,6 +52,13 @@ Non-deterministic progresses behave the same, but omit the total in the construc
     # Explicitly send a progressEnd, otherwise this will be sent
     # when the python runtime cleans up this object.
     non_deterministic_progress.Finalize()
+
+Additionally for Python, progress is supported in a with statement. ::
+    with lldb.SBProgress('Non deterministic progress, 'Detail', lldb.SBDebugger) as progress:
+        for i in range(10):
+            progress.Increment(1)
+    # The progress object is automatically finalized when the with statement
+
 ") lldb::SBProgress;    
 
 %feature("docstring",



More information about the lldb-commits mailing list