Re: [Zope-dev] A Modest Proposal Concerning Monkey Patches
On Tue Aug 13, 2002, Jim Penny wrote:
There is a large problem looming with Moneky Patches. The problem is that monkey patches are so Highlander. "There can be Only One".
For example, there are at least five or six products that monkey patch manage_main. Each simply replaces whatever manage_main exists at the time of instantation, and blows away any previous monkey patch. Some coordinated way of dealing with this problem needs to be arrived at.
And if you upgrade Zope, the patched version of manage_main will discard any changes made in the new version of Zope.
Proposal:
[ideas on how to check for previous changes and what to do about it] Here is a more surgical option for small changes: Instead of indiscriminately replacing the whole function or method, decompile and look for and replace only that part of the code that you want to change. In that way, as long as that part of the code remains valid between versions, the change probably remains valid, and you apply it. If you can't find the part of the code that you want to change, then some other change you are not aware of happened, so do not apply your change. I use decompyle and re to do the work. Here is an example: -- code snippet from my site monkey patch product -- from decompyle import decompyle import re import cStringIO # ------------- # 'Fix' dtml-in so previous-sequence and next-sequence are # available everywhere in the batch from DocumentTemplate.DT_In import InClass tochangeF = cStringIO.StringIO() decompyle(InClass.renderwb.im_func.func_code,out=tochangeF) tochange = tochangeF.getvalue() tochangeF.close() # The change is to remove the if index == first | last conditions print 'Changing dtml-in to provide previous and next sequence everywhere in the batch' tochange,num = re.subn(r"if\s+\(index\s*==\s*(first|last)\):\s*pkw\['(previous|next)-se quence'\]\s*=\s*1", r"pkw['\2-sequence'] = 1\n",tochange) if num == 2: print 'Success' # Replacement seemed successful, so go ahead and make the swap exec 'def renderwb(self,md):\n ' + tochange.replace('\n','\n ')[:-4] InClass.renderwb = renderwb else: print 'Was expected to make 2 changes, got %s. Check the DT_In code' % num -- end code snippet -- Of course, some monkey patches are so incompatible that even that approach might not work or produce unexpected results. Cheers, Jean
On Tuesday 13 August 2002 02:10 pm, jlagarde@bigfoot.com wrote:
On Tue Aug 13, 2002, Jim Penny wrote:
There is a large problem looming with Moneky Patches. The problem is that monkey patches are so Highlander. "There can be Only One".
For example, there are at least five or six products that monkey patch manage_main. Each simply replaces whatever manage_main exists at the time of instantation, and blows away any previous monkey patch. Some coordinated way of dealing with this problem needs to be arrived at.
And if you upgrade Zope, the patched version of manage_main will discard any changes made in the new version of Zope.
That is why it would be beneficial to make the thing being patched extensible in the first place thereby alleviating the need to patch it.
Proposal: [ideas on how to check for previous changes and what to do about it]
Here is a more surgical option for small changes: Instead of indiscriminately replacing the whole function or method, decompile and look for and replace only that part of the code that you want to change. In that way, as long as that part of the code remains valid between versions, the change probably remains valid, and you apply it. If you can't find the part of the code that you want to change, then some other change you are not aware of happened, so do not apply your change. I use decompyle and re to do the work. Here is an example:
[snip example] I thought about an approach like this, but I think it is susceptible to subtle bugs. It is very hard to predict the interaction of products independently changing the same template. As a product author, trying to support such a thing is not very attractive. I would prefer to make the template itself more flexible then try to jam new code into it sideways at run-time. -Casey
On Tue, 13 Aug 2002, Casey Duncan wrote:
That is why it would be beneficial to make the thing being patched extensible in the first place thereby alleviating the need to patch it.
This is a very good point. Now that we have comitters outside zope corp, Product authors probably ought to think of this as an opportunity to refactor the base zope code. In other words, if you need to monkey patch, instead refactor the code so that there's a hook you can use, and submit the patch for inclusion in the next version of zope. Then you can monkey patch if you need to make your product work with the current zope version, but you won't have to worry about upgrade issues. --RDM
participants (3)
-
Casey Duncan -
jlagardeï¼ bigfoot.com -
R. David Murray