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