[Checkins] SVN: z3c.memhunt.objgraph/trunk/z3c/memhunt/objgraph/ Removed garbage from package

Daniel Blackburn blackburnd at gmail.com
Wed Nov 10 05:29:44 EST 2010


Log message for revision 118311:
  Removed garbage from package

Changed:
  D   z3c.memhunt.objgraph/trunk/z3c/memhunt/objgraph/checks.py
  D   z3c.memhunt.objgraph/trunk/z3c/memhunt/objgraph/cond_perms.py
  D   z3c.memhunt.objgraph/trunk/z3c/memhunt/objgraph/objgraph-1.py
  D   z3c.memhunt.objgraph/trunk/z3c/memhunt/objgraph/objgraph.py
  D   z3c.memhunt.objgraph/trunk/z3c/memhunt/objgraph/objgraph_orig.py
  D   z3c.memhunt.objgraph/trunk/z3c/memhunt/objgraph/objgraph_trunk.diff

-=-
Deleted: z3c.memhunt.objgraph/trunk/z3c/memhunt/objgraph/checks.py
===================================================================
--- z3c.memhunt.objgraph/trunk/z3c/memhunt/objgraph/checks.py	2010-11-10 10:26:41 UTC (rev 118310)
+++ z3c.memhunt.objgraph/trunk/z3c/memhunt/objgraph/checks.py	2010-11-10 10:29:43 UTC (rev 118311)
@@ -1,503 +0,0 @@
-"""
-Ad-hoc tools for drawing Python object reference graphs with graphviz.
-
-This module is more useful as a repository of sample code and ideas, than
-as a finished product.  For documentation and background, read
-
-  http://mg.pov.lt/blog/hunting-python-memleaks.html
-  http://mg.pov.lt/blog/python-object-graphs.html
-  http://mg.pov.lt/blog/object-graphs-with-graphviz.html
-
-in that order.  Then use pydoc to read the docstrings, as there were
-improvements made since those blog posts.
-
-Copyright (c) 2008-2010 Marius Gedminas <marius at pov.lt>
-
-Released under the MIT licence.
-
-
-Changes
-=======
-
-1.3.2 (unreleased)
-------------------
-
-Compatibility with Python 2.4 and 2.5 (tempfile.NamedTemporaryFile has no
-delete argument).
-
-New function: most_common_types().
-
-
-1.3.1 (2010-07-17)
-------------------
-
-Rebuild an sdist with no missing files (fixes LP#606604).
-
-Added MANIFEST.in and a Makefile to check that setup.py sdist generates
-source distributions with no files missing.
-
-
-1.3 (2010-07-13)
-----------------
-
-Highlight objects with a __del__ method.
-
-Fixes LP#483411: suggest always passing [obj] to show_refs, show_backrefs,
-since obj might be a list/tuple.
-
-Fixes LP#514422: show_refs, show_backrefs don't create files in the current
-working directory any more.  Instead they accept a filename argument, which
-can be a .dot file or a .png file.  If None or not specified, those functions
-will try to spawn xdot as before.
-
-New extra_info argument to graph-generating functions (patch by Thouis Jones,
-LP#558914).
-
-setup.py should work with distutils now (LP#604430, thanks to Randy Heydon).
-
-
-1.2 (2009-03-25)
-----------------
-
-Project website, public source repository, uploaded to PyPI.
-
-No code changes.
-
-
-1.1dev (2008-09-05)
--------------------
-
-New function: show_refs() for showing forward references.
-
-New functions: typestats() and show_most_common_types().
-
-Object boxes are less crammed with useless information (such as IDs).
-
-Spawns xdot if it is available.
-"""
-# Permission is hereby granted, free of charge, to any person obtaining a
-# copy of this software and associated documentation files (the "Software"),
-# to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense,
-# and/or sell copies of the Software, and to permit persons to whom the
-# Software is furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-__author__ = "Marius Gedminas (marius at gedmin.as)"
-__copyright__ = "Copyright (c) 2008-2010 Marius Gedminas"
-__license__ = "MIT"
-__version__ = "1.3.2dev"
-__date__ = "2010-11-02"
-
-
-import gc
-import inspect
-import types
-import weakref
-import operator
-import os
-import subprocess
-import tempfile
-
-
-def count(typename):
-    """Count objects tracked by the garbage collector with a given class name.
-
-    Example:
-
-        >>> count('dict')
-        42
-        >>> count('MyClass')
-        3
-
-    Note that the GC does not track simple objects like int or str.
-    """
-    return sum(1 for o in gc.get_objects() if type(o).__name__ == typename)
-
-
-def typestats():
-    """Count the number of instances for each type tracked by the GC.
-
-    Note that the GC does not track simple objects like int or str.
-
-    Note that classes with the same name but defined in different modules
-    will be lumped together.
-    """
-    stats = {}
-    for o in gc.get_objects():
-        stats.setdefault(type(o).__name__, 0)
-        stats[type(o).__name__] += 1
-    return stats
-
-
-def most_common_types(limit=10):
-    """Count the names of types with the most instances.
-
-    Note that the GC does not track simple objects like int or str.
-
-    Note that classes with the same name but defined in different modules
-    will be lumped together.
-
-    Returns a list of (type_name, count), sorted most-frequent-first.
-    """
-    stats = sorted(typestats().items(), key=operator.itemgetter(1),
-                   reverse=True)
-    if limit:
-        stats = stats[:limit]
-    return stats
-
-
-def show_most_common_types(limit=10):
-    """Print the table of types of most common instances
-
-    Note that the GC does not track simple objects like int or str.
-
-    Note that classes with the same name but defined in different modules
-    will be lumped together.
-    """
-    stats = most_common_types(limit)
-    width = max(len(name) for name, count in stats)
-    for name, count in stats:
-        print name.ljust(width), count
-
-
-def by_type(typename):
-    """Return objects tracked by the garbage collector with a given class name.
-
-    Example:
-
-        >>> by_type('MyClass')
-        [<mymodule.MyClass object at 0x...>]
-
-    Note that the GC does not track simple objects like int or str.
-    """
-    return [o for o in gc.get_objects() if type(o).__name__ == typename]
-
-
-def at(addr):
-    """Return an object at a given memory address.
-
-    The reverse of id(obj):
-
-        >>> at(id(obj)) is obj
-        True
-
-    Note that this function does not work on objects that are not tracked by
-    the GC (e.g. ints or strings).
-    """
-    for o in gc.get_objects():
-        if id(o) == addr:
-            return o
-    return None
-
-
-def find_backref_chain(obj, predicate, max_depth=20, extra_ignore=()):
-    """Find a shortest chain of references leading to obj.
-
-    The start of the chain will be some object that matches your predicate.
-
-    ``max_depth`` limits the search depth.
-
-    ``extra_ignore`` can be a list of object IDs to exclude those objects from
-    your search.
-
-    Example:
-
-        >>> find_backref_chain(obj, inspect.ismodule)
-        [<module ...>, ..., obj]
-
-    Returns None if such a chain could not be found.
-    """
-    queue = [obj]
-    depth = {id(obj): 0}
-    parent = {id(obj): None}
-    ignore = set(extra_ignore)
-    ignore.add(id(extra_ignore))
-    ignore.add(id(queue))
-    ignore.add(id(depth))
-    ignore.add(id(parent))
-    ignore.add(id(ignore))
-    gc.collect()
-    while queue:
-        target = queue.pop(0)
-        if predicate(target):
-            chain = [target]
-            while parent[id(target)] is not None:
-                target = parent[id(target)]
-                chain.append(target)
-            return chain
-        tdepth = depth[id(target)]
-        if tdepth < max_depth:
-            referrers = gc.get_referrers(target)
-            ignore.add(id(referrers))
-            for source in referrers:
-                if inspect.isframe(source) or id(source) in ignore:
-                    continue
-                if id(source) not in depth:
-                    depth[id(source)] = tdepth + 1
-                    parent[id(source)] = target
-                    queue.append(source)
-    return None # not found
-
-
-def show_backrefs(objs, max_depth=3, extra_ignore=(), filter=None, too_many=10,
-                  highlight=None, filename=None, extra_info=(lambda _: '')):
-    """Generate an object reference graph ending at ``objs``
-
-    The graph will show you what objects refer to ``objs``, directly and
-    indirectly.
-
-    ``objs`` can be a single object, or it can be a list of objects.  If
-    unsure, wrap the single object in a new list.
-
-    Produces a Graphviz .dot file and spawns a viewer (xdot) if one is
-    installed, otherwise converts the graph to a .png image.
-
-    Use ``max_depth`` and ``too_many`` to limit the depth and breadth of the
-    graph.
-
-    Use ``filter`` (a predicate) and ``extra_ignore`` (a list of object IDs) to
-    remove undesired objects from the graph.
-
-    Use ``highlight`` (a predicate) to highlight certain graph nodes in blue.
-
-    Use ``extra_info`` (a function returning a string) to report extra
-    information for objects.
-
-    Examples:
-
-        >>> show_backrefs(obj)
-        >>> show_backrefs([obj1, obj2])
-        >>> show_backrefs(obj, max_depth=5)
-        >>> show_backrefs(obj, filter=lambda x: not inspect.isclass(x))
-        >>> show_backrefs(obj, highlight=inspect.isclass)
-        >>> show_backrefs(obj, extra_ignore=[id(locals())])
-
-    """
-    show_graph(objs, max_depth=max_depth, extra_ignore=extra_ignore,
-               filter=filter, too_many=too_many, highlight=highlight,
-               edge_func=gc.get_referrers, swap_source_target=False,
-               filename=filename, extra_info=extra_info)
-
-
-def show_refs(objs, max_depth=3, extra_ignore=(), filter=None, too_many=10,
-              highlight=None, filename=None, extra_info=(lambda _: '')):
-    """Generate an object reference graph starting at ``objs``
-
-    The graph will show you what objects are reachable from ``objs``, directly
-    and indirectly.
-
-    ``objs`` can be a single object, or it can be a list of objects.  If
-    unsure, wrap the single object in a new list.
-
-    Produces a Graphviz .dot file and spawns a viewer (xdot) if one is
-    installed, otherwise converts the graph to a .png image.
-
-    Use ``max_depth`` and ``too_many`` to limit the depth and breadth of the
-    graph.
-
-    Use ``filter`` (a predicate) and ``extra_ignore`` (a list of object IDs) to
-    remove undesired objects from the graph.
-
-    Use ``highlight`` (a predicate) to highlight certain graph nodes in blue.
-
-    Use ``extra_info`` (a function returning a string) to report extra
-    information for objects.
-
-    Examples:
-
-        >>> show_refs(obj)
-        >>> show_refs([obj1, obj2])
-        >>> show_refs(obj, max_depth=5)
-        >>> show_refs(obj, filter=lambda x: not inspect.isclass(x))
-        >>> show_refs(obj, highlight=inspect.isclass)
-        >>> show_refs(obj, extra_ignore=[id(locals())])
-
-    """
-    show_graph(objs, max_depth=max_depth, extra_ignore=extra_ignore,
-               filter=filter, too_many=too_many, highlight=highlight,
-               edge_func=gc.get_referents, swap_source_target=True,
-               filename=filename, extra_info=extra_info)
-
-#
-# Internal helpers
-#
-
-def show_graph(objs, edge_func, swap_source_target,
-               max_depth=3, extra_ignore=(), filter=None, too_many=10,
-               highlight=None, filename=None, extra_info=(lambda _: '')):
-    if not isinstance(objs, (list, tuple)):
-        objs = [objs]
-    if filename and filename.endswith('.dot'):
-        f = file(filename, 'w')
-        dot_filename = filename
-    else:
-        fd, dot_filename = tempfile.mkstemp('.dot', text=True)
-        f = os.fdopen(fd, "w")
-    print >> f, 'digraph ObjectGraph {'
-    print >> f, '  node[shape=box, style=filled, fillcolor=white];'
-    queue = []
-    depth = {}
-    ignore = set(extra_ignore)
-    ignore.add(id(objs))
-    ignore.add(id(extra_ignore))
-    ignore.add(id(queue))
-    ignore.add(id(depth))
-    ignore.add(id(ignore))
-    for obj in objs:
-        print >> f, '  %s[fontcolor=red];' % (obj_node_id(obj))
-        depth[id(obj)] = 0
-        queue.append(obj)
-    gc.collect()
-    nodes = 0
-    while queue:
-        nodes += 1
-        target = queue.pop(0)
-        tdepth = depth[id(target)]
-        print >> f, '  %s[label="%s"];' % (obj_node_id(target), obj_label(target, tdepth, extra_info))
-        h, s, v = gradient((0, 0, 1), (0, 0, .3), tdepth, max_depth)
-        if inspect.ismodule(target):
-            h = .3
-            s = 1
-        if highlight and highlight(target):
-            h = .6
-            s = .6
-            v = 0.5 + v * 0.5
-        print >> f, '  %s[fillcolor="%g,%g,%g"];' % (obj_node_id(target), h, s, v)
-        if v < 0.5:
-            print >> f, '  %s[fontcolor=white];' % (obj_node_id(target))
-        if hasattr(target, '__del__'):
-            print >> f, "  %s->%s_has_a_del[color=red,style=dotted,len=0.25,weight=10];" % (obj_node_id(target), obj_node_id(target))
-            print >> f, '  %s_has_a_del[label="__del__",shape=doublecircle,height=0.25,color=red,fillcolor="0,.5,1",fontsize=6];' % (obj_node_id(target))
-        if inspect.ismodule(target) or tdepth >= max_depth:
-            continue
-        neighbours = edge_func(target)
-        ignore.add(id(neighbours))
-        n = 0
-        for source in neighbours:
-            if inspect.isframe(source) or id(source) in ignore:
-                continue
-            if filter and not filter(source):
-                continue
-            if swap_source_target:
-                srcnode, tgtnode = target, source
-            else:
-                srcnode, tgtnode = source, target
-            elabel = edge_label(srcnode, tgtnode)
-            print >> f, '  %s -> %s%s;' % (obj_node_id(srcnode), obj_node_id(tgtnode), elabel)
-            if id(source) not in depth:
-                depth[id(source)] = tdepth + 1
-                queue.append(source)
-            n += 1
-            if n >= too_many:
-                print >> f, '  %s[color=red];' % obj_node_id(target)
-                break
-    print >> f, "}"
-    f.close()
-    print "Graph written to %s (%d nodes)" % (dot_filename, nodes)
-    if filename is None and program_in_path('xdot'):
-        print "Spawning graph viewer (xdot)"
-        subprocess.Popen(['xdot', dot_filename])
-    elif program_in_path('dot'):
-        if filename is None:
-            print "Graph viewer (xdot) not found, generating a png instead"
-        if filename and filename.endswith('.png'):
-            f = file(filename, 'wb')
-            png_filename = filename
-        else:
-            if filename is not None:
-                print "Unrecognized file type (%s)" % filename
-            fd, png_filename = tempfile.mkstemp('.png', text=False)
-            f = os.fdopen(fd, "wb")
-        dot = subprocess.Popen(['dot', '-Tpng', dot_filename],
-                               stdout=f)
-        dot.wait()
-        f.close()
-        print "Image generated as %s" % png_filename
-    else:
-        if filename is None:
-            print "Graph viewer (xdot) and image renderer (dot) not found, not doing anything else"
-        else:
-            print "Unrecognized file type (%s), not doing anything else" % filename
-
-
-def obj_node_id(obj):
-    if isinstance(obj, weakref.ref):
-        return 'all_weakrefs_are_one'
-    return ('o%d' % id(obj)).replace('-', '_')
-
-
-def obj_label(obj, depth, extra_info):
-    return quote(type(obj).__name__ + ':\n' +
-                 safe_repr(obj) + '\n' +
-                 extra_info(obj))
-
-
-def quote(s):
-    return s.replace("\\", "\\\\").replace("\"", "\\\"").replace("\n", "\\n")
-
-
-def safe_repr(obj):
-    try:
-        return short_repr(obj)
-    except:
-        return '(unrepresentable)'
-
-
-def short_repr(obj):
-    if isinstance(obj, (type, types.ModuleType, types.BuiltinMethodType,
-                        types.BuiltinFunctionType)):
-        return obj.__name__
-    if isinstance(obj, types.MethodType):
-        if obj.im_self is not None:
-            return obj.im_func.__name__ + ' (bound)'
-        else:
-            return obj.im_func.__name__
-    if isinstance(obj, (tuple, list, dict, set)):
-        return '%d items' % len(obj)
-    if isinstance(obj, weakref.ref):
-        return 'all_weakrefs_are_one'
-    return repr(obj)[:40]
-
-
-def gradient(start_color, end_color, depth, max_depth):
-    if max_depth == 0:
-        # avoid division by zero
-        return start_color
-    h1, s1, v1 = start_color
-    h2, s2, v2 = end_color
-    f = float(depth) / max_depth
-    h = h1 * (1-f) + h2 * f
-    s = s1 * (1-f) + s2 * f
-    v = v1 * (1-f) + v2 * f
-    return h, s, v
-
-
-def edge_label(source, target):
-    if isinstance(target, dict) and target is getattr(source, '__dict__', None):
-        return ' [label="__dict__",weight=10]'
-    elif isinstance(source, dict):
-        for k, v in source.iteritems():
-            if v is target:
-                if isinstance(k, basestring) and k:
-                    return ' [label="%s",weight=2]' % quote(k)
-                else:
-                    return ' [label="%s"]' % quote(safe_repr(k))
-    return ''
-
-
-def program_in_path(program):
-    path = os.environ.get("PATH", os.defpath).split(os.pathsep)
-    path = [os.path.join(dir, program) for dir in path]
-    path = [True for file in path if os.path.isfile(file)]
-    return bool(path)

Deleted: z3c.memhunt.objgraph/trunk/z3c/memhunt/objgraph/cond_perms.py
===================================================================
--- z3c.memhunt.objgraph/trunk/z3c/memhunt/objgraph/cond_perms.py	2010-11-10 10:26:41 UTC (rev 118310)
+++ z3c.memhunt.objgraph/trunk/z3c/memhunt/objgraph/cond_perms.py	2010-11-10 10:29:43 UTC (rev 118311)
@@ -1,4 +0,0 @@
-
-
-def version():
-    import pdb; pdb.set_trace()

Deleted: z3c.memhunt.objgraph/trunk/z3c/memhunt/objgraph/objgraph-1.py
===================================================================
--- z3c.memhunt.objgraph/trunk/z3c/memhunt/objgraph/objgraph-1.py	2010-11-10 10:26:41 UTC (rev 118310)
+++ z3c.memhunt.objgraph/trunk/z3c/memhunt/objgraph/objgraph-1.py	2010-11-10 10:29:43 UTC (rev 118311)
@@ -1,503 +0,0 @@
-"""
-Ad-hoc tools for drawing Python object reference graphs with graphviz.
-
-This module is more useful as a repository of sample code and ideas, than
-as a finished product.  For documentation and background, read
-
-  http://mg.pov.lt/blog/hunting-python-memleaks.html
-  http://mg.pov.lt/blog/python-object-graphs.html
-  http://mg.pov.lt/blog/object-graphs-with-graphviz.html
-
-in that order.  Then use pydoc to read the docstrings, as there were
-improvements made since those blog posts.
-
-Copyright (c) 2008-2010 Marius Gedminas <marius at pov.lt>
-
-Released under the MIT licence.
-
-
-Changes
-=======
-
-1.3.2 (unreleased)
-------------------
-
-Compatibility with Python 2.4 and 2.5 (tempfile.NamedTemporaryFile has no
-delete argument).
-
-New function: most_common_types().
-
-
-1.3.1 (2010-07-17)
-------------------
-
-Rebuild an sdist with no missing files (fixes LP#606604).
-
-Added MANIFEST.in and a Makefile to check that setup.py sdist generates
-source distributions with no files missing.
-
-
-1.3 (2010-07-13)
-----------------
-
-Highlight objects with a __del__ method.
-
-Fixes LP#483411: suggest always passing [obj] to show_refs, show_backrefs,
-since obj might be a list/tuple.
-
-Fixes LP#514422: show_refs, show_backrefs don't create files in the current
-working directory any more.  Instead they accept a filename argument, which
-can be a .dot file or a .png file.  If None or not specified, those functions
-will try to spawn xdot as before.
-
-New extra_info argument to graph-generating functions (patch by Thouis Jones,
-LP#558914).
-
-setup.py should work with distutils now (LP#604430, thanks to Randy Heydon).
-
-
-1.2 (2009-03-25)
-----------------
-
-Project website, public source repository, uploaded to PyPI.
-
-No code changes.
-
-
-1.1dev (2008-09-05)
--------------------
-
-New function: show_refs() for showing forward references.
-
-New functions: typestats() and show_most_common_types().
-
-Object boxes are less crammed with useless information (such as IDs).
-
-Spawns xdot if it is available.
-"""
-# Permission is hereby granted, free of charge, to any person obtaining a
-# copy of this software and associated documentation files (the "Software"),
-# to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense,
-# and/or sell copies of the Software, and to permit persons to whom the
-# Software is furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-__author__ = "Marius Gedminas (marius at gedmin.as)"
-__copyright__ = "Copyright (c) 2008-2010 Marius Gedminas"
-__license__ = "MIT"
-__version__ = "1.3.2dev"
-__date__ = "2010-11-02"
-
-
-import gc
-import inspect
-import types
-import weakref
-import operator
-import os
-import subprocess
-import tempfile
-
-
-def count(typename):
-    """Count objects tracked by the garbage collector with a given class name.
-
-    Example:
-
-        >>> count('dict')
-        42
-        >>> count('MyClass')
-        3
-
-    Note that the GC does not track simple objects like int or str.
-    """
-    return sum(1 for o in gc.get_objects() if type(o).__name__ == typename)
-
-
-def typestats():
-    """Count the number of instances for each type tracked by the GC.
-
-    Note that the GC does not track simple objects like int or str.
-
-    Note that classes with the same name but defined in different modules
-    will be lumped together.
-    """
-    stats = {}
-    for o in gc.get_objects():
-        stats.setdefault(type(o).__name__, 0)
-        stats[type(o).__name__] += 1
-    return stats
-
-
-def most_common_types(limit=10):
-    """Count the names of types with the most instances.
-
-    Note that the GC does not track simple objects like int or str.
-
-    Note that classes with the same name but defined in different modules
-    will be lumped together.
-
-    Returns a list of (type_name, count), sorted most-frequent-first.
-    """
-    stats = sorted(typestats().items(), key=operator.itemgetter(1),
-                   reverse=True)
-    if limit:
-        stats = stats[:limit]
-    return stats
-
-
-def show_most_common_types(limit=10):
-    """Print the table of types of most common instances
-
-    Note that the GC does not track simple objects like int or str.
-
-    Note that classes with the same name but defined in different modules
-    will be lumped together.
-    """
-    stats = most_common_types(limit)
-    width = max(len(name) for name, count in stats)
-    for name, count in stats:
-        print name.ljust(width), count
-
-
-def by_type(typename):
-    """Return objects tracked by the garbage collector with a given class name.
-
-    Example:
-
-        >>> by_type('MyClass')
-        [<mymodule.MyClass object at 0x...>]
-
-    Note that the GC does not track simple objects like int or str.
-    """
-    return [o for o in gc.get_objects() if type(o).__name__ == typename]
-
-
-def at(addr):
-    """Return an object at a given memory address.
-
-    The reverse of id(obj):
-
-        >>> at(id(obj)) is obj
-        True
-
-    Note that this function does not work on objects that are not tracked by
-    the GC (e.g. ints or strings).
-    """
-    for o in gc.get_objects():
-        if id(o) == addr:
-            return o
-    return None
-
-
-def find_backref_chain(obj, predicate, max_depth=20, extra_ignore=()):
-    """Find a shortest chain of references leading to obj.
-
-    The start of the chain will be some object that matches your predicate.
-
-    ``max_depth`` limits the search depth.
-
-    ``extra_ignore`` can be a list of object IDs to exclude those objects from
-    your search.
-
-    Example:
-
-        >>> find_backref_chain(obj, inspect.ismodule)
-        [<module ...>, ..., obj]
-
-    Returns None if such a chain could not be found.
-    """
-    queue = [obj]
-    depth = {id(obj): 0}
-    parent = {id(obj): None}
-    ignore = set(extra_ignore)
-    ignore.add(id(extra_ignore))
-    ignore.add(id(queue))
-    ignore.add(id(depth))
-    ignore.add(id(parent))
-    ignore.add(id(ignore))
-    gc.collect()
-    while queue:
-        target = queue.pop(0)
-        if predicate(target):
-            chain = [target]
-            while parent[id(target)] is not None:
-                target = parent[id(target)]
-                chain.append(target)
-            return chain
-        tdepth = depth[id(target)]
-        if tdepth < max_depth:
-            referrers = gc.get_referrers(target)
-            ignore.add(id(referrers))
-            for source in referrers:
-                if inspect.isframe(source) or id(source) in ignore:
-                    continue
-                if id(source) not in depth:
-                    depth[id(source)] = tdepth + 1
-                    parent[id(source)] = target
-                    queue.append(source)
-    return None # not found
-
-
-def show_backrefs(objs, max_depth=3, extra_ignore=(), filter=None, too_many=10,
-                  highlight=None, filename=None, extra_info=(lambda _: '')):
-    """Generate an object reference graph ending at ``objs``
-
-    The graph will show you what objects refer to ``objs``, directly and
-    indirectly.
-
-    ``objs`` can be a single object, or it can be a list of objects.  If
-    unsure, wrap the single object in a new list.
-
-    Produces a Graphviz .dot file and spawns a viewer (xdot) if one is
-    installed, otherwise converts the graph to a .png image.
-
-    Use ``max_depth`` and ``too_many`` to limit the depth and breadth of the
-    graph.
-
-    Use ``filter`` (a predicate) and ``extra_ignore`` (a list of object IDs) to
-    remove undesired objects from the graph.
-
-    Use ``highlight`` (a predicate) to highlight certain graph nodes in blue.
-
-    Use ``extra_info`` (a function returning a string) to report extra
-    information for objects.
-
-    Examples:
-
-        >>> show_backrefs(obj)
-        >>> show_backrefs([obj1, obj2])
-        >>> show_backrefs(obj, max_depth=5)
-        >>> show_backrefs(obj, filter=lambda x: not inspect.isclass(x))
-        >>> show_backrefs(obj, highlight=inspect.isclass)
-        >>> show_backrefs(obj, extra_ignore=[id(locals())])
-
-    """
-    show_graph(objs, max_depth=max_depth, extra_ignore=extra_ignore,
-               filter=filter, too_many=too_many, highlight=highlight,
-               edge_func=gc.get_referrers, swap_source_target=False,
-               filename=filename, extra_info=extra_info)
-
-
-def show_refs(objs, max_depth=3, extra_ignore=(), filter=None, too_many=10,
-              highlight=None, filename=None, extra_info=(lambda _: '')):
-    """Generate an object reference graph starting at ``objs``
-
-    The graph will show you what objects are reachable from ``objs``, directly
-    and indirectly.
-
-    ``objs`` can be a single object, or it can be a list of objects.  If
-    unsure, wrap the single object in a new list.
-
-    Produces a Graphviz .dot file and spawns a viewer (xdot) if one is
-    installed, otherwise converts the graph to a .png image.
-
-    Use ``max_depth`` and ``too_many`` to limit the depth and breadth of the
-    graph.
-
-    Use ``filter`` (a predicate) and ``extra_ignore`` (a list of object IDs) to
-    remove undesired objects from the graph.
-
-    Use ``highlight`` (a predicate) to highlight certain graph nodes in blue.
-
-    Use ``extra_info`` (a function returning a string) to report extra
-    information for objects.
-
-    Examples:
-
-        >>> show_refs(obj)
-        >>> show_refs([obj1, obj2])
-        >>> show_refs(obj, max_depth=5)
-        >>> show_refs(obj, filter=lambda x: not inspect.isclass(x))
-        >>> show_refs(obj, highlight=inspect.isclass)
-        >>> show_refs(obj, extra_ignore=[id(locals())])
-
-    """
-    show_graph(objs, max_depth=max_depth, extra_ignore=extra_ignore,
-               filter=filter, too_many=too_many, highlight=highlight,
-               edge_func=gc.get_referents, swap_source_target=True,
-               filename=filename, extra_info=extra_info)
-
-#
-# Internal helpers
-#
-
-def show_graph(objs, edge_func, swap_source_target,
-               max_depth=3, extra_ignore=(), filter=None, too_many=10,
-               highlight=None, filename=None, extra_info=(lambda _: '')):
-    if not isinstance(objs, (list, tuple)):
-        objs = [objs]
-    if filename and filename.endswith('.dot'):
-        f = file(filename, 'w')
-        dot_filename = filename
-    else:
-        fd, dot_filename = tempfile.mkstemp('.dot', text=True)
-        f = os.fdopen(fd, "w")
-    print >> f, 'digraph ObjectGraph {'
-    print >> f, '  node[shape=box, style=filled, fillcolor=white];'
-    queue = []
-    depth = {}
-    ignore = set(extra_ignore)
-    ignore.add(id(objs))
-    ignore.add(id(extra_ignore))
-    ignore.add(id(queue))
-    ignore.add(id(depth))
-    ignore.add(id(ignore))
-    for obj in objs:
-        print >> f, '  %s[fontcolor=red];' % (obj_node_id(obj))
-        depth[id(obj)] = 0
-        queue.append(obj)
-    gc.collect()
-    nodes = 0
-    while queue:
-        nodes += 1
-        target = queue.pop(0)
-        tdepth = depth[id(target)]
-        print >> f, '  %s[label="%s"];' % (obj_node_id(target), obj_label(target, tdepth, extra_info))
-        h, s, v = gradient((0, 0, 1), (0, 0, .3), tdepth, max_depth)
-        if inspect.ismodule(target):
-            h = .3
-            s = 1
-        if highlight and highlight(target):
-            h = .6
-            s = .6
-            v = 0.5 + v * 0.5
-        print >> f, '  %s[fillcolor="%g,%g,%g"];' % (obj_node_id(target), h, s, v)
-        if v < 0.5:
-            print >> f, '  %s[fontcolor=white];' % (obj_node_id(target))
-        if hasattr(target, '__del__'):
-            print >> f, "  %s->%s_has_a_del[color=red,style=dotted,len=0.25,weight=10];" % (obj_node_id(target), obj_node_id(target))
-            print >> f, '  %s_has_a_del[label="__del__",shape=doublecircle,height=0.25,color=red,fillcolor="0,.5,1",fontsize=6];' % (obj_node_id(target))
-        if inspect.ismodule(target) or tdepth >= max_depth:
-            continue
-        neighbours = edge_func(target)
-        ignore.add(id(neighbours))
-        n = 0
-        for source in neighbours:
-            if inspect.isframe(source) or id(source) in ignore:
-                continue
-            if filter and not filter(source):
-                continue
-            if swap_source_target:
-                srcnode, tgtnode = target, source
-            else:
-                srcnode, tgtnode = source, target
-            elabel = edge_label(srcnode, tgtnode)
-            print >> f, '  %s -> %s%s;' % (obj_node_id(srcnode), obj_node_id(tgtnode), elabel)
-            if id(source) not in depth:
-                depth[id(source)] = tdepth + 1
-                queue.append(source)
-            n += 1
-            if n >= too_many:
-                print >> f, '  %s[color=red];' % obj_node_id(target)
-                break
-    print >> f, "}"
-    f.close()
-    print "Graph written to %s (%d nodes)" % (dot_filename, nodes)
-    if filename is None and program_in_path('xdot'):
-        print "Spawning graph viewer (xdot)"
-        subprocess.Popen(['xdot', dot_filename])
-    elif program_in_path('dot'):
-        if filename is None:
-            print "Graph viewer (xdot) not found, generating a png instead"
-        if filename and filename.endswith('.png'):
-            f = file(filename, 'wb')
-            png_filename = filename
-        else:
-            if filename is not None:
-                print "Unrecognized file type (%s)" % filename
-            fd, png_filename = tempfile.mkstemp('.png', text=False)
-            f = os.fdopen(fd, "wb")
-        dot = subprocess.Popen(['dot', '-Tpng', dot_filename],
-                               stdout=f)
-        dot.wait()
-        f.close()
-        print "Image generated as %s" % png_filename
-    else:
-        if filename is None:
-            print "Graph viewer (xdot) and image renderer (dot) not found, not doing anything else"
-        else:
-            print "Unrecognized file type (%s), not doing anything else" % filename
-
-
-def obj_node_id(obj):
-    if isinstance(obj, weakref.ref):
-        return 'all_weakrefs_are_one'
-    return ('o%d' % id(obj)).replace('-', '_')
-
-
-def obj_label(obj, depth, extra_info):
-    return quote(type(obj).__name__ + ':\n' +
-                 safe_repr(obj) + '\n' +
-                 extra_info(obj))
-
-
-def quote(s):
-    return s.replace("\\", "\\\\").replace("\"", "\\\"").replace("\n", "\\n")
-
-
-def safe_repr(obj):
-    try:
-        return short_repr(obj)
-    except:
-        return '(unrepresentable)'
-
-
-def short_repr(obj):
-    if isinstance(obj, (type, types.ModuleType, types.BuiltinMethodType,
-                        types.BuiltinFunctionType)):
-        return obj.__name__
-    if isinstance(obj, types.MethodType):
-        if obj.im_self is not None:
-            return obj.im_func.__name__ + ' (bound)'
-        else:
-            return obj.im_func.__name__
-    if isinstance(obj, (tuple, list, dict, set)):
-        return '%d items' % len(obj)
-    if isinstance(obj, weakref.ref):
-        return 'all_weakrefs_are_one'
-    return repr(obj)[:40]
-
-
-def gradient(start_color, end_color, depth, max_depth):
-    if max_depth == 0:
-        # avoid division by zero
-        return start_color
-    h1, s1, v1 = start_color
-    h2, s2, v2 = end_color
-    f = float(depth) / max_depth
-    h = h1 * (1-f) + h2 * f
-    s = s1 * (1-f) + s2 * f
-    v = v1 * (1-f) + v2 * f
-    return h, s, v
-
-
-def edge_label(source, target):
-    if isinstance(target, dict) and target is getattr(source, '__dict__', None):
-        return ' [label="__dict__",weight=10]'
-    elif isinstance(source, dict):
-        for k, v in source.iteritems():
-            if v is target:
-                if isinstance(k, basestring) and k:
-                    return ' [label="%s",weight=2]' % quote(k)
-                else:
-                    return ' [label="%s"]' % quote(safe_repr(k))
-    return ''
-
-
-def program_in_path(program):
-    path = os.environ.get("PATH", os.defpath).split(os.pathsep)
-    path = [os.path.join(dir, program) for dir in path]
-    path = [True for file in path if os.path.isfile(file)]
-    return bool(path)

Deleted: z3c.memhunt.objgraph/trunk/z3c/memhunt/objgraph/objgraph.py
===================================================================
--- z3c.memhunt.objgraph/trunk/z3c/memhunt/objgraph/objgraph.py	2010-11-10 10:26:41 UTC (rev 118310)
+++ z3c.memhunt.objgraph/trunk/z3c/memhunt/objgraph/objgraph.py	2010-11-10 10:29:43 UTC (rev 118311)
@@ -1,485 +0,0 @@
-"""
-Ad-hoc tools for drawing Python object reference graphs with graphviz.
-
-This module is more useful as a repository of sample code and ideas, than
-as a finished product.  For documentation and background, read
-
-  http://mg.pov.lt/blog/hunting-python-memleaks.html
-  http://mg.pov.lt/blog/python-object-graphs.html
-  http://mg.pov.lt/blog/object-graphs-with-graphviz.html
-
-in that order.  Then use pydoc to read the docstrings, as there were
-improvements made since those blog posts.
-
-Copyright (c) 2008-2010 Marius Gedminas <marius at pov.lt>
-
-Released under the MIT licence.
-
-
-Changes
-=======
-
-1.3.2 (unreleased)
-------------------
-
-(no changes yet)
-
-
-1.3.1 (2010-07-17)
-------------------
-
-Rebuild an sdist with no missing files (fixes LP#606604)
-
-Added MANIFEST.in and a Makefile to check that setup.py sdist generates
-source distributions with no files missing.
-
-
-1.3 (2010-07-13)
-----------------
-
-Highlight objects with a __del__ method.
-
-Fixes LP#483411, LP#514422, 
-
-show_refs, show_backrefs don't create files in the current working
-directory any more.  Instead they accept a filename argument.  It can be a
-.dot file or a .png file.  If None or not specified, those functions will try
-to spawn xdot as before.  Fixes LP#514422.
-
-New extra_info argument to graph-generating functions (patch by Thouis Jones,
-LP#558914).
-
-setup.py should work with distutils now (LP#604430, thanks to Randy Heydon).
-
-
-1.2 (2009-03-25)
-----------------
-
-Project website, public source repository, uploaded to PyPI.
-
-No code changes.
-
-
-1.1dev (2008-09-05)
--------------------
-
-New function: show_refs() for showing forward references.
-
-New functions: typestats() and show_most_common_types().
-
-Object boxes are less crammed with useless information (such as IDs).
-
-Spawns xdot if it is available.
-"""
-# Permission is hereby granted, free of charge, to any person obtaining a
-# copy of this software and associated documentation files (the "Software"),
-# to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense,
-# and/or sell copies of the Software, and to permit persons to whom the
-# Software is furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-__author__ = "Marius Gedminas (marius at gedmin.as)"
-__copyright__ = "Copyright (c) 2008-2010 Marius Gedminas"
-__license__ = "MIT"
-__version__ = "1.3.2dev"
-__date__ = "2010-07-17"
-
-
-import gc
-import inspect
-import types
-import weakref
-import operator
-import os
-import subprocess
-from tempfile import NamedTemporaryFile
-
-
-def count(typename):
-    """Count objects tracked by the garbage collector with a given class name.
-
-    Example:
-
-        >>> count('dict')
-        42
-        >>> count('MyClass')
-        3
-
-    Note that the GC does not track simple objects like int or str.
-    """
-    return sum(1 for o in gc.get_objects() if type(o).__name__ == typename)
-
-
-def typestats():
-    """Count the number of instances for each type tracked by the GC.
-
-    Note that the GC does not track simple objects like int or str.
-
-    Note that classes with the same name but defined in different modules
-    will be lumped together.
-    """
-    stats = {}
-    for o in gc.get_objects():
-        stats.setdefault(type(o).__name__, 0)
-        stats[type(o).__name__] += 1
-    return stats
-
-
-def show_most_common_types(limit=10):
-    """Count the names of types with the most instances.
-
-    Note that the GC does not track simple objects like int or str.
-
-    Note that classes with the same name but defined in different modules
-    will be lumped together.
-    """
-    stats = sorted(typestats().items(), key=operator.itemgetter(1),
-                   reverse=True)
-    if limit:
-        stats = stats[:limit]
-    width = max(len(name) for name, count in stats)
-    for name, count in stats[:limit]:
-        print name.ljust(width), count
-
-
-def by_type(typename):
-    """Return objects tracked by the garbage collector with a given class name.
-
-    Example:
-
-        >>> by_type('MyClass')
-        [<mymodule.MyClass object at 0x...>]
-
-    Note that the GC does not track simple objects like int or str.
-    """
-    return [o for o in gc.get_objects() if type(o).__name__ == typename]
-
-
-def at(addr):
-    """Return an object at a given memory address.
-    
-    The reverse of id(obj):
-
-        >>> at(id(obj)) is obj
-        True
-
-    Note that this function does not work on objects that are not tracked by
-    the GC (e.g. ints or strings).
-    """
-    for o in gc.get_objects():
-        if id(o) == addr:
-            return o
-    return None
-
-
-def find_backref_chain(obj, predicate, max_depth=20, extra_ignore=()):
-    """Find a shortest chain of references leading to obj.
-
-    The start of the chain will be some object that matches your predicate.
-
-    ``max_depth`` limits the search depth.
-
-    ``extra_ignore`` can be a list of object IDs to exclude those objects from
-    your search.
-
-    Example:
-
-        >>> find_backref_chain(obj, inspect.ismodule)
-        [<module ...>, ..., obj]
-
-    Returns None if such a chain could not be found.
-    """
-    queue = [obj]
-    depth = {id(obj): 0}
-    parent = {id(obj): None}
-    ignore = set(extra_ignore)
-    ignore.add(id(extra_ignore))
-    ignore.add(id(queue))
-    ignore.add(id(depth))
-    ignore.add(id(parent))
-    ignore.add(id(ignore))
-    gc.collect()
-    while queue:
-        target = queue.pop(0)
-        if predicate(target):
-            chain = [target]
-            while parent[id(target)] is not None:
-                target = parent[id(target)]
-                chain.append(target)
-            return chain
-        tdepth = depth[id(target)]
-        if tdepth < max_depth:
-            referrers = gc.get_referrers(target)
-            ignore.add(id(referrers))
-            for source in referrers:
-                if inspect.isframe(source) or id(source) in ignore:
-                    continue
-                if id(source) not in depth:
-                    depth[id(source)] = tdepth + 1
-                    parent[id(source)] = target
-                    queue.append(source)
-    return None # not found
-
-
-def show_backrefs(objs, max_depth=3, extra_ignore=(), filter=None, too_many=10,
-                  highlight=None, filename=None, extra_info=(lambda _: '')):
-    """Generate an object reference graph ending at ``objs``
-
-    The graph will show you what objects refer to ``objs``, directly and
-    indirectly.
-
-    ``objs`` can be a single object, or it can be a list of objects.  If
-    unsure, wrap the single object in a new list.
-
-    Produces a Graphviz .dot file and spawns a viewer (xdot) if one is
-    installed, otherwise converts the graph to a .png image.
-
-    Use ``max_depth`` and ``too_many`` to limit the depth and breadth of the
-    graph.
-
-    Use ``filter`` (a predicate) and ``extra_ignore`` (a list of object IDs) to
-    remove undesired objects from the graph.
-
-    Use ``highlight`` (a predicate) to highlight certain graph nodes in blue.
-
-    Use ``extra_info`` (a function returning a string) to report extra
-    information for objects.
-
-    Examples:
-
-        >>> show_backrefs(obj)
-        >>> show_backrefs([obj1, obj2])
-        >>> show_backrefs(obj, max_depth=5)
-        >>> show_backrefs(obj, filter=lambda x: not inspect.isclass(x))
-        >>> show_backrefs(obj, highlight=inspect.isclass)
-        >>> show_backrefs(obj, extra_ignore=[id(locals())])
-
-    """
-    show_graph(objs, max_depth=max_depth, extra_ignore=extra_ignore,
-               filter=filter, too_many=too_many, highlight=highlight,
-               edge_func=gc.get_referrers, swap_source_target=False,
-               filename=filename, extra_info=extra_info)
-
-
-def show_refs(objs, max_depth=3, extra_ignore=(), filter=None, too_many=10,
-              highlight=None, filename=None, extra_info=(lambda _: '')):
-    """Generate an object reference graph starting at ``objs``
-
-    The graph will show you what objects are reachable from ``objs``, directly
-    and indirectly.
-
-    ``objs`` can be a single object, or it can be a list of objects.  If
-    unsure, wrap the single object in a new list.
-
-    Produces a Graphviz .dot file and spawns a viewer (xdot) if one is
-    installed, otherwise converts the graph to a .png image.
-
-    Use ``max_depth`` and ``too_many`` to limit the depth and breadth of the
-    graph.
-
-    Use ``filter`` (a predicate) and ``extra_ignore`` (a list of object IDs) to
-    remove undesired objects from the graph.
-
-    Use ``highlight`` (a predicate) to highlight certain graph nodes in blue.
-
-    Use ``extra_info`` (a function returning a string) to report extra
-    information for objects.
-
-    Examples:
-
-        >>> show_refs(obj)
-        >>> show_refs([obj1, obj2])
-        >>> show_refs(obj, max_depth=5)
-        >>> show_refs(obj, filter=lambda x: not inspect.isclass(x))
-        >>> show_refs(obj, highlight=inspect.isclass)
-        >>> show_refs(obj, extra_ignore=[id(locals())])
-
-    """
-    show_graph(objs, max_depth=max_depth, extra_ignore=extra_ignore,
-               filter=filter, too_many=too_many, highlight=highlight,
-               edge_func=gc.get_referents, swap_source_target=True,
-               filename=filename, extra_info=extra_info)
-
-#
-# Internal helpers
-#
-
-def show_graph(objs, edge_func, swap_source_target,
-               max_depth=3, extra_ignore=(), filter=None, too_many=10,
-               highlight=None, filename=None, extra_info=(lambda _: '')):
-    if not isinstance(objs, (list, tuple)):
-        objs = [objs]
-    if filename and filename.endswith('.dot'):
-        f = file(filename, 'w')
-        dot_filename = filename
-    else:
-        f = NamedTemporaryFile('w', suffix='.dot', delete=False)
-        dot_filename = f.name
-    print >> f, 'digraph ObjectGraph {'
-    print >> f, '  node[shape=box, style=filled, fillcolor=white];'
-    queue = []
-    depth = {}
-    ignore = set(extra_ignore)
-    ignore.add(id(objs))
-    ignore.add(id(extra_ignore))
-    ignore.add(id(queue))
-    ignore.add(id(depth))
-    ignore.add(id(ignore))
-    for obj in objs:
-        print >> f, '  %s[fontcolor=red];' % (obj_node_id(obj))
-        depth[id(obj)] = 0
-        queue.append(obj)
-    gc.collect()
-    nodes = 0
-    while queue:
-        nodes += 1
-        target = queue.pop(0)
-        tdepth = depth[id(target)]
-        print >> f, '  %s[label="%s"];' % (obj_node_id(target), obj_label(target, tdepth, extra_info))
-        h, s, v = gradient((0, 0, 1), (0, 0, .3), tdepth, max_depth)
-        if inspect.ismodule(target):
-            h = .3
-            s = 1
-        if highlight and highlight(target):
-            h = .6
-            s = .6
-            v = 0.5 + v * 0.5
-        print >> f, '  %s[fillcolor="%g,%g,%g"];' % (obj_node_id(target), h, s, v)
-        if v < 0.5:
-            print >> f, '  %s[fontcolor=white];' % (obj_node_id(target))
-        if hasattr(target, '__del__'):
-            print >> f, "  %s->%s_has_a_del[color=red,style=dotted,len=0.25,weight=10];" % (obj_node_id(target), obj_node_id(target))
-            print >> f, '  %s_has_a_del[label="__del__",shape=doublecircle,height=0.25,color=red,fillcolor="0,.5,1",fontsize=6];' % (obj_node_id(target))
-        if inspect.ismodule(target) or tdepth >= max_depth:
-            continue
-        neighbours = edge_func(target)
-        ignore.add(id(neighbours))
-        n = 0
-        for source in neighbours:
-            if inspect.isframe(source) or id(source) in ignore:
-                continue
-            if filter and not filter(source):
-                continue
-            if swap_source_target:
-                srcnode, tgtnode = target, source
-            else:
-                srcnode, tgtnode = source, target
-            elabel = edge_label(srcnode, tgtnode)
-            print >> f, '  %s -> %s%s;' % (obj_node_id(srcnode), obj_node_id(tgtnode), elabel)
-            if id(source) not in depth:
-                depth[id(source)] = tdepth + 1
-                queue.append(source)
-            n += 1
-            if n >= too_many:
-                print >> f, '  %s[color=red];' % obj_node_id(target)
-                break
-    print >> f, "}"
-    f.close()
-    print "Graph written to %s (%d nodes)" % (dot_filename, nodes)
-    if filename is None and program_in_path('xdot'):
-        print "Spawning graph viewer (xdot)"
-        subprocess.Popen(['xdot', dot_filename])
-    elif program_in_path('dot'):
-        if filename is None:
-            print "Graph viewer (xdot) not found, generating a png instead"
-        if filename and filename.endswith('.png'):
-            f = file(filename, 'wb')
-            png_filename = filename
-        else:
-            if filename is not None:
-                print "Unrecognized file type (%s)" % filename
-            f = NamedTemporaryFile('wb', suffix='.png', delete=False)
-            png_filename = f.name
-        dot = subprocess.Popen(['dot', '-Tpng', dot_filename],
-                               stdout=f)
-        dot.wait()
-        f.close()
-        print "Image generated as %s" % png_filename
-    else:
-        if filename is None:
-            print "Graph viewer (xdot) and image renderer (dot) not found, not doing anything else"
-        else:
-            print "Unrecognized file type (%s), not doing anything else" % filename
-
-
-def obj_node_id(obj):
-    if isinstance(obj, weakref.ref):
-        return 'all_weakrefs_are_one'
-    return ('o%d' % id(obj)).replace('-', '_')
-
-
-def obj_label(obj, depth, extra_info):
-    return quote(type(obj).__name__ + ':\n' +
-                 safe_repr(obj) + '\n' +
-                 extra_info(obj))
-
-
-def quote(s):
-    return s.replace("\\", "\\\\").replace("\"", "\\\"").replace("\n", "\\n")
-
-
-def safe_repr(obj):
-    try:
-        return short_repr(obj)
-    except:
-        return '(unrepresentable)'
-
-
-def short_repr(obj):
-    if isinstance(obj, (type, types.ModuleType, types.BuiltinMethodType,
-                        types.BuiltinFunctionType)):
-        return obj.__name__
-    if isinstance(obj, types.MethodType):
-        if obj.im_self is not None:
-            return obj.im_func.__name__ + ' (bound)'
-        else:
-            return obj.im_func.__name__
-    if isinstance(obj, (tuple, list, dict, set)):
-        return '%d items' % len(obj)
-    if isinstance(obj, weakref.ref):
-        return 'all_weakrefs_are_one'
-    return repr(obj)[:40]
-
-
-def gradient(start_color, end_color, depth, max_depth):
-    if max_depth == 0:
-        # avoid division by zero
-        return start_color
-    h1, s1, v1 = start_color
-    h2, s2, v2 = end_color
-    f = float(depth) / max_depth
-    h = h1 * (1-f) + h2 * f
-    s = s1 * (1-f) + s2 * f
-    v = v1 * (1-f) + v2 * f
-    return h, s, v
-
-
-def edge_label(source, target):
-    if isinstance(target, dict) and target is getattr(source, '__dict__', None):
-        return ' [label="__dict__",weight=10]'
-    elif isinstance(source, dict):
-        for k, v in source.iteritems():
-            if v is target:
-                if isinstance(k, basestring) and k:
-                    return ' [label="%s",weight=2]' % quote(k)
-                else:
-                    return ' [label="%s"]' % quote(safe_repr(k))
-    return ''
-
-
-def program_in_path(program):
-    path = os.environ.get("PATH", os.defpath).split(os.pathsep)
-    path = [os.path.join(dir, program) for dir in path]
-    path = [True for file in path if os.path.isfile(file)]
-    return bool(path)

Deleted: z3c.memhunt.objgraph/trunk/z3c/memhunt/objgraph/objgraph_orig.py
===================================================================
--- z3c.memhunt.objgraph/trunk/z3c/memhunt/objgraph/objgraph_orig.py	2010-11-10 10:26:41 UTC (rev 118310)
+++ z3c.memhunt.objgraph/trunk/z3c/memhunt/objgraph/objgraph_orig.py	2010-11-10 10:29:43 UTC (rev 118311)
@@ -1,485 +0,0 @@
-"""
-Ad-hoc tools for drawing Python object reference graphs with graphviz.
-
-This module is more useful as a repository of sample code and ideas, than
-as a finished product.  For documentation and background, read
-
-  http://mg.pov.lt/blog/hunting-python-memleaks.html
-  http://mg.pov.lt/blog/python-object-graphs.html
-  http://mg.pov.lt/blog/object-graphs-with-graphviz.html
-
-in that order.  Then use pydoc to read the docstrings, as there were
-improvements made since those blog posts.
-
-Copyright (c) 2008-2010 Marius Gedminas <marius at pov.lt>
-
-Released under the MIT licence.
-
-
-Changes
-=======
-
-1.3.2 (unreleased)
-------------------
-
-(no changes yet)
-
-
-1.3.1 (2010-07-17)
-------------------
-
-Rebuild an sdist with no missing files (fixes LP#606604)
-
-Added MANIFEST.in and a Makefile to check that setup.py sdist generates
-source distributions with no files missing.
-
-
-1.3 (2010-07-13)
-----------------
-
-Highlight objects with a __del__ method.
-
-Fixes LP#483411, LP#514422, 
-
-show_refs, show_backrefs don't create files in the current working
-directory any more.  Instead they accept a filename argument.  It can be a
-.dot file or a .png file.  If None or not specified, those functions will try
-to spawn xdot as before.  Fixes LP#514422.
-
-New extra_info argument to graph-generating functions (patch by Thouis Jones,
-LP#558914).
-
-setup.py should work with distutils now (LP#604430, thanks to Randy Heydon).
-
-
-1.2 (2009-03-25)
-----------------
-
-Project website, public source repository, uploaded to PyPI.
-
-No code changes.
-
-
-1.1dev (2008-09-05)
--------------------
-
-New function: show_refs() for showing forward references.
-
-New functions: typestats() and show_most_common_types().
-
-Object boxes are less crammed with useless information (such as IDs).
-
-Spawns xdot if it is available.
-"""
-# Permission is hereby granted, free of charge, to any person obtaining a
-# copy of this software and associated documentation files (the "Software"),
-# to deal in the Software without restriction, including without limitation
-# the rights to use, copy, modify, merge, publish, distribute, sublicense,
-# and/or sell copies of the Software, and to permit persons to whom the
-# Software is furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-# DEALINGS IN THE SOFTWARE.
-
-__author__ = "Marius Gedminas (marius at gedmin.as)"
-__copyright__ = "Copyright (c) 2008-2010 Marius Gedminas"
-__license__ = "MIT"
-__version__ = "1.3.2dev"
-__date__ = "2010-07-17"
-
-
-import gc
-import inspect
-import types
-import weakref
-import operator
-import os
-import subprocess
-from tempfile import NamedTemporaryFile
-
-
-def count(typename):
-    """Count objects tracked by the garbage collector with a given class name.
-
-    Example:
-
-        >>> count('dict')
-        42
-        >>> count('MyClass')
-        3
-
-    Note that the GC does not track simple objects like int or str.
-    """
-    return sum(1 for o in gc.get_objects() if type(o).__name__ == typename)
-
-
-def typestats():
-    """Count the number of instances for each type tracked by the GC.
-
-    Note that the GC does not track simple objects like int or str.
-
-    Note that classes with the same name but defined in different modules
-    will be lumped together.
-    """
-    stats = {}
-    for o in gc.get_objects():
-        stats.setdefault(type(o).__name__, 0)
-        stats[type(o).__name__] += 1
-    return stats
-
-
-def show_most_common_types(limit=10):
-    """Count the names of types with the most instances.
-
-    Note that the GC does not track simple objects like int or str.
-
-    Note that classes with the same name but defined in different modules
-    will be lumped together.
-    """
-    stats = sorted(typestats().items(), key=operator.itemgetter(1),
-                   reverse=True)
-    if limit:
-        stats = stats[:limit]
-    width = max(len(name) for name, count in stats)
-    for name, count in stats[:limit]:
-        print name.ljust(width), count
-
-
-def by_type(typename):
-    """Return objects tracked by the garbage collector with a given class name.
-
-    Example:
-
-        >>> by_type('MyClass')
-        [<mymodule.MyClass object at 0x...>]
-
-    Note that the GC does not track simple objects like int or str.
-    """
-    return [o for o in gc.get_objects() if type(o).__name__ == typename]
-
-
-def at(addr):
-    """Return an object at a given memory address.
-    
-    The reverse of id(obj):
-
-        >>> at(id(obj)) is obj
-        True
-
-    Note that this function does not work on objects that are not tracked by
-    the GC (e.g. ints or strings).
-    """
-    for o in gc.get_objects():
-        if id(o) == addr:
-            return o
-    return None
-
-
-def find_backref_chain(obj, predicate, max_depth=20, extra_ignore=()):
-    """Find a shortest chain of references leading to obj.
-
-    The start of the chain will be some object that matches your predicate.
-
-    ``max_depth`` limits the search depth.
-
-    ``extra_ignore`` can be a list of object IDs to exclude those objects from
-    your search.
-
-    Example:
-
-        >>> find_backref_chain(obj, inspect.ismodule)
-        [<module ...>, ..., obj]
-
-    Returns None if such a chain could not be found.
-    """
-    queue = [obj]
-    depth = {id(obj): 0}
-    parent = {id(obj): None}
-    ignore = set(extra_ignore)
-    ignore.add(id(extra_ignore))
-    ignore.add(id(queue))
-    ignore.add(id(depth))
-    ignore.add(id(parent))
-    ignore.add(id(ignore))
-    gc.collect()
-    while queue:
-        target = queue.pop(0)
-        if predicate(target):
-            chain = [target]
-            while parent[id(target)] is not None:
-                target = parent[id(target)]
-                chain.append(target)
-            return chain
-        tdepth = depth[id(target)]
-        if tdepth < max_depth:
-            referrers = gc.get_referrers(target)
-            ignore.add(id(referrers))
-            for source in referrers:
-                if inspect.isframe(source) or id(source) in ignore:
-                    continue
-                if id(source) not in depth:
-                    depth[id(source)] = tdepth + 1
-                    parent[id(source)] = target
-                    queue.append(source)
-    return None # not found
-
-
-def show_backrefs(objs, max_depth=3, extra_ignore=(), filter=None, too_many=10,
-                  highlight=None, filename=None, extra_info=(lambda _: '')):
-    """Generate an object reference graph ending at ``objs``
-
-    The graph will show you what objects refer to ``objs``, directly and
-    indirectly.
-
-    ``objs`` can be a single object, or it can be a list of objects.  If
-    unsure, wrap the single object in a new list.
-
-    Produces a Graphviz .dot file and spawns a viewer (xdot) if one is
-    installed, otherwise converts the graph to a .png image.
-
-    Use ``max_depth`` and ``too_many`` to limit the depth and breadth of the
-    graph.
-
-    Use ``filter`` (a predicate) and ``extra_ignore`` (a list of object IDs) to
-    remove undesired objects from the graph.
-
-    Use ``highlight`` (a predicate) to highlight certain graph nodes in blue.
-
-    Use ``extra_info`` (a function returning a string) to report extra
-    information for objects.
-
-    Examples:
-
-        >>> show_backrefs(obj)
-        >>> show_backrefs([obj1, obj2])
-        >>> show_backrefs(obj, max_depth=5)
-        >>> show_backrefs(obj, filter=lambda x: not inspect.isclass(x))
-        >>> show_backrefs(obj, highlight=inspect.isclass)
-        >>> show_backrefs(obj, extra_ignore=[id(locals())])
-
-    """
-    show_graph(objs, max_depth=max_depth, extra_ignore=extra_ignore,
-               filter=filter, too_many=too_many, highlight=highlight,
-               edge_func=gc.get_referrers, swap_source_target=False,
-               filename=filename, extra_info=extra_info)
-
-
-def show_refs(objs, max_depth=3, extra_ignore=(), filter=None, too_many=10,
-              highlight=None, filename=None, extra_info=(lambda _: '')):
-    """Generate an object reference graph starting at ``objs``
-
-    The graph will show you what objects are reachable from ``objs``, directly
-    and indirectly.
-
-    ``objs`` can be a single object, or it can be a list of objects.  If
-    unsure, wrap the single object in a new list.
-
-    Produces a Graphviz .dot file and spawns a viewer (xdot) if one is
-    installed, otherwise converts the graph to a .png image.
-
-    Use ``max_depth`` and ``too_many`` to limit the depth and breadth of the
-    graph.
-
-    Use ``filter`` (a predicate) and ``extra_ignore`` (a list of object IDs) to
-    remove undesired objects from the graph.
-
-    Use ``highlight`` (a predicate) to highlight certain graph nodes in blue.
-
-    Use ``extra_info`` (a function returning a string) to report extra
-    information for objects.
-
-    Examples:
-
-        >>> show_refs(obj)
-        >>> show_refs([obj1, obj2])
-        >>> show_refs(obj, max_depth=5)
-        >>> show_refs(obj, filter=lambda x: not inspect.isclass(x))
-        >>> show_refs(obj, highlight=inspect.isclass)
-        >>> show_refs(obj, extra_ignore=[id(locals())])
-
-    """
-    show_graph(objs, max_depth=max_depth, extra_ignore=extra_ignore,
-               filter=filter, too_many=too_many, highlight=highlight,
-               edge_func=gc.get_referents, swap_source_target=True,
-               filename=filename, extra_info=extra_info)
-
-#
-# Internal helpers
-#
-
-def show_graph(objs, edge_func, swap_source_target,
-               max_depth=3, extra_ignore=(), filter=None, too_many=10,
-               highlight=None, filename=None, extra_info=(lambda _: '')):
-    if not isinstance(objs, (list, tuple)):
-        objs = [objs]
-    if filename and filename.endswith('.dot'):
-        f = file(filename, 'w')
-        dot_filename = filename
-    else:
-        f = NamedTemporaryFile('w', suffix='.dot', delete=False)
-        dot_filename = f.name
-    print >> f, 'digraph ObjectGraph {'
-    print >> f, '  node[shape=box, style=filled, fillcolor=white];'
-    queue = []
-    depth = {}
-    ignore = set(extra_ignore)
-    ignore.add(id(objs))
-    ignore.add(id(extra_ignore))
-    ignore.add(id(queue))
-    ignore.add(id(depth))
-    ignore.add(id(ignore))
-    for obj in objs:
-        print >> f, '  %s[fontcolor=red];' % (obj_node_id(obj))
-        depth[id(obj)] = 0
-        queue.append(obj)
-    gc.collect()
-    nodes = 0
-    while queue:
-        nodes += 1
-        target = queue.pop(0)
-        tdepth = depth[id(target)]
-        print >> f, '  %s[label="%s"];' % (obj_node_id(target), obj_label(target, tdepth, extra_info))
-        h, s, v = gradient((0, 0, 1), (0, 0, .3), tdepth, max_depth)
-        if inspect.ismodule(target):
-            h = .3
-            s = 1
-        if highlight and highlight(target):
-            h = .6
-            s = .6
-            v = 0.5 + v * 0.5
-        print >> f, '  %s[fillcolor="%g,%g,%g"];' % (obj_node_id(target), h, s, v)
-        if v < 0.5:
-            print >> f, '  %s[fontcolor=white];' % (obj_node_id(target))
-        if hasattr(target, '__del__'):
-            print >> f, "  %s->%s_has_a_del[color=red,style=dotted,len=0.25,weight=10];" % (obj_node_id(target), obj_node_id(target))
-            print >> f, '  %s_has_a_del[label="__del__",shape=doublecircle,height=0.25,color=red,fillcolor="0,.5,1",fontsize=6];' % (obj_node_id(target))
-        if inspect.ismodule(target) or tdepth >= max_depth:
-            continue
-        neighbours = edge_func(target)
-        ignore.add(id(neighbours))
-        n = 0
-        for source in neighbours:
-            if inspect.isframe(source) or id(source) in ignore:
-                continue
-            if filter and not filter(source):
-                continue
-            if swap_source_target:
-                srcnode, tgtnode = target, source
-            else:
-                srcnode, tgtnode = source, target
-            elabel = edge_label(srcnode, tgtnode)
-            print >> f, '  %s -> %s%s;' % (obj_node_id(srcnode), obj_node_id(tgtnode), elabel)
-            if id(source) not in depth:
-                depth[id(source)] = tdepth + 1
-                queue.append(source)
-            n += 1
-            if n >= too_many:
-                print >> f, '  %s[color=red];' % obj_node_id(target)
-                break
-    print >> f, "}"
-    f.close()
-    print "Graph written to %s (%d nodes)" % (dot_filename, nodes)
-    if filename is None and program_in_path('xdot'):
-        print "Spawning graph viewer (xdot)"
-        subprocess.Popen(['xdot', dot_filename])
-    elif program_in_path('dot'):
-        if filename is None:
-            print "Graph viewer (xdot) not found, generating a png instead"
-        if filename and filename.endswith('.png'):
-            f = file(filename, 'wb')
-            png_filename = filename
-        else:
-            if filename is not None:
-                print "Unrecognized file type (%s)" % filename
-            f = NamedTemporaryFile('wb', suffix='.png', delete=False)
-            png_filename = f.name
-        dot = subprocess.Popen(['dot', '-Tpng', dot_filename],
-                               stdout=f)
-        dot.wait()
-        f.close()
-        print "Image generated as %s" % png_filename
-    else:
-        if filename is None:
-            print "Graph viewer (xdot) and image renderer (dot) not found, not doing anything else"
-        else:
-            print "Unrecognized file type (%s), not doing anything else" % filename
-
-
-def obj_node_id(obj):
-    if isinstance(obj, weakref.ref):
-        return 'all_weakrefs_are_one'
-    return ('o%d' % id(obj)).replace('-', '_')
-
-
-def obj_label(obj, depth, extra_info):
-    return quote(type(obj).__name__ + ':\n' +
-                 safe_repr(obj) + '\n' +
-                 extra_info(obj))
-
-
-def quote(s):
-    return s.replace("\\", "\\\\").replace("\"", "\\\"").replace("\n", "\\n")
-
-
-def safe_repr(obj):
-    try:
-        return short_repr(obj)
-    except:
-        return '(unrepresentable)'
-
-
-def short_repr(obj):
-    if isinstance(obj, (type, types.ModuleType, types.BuiltinMethodType,
-                        types.BuiltinFunctionType)):
-        return obj.__name__
-    if isinstance(obj, types.MethodType):
-        if obj.im_self is not None:
-            return obj.im_func.__name__ + ' (bound)'
-        else:
-            return obj.im_func.__name__
-    if isinstance(obj, (tuple, list, dict, set)):
-        return '%d items' % len(obj)
-    if isinstance(obj, weakref.ref):
-        return 'all_weakrefs_are_one'
-    return repr(obj)[:40]
-
-
-def gradient(start_color, end_color, depth, max_depth):
-    if max_depth == 0:
-        # avoid division by zero
-        return start_color
-    h1, s1, v1 = start_color
-    h2, s2, v2 = end_color
-    f = float(depth) / max_depth
-    h = h1 * (1-f) + h2 * f
-    s = s1 * (1-f) + s2 * f
-    v = v1 * (1-f) + v2 * f
-    return h, s, v
-
-
-def edge_label(source, target):
-    if isinstance(target, dict) and target is getattr(source, '__dict__', None):
-        return ' [label="__dict__",weight=10]'
-    elif isinstance(source, dict):
-        for k, v in source.iteritems():
-            if v is target:
-                if isinstance(k, basestring) and k:
-                    return ' [label="%s",weight=2]' % quote(k)
-                else:
-                    return ' [label="%s"]' % quote(safe_repr(k))
-    return ''
-
-
-def program_in_path(program):
-    path = os.environ.get("PATH", os.defpath).split(os.pathsep)
-    path = [os.path.join(dir, program) for dir in path]
-    path = [True for file in path if os.path.isfile(file)]
-    return bool(path)

Deleted: z3c.memhunt.objgraph/trunk/z3c/memhunt/objgraph/objgraph_trunk.diff
===================================================================
--- z3c.memhunt.objgraph/trunk/z3c/memhunt/objgraph/objgraph_trunk.diff	2010-11-10 10:26:41 UTC (rev 118310)
+++ z3c.memhunt.objgraph/trunk/z3c/memhunt/objgraph/objgraph_trunk.diff	2010-11-10 10:29:43 UTC (rev 118311)
@@ -1,32 +0,0 @@
-152d151
-<     res = set([])
-154,155c153
-<         res.add((name.ljust(width), count))
-<     return res
----
->         print name.ljust(width), count
-325,328d322
-< 
-<     if filename and os.path.exists(filename):
-<         os.unlink(filename)
-< 
-330c324
-<         f = file(filename, 'wb')
----
->         f = file(filename, 'w')
-333c327
-<         f = NamedTemporaryFile('wb', suffix='.dot')
----
->         f = NamedTemporaryFile('w', suffix='.dot', delete=False)
-335,341d328
-< 
-<     # NOTE:
-<     # Need to do this to ensure the file is created within transaction??
-<     f.close()
-<     f = open(f.name, 'wb')
-<     f.write('')
-< 
-415c402
-<             f = NamedTemporaryFile('wb', suffix='.png')
----
->             f = NamedTemporaryFile('wb', suffix='.png', delete=False)



More information about the checkins mailing list