Submitter | Mads Kiilerich |
---|---|
Date | Jan. 12, 2014, 10:28 p.m. |
Message ID | <72b1891f41b81efa6ec1.1389565723@localhost.localdomain> |
Download | mbox | patch |
Permalink | /patch/3315/ |
State | Accepted |
Commit | 47d0843647d1e32f6af4482867327cec5db11a1f |
Headers | show |
Comments
On Sun, Jan 12, 2014 at 11:28:43PM +0100, Mads Kiilerich wrote: > # HG changeset patch > # User Mads Kiilerich <madski@unity3d.com> > # Date 1389565701 -3600 > # Sun Jan 12 23:28:21 2014 +0100 > # Node ID 72b1891f41b81efa6ec13f04371c2c0740f01300 > # Parent d2704c48f4176d8cd6f21d33500820d44763585c > util: introduce util.debugstacktrace for showing a stack trace without crashing sure, queued > > This is often very handy when hacking/debugging. > > Calling util.debugstacktrace('hey') from a place in hg will give something like: > hey at: > ./hg:38 in <module> > /home/user/hgsrc/mercurial/dispatch.py:28 in run > /home/user/hgsrc/mercurial/dispatch.py:65 in dispatch > /home/user/hgsrc/mercurial/dispatch.py:88 in _runcatch > /home/user/hgsrc/mercurial/dispatch.py:740 in _dispatch > /home/user/hgsrc/mercurial/dispatch.py:514 in runcommand > /home/user/hgsrc/mercurial/dispatch.py:830 in _runcommand > /home/user/hgsrc/mercurial/dispatch.py:801 in checkargs > /home/user/hgsrc/mercurial/dispatch.py:737 in <lambda> > /home/user/hgsrc/mercurial/util.py:472 in check > ... > > diff --git a/contrib/lock-checker.py b/contrib/lock-checker.py > --- a/contrib/lock-checker.py > +++ b/contrib/lock-checker.py > @@ -7,21 +7,12 @@ traceback printed to stderr. > This currently only checks store locks, not working copy locks. > """ > import os > -import traceback > - > -def _warnstack(ui, msg, skip=1): > - '''issue warning with the message and the current stack, skipping the > - skip last entries''' > - ui.warn('%s at:\n' % msg) > - entries = traceback.extract_stack()[:-skip] > - fnmax = max(len(entry[0]) for entry in entries) > - for fn, ln, func, _text in entries: > - ui.warn(' %*s:%-4s in %s\n' % (fnmax, fn, ln, func)) > +from mercurial import util > > def _checklock(repo): > l = repo._lockref and repo._lockref() > if l is None or not l.held: > - _warnstack(repo.ui, 'missing lock', skip=2) > + util.debugstacktrace('missing lock', skip=1) > > def reposetup(ui, repo): > orig = repo.__class__ > diff --git a/mercurial/util.py b/mercurial/util.py > --- a/mercurial/util.py > +++ b/mercurial/util.py > @@ -1983,3 +1983,20 @@ class hooks(object): > self._hooks.sort(key=lambda x: x[0]) > for source, hook in self._hooks: > hook(*args) > + > +def debugstacktrace(msg='stacktrace', skip=0, f=sys.stderr): > + '''Writes a message to f (stderr) with a nicely formatted stacktrace. > + Skips the 'skip' last entries. > + It can be used everywhere and do intentionally not require an ui object. > + Not be used in production code but very convenient while developing. > + ''' > + f.write('%s at:\n' % msg) > + entries = [('%s:%s' % (fn, ln), func) > + for fn, ln, func, _text in traceback.extract_stack()[:-skip - 1]] > + if entries: > + fnmax = max(len(entry[0]) for entry in entries) > + for fnln, func in entries: > + f.write(' %-*s in %s\n' % (fnmax, fnln, func)) > + > +# convenient shortcut > +dst = debugstacktrace > diff --git a/tests/test-debugcommands.t b/tests/test-debugcommands.t > --- a/tests/test-debugcommands.t > +++ b/tests/test-debugcommands.t > @@ -23,3 +23,25 @@ > uncompressed data size (min/max/avg) : 43 / 43 / 43 > full revision size (min/max/avg) : 44 / 44 / 44 > delta size (min/max/avg) : 0 / 0 / 0 > + > + > +Test internal debugstacktrace command > + > + $ cat > debugstacktrace.py << EOF > + > from mercurial.util import debugstacktrace, dst, sys > + > def f(): > + > dst('hello world') > + > def g(): > + > f() > + > debugstacktrace(skip=-5, f=sys.stdout) > + > g() > + > EOF > + $ python debugstacktrace.py > + hello world at: > + debugstacktrace.py:7 in <module> > + debugstacktrace.py:5 in g > + debugstacktrace.py:3 in f > + stacktrace at: > + debugstacktrace.py:7 *in <module> (glob) > + debugstacktrace.py:6 *in g (glob) > + */util.py:* in debugstacktrace (glob) > _______________________________________________ > Mercurial-devel mailing list > Mercurial-devel@selenic.com > http://selenic.com/mailman/listinfo/mercurial-devel
Patch
diff --git a/contrib/lock-checker.py b/contrib/lock-checker.py --- a/contrib/lock-checker.py +++ b/contrib/lock-checker.py @@ -7,21 +7,12 @@ traceback printed to stderr. This currently only checks store locks, not working copy locks. """ import os -import traceback - -def _warnstack(ui, msg, skip=1): - '''issue warning with the message and the current stack, skipping the - skip last entries''' - ui.warn('%s at:\n' % msg) - entries = traceback.extract_stack()[:-skip] - fnmax = max(len(entry[0]) for entry in entries) - for fn, ln, func, _text in entries: - ui.warn(' %*s:%-4s in %s\n' % (fnmax, fn, ln, func)) +from mercurial import util def _checklock(repo): l = repo._lockref and repo._lockref() if l is None or not l.held: - _warnstack(repo.ui, 'missing lock', skip=2) + util.debugstacktrace('missing lock', skip=1) def reposetup(ui, repo): orig = repo.__class__ diff --git a/mercurial/util.py b/mercurial/util.py --- a/mercurial/util.py +++ b/mercurial/util.py @@ -1983,3 +1983,20 @@ class hooks(object): self._hooks.sort(key=lambda x: x[0]) for source, hook in self._hooks: hook(*args) + +def debugstacktrace(msg='stacktrace', skip=0, f=sys.stderr): + '''Writes a message to f (stderr) with a nicely formatted stacktrace. + Skips the 'skip' last entries. + It can be used everywhere and do intentionally not require an ui object. + Not be used in production code but very convenient while developing. + ''' + f.write('%s at:\n' % msg) + entries = [('%s:%s' % (fn, ln), func) + for fn, ln, func, _text in traceback.extract_stack()[:-skip - 1]] + if entries: + fnmax = max(len(entry[0]) for entry in entries) + for fnln, func in entries: + f.write(' %-*s in %s\n' % (fnmax, fnln, func)) + +# convenient shortcut +dst = debugstacktrace diff --git a/tests/test-debugcommands.t b/tests/test-debugcommands.t --- a/tests/test-debugcommands.t +++ b/tests/test-debugcommands.t @@ -23,3 +23,25 @@ uncompressed data size (min/max/avg) : 43 / 43 / 43 full revision size (min/max/avg) : 44 / 44 / 44 delta size (min/max/avg) : 0 / 0 / 0 + + +Test internal debugstacktrace command + + $ cat > debugstacktrace.py << EOF + > from mercurial.util import debugstacktrace, dst, sys + > def f(): + > dst('hello world') + > def g(): + > f() + > debugstacktrace(skip=-5, f=sys.stdout) + > g() + > EOF + $ python debugstacktrace.py + hello world at: + debugstacktrace.py:7 in <module> + debugstacktrace.py:5 in g + debugstacktrace.py:3 in f + stacktrace at: + debugstacktrace.py:7 *in <module> (glob) + debugstacktrace.py:6 *in g (glob) + */util.py:* in debugstacktrace (glob)