[ZODB-Dev] Odd output from checkbtrees.py

Paul Winkler pw_lists at slinkp.com
Wed Aug 27 19:33:41 EDT 2003


On Wed, Aug 27, 2003 at 11:39:18AM -0400, Shane Hathaway wrote:
> DCWorkflow doesn't use BTrees.  My guess is that checkbtrees is actually 
> traversing a single object many times, making it a bug in checkbtrees.

Correct. And in fact, there were 2 issues to deal with:
1) obj.__dict__.items() sometimes picks things up
through acquisition, as demonstrated by the problem with DCWorkflow
transitions (and states, BTW).

2) it's possible for an object to contain a reference to itself,
e.g. a LocalFS instance has a root attribute that (sometimes?
always?) points to itself. So checkbtrees.py was infinitely
descending into spam.root.root.root.root...

Both of these were trivial to fix. 
Attached is a patch against checkbtrees.py from the ZODB3 main branch.
I have check-in privileges and would be happy to check this in,
but there's no unit tests for checkbtrees.py and I'd like 
some comments on whether i've broken anything.
"It works for me" - that is, it runs (on a 2 GB Data.fs), prints a whole
lot of output, and doesn't give any errors.

-- 

Paul Winkler
http://www.slinkp.com
Look! Up in the sky! It's WOODEN GLOVE POLE-LICKER!
(random hero from isometric.spaceninja.com)
-------------- next part --------------
*** checkbtrees.py.CVS_ORIG     Wed Aug 27 18:26:00 2003
--- checkbtrees.py      Wed Aug 27 17:14:12 2003
***************
*** 17,37 ****
          L.append((obj, path))
  
  def get_subobjects(obj):
      getattr(obj, '_', None) # unghostify
      sub = []
      try:
          attrs = obj.__dict__.items()
      except AttributeError:
          attrs = ()
!     for pair in attrs:
!         sub.append(pair)
! 
      # what if it is a mapping?
      try:
          items = obj.items()
      except AttributeError:
          items = ()
      for k, v in items:
          if not isinstance(k, IntType):
              sub.append(("<key>", k))
          if not isinstance(v, IntType):
--- 17,50 ----
          L.append((obj, path))
  
  def get_subobjects(obj):
+     ''' Get all subobjects, but carefully - don't
+     go into an infinite loop!'''
+ 
      getattr(obj, '_', None) # unghostify
      sub = []
+     # don't accidentally wander into obj's siblings
+     try:
+         obj = obj.aq_base
+     except AttributeError:
+         pass
+ 
      try:
          attrs = obj.__dict__.items()
      except AttributeError:
          attrs = ()
!     # don't loop if object contains reference to itself
!     sub.extend([pair for pair in attrs if not (pair[1] is obj)])
!         
      # what if it is a mapping?
      try:
          items = obj.items()
      except AttributeError:
          items = ()
      for k, v in items:
+         # don't loop if object contains reference to itself
+         if v is obj:
+             continue
+         # ok, v is not a self reference.
          if not isinstance(k, IntType):
              sub.append(("<key>", k))
          if not isinstance(v, IntType):


More information about the ZODB-Dev mailing list