Overriding variables used by base classes

Bengt Richter bokr at oz.net
Fri Nov 14 18:24:40 EST 2003


On 14 Nov 2003 13:06:36 -0800, google_mail at aristoweb.net (Corey Lubin) wrote:

>It seems that in trying to present simple concept code, for the
>purpose of example, I forgot to mention some of the restrictions on
>what can be done. original.py is not of my own creation; it's a
>seperately maintained module, external to the project, and thus cannot
>be modified.
>
>For those that care to hear the full background/details of this
>problem: I make use of HTMLParser ("Original", from the example), but
>it's not resilient enough for real world pseudo-HTML, so I decided to
>modify it through extension. I've subclassed it (currently with no
>overriden methods, in an attempt to allow the subclass to benefit from
>changes to the base class) and attempted to override a global variable
>that the base class uses, however my approach doesn't work. In this
>case, "doesn't work" means that, in terms of my example, Tainted.foo
>uses original.someGlobal rather than tainted.someGlobal. This happens
>presumably because Tainted.foo is actually Original.foo (the foo
>method is inherited) and inherited methods apparently don't pay any
>mind to the namespace of their inheritors (take note that I'm not
>saying that they /should/; I haven't given any thought to that; I'm
>just saying that I expected this approach to work). This apparent
>failure in my approach leads me to think that eval/exec is my
>solution; I'm just hoping to hear that there is something more simple
>than that.
>
>My "import everything into this namespace and just modify what I need
>to" approach was my attempt at duplicating the original module (for
>miniature modification) without actually duplicating it's code (so
>that my modified version won't grow stale as the original module's
>code is updated by it's maintainer).
>
>Example translation guide (for those that feel the details make a
>diff.):
>original.py = HTMLParser.py
>original.someGlobal = HTMLParser.locatestarttagend (a regex object)
>original.Original.foo = HTMLParse.HTMLParser.check_for_whole_start_tag
>
>I hope this clears some things up.
>
Still not 100% sure what you're doing, but suppose that you wanted to get the
effect of modifying HTMLParser.py without modifying the original file, and be
able to proceed as if your modified file were "myHTMLParser.py".

I think you could make a small actual myHTMLParser.py that starts by _executing_
(not importing) the code of the original HTMLParser, and then just modfies the
result of that as desired. E.g., (untested beyond what you see below ;-)

==< myHTMLParser.py >======
import sys, os
origname = 'HTMLParser'
for lookdir in sys.path:
    path = os.path.join(lookdir, origname+'.py')
    print path
    if os.path.exists(path):
        print 'found', path
        break
else:
    raise ImportError,'Could not find "%s.py"' %origname
execfile(path, globals())

def demo(*args): print 'demo',args
locatestarttagend = demo
HTMLParser.check_for_whole_start_tag = demo
newglobal = 'new global'
===========================

Now, using it interactively:

 >>> import myHTMLParser as HTMLParser

(of course, you can take out the print statements that generated this printout...
 (BTW, since I blithely ignored the .zip in the path, this won't work for something in the zip file.)
 HTMLParser.py
 c:\pywk\HTMLParser.py
 C:\WINNT\System32\python23.zip\HTMLParser.py
 D:\python23\DLLs\HTMLParser.py
 D:\python23\lib\HTMLParser.py
 found D:\python23\lib\HTMLParser.py
)

Now we'll check our mods:

 >>> HTMLParser.newglobal
 'new global'

 >>> HTMLParser.locatestarttagend
 <function demo at 0x009587B0>
 >>> HTMLParser.locatestarttagend()
 demo ()

 >>> p = HTMLParser.HTMLParser()
 >>> p.check_for_whole_start_tag
 <bound method HTMLParser.demo of <myHTMLParser.HTMLParser instance at 0x00900828>>
 >>> p.check_for_whole_start_tag()
 demo (<myHTMLParser.HTMLParser instance at 0x00900828>,)

Maybe this gives some ideas? It's not a subclass/base class thing, but maybe it will
do what you need. Of course, you could subclass or rebind or whatever in the mod code
(which only executes when you import myHTMLParser, BTW).

Regards,
Bengt Richter




More information about the Python-list mailing list