degal/html.py
author Tero Marttila <terom@fixme.fi>
Fri, 05 Jun 2009 23:59:14 +0300
changeset 77 2a53c5ade434
parent 76 e22d9f699081
child 78 d580323b4bfa
permissions -rw-r--r--
misc. fixes, it runs now, but HTML output is corrupt (no flattening)
52
3071d0709c4a start writing some kind of nested-HTML-tag-generators magic to use instead of templates :)
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     1
"""
61
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
     2
    Generating XHTML output
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
     3
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
     4
    XXX: use a 'real' XML builder?
52
3071d0709c4a start writing some kind of nested-HTML-tag-generators magic to use instead of templates :)
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     5
"""
3071d0709c4a start writing some kind of nested-HTML-tag-generators magic to use instead of templates :)
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     6
3071d0709c4a start writing some kind of nested-HTML-tag-generators magic to use instead of templates :)
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     7
from cgi import escape
53
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
     8
import itertools as _itertools
52
3071d0709c4a start writing some kind of nested-HTML-tag-generators magic to use instead of templates :)
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
     9
53
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    10
class IRenderable (object) :
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    11
    """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    12
        Something that's renderable as the contents of a HTML tag
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    13
    """
52
3071d0709c4a start writing some kind of nested-HTML-tag-generators magic to use instead of templates :)
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
    14
53
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    15
    def render_raw_lines (self, indent=u'\t') :
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    16
        """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    17
            Render the indented lines for tag and contents, without newlines
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    18
        """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    19
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    20
        abstract
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    21
61
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    22
    def render_lines (self, indent=u'\t', newline=u'\n') :
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    23
        """
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    24
            Render full output lines with given newlines
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    25
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    26
            >>> list(Tag('xx', 'yy').render_lines())
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    27
            [u'<xx>\\n', u'\\tyy\\n', u'</xx>\\n']
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    28
        """
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    29
77
2a53c5ade434 misc. fixes, it runs now, but HTML output is corrupt (no flattening)
Tero Marttila <terom@fixme.fi>
parents: 76
diff changeset
    30
        for line in self.render_raw_lines(indent=indent) :
61
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    31
            yield line + newline
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    32
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    33
    def render_unicode (self, **render_opts) :
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    34
        """
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    35
            Render full tag as a single unicode string
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    36
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    37
            >>> Tag('xx', 'yy').render_unicode()
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    38
            u'<xx>\\n\\tyy\\n</xx>\\n'
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    39
        """
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    40
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    41
        return "".join(self.render_lines(**render_opts))
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    42
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    43
    def render_str (self, encoding='ascii', **render_opts) :
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    44
        """
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    45
            Render full tag as an encoded string
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    46
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    47
            >>> Tag('xx', 'yy').render_str()
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    48
            '<xx>\\n\\tyy\\n</xx>\\n'
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    49
        """
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    50
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    51
        return self.render_unicode(**render_opts).encode(encoding)
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    52
69
5b53fe294034 add render_file method for html.IRenderable
Tero Marttila <terom@fixme.fi>
parents: 61
diff changeset
    53
    def render_out (self, stream, encoding=None, **render_opts) :
61
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    54
        """
69
5b53fe294034 add render_file method for html.IRenderable
Tero Marttila <terom@fixme.fi>
parents: 61
diff changeset
    55
            Render output into the given stream, encoding using the given encoding if given.
61
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    56
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    57
            >>> from StringIO import StringIO; buf = StringIO(); Tag('xx', 'yy').render_out(buf, 'ascii'); buf.getvalue()
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    58
            '<xx>\\n\\tyy\\n</xx>\\n'
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    59
        """
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    60
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    61
        for line in self.render_lines(**render_opts) :
69
5b53fe294034 add render_file method for html.IRenderable
Tero Marttila <terom@fixme.fi>
parents: 61
diff changeset
    62
            if encoding :
5b53fe294034 add render_file method for html.IRenderable
Tero Marttila <terom@fixme.fi>
parents: 61
diff changeset
    63
                line = line.encode(encoding)
5b53fe294034 add render_file method for html.IRenderable
Tero Marttila <terom@fixme.fi>
parents: 61
diff changeset
    64
5b53fe294034 add render_file method for html.IRenderable
Tero Marttila <terom@fixme.fi>
parents: 61
diff changeset
    65
            stream.write(line)
61
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    66
    
69
5b53fe294034 add render_file method for html.IRenderable
Tero Marttila <terom@fixme.fi>
parents: 61
diff changeset
    67
    def render_file (self, file, encoding=None, **render_opts) :
5b53fe294034 add render_file method for html.IRenderable
Tero Marttila <terom@fixme.fi>
parents: 61
diff changeset
    68
        """
5b53fe294034 add render_file method for html.IRenderable
Tero Marttila <terom@fixme.fi>
parents: 61
diff changeset
    69
            Render output to given file, overwriteing anything already there
5b53fe294034 add render_file method for html.IRenderable
Tero Marttila <terom@fixme.fi>
parents: 61
diff changeset
    70
        """
5b53fe294034 add render_file method for html.IRenderable
Tero Marttila <terom@fixme.fi>
parents: 61
diff changeset
    71
77
2a53c5ade434 misc. fixes, it runs now, but HTML output is corrupt (no flattening)
Tero Marttila <terom@fixme.fi>
parents: 76
diff changeset
    72
        self.render_out(file.open_write(encoding), **render_opts)
69
5b53fe294034 add render_file method for html.IRenderable
Tero Marttila <terom@fixme.fi>
parents: 61
diff changeset
    73
61
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    74
    # default output
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    75
    __str__ = render_str
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    76
    __unicode__ = render_unicode
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    77
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    78
    # default .render method
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    79
    render = render_unicode
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    80
53
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    81
class Tag (IRenderable) :
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    82
    """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    83
        A HTML tag, with attributes and contents, which can a mixture of data and other renderables(tags).
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    84
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    85
        Provides various kinds of rendering output
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    86
    """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    87
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    88
    @staticmethod
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    89
    def process_contents (contents) :
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    90
        """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    91
            Postprocess contents iterable to return new list.
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    92
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    93
            Items that are None will be omitted from the return value.
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    94
61
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    95
            XXX: flatten
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
    96
53
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    97
            >>> Tag.process_contents([])
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    98
            []
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
    99
            >>> Tag.process_contents([None])
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   100
            []
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   101
            >>> Tag.process_contents([u'foo'])
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   102
            [u'foo']
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   103
        """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   104
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   105
        return [c for c in contents if c is not None]
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   106
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   107
    @staticmethod
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   108
    def process_attrs (attrs) :
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   109
        """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   110
            Postprocess attributes.
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   111
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   112
            Key-value pairs where the value is None will be ommitted, and any trailing underscores in the key omitted.
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   113
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   114
            TODO: only remove one underscore
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   115
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   116
            >>> Tag.process_attrs(dict())
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   117
            {}
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   118
            >>> Tag.process_attrs(dict(foo='bar'))
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   119
            {'foo': 'bar'}
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   120
            >>> Tag.process_attrs(dict(class_='bar', frob=None))
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   121
            {'class': 'bar'}
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   122
        """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   123
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   124
        return dict((k.rstrip('_'), v) for k, v in attrs.iteritems() if v is not None)
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   125
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   126
    def __init__ (self, name, *contents, **attrs) :
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   127
        """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   128
            Construct tag with given name/attributes or contents.
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   129
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   130
            The filtering rules desribed in process_contents/process_attrs apply.
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   131
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   132
            >>> Tag('foo')
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   133
            Tag('foo')
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   134
            >>> Tag('foo', 'quux')
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   135
            Tag('foo', 'quux')
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   136
            >>> Tag('foo', 'quux', bar=5)
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   137
            Tag('foo', 'quux', bar=5)
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   138
            >>> Tag('foo', class_='ten')
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   139
            Tag('foo', class='ten')
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   140
        """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   141
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   142
        self.name = name
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   143
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   144
        # store filtered/processed versions
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   145
        self.contents = self.process_contents(contents)
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   146
        self.attrs = self.process_attrs(attrs)
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   147
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   148
    def __call__ (self, *contents, **attrs) :
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   149
        """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   150
            Return a new Tag with this tag's attributes and contents, as well as the given attributes/contents.
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   151
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   152
            The filtering rules desribed in process_contents/process_attrs apply.
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   153
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   154
            >>> Tag('foo')('bar')
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   155
            Tag('foo', 'bar')
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   156
            >>> Tag('a', href='index.html')("Home")
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   157
            Tag('a', 'Home', href='index.html')
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   158
            >>> Tag('bar', None)(5, foo=None, class_='bar')
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   159
            Tag('bar', 5, class='bar')
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   160
            >>> Tag('a')('b')('c')(asdf=5)
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   161
            Tag('a', 'b', 'c', asdf=5)
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   162
            >>> t1 = Tag('a'); t2 = t1('b'); t1
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   163
            Tag('a')
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   164
        """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   165
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   166
        # merge attrs/contents
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   167
        # XXX: new_attrs is not an iterator...
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   168
        new_attrs = dict(_itertools.chain(self.attrs.iteritems(), attrs.iteritems()))
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   169
        new_contents = _itertools.chain(self.contents, contents)
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   170
        
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   171
        # build new tag
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   172
        return Tag(self.name, *new_contents, **new_attrs)
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   173
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   174
    @staticmethod
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   175
    def format_attr (name, value) :
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   176
        """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   177
            Format a single HTML tag attribute
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   178
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   179
            >>> Tag.format_attr('name', 'value')
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   180
            u'name="value"'
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   181
            >>> Tag.format_attr('this', '<a"b>')
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   182
            u'this="&lt;a&quot;b&gt;"'
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   183
            >>> Tag.format_attr('xx', 1337)
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   184
            u'xx="1337"'
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   185
        """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   186
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   187
        return u'%s="%s"' % (name, escape(unicode(value), True))
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   188
 
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   189
    def render_attrs (self) :
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   190
        """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   191
            Return the HTML attributes string
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   192
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   193
            >>> Tag('x', foo=5, bar='<').render_attrs()
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   194
            u'foo="5" bar="&lt;"'
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   195
        """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   196
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   197
        return " ".join(self.format_attr(n, v) for n, v in self.attrs.iteritems())
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   198
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   199
    def render_contents (self, **render_opts) :
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   200
        """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   201
            Render the contents of the tag as a series of indented lines, with given render_lines options for subtags
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   202
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   203
            >>> list(Tag('x', 5).render_contents())
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   204
            [u'5']
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   205
            >>> list(Tag('x', 'line1', 'line2').render_contents())
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   206
            [u'line1', u'line2']
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   207
            >>> list(Tag('x', 'a', Tag('b', 'bb'), 'c').render_contents())
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   208
            [u'a', u'<b>', u'\\tbb', u'</b>', u'c']
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   209
        """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   210
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   211
        for content in self.contents :
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   212
            if isinstance(content, IRenderable) :
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   213
                # sub-tags
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   214
                for line in content.render_raw_lines(**render_opts) :
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   215
                    yield line
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   216
            
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   217
            else :
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   218
                # escape raw values
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   219
                yield escape(unicode(content))
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   220
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   221
    def render_raw_lines (self, indent=u'\t') :
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   222
        """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   223
            Render the tag and indented content
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   224
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   225
            >>> list(Tag('xx', 'yy', zz='foo').render_raw_lines(indent=' '))
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   226
            [u'<xx zz="foo">', u' yy', u'</xx>']
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   227
        """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   228
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   229
        # render attr string, including preceding space
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   230
        attrs_stuff = (" " + self.render_attrs()) if self.attrs else ""
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   231
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   232
        if self.contents :
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   233
            # tag with content
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   234
            yield u"<%s%s>" % (self.name, attrs_stuff)
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   235
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   236
            for line in self.render_contents(indent=indent) :
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   237
                yield indent + line
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   238
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   239
            yield u"</%s>" % (self.name, )
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   240
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   241
        else :
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   242
            # singleton tag
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   243
            yield u"<%s%s />" % (self.name, attrs_stuff)
52
3071d0709c4a start writing some kind of nested-HTML-tag-generators magic to use instead of templates :)
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   244
    
3071d0709c4a start writing some kind of nested-HTML-tag-generators magic to use instead of templates :)
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   245
53
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   246
    def __repr__ (self) :
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   247
        return 'Tag(%s)' % ', '.join(
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   248
            [
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   249
                repr(self.name)
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   250
            ] + [
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   251
                repr(c) for c in self.contents
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   252
            ] + [
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   253
                '%s=%r' % (name, value) for name, value in self.attrs.iteritems()
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   254
            ]
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   255
        )
52
3071d0709c4a start writing some kind of nested-HTML-tag-generators magic to use instead of templates :)
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   256
53
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   257
class Text (IRenderable) :
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   258
    """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   259
        Raw HTML text
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   260
    """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   261
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   262
    def __init__ (self, line) :
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   263
        """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   264
            Initialize to render as the given lines
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   265
        """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   266
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   267
        self.lines = [line]
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   268
    
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   269
    def render_raw_lines (self, indent=u'\t') :
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   270
        return self.lines
52
3071d0709c4a start writing some kind of nested-HTML-tag-generators magic to use instead of templates :)
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   271
61
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   272
class XHTMLDocument (IRenderable) :
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   273
    """
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   274
        <?xml version="..." encoding="..." ?>
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   275
        <!DOCTYPE ...>
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   276
        
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   277
        <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   278
            <head>
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   279
                ...
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   280
            </head>
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   281
            <body>
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   282
                ...
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   283
            </body>
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   284
        </html>
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   285
    """
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   286
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   287
    def __init__ (self, 
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   288
        head, body,
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   289
        xml_version='1.0', xml_encoding='utf-8', 
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   290
        doctype='html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"',
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   291
        html_xmlns='http://www.w3.org/1999/xhtml', html_lang='en'
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   292
    ) :
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   293
        # store
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   294
        self.xml_version = xml_version
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   295
        self.xml_encoding = xml_encoding
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   296
        self.doctype = doctype
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   297
        
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   298
        # build the document
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   299
        self.document = Tag('html', **{'xmlns': html_xmlns, 'xml:lang': html_lang})(
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   300
            Tag('head', head),
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   301
            Tag('body', body),
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   302
        )
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   303
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   304
    def render_raw_lines (self, **render_opts) :
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   305
        """
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   306
            Render the two header lines, and then the document
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   307
        """
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   308
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   309
        yield '<?xml version="%s" encoding="%s" ?>' % (self.xml_version, self.xml_encoding)
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   310
        yield '<!DOCTYPE %s>' % (self.doctype)
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   311
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   312
        for line in self.document.render_raw_lines(**render_opts) :
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   313
            yield line
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   314
    
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   315
    def _check_encoding (self, encoding) :
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   316
        if encoding and encoding != self.xml_encoding :
76
e22d9f699081 misc. fixes
Tero Marttila <terom@fixme.fi>
parents: 69
diff changeset
   317
            raise ValueError("encoding mismatch: %r should be %r" % (encoding, self.xml_encoding))
61
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   318
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   319
    def render_str (self, encoding=None, **render_opts) :
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   320
        """
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   321
            Wrap render_str to verify that the right encoding is used
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   322
        """
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   323
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   324
        self._check_encoding(encoding)
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   325
        
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   326
        return super(XHTMLDocument, self).render_str(self.xml_encoding, **render_opts)
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   327
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   328
    def render_out (self, stream, encoding=None, **render_opts) :
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   329
        """
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   330
            Wrap render_out to verify that the right encoding is used
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   331
        """
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   332
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   333
        self._check_encoding(encoding)
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   334
        
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   335
        return super(XHTMLDocument, self).render_out(stream, self.xml_encoding, **render_opts)
fad360dd01da rework html a bit to move the render_* funcs to IRenderable, add XHTMLDocument (ugh), missing flatten
Tero Marttila <terom@fixme.fi>
parents: 53
diff changeset
   336
52
3071d0709c4a start writing some kind of nested-HTML-tag-generators magic to use instead of templates :)
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   337
class TagFactory (object) :
3071d0709c4a start writing some kind of nested-HTML-tag-generators magic to use instead of templates :)
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   338
    """
53
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   339
        Build Tags with names give as attribute names
52
3071d0709c4a start writing some kind of nested-HTML-tag-generators magic to use instead of templates :)
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   340
    """
3071d0709c4a start writing some kind of nested-HTML-tag-generators magic to use instead of templates :)
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   341
53
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   342
    def __getattr__ (self, name) :
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   343
        """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   344
            Get a Tag object with the given name, but no contents
52
3071d0709c4a start writing some kind of nested-HTML-tag-generators magic to use instead of templates :)
Tero Marttila <terom@fixme.fi>
parents:
diff changeset
   345
53
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   346
            >>> TagFactory().a(href='bar')('quux')
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   347
            Tag('a', 'quux', href='bar')
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   348
        """
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   349
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   350
        return Tag(name)
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   351
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   352
# pretty names
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   353
tag = Tag
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   354
tags = TagFactory()
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   355
raw = Text
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   356
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   357
# testing
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   358
if __name__ == '__main__' :
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   359
    import doctest
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   360
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   361
    doctest.testmod()
14d73f544764 expressive HTML-rendering module with doctests
Tero Marttila <terom@fixme.fi>
parents: 52
diff changeset
   362