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