Magic Method Recipe: HTML Generation

Step 2

Using the item and append functions makes for some ugly, verbose code. This time, you will implement the same functionality, except that this time you will take advantage of Python’s operators:

e = div(id='address') [
    p(id='line1') [ '1313 Grisly Drive' ],
    p(id='line2') [ 'Horrorville, IL 66666' ],
]

Implement the __call__ and __getitem__ magic methods.

import copy

class Tag(object):
    def __init__(self, name):
        self.name = name
        self.attrs = {}
        self.children = []

    def __call__(self, **kwargs):
        # Implement this method

    def __getitem__(self, children):
        # Implement this method

    def __str__(self):
        result = '<' + self.name
        if self.attrs:
            result += ' '
            result += ' '.join('%s="%s"' % item for item in self.attrs.items())
        if self.children:
            result += '>'
            result += ''.join(str(c) for c in self.children)
            result += '</%s>\n' % self.name
        else:
            result += ' />\n'
        return result

div = Tag('div')
img = Tag('img')
h1 = Tag('h1')
p = Tag('p')
a = Tag('a')

if __name__ == '__main__':
    print img(src='http://www.google.com/intl/en_ALL/images/logo.gif')

    e = div(id='address') [
        p(id='line1') [ '1313 Grisly Drive' ],
        p(id='line2') [ 'Horrorville, IL 66666' ],
    ]
    print e

Expected output:

<img src="http://www.google.com/intl/en_ALL/images/logo.gif" />

<div id="address"><p id="line1">1313 Grisly Drive</p>
<p id="line2">Horrorville, IL 66666</p>
</div>

Solution: solutions/html2.py

Go to next step