Rev 166: Change the api a bit. obj.iter_recursive_refs() now returns self. in http://bazaar.launchpad.net/~meliae-dev/meliae/trunk

John Arbash Meinel john at arbash-meinel.com
Thu Jul 29 16:50:48 BST 2010


At http://bazaar.launchpad.net/~meliae-dev/meliae/trunk

------------------------------------------------------------
revno: 166
revision-id: john at arbash-meinel.com-20100729155028-7s18qj51b22v4o08
parent: john at arbash-meinel.com-20100729152358-4p8h7ke9rwvxb5it
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: trunk
timestamp: Thu 2010-07-29 10:50:28 -0500
message:
  Change the api a bit. obj.iter_recursive_refs() now returns self.
  
  This allows us to:
   a) skip over it if it is what we really want
   b) simplify some code that wanted to exclude everything referenced from an object
      including itself, which I imagine is more common.
-------------- next part --------------
=== modified file 'meliae/_loader.pyx'
--- a/meliae/_loader.pyx	2010-07-29 15:23:58 +0000
+++ b/meliae/_loader.pyx	2010-07-29 15:50:28 +0000
@@ -605,9 +605,18 @@
             as_dict[key] = val
         return as_dict
 
-    def iter_recursive_refs(self):
+    def iter_recursive_refs(self, excluding=None):
+        """Find all objects referenced from this one (including self).
+
+        Self will always be the first object returned, in case you want to
+        exclude it (though it can be excluded in the excluding list).
+
+        :param excluding: This can be any iterable of addresses. We will not
+            walk to anything in this list (including self).
+        :return: Iterator over all objects that can be reached.
+        """
         cdef _MOPReferencedIterator iterator
-        iterator = _MOPReferencedIterator(self)
+        iterator = _MOPReferencedIterator(self, excluding)
         return iterator
 
 
@@ -991,16 +1000,18 @@
     cdef list pending_addresses
     cdef int pending_offset
 
-    def __init__(self, proxy):
+    def __init__(self, proxy, excluding=None):
         cdef _MemObjectProxy c_proxy
 
         from meliae import _intset
         c_proxy = proxy
         self.collection = c_proxy.collection
-        self.seen_addresses = _intset.IDSet()
-        self.seen_addresses.add(c_proxy.address)
-        self.pending_addresses = list(c_proxy.children)
-        self.pending_offset = len(self.pending_addresses) - 1
+        if excluding is not None:
+            self.seen_addresses = _intset.IDSet(excluding)
+        else:
+            self.seen_addresses = _intset.IDSet()
+        self.pending_addresses = [c_proxy.address]
+        self.pending_offset = 0
 
     def __iter__(self):
         return self

=== modified file 'meliae/loader.py'
--- a/meliae/loader.py	2010-07-29 15:23:58 +0000
+++ b/meliae/loader.py	2010-07-29 15:50:28 +0000
@@ -316,8 +316,7 @@
 
     def compute_total_size(self, obj):
         """Sum the size of all referenced objects (recursively)."""
-        obj.total_size = (obj.size
-            + sum(c.size for c in obj.iter_recursive_refs()))
+        obj.total_size = sum(c.size for c in obj.iter_recursive_refs())
         return obj
 
     def summarize(self):

=== modified file 'meliae/tests/test__loader.py'
--- a/meliae/tests/test__loader.py	2010-07-29 15:23:58 +0000
+++ b/meliae/tests/test__loader.py	2010-07-29 15:50:28 +0000
@@ -523,16 +523,16 @@
         self.moc.add(0, 'foo', 100)
         self.moc.add(255, 'baz', 300)
 
-    def assertIterRecursiveRefs(self, addresses, obj):
+    def assertIterRecursiveRefs(self, addresses, obj, excluding=None):
         self.assertEqual(addresses,
-                         [o.address for o in obj.iter_recursive_refs()])
+            [o.address for o in obj.iter_recursive_refs(excluding=excluding)])
 
     def test_no_refs(self):
-        self.assertIterRecursiveRefs([], self.moc[1024])
+        self.assertIterRecursiveRefs([1024], self.moc[1024])
 
     def test_single_depth_refs(self):
         obj = self.moc.add(1, 'test', 1234, children=[1024])
-        self.assertIterRecursiveRefs([1024], obj)
+        self.assertIterRecursiveRefs([1, 1024], obj)
 
     def test_deep_refs(self):
         obj = self.moc.add(1, '1', 1234, children=[2])
@@ -541,9 +541,33 @@
         self.moc.add(4, '4', 1234, children=[5])
         self.moc.add(5, '5', 1234, children=[6])
         self.moc.add(6, '6', 1234, children=[])
-        self.assertIterRecursiveRefs([2, 3, 4, 5, 6], obj)
+        self.assertIterRecursiveRefs([1, 2, 3, 4, 5, 6], obj)
 
     def test_self_referenced(self):
         self.moc.add(1, 'test', 1234, children=[1024, 2])
         obj = self.moc.add(2, 'test2', 1234, children=[1])
-        self.assertIterRecursiveRefs([1, 1024], obj)
+        self.assertIterRecursiveRefs([2, 1, 1024], obj)
+
+    def test_excluding(self):
+        obj = self.moc.add(1, 'test', 1234, children=[1024])
+        self.assertIterRecursiveRefs([1], obj, excluding=[1024])
+
+    def test_excluding_nested(self):
+        self.moc.add(1, 'test', 1234, children=[1024])
+        obj = self.moc.add(2, 'test', 1234, children=[1])
+        self.assertIterRecursiveRefs([2, 1, 1024], obj)
+        self.assertIterRecursiveRefs([2], obj, excluding=[1])
+
+    def test_excluding_wraparound(self):
+        self.moc.add(1, 'test', 1234, children=[1024])
+        self.moc.add(2, 'test', 1234, children=[1024])
+        obj = self.moc.add(3, 'test', 1234, children=[1, 2])
+        self.assertIterRecursiveRefs([3, 2, 1024, 1], obj)
+        self.assertIterRecursiveRefs([3, 2, 1024], obj, excluding=[1])
+        refed = (o.address for o in self.moc[1].iter_recursive_refs())
+        self.assertIterRecursiveRefs([3, 2], obj, excluding=refed)
+
+    def test_excluding_self(self):
+        self.assertIterRecursiveRefs([], self.moc[1024], excluding=[1024])
+        obj = self.moc.add(1, '1', 1234, children=[1024])
+        self.assertIterRecursiveRefs([], obj, excluding=[1])



More information about the bazaar-commits mailing list