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 -- Steve Alexander Software Engineer Cat-Box limited http://www.cat-box.net
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
Hi David, David Trudgett wrote:
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.
Sounds fair enough. I really shouldn't have used PrincipiaSearchSource(), as the method name doesn't reflect the function I wanted it to perform. The method read_raw() would have been more appropriate. However, my background developing Java applications programs causes me to favour calling methods to directly pulling in attributes. I *know* the Python idiom, but I'm not completely comfortable with it yet :-)
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?
My external method isn't returning anything, and isn't passing a REQUEST or a RESPONSE, so there is nothing returned to the browser at all. A better version of the external method would return a nicely formatted status message to the browser. The difference between setting "raw" directly and using manage_edit() is that the latter will parse and check the syntax of and save a cooked version of the DTML. As you just directly set the attribute "raw", you *might* find that your change aren't all reflected in the operation of the methods you've changed. However, as you've only changed some HTML formatting, this shouldn't be a problem with what you've done as yet. Using manage_edit() will also alert you to invalid syntax in your changed version by raising a ParseError, that will be visible in the browser. If there are additional triggers in a class to get it recatalogued in various special ways, these might only be triggered from methods like manage_edit(), whereas setting an attribute will only trigger standard catalogue awareness.
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.
I agree somewhat. However, I think that testing the meta_type is the most Zope-friendly way to do it :-) For example, in a pathological case, I could write a Python class in a Product that ostensibly inherits from DTML Method, but completely changes the way the attribute "raw" is used.
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.
Think about the way Python loads in functions and classes: the file gets read into the interpreter, and statements get executed (which runs them), whilst function definitions get executed (which causes their definitions to appear in the namespace somewhere). -- Steve Alexander Software Engineer Cat-Box limited http://www.cat-box.net
David Trudgett wrote:
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?
I just tried running my external method to convert DTML methods and documents from old-style to new-style. I ran it on the QuickStart tree of a fresh install of Zope 2.2.x, from CVS. Interestingly, because I'm calling manage_edit() rather than just setting the "raw" attribute, I was alerted that my external method doesn't cover all the possible ways of writing old-style DTML. Specifically, it stopped with an error on this method: ----end---- convert_dtml: id=dtcTemplate converting... ----data---- <!--#var standard_html_header--> <!--#in expr="_.namespace(standard_html_header='', standard_html_footer='')"--> <!--#var dtContent--> <!--#endin--> <HR> <!--#var standard_html_footer--> ----newdata---- <dtml-var standard_html_header> <dtml-in expr="_.namespace(standard_html_header='', standard_html_footer='')"> <dtml-var dtContent> <dtml-endin> <HR> <dtml-var standard_html_footer> ----end---- The error is "Unexpected tag, for tag <dtml-endin>". Is the old syntax <!--#end...--> equivalent to <!--#/...--> ? If so, it isn't documented in the current DTML Reference, and my regular expression should be changed to accommodate it. -- Steve Alexander Software Engineer Cat-Box limited http://www.cat-box.net
participants (2)
-
David Trudgett -
Steve Alexander