[Zope] Re: Traversal of ZODB

David Trudgett dkt@registriesltd.com.au
Wed, 05 Jul 2000 10:22:38 -1000


At 2000-07-04 20:32 +0100, Steve Alexander <steve@cat-box.net> wrote:

>On Fri, 30 Jun 2000, David Trudgett wrote:
> > I wonder if anyone has a sample Python script that traverses the ZODB to
> > query or perform arbitrary operations on the objects found in it? My
> > present requirement is to write a script that goes through and does some
> > automated updating of several dozen DTML documents.
>
>Hi David,
>
>I just posted something similar to Zope-Dev:
>
>   http://lists.zope.org/pipermail/zope-dev/2000-July/005744.html

Thanks for that. I actually worked out a fairly similar hack myself, which 
only did one folder (which was OK for the particular task that I wanted it 
to do). Your recursive method has no doubt saved me quite a bit of time in 
generalising it. There are still a couple of little question marks in my 
mind, though. But before I get to them, I'll just post a sample of what I 
came up with (minus most of the gory details of the actual processing I 
wanted to do:

************

def processDTML(self):
     """Process DTML documents within a folder."""
     import re
     myregex = re.compile(r"(<H1>.*?</H1>)")
     thisdoc = self.getFirstChild()
     while thisdoc is not None:
         if hasattr(thisdoc, 'meta_type'):
             if thisdoc.meta_type == 'DTML Document':
                 # Do processing stuff here
                 doctext = thisdoc.raw
                 doctext = myregex.sub(r"\1\n\n<H2>Profile</H2>\n", doctext)
                 thisdoc.raw = doctext
         thisdoc = thisdoc.getNextSibling()
     return 'Complete!'

************

Just for easy reference, this was what you came up with:


************

import re

def convert_dtml(self):
     """Convert DTML Methods and DTML Documents from old syntax to
        new syntax.
        Warning: recursive!
        This assumes that DTML Method and DTML Document haven't been
        subclassed.
     """
     print 'convert_dtml: id=%s' % self.title_and_id()
     if hasattr(self, 'meta_type') and \
           (self.meta_type == 'DTML Method' or \
            self.meta_type == 'DTML Document'):
         convert(self)

     # should this be "isPrincipiaFolderish"?
     if hasattr(self, 'isAnObjectManager') and self.isAnObjectManager:
         for v in self.objectValues():
             v.convert_dtml()

_convert_regex =
re.compile('''<!--#(/?)(([^"-]+?|"[^"]*?"|'[^']*?'|-[^-])+?)-->''')

def convert(dtml_item):
     print 'converting...'
     title = dtml_item.title
            # like document_src, but doesn't require RESPONSE
     data = dtml_item.PrincipiaSearchSource()
     print '----data----'
     print data
     newdata = _convert_regex.sub('<\g<1>dtml-\g<2>>', data)
     print '----newdata----'
     print newdata
     print '----end----'
     dtml_item.manage_edit(newdata, title)

************


Some questions I have in my mind:

1. I used "raw" and you used "PrincipiaSearchSource()" . The reason I used 
raw was because I wanted to be sure that what I got wasn't munged in any 
way, and that what I put back reflects what was actually there before.

2. You used the "manage_edit()" method, whereas I just assigned to the 
"raw" property. My way seems to work OK, but I'm not sure how yours works: 
I assume it brings up an edit page in the browser for each document?

3. I don't like resorting to testing the "meta_type" for a particular 
string value. As you noted in your code, it doesn't allow for subclassing, 
so it's not fully general.

4. I was surprised that the import statement (not to mention 
"re.compile()") could be put outside of the method definition, considering 
that Zope's external methods grab on to individual methods within a Python 
module.



David Trudgett