[PATCH 3 of 3] util: add debugstacktrace depth limit

Mads Kiilerich mads at kiilerich.com
Sat Mar 11 17:31:13 EST 2017


# HG changeset patch
# User Mads Kiilerich <madski at unity3d.com>
# Date 1421194526 -3600
#      Wed Jan 14 01:15:26 2015 +0100
# Node ID ce250992a9b953235c787ed6225d21ebe037cb0a
# Parent  dbf53b1ab67f06fcf13736c1bd91f8472a851be5
util: add debugstacktrace depth limit

Useful when you don't care about the start of the stack, but only want to see
the last entries.

diff --git a/mercurial/util.py b/mercurial/util.py
--- a/mercurial/util.py
+++ b/mercurial/util.py
@@ -2841,9 +2841,9 @@ class hooks(object):
             results.append(hook(*args))
         return results
 
-def getstackframes(skip=0, line=' %-*s in %s\n', fileline='%s:%s'):
+def getstackframes(skip=0, line=' %-*s in %s\n', fileline='%s:%s', depth=0):
     '''Yields lines for a nicely formatted stacktrace.
-    Skips the 'skip' last entries.
+    Skips the 'skip' last entries, then return the last 'depth' entries.
     Each file+linenumber is formatted according to fileline.
     Each line is formatted according to line.
     If line is None, it yields:
@@ -2854,7 +2854,8 @@ def getstackframes(skip=0, line=' %-*s i
     Not be used in production code but very convenient while developing.
     '''
     entries = [(fileline % (fn, ln), func)
-        for fn, ln, func, _text in traceback.extract_stack()[:-skip - 1]]
+        for fn, ln, func, _text in traceback.extract_stack()[:-skip - 1]
+        ][-depth:]
     if entries:
         fnmax = max(len(entry[0]) for entry in entries)
         for fnln, func in entries:
@@ -2863,16 +2864,18 @@ def getstackframes(skip=0, line=' %-*s i
             else:
                 yield line % (fnmax, fnln, func)
 
-def debugstacktrace(msg='stacktrace', skip=0, f=stderr, otherf=stdout):
+def debugstacktrace(msg='stacktrace', skip=0,
+                    f=stderr, otherf=stdout, depth=0):
     '''Writes a message to f (stderr) with a nicely formatted stacktrace.
-    Skips the 'skip' last entries. By default it will flush stdout first.
+    Skips the 'skip' entries closest to the call, then show 'depth' entries.
+    By default it will flush stdout first.
     It can be used everywhere and intentionally does not require an ui object.
     Not be used in production code but very convenient while developing.
     '''
     if otherf:
         otherf.flush()
     f.write('%s at:\n' % msg.rstrip())
-    for line in getstackframes(skip + 1):
+    for line in getstackframes(skip + 1, depth=depth):
         f.write(line)
     f.flush()
 
diff --git a/tests/test-debugcommands.t b/tests/test-debugcommands.t
--- a/tests/test-debugcommands.t
+++ b/tests/test-debugcommands.t
@@ -122,7 +122,7 @@ Test internal debugstacktrace command
   >     dst('hello from g\\n', skip=1)
   >     h()
   > def h():
-  >     dst('hi ...\\nfrom h hidden in g', 1)
+  >     dst('hi ...\\nfrom h hidden in g', 1, depth=2)
   > f()
   > EOF
   $ python debugstacktrace.py
@@ -134,6 +134,5 @@ Test internal debugstacktrace command
    debugstacktrace.py:4  in f
   hi ...
   from h hidden in g at:
-   debugstacktrace.py:10 in * (glob)
-   debugstacktrace.py:4  in f
-   debugstacktrace.py:7  in g
+   debugstacktrace.py:4 in f
+   debugstacktrace.py:7 in g


More information about the Mercurial-devel mailing list