diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 16:40:16 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 16:40:16 +0000 |
commit | 3f25952c13d5847d510c0cae22a8ba876638d570 (patch) | |
tree | 02f505f016ed5a1029277dcae520d5e2a75906fb /powerline/lib/debug.py | |
parent | Initial commit. (diff) | |
download | powerline-3f25952c13d5847d510c0cae22a8ba876638d570.tar.xz powerline-3f25952c13d5847d510c0cae22a8ba876638d570.zip |
Adding upstream version 2.8.3.upstream/2.8.3upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'powerline/lib/debug.py')
-rwxr-xr-x | powerline/lib/debug.py | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/powerline/lib/debug.py b/powerline/lib/debug.py new file mode 100755 index 0000000..515e8c4 --- /dev/null +++ b/powerline/lib/debug.py @@ -0,0 +1,97 @@ +# vim:fileencoding=utf-8:noet +from __future__ import (unicode_literals, division, absolute_import, print_function) + +import gc +import sys + +from types import FrameType +from itertools import chain + + +# From http://code.activestate.com/recipes/523004-find-cyclical-references/ +def print_cycles(objects, outstream=sys.stdout, show_progress=False): + '''Find reference cycles + + :param list objects: + A list of objects to find cycles in. It is often useful to pass in + gc.garbage to find the cycles that are preventing some objects from + being garbage collected. + :param file outstream: + The stream for output. + :param bool show_progress: + If True, print the number of objects reached as they are found. + ''' + def print_path(path): + for i, step in enumerate(path): + # next “wraps around” + next = path[(i + 1) % len(path)] + + outstream.write(' %s -- ' % str(type(step))) + written = False + if isinstance(step, dict): + for key, val in step.items(): + if val is next: + outstream.write('[%s]' % repr(key)) + written = True + break + if key is next: + outstream.write('[key] = %s' % repr(val)) + written = True + break + elif isinstance(step, (list, tuple)): + for i, item in enumerate(step): + if item is next: + outstream.write('[%d]' % i) + written = True + elif getattr(type(step), '__getattribute__', None) in (object.__getattribute__, type.__getattribute__): + for attr in chain(dir(step), getattr(step, '__dict__', ())): + if getattr(step, attr, None) is next: + try: + outstream.write('%r.%s' % (step, attr)) + except TypeError: + outstream.write('.%s' % (step, attr)) + written = True + break + if not written: + outstream.write(repr(step)) + outstream.write(' ->\n') + outstream.write('\n') + + def recurse(obj, start, all, current_path): + if show_progress: + outstream.write('%d\r' % len(all)) + + all[id(obj)] = None + + referents = gc.get_referents(obj) + for referent in referents: + # If we’ve found our way back to the start, this is + # a cycle, so print it out + if referent is start: + try: + outstream.write('Cyclic reference: %r\n' % referent) + except TypeError: + try: + outstream.write('Cyclic reference: %i (%r)\n' % (id(referent), type(referent))) + except TypeError: + outstream.write('Cyclic reference: %i\n' % id(referent)) + print_path(current_path) + + # Don’t go back through the original list of objects, or + # through temporary references to the object, since those + # are just an artifact of the cycle detector itself. + elif referent is objects or isinstance(referent, FrameType): + continue + + # We haven’t seen this object before, so recurse + elif id(referent) not in all: + recurse(referent, start, all, current_path + (obj,)) + + for obj in objects: + # We are not interested in non-powerline cyclic references + try: + if not type(obj).__module__.startswith('powerline'): + continue + except AttributeError: + continue + recurse(obj, obj, {}, ()) |