def byframe(wrappers):
    """Collect objects according to the file name and line number of code where
    they were created.

    Can be printed using formatting.printsizesop."""

    frames = ignoredict()
    for w in wrappers.values():
        frame = utils.objframe(w.obj)

        if not frames.has_key(frame):
            val = (frame, 0, w)
            frames[frame] = val
        else:
            val = frames[frame]

        frames[frame] = (val[0], val[1] + w.size, val[2])

    return frames
def findcreators(wrappers):
    """Given a set of wrappers, returns a structure which can be used to
    find what objects each line of code created.
    
    The structure it returns has a "members" field, which contains all
    scanned objects, a "size" field, which gives the total size of all objects,
    and a "back" field, which contains a dictionary with a structure for each
    function that created an object. The dict maps from (file name, line number)
    or None to structure. None is used when there are no functions to go
    back to - i.e. it was this function that started the sequence of calls
    that led to the creation of the object.
    
    Following a member of "back" will give a structure with "filename" and
    "line" fields. In this structure, the "members" field contains the
    objects that were created on this file/line, and the "size" field the size
    of those objects.
    
    The "back" field contains a dictionary with a structure for each function
    that had called this function to make an object.
    
    You can print these using formatting.printsizes(creators.back)
    where creators is the value returned by this function.
    """
    
    try:
        from cpython.utils import objframe
    except ImportError:
        raise Exception, "Couldn't find cpython.utils.objframe - " + \
              "you need a patched copy of Python, and you need to " \
              "build the profiler using that copy."

    # First, collect all objects with the same frame traceback together.
    objects = {}
    for w in wrappers.itervalues():
        traceback = objframe(w.obj)
        val = objects.setdefault(traceback, [])
        val.append(w)
        
    # Now make the structure (a trie).
    return _Creator(wrappers, objects, "<interpreter>", 0)