Example #1
0
    def test_garbage(self):
        with restore_gc_state():
            gc.disable()
            a = []
            b = []
            c = []
            a.append(a)
            b.append(c)
            c.append(b)
            del a, b, c

            graph = garbage()
            self.assertEqual(len(gc.garbage), 0)
            self.assertEqual(len(graph), 3)

            # A second call to garbage should
            # produce nothing new.
            graph2 = garbage()
            self.assertEqual(gc.garbage, [])
            self.assertEqual(len(graph2), 0)

            # But if we delete graph then
            # a, b and c become collectable again.
            del graph
            graph = garbage()
            self.assertEqual(gc.garbage, [])
            self.assertEqual(len(graph), 3)

            # Get rid of everything.
            del graph, graph2
            gc.collect()
            graph = garbage()
            self.assertEqual(gc.garbage, [])
            self.assertEqual(len(graph), 0)
Example #2
0
def cycles_created_by(callable):
    """
    Return graph of cyclic garbage created by the given callable.

    Return an :class:`~refcycle.object_graph.ObjectGraph` representing those
    objects generated by the given callable that can't be collected by Python's
    usual reference-count based garbage collection.

    This includes objects that will eventually be collected by the cyclic
    garbage collector, as well as genuinely unreachable objects that will
    never be collected.

    `callable` should be a callable that takes no arguments; its return
    value (if any) will be ignored.

    """
    with restore_gc_state():
        gc.disable()
        gc.collect()
        gc.set_debug(gc.DEBUG_SAVEALL)
        callable()
        new_object_count = gc.collect()
        if new_object_count:
            objects = gc.garbage[-new_object_count:]
            del gc.garbage[-new_object_count:]
        else:
            objects = []
        return ObjectGraph(objects)
Example #3
0
 def test_snapshot(self):
     with restore_gc_state():
         gc.disable()
         original_objects = snapshot()
         create_cycles()
         new_objects = snapshot()
         diff = new_objects - original_objects - ObjectGraph(
             original_objects.owned_objects())
         self.assertEqual(len(diff), 4)
Example #4
0
    def test_key_cycles(self):
        with restore_gc_state():
            gc.disable()
            a = ['a']
            b = ['b']
            c = ['c']
            d = ['d']
            a.append(b)
            b.append(a)
            c.append(d)
            d.append(c)
            b.append(d)
            del a, b, c, d

            sccs = key_cycles()
            self.assertEqual(len(sccs), 1)
            self.assertEqual(len(sccs[0]), 2)
            # Make sure to remove the sccs for good.
            del sccs
            gc.collect()

        # Same again, but with no connections between {a, b} and {c, d}.
        with restore_gc_state():
            gc.disable()
            a = ['a']
            b = ['b']
            c = ['c']
            d = ['d']
            a.append(b)
            b.append(a)
            c.append(d)
            d.append(c)
            del a, b, c, d

            sccs = key_cycles()
            self.assertEqual(len(sccs), 2)
            self.assertEqual(len(sccs[0]), 2)
            self.assertEqual(len(sccs[1]), 2)
            # Make sure to remove the sccs for good.
            del sccs
            gc.collect()
Example #5
0
def garbage():
    """
    Collect garbage and return an :class:`~refcycle.object_graph.ObjectGraph`
    based on collected garbage.

    The collected elements are removed from ``gc.garbage``, but are still kept
    alive by the references in the graph.  Deleting the
    :class:`~refcycle.object_graph.ObjectGraph` instance and doing another
    ``gc.collect`` will remove those objects for good.

    """
    with restore_gc_state():
        gc.disable()
        gc.set_debug(gc.DEBUG_SAVEALL)
        collected_count = gc.collect()
        if collected_count:
            objects = gc.garbage[-collected_count:]
            del gc.garbage[-collected_count:]
        else:
            objects = []
        return ObjectGraph(objects)