Newbie Class Questions
Peter Otten
__peter__ at web.de
Sun Mar 28 06:43:28 EST 2004
Ed Suominen wrote:
> I think it would be cool for my "AutoText" class (see below, hereby GPL'd)
> to be able to tell what subclasses inherit from it and instantiate objects
> for all of those subclasses to implement a "AutoAll" function.. Any ideas?
Not exactly what you asked for, but I have at least ensured that you can
combine AutoUrl and AutoEmphasis (and the yet to write AutoCamelCase) ad
libitum.
> Also, are there any comments on my use of "import" in the parent class?
It does not work the way you access the sre module in AutoUrl:
>>> class A:
... import sre
... def accessSre(self):
... try: sre
... except NameError: print "sre failed"
... try: A.sre
... except NameError: pass
... else: print "A.sre worked"
... try: self.sre
... except NameError: pass
... else: print "self.sre worked"
...
>>> A().accessSre()
sre failed
A.sre worked
self.sre worked
Frankly, I don't see the benefit of putting a module in a class instead of
the module namespace
> I have all of 3 days experience with OOP and Python, so please bear with
> me.
You are probably unreceptive to the fact that you could put the AutoXXX
functionality into plain old functions then...
> For a short while at least, the code is also available at
> http://rafb.net/paste/results/PyX42087.html
>
> Thanks,
> Ed Suominen
>
> ------------------------------------------------------------------------
> class AutoText(HTMLgen.RawText):
> """
> Implements Wiki-like markups of text, returning text in an RawText
> object
> to preserve any tags.
> """
> import sre
>
> def __init__(self, text):
> HTMLgen.RawText.__init__(self, text=text)
>
>
> class AutoUrl(AutoText):
> """
> Scans string (or string-like object) for urls and replaces them with
> lookalike links. Returns the text in an RawText object to preserve any
> tags. Passes keywords on to href except text and url.
> """
> def __init__(self, text='', **kw):
> text = str(text)
> for i in ['text', 'url']:
text can never appear in kw:
>>> class B:
... def __init__(self, text, **kw):
... pass
...
>>> B("abc", text="def")
Traceback (most recent call last):
File "<stdin>", line 1, in ?
TypeError: __init__() got multiple values for keyword argument 'text'
>>>
> if i in kw: del kw[i]
> while 1:
> m = sre.search('(\s+|\()(http://[a-zA-Z0-9\-\_\.\/\:\?\&]+)',
> text)
I recommend rawstrings like r'(\s+|\()(http://[a-zA-Z0-9\-\_\.\/\:\?\&]+)'
even if it works here without the r prefix.
> if m is None: break
> url = m.group(2).rstrip('.?')
> x = HTMLgen.Href(url=url, text=url, **kw)
> text = text.replace(url, str(x))
> AutoText.__init__(self, text)
>
>
> class AutoEmphasis(AutoText):
> """
> Scans string (or string-like object) for Wiki-type emphasis markups
> and replaces them with HTML markup. Returns the text in an RawText
> object to preserve any tags.
> """
> def __init__(self, text=''):
> text = str(text)
> for xy in [("""''""", 'Emphasis'), ("""'''""", 'Strong')]:
> while 1:
> m = sre.search('\s+'+xy[0]+'([^\'].+?)'+xy[0]+'\s+',text)
> if m is None: break
> x = eval('HTMLgen.'+xy[1]+'(\''+m.group(1)+'\')')
I think eval() should be spelt evil() so people think twice before resorting
to it.
> text = text.replace(xy[0]+m.group(1)+xy[0], str(x))
> AutoText.__init__(self, text)
Now for my variant:
<auto.py>
import HTMLgen, re
# for the super() mechanism to work we need to inherit from object.
# Just mixing it in seems to work.
class AutoText(HTMLgen.RawText, object):
def __init__(self, text, **kw):
HTMLgen.RawText.__init__(self, text=text)
class AutoUrl(AutoText):
def __init__(self, text, **kw):
# remove "url" key from kw; not clear why this is necessary
# an alternative might be
# assert "url" not in kw
kw.pop("url", None)
def replfunc(match):
url = match.group(2).rstrip('.?')
return match.group(1) + str(HTMLgen.Href(url=url, text=url,
**kw))
text = re.sub(r'(\s+|\()(http://[a-zA-Z0-9\-\_\.\/\:\?\&]+)',
replfunc, text)
super(AutoUrl, self).__init__(text, **kw)
class AutoEmphasis(AutoText):
def __init__(self, text, **kw):
for quote, Class in [("""''""", HTMLgen.Emphasis), ("""'''""",
HTMLgen.Strong)]:
while 1:
m = re.search(r'\s+('+quote+'([^\'].+?)'+quote+')\s+', text)
if m is None: break
x = Class(m.group(2))
text = text.replace(m.group(1), str(x))
super(AutoEmphasis, self).__init__(text, **kw)
class AutoAll(AutoEmphasis, AutoUrl):
pass
if __name__ == "__main__":
sample = """
'''foolish''' consciousness is ''the'' hobgobblin of
little minds, see http://www.hope-they-dont-exist.com
On ''second'' thought, another http://www.nonexistant-url.com
might be warranted.
"""
print AutoEmphasis(sample, target="another")
print AutoUrl(sample, target="another")
print AutoAll(sample, target="another")
</auto.py>
Random remarks:
I've left the regular expressions untouched as you seem to know more about
them than me. You might have a look a re.sub() as a means to replace the
while 1:
# make subsitutions
loops, though. See my AutoUrl variant for an example.
More people will try out your code if you provide a little driver like the
if __name__ == "__main__":
# demo code
above.
While I like your clear docstrings, they reveal that you have got the
concept of __init__() slightly wrong. It does not return an object (that's
what __new__() is for) but initializes it. Also, you generate AutoXXX
rather than RawText instances.
Peter
PS: auto.py is published under the industrial strength "ample usage
encouraged, so I can sue you later for an even larger pile of dough"
license :-)
More information about the Python-list
mailing list