Parse the parameters from a block signature .

def parse_params(self, parameters, clear=None, align_type='block'):
        """Parse the parameters from a block signature.

        This function parses the parameters from a block signature,
        splitting the information about class, id, language and
        style. The positioning (indentation and alignment) is parsed
        and stored in the style.

        A paragraph like:

            p>(class#id){color:red}[en]. Paragraph.

        or:

            p{color:red}[en](class#id)>. Paragraph.

        will have its parameters parsed to:

            output = {'lang' : 'en',
                      'class': 'class',
                      'id'   : 'id',
                      'style': 'color:red;text-align:right;'}

        Note that order is not important.
        """
        if not parameters:
            if clear:
                return {'style': clear}
            else:
                return {}

        output = {}

        # Match class from (class) or (class#id).
        m = re.search(r'''\((?P<class>[\w]+(\s[\w]+)*)(\#[\w]+)?\)''', parameters)
        if m: output['class'] = m.group('class')

        # Match id from (#id) or (class#id).
        m = re.search(r'''\([\w]*(\s[\w]+)*\#(?P<id>[\w]+)\)''', parameters)
        if m: output['id'] = m.group('id')

        # Match [language].
        m = re.search(r'''\[(?P<lang>[\w-]+)\]''', parameters)
        if m: output['lang'] = m.group('lang')

        # Match {style}.
        m = re.search(r'''{(?P<style>[^\}]+)}''', parameters)
        if m:
            output['style'] = m.group('style').replace('\n', '')

            # If necessary, apppend a semi-comma to the style.
            if not output['style'].endswith(';'):
                output['style'] += ';'

        # Clear the block?
        if clear:
            output['style'] = output.get('style', '') + clear

        # Remove classes, ids, langs and styles. This makes the
        # regular expression for the positioning much easier.
        parameters = preg_replace(r'''\([\#\w\s]+\)''', '', parameters)
        parameters = preg_replace(r'''\[[\w-]+\]''', '', parameters)
        parameters = preg_replace(r'''{[\w:;#%-]+}''', '', parameters)

        style = []

        # Count the left indentation.
        l_indent = parameters.count('(')
        if l_indent: style.append('padding-left:%dem;' % l_indent)

        # Count the right indentation.
        r_indent = parameters.count(')')
        if r_indent: style.append('padding-right:%dem;' % r_indent)

        # Add alignment.
        if align_type == 'image':
            align = [('<', 'float:left;', ' left'),
                     ('>', 'float:right;', ' right')]

            valign = [('^', 'vertical-align:text-top;', ' top'),
                      ('-', 'vertical-align:middle;', ' middle'),
                      ('~', 'vertical-align:text-bottom;', ' bottom')]

            # Images can have both a vertical and a horizontal alignment.
            for alignments in [align, valign]:
                for _align, _style, _class in alignments:
                    if parameters.count(_align):
                        style.append(_style)

                        # Append a class name related to the alignment.
                        output['class'] = output.get('class', '') + _class
                        break

        elif align_type == 'table':
            align = [('<', 'left'),
                     ('>', 'right'),
                     ('=', 'center'),
                     ('<>', 'justify')]

            valign = [('^', 'top'),
                      ('~', 'bottom')]

            # Horizontal alignment.
            for _align, _style, in align:
                if parameters.count(_align):
                    output['align'] = _style

            # Vertical alignment.
            for _align, _style, in valign:
                if parameters.count(_align):
                    output['valign'] = _style

            # Colspan and rowspan.
            m = re.search(r'''\\(\d+)''', parameters)
            if m:
                #output['colspan'] = m.groups()
                output['colspan'] = int(m.groups()[0])

            m = re.search(r'''/(\d+)''', parameters)
            if m:
                output['rowspan'] = int(m.groups()[0])

        else:
            if l_indent or r_indent:
                alignments = [('<>', 'text-align:justify;', ' justify'),
                              ('=', 'text-align:center;', ' center'),
                              ('<', 'float:left;', ' left'),
                              ('>', 'float:right;', ' right')]
            else:
                alignments = [('<>', 'text-align:justify;', ' justify'),
                              ('=', 'text-align:center;', ' center'),
                              ('<', 'text-align:left;', ' left'),
                              ('>', 'text-align:right;', ' right')]

            for _align, _style, _class in alignments:
                if parameters.count(_align):
                    style.append(_style)

                    # Append a class name related to the alignment.
                    output['class'] = output.get('class', '') + _class
                    break

        # Join all the styles.
        output['style'] = output.get('style', '') + ''.join(style)

        # Remove excess whitespace.
        if output.has_key('class'):
            output['class'] = output['class'].strip()

        return output


Build the open tag with specified attributes .

def build_open_tag(self, tag, attributes={}, single=0):
        """Build the open tag with specified attributes.

        This function is used by all block builders to
        generate the opening tags with the attributes of
        the block.
        """
        # Open tag.
        open_tag = ['<%s' % tag]
        for k,v in attributes.items():
            # The ALT attribute can be empty.
            if k == 'alt' or v: open_tag.append(' %s="%s"' % (k, v))

        if single:
            open_tag.append(' /')

        # Close tag.
        open_tag.append('>')

        return ''.join(open_tag)

def
build_open_tag
(
self
,
tag
,
attributes
=
{
}
,
single
=
0
)
:
# Open tag.
open_tag
=
[
'<%s'
%
tag
]
for
k
,
v
in
attributes
.
items
(
)
:
# The ALT attribute can be empty.
if
k
==
'alt'
or
v
:
open_tag
.
append
(
' %s="%s"'
%
(
k
,
v
)
)
if
single
:
open_tag
.
append
(
' /'
)
# Close tag.
open_tag
.
append
(
'>'
)
return
''
.
join
(
open_tag
)


def paragraph(self, text, parameters=None, attributes=None, clear=None):
        """Process a paragraph.

        This function processes the paragraphs, enclosing the text in a

 tag and breaking lines with
. Paragraphs are formatted
        with all the inline rules.

        ---
        h1. Paragraph

        This is how you write a paragraph:

        pre. p. This is a paragraph, although a short one.

        Since the paragraph is the default block, you can safely omit its
        signature ([@p@]). Simply write:

        pre. This is a paragraph, although a short one.

        Text in a paragraph block is wrapped in @

@ tags, and
        newlines receive a
 tag. In both cases Textile will process
        the text to:

        pre.
This is a paragraph, although a short one.

        Text in a paragraph block is processed with all the inline rules.
        """
        # Split the lines.
        lines = re.split('\n{2,}', text)

        # Get the attributes.
        attributes = attributes or self.parse_params(parameters, clear)

        output = []
        for line in lines:
            if line:
                # Clean the line.
                line = line.strip()

                # Build the tag.
                open_tag = self.build_open_tag('p', attributes)
                close_tag = '
'

                # Pop the id because it must be unique.
                if attributes.has_key('id'): del attributes['id']

                # Break lines.
                line = preg_replace(r'(
|\n)+', '
\n', line)

                # Remove
 from inside broken HTML tags.
                line = preg_replace(r'(<[^>]*)
\n(.*?>)', r'\1 \2', line)

                # Inline formatting.
                line = self.inline(line)

                output.append(open_tag + line + close_tag)

        return '\n\n'.join(output)

# Remove <br /> from inside broken HTML tags.


Process pre-formatted text.

        This function processes pre-formatted text into a <pre> tag.
        No HTML is added for the lines, but @<@ and @>@ are translated into
        HTML entities.

        ---
        h1. Pre-formatted text

        Pre-formatted text can be specified using the @pre@ signature.
        Inside a "pre" block, whitespace is preserved and @<@ and @>@ are
        translated into HTML(HyperText Markup Language) entities
        automatically.

        Text in a "pre" block is _not processed_ with any inline rule.

        Here's a simple example:

        pre. pre. This text is pre-formatted.
        Nothing interesting happens inside here...

        Will become:

        pre. <pre>
        This text is pre-formatted.
        Nothing interesting happens inside here...
        </pre>

def pre(self, text, parameters=None, clear=None):
        """Process pre-formatted text.

        This function processes pre-formatted text into a
 tag.
        No HTML is added for the lines, but @<@ and @>@ are translated into
        HTML entities.

        ---
        h1. Pre-formatted text

        Pre-formatted text can be specified using the @pre@ signature.
        Inside a "pre" block, whitespace is preserved and @<@ and @>@ are
        translated into HTML(HyperText Markup Language) entities
        automatically.

        Text in a "pre" block is _not processed_ with any inline rule.

        Here's a simple example:

        pre. pre. This text is pre-formatted.
        Nothing interesting happens inside here...

        Will become:

        pre.

        This text is pre-formatted.
        Nothing interesting happens inside here...

        """

        # Remove trailing whitespace.
        text = text.rstrip()

        # Get the attributes.
        attributes = self.parse_params(parameters, clear)

        # Build the tag.
        #open_tag = self.build_open_tag('pre', attributes) + '\n'
        open_tag = self.build_open_tag('pre', attributes)
        close_tag = '\n
'

        # Replace < and >.
        text = text.replace('<', '<')
        text = text.replace('>', '>')

        return open_tag + text + close_tag


def bc(self, text, parameters=None, clear=None):
        """Process block code.

        This function processes block code into a  tag inside a

. No HTML is added for the lines, but @<@ and @>@ are translated
        into HTML entities.

        ---
        h1. Block code

        A block code, specified by the @bc@ signature, is a block of
        pre-formatted text which also receives a @@ tag. As
        with "pre", whitespace is preserved and @<@ and @>@ are translated
        into HTML(HyperText Markup Language) entities automatically.

        Text in a "bc" code is _not processed_ with the inline rules.

        If you have "Twisted":http://www.twistedmatrix.com/ installed,
        Textile can automatically colorize your Python code if you
        specify its language as "Python":

        pre. bc[python]. from twisted.python import htmlizer

        This will become:

        pre.

        from twisted.python import htmlizer

        The colors can be specified in your CSS(Cascading Style Sheets)
        file. If you don't want to install Twisted, you can download just
        the @htmlizer@ module "independently":http://dealmeida.net/code/htmlizer.py.txt.
        """

        # Get the attributes.
        attributes = self.parse_params(parameters, clear)

        # XHTML  can't have the attribute lang.
        if attributes.has_key('lang'):
            lang = attributes['lang']
            del attributes['lang']
        else:
            lang = None

        # Build the tag.
        open_tag = '
\n' + self.build_open_tag('code', attributes) + '\n'
        close_tag = '\n\n
'

        # Colorize Python code?
        if htmlizer and lang == 'python':
            text = _color(text)
        else:
            # Replace < and >.
            text = text.replace('<', '<')
            text = text.replace('>', '>')

        return open_tag + text + close_tag

# XHTML <code> can't have the attribute lang.


def dl(self, text, parameters=None, clear=None):
        """Process definition list.

        This function process definition lists. The text inside
        the
 and
 tags is processed for inline formatting.

        ---
        h1. Definition list

        A definition list starts with the signature @dl@, and has
        its items separated by a @:@. Here's a simple example:

        pre. dl. name:Sir Lancelot of Camelot.
        quest:To seek the Holy Grail.
        color:Blue.

        Becomes:

        pre.

name

Sir Lancelot of Camelot.

quest

To seek the Holy Grail.

color

Blue.

        """
        # Get the attributes.
        attributes = self.parse_params(parameters, clear)

        # Build the tag.
        open_tag = self.build_open_tag('dl', attributes) + '\n'
        close_tag = '\n
'

        lines = text.split('\n')
        output = []
        for line in lines:
            if line.count(':'):
                [dt, dd] = line.split(':', 1)
            else:
                dt,dd = line, ''

            if dt: output.append('
%s
\n
%s
' % (dt, dd))

        text = '\n'.join(output)

        text = self.inline(text)

        return open_tag + text + close_tag

def
dl
(
self
,
text
,
parameters
=
,
clear
=
)
:
# Get the attributes.
attributes
=
self
.
parse_params
(
parameters
,
clear
)
# Build the tag.
open_tag
=
self
.
build_open_tag
(
'dl'
,
attributes
)
+
'\n'
close_tag
=
'\n
'
lines
=
text
.
split
(
'\n'
)
output
=
[
]
for
line
in
lines
:
if
line
.
count
(
':'
)
:
[
dt
,
dd
]
=
line
.
split
(
':'
,
1
)
else
:
dt
,
dd
=
line
,
''
if
dt
:
output
.
append
(
'
%s
\n
%s
'
%
(
dt
,
dd
)
)
text
=
'\n'
.
join
(
output
)
text
=
self
.
inline
(
text
)
return
open_tag
+
text
+
close_tag


def blockquote(self, text, parameters=None, cite=None, clear=None):
        """Process block quote.

        The block quote is inserted into a
 tag, and
        processed as a paragraph. An optional cite attribute can
        be appended on the last line after two dashes (--), or
        after the period following ':' for compatibility with the
        Perl version.

        ---
        h1. Blockquote

        A blockquote is denoted by the signature @bq@. The text in this
        block will be enclosed in @

@ and @

@,
        receiving the same formatting as a paragraph. For example:

        pre. bq. This is a blockquote.

        Becomes:

        pre.

This is a blockquote.

        You can optionally specify the @cite@ attribute of the blockquote,
        using the following syntax:

        pre. bq.:http://example.com Some text.

        pre. bq.:"John Doe" Some other text.

        Becomes:

        pre.

Some text.

        pre.

Some other text.

        You can also specify the @cite@ using a pair of dashes on the
        last line of the blockquote:

        pre. bq. Some text.
        -- http://example.com
        """

        # Get the attributes.
        attributes = self.parse_params(parameters, clear)

        if cite:
            # Remove the quotes?
            cite = cite.strip('"')
            attributes['cite'] = cite
        else:
            # The citation should be on the last line.
            text = text.split('\n')
            if text[-1].startswith('-- '):
                attributes['cite'] = text.pop()[3:]

            text = '\n'.join(text)

        # Build the tag.
        open_tag = self.build_open_tag('blockquote', attributes) + '\n'
        close_tag = '\n
'

        # Process the paragraph, passing the attributes.
        # Does it make sense to pass the id, class, etc. to
        # the paragraph instead of applying it to the
        # blockquote tag?
        text = self.paragraph(text)

        return open_tag + text + close_tag


def header(self, text, parameters=None, header=1, clear=None):
        """Process a header.

        The header number is captured by the regular
        expression and lives in header. If head_offset is
        set, it is adjusted accordingly.

        ---
        h1. Header

        A header is produced by the signature @hn@, where @n@ goes
        from 1 to 6. You can adjust the relative output of the headers
        passing a @head_offset@ attribute when calling @textile()@.

        To make a header:

        pre. h1. This is a header.

        Becomes:

        pre.
This is a header.

        """
        # Get the attributes.
        attributes = self.parse_params(parameters, clear)

        # Get the header number and limit it between 1 and 6.
        n = header
        n = min(n,6)
        n = max(n,1)

        # Build the tag.
        open_tag = self.build_open_tag('h%d' % n, attributes)
        close_tag = '</h%d>' % n

        text = self.inline(text)

        return open_tag + text + close_tag


def footnote(self, text, parameters=None, footnote=1, clear=None):
        """Process a footnote.

        A footnote is formatted as a paragraph of class
        'footnote' and id 'fn%d', starting with the footnote
        number in a  tag. Here we just build the
        attributes and pass them directly to self.paragraph().

        ---
        h1. Footnote

        A footnote is produced by the signature @fn@ followed by
        a number. Footnotes are paragraphs of a special CSS(Cascading Style Sheets)
        class. An example:

        pre. fn1. This is footnote number one.

        Will produce this:

        pre.
1 This is footnote number one.

        This footnote can be referenced anywhere on the text by the
        following way:

        pre. This is a reference[1] to footnote number one.

        Which becomes:

        pre.
This is a reference1 to footnote number 1.

        Note that the text from the footnote appears in the @title@ of the
        link pointing to it.
        """
        # Get the number.
        n = int(footnote)

        # Build the attributes to the paragraph.
        attributes = self.parse_params(parameters, clear)
        attributes['class'] = 'footnote'
        attributes['id']    = 'fn%d' % n

        # Build the paragraph text.
        text = ('%d ' % n) + text

        # And return the paragraph.
        return self.paragraph(text=text, attributes=attributes)


def build_li(self, items, liattributes):
        """Build the list item.

        This function build the list item of an (un)ordered list. It
        works by peeking at the next list item, and searching for a
        multi-list. If a multi-list is found, it is processed and
        appended inside the list item tags, as it should be.
        """
        lines = []
        while len(items):
            item = items.pop(0)

            # Clean the line.
            item = item.lstrip()
            item = item.replace('\n', '
\n')

            # Get list item attributes.
            p = re.compile(r'''^%(liattr)s\s''' % self.res, re.VERBOSE)
            m = p.match(item)
            if m:
                c = m.groupdict('')
                liparameters = c['liparameters']
                item = p.sub('', item)
            else:
                liparameters = ''

            liattributes = liattributes or self.parse_params(liparameters)

            # Build the item tag.
            open_tag_li = self.build_open_tag('li', liattributes)

            # Reset the attributes, which should be applied
            # only to the first
.
            liattributes = {}

            # Build the closing tag.
            close_tag_li = '
'

            # Multi-list recursive routine.
            # Here we check the _next_ items for a multi-list. If we
            # find one, we extract all items of the multi-list and
            # process them recursively.
            if len(items):
                inlist = []

                # Grab all the items that start with # or *.
                n_item = items.pop(0)

                # Grab the
 parameters.
                p = re.compile(r'''^%(olattr)s''' % self.res, re.VERBOSE)
                m = p.match(n_item)
                if m:
                    c = m.groupdict('')
                    olparameters = c['olparameters']
                    tmp = p.sub('', n_item)
                else:
                    olparameters = ''

                # Check for an ordered list inside this one.
                if tmp.startswith('#'):
                    n_item = tmp
                    inlist.append(n_item)
                    while len(items):
                        # Peek into the next item.
                        n_item = items.pop(0)
                        if n_item.startswith('#'):
                            inlist.append(n_item)
                        else:
                            items.insert(0, n_item)
                            break

                    inlist = self.ol('\n'.join(inlist), olparameters=olparameters)
                    item = item + '\n' + inlist + '\n'

                # Check for an unordered list inside this one.
                elif tmp.startswith('*'):
                    n_item = tmp
                    inlist.append(n_item)
                    while len(items):
                        # Peek into the next item.
                        n_item = items.pop(0)
                        if n_item.startswith('*'):
                            inlist.append(n_item)
                        else:
                            items.insert(0, n_item)
                            break

                    inlist = self.ul('\n'.join(inlist), olparameters=olparameters)
                    item = item + '\n' + inlist + '\n'

                # Otherwise we just put it back in the list.
                else:
                    items.insert(0, n_item)

            item = self.inline(item)

            item = open_tag_li + item + close_tag_li
            lines.append(item)

        return '\n'.join(lines)


def ol(self, text, liparameters=None, olparameters=None, clear=None):
        """Build an ordered list.

        This function basically just sets the

 with the
        right attributes, and then pass everything inside to
        _build_li, which does the real tough recursive job.

        ---
        h1. Ordered lists

        Ordered lists can be constructed this way:

        pre. # Item number 1.
        # Item number 2.
        # Item number 3.

        And you get:

        pre.

Item number 1.

Item number 2.

Item number 3.

        If you want a list to "break" an extended block, you should
        add a period after the hash. This is useful for writing
        Python code:

        pre.. bc[python].. #!/usr/bin/env python

        # This is a comment, not an ordered list!
        # So this won't break the extended "bc".

        p. Lists can be nested:

        pre. # Item number 1.
        ## Item number 1a.
        ## Item number 1b.
        # Item number 2.
        ## Item number 2a.

        Textile will transform this to:

        pre.

Item number 1.

Item number 1a.

Item number 1b.

Item number 2.

Item number 2a.

        You can also mix ordered and unordered lists:

        pre. * To write well you need:
        *# to read every day
        *# to write every day
        *# and X

        You'll get this:

        pre.

To write well you need:

to read every day

to write every day

and X

        To style a list, the parameters should go before the hash if you want
        to set the attributes on the @
@ tag:

        pre. (class#id)# one
        # two
        # three

        If you want to customize the firsr @
@ tag, apply the parameters
        after the hash:

        pre. #(class#id) one
        # two
        # three
        """
        # Get the attributes.
        olattributes = self.parse_params(olparameters, clear)
        liattributes = self.parse_params(liparameters)

        # Remove list depth.
        if text.startswith('#'):
            text = text[1:]

        items = text.split('\n#')

        # Build the open tag.
        open_tag = self.build_open_tag('ol', olattributes) + '\n'

        close_tag = '\n
'

        # Build the list items.
        text = self.build_li(items, liattributes)

        return open_tag + text + close_tag

def
ol
(
self
,
text
,
liparameters
=
,
olparameters
=
,
clear
=
)
:
# Get the attributes.
olattributes
=
self
.
parse_params
(
olparameters
,
clear
)
liattributes
=
self
.
parse_params
(
liparameters
)
# Remove list depth.
if
text
.
startswith
(
'#'
)
:
text
=
text
[
1
:
]
items
=
text
.
split
(
'\n#'
)
# Build the open tag.
open_tag
=
self
.
build_open_tag
(
'ol'
,
olattributes
)
+
'\n'
close_tag
=
'\n</ol>'
# Build the list items.
text
=
self
.
build_li
(
items
,
liattributes
)
return
open_tag
+
text
+
close_tag


def ul(self, text, liparameters=None, olparameters=None, clear=None):
        """Build an unordered list.

        This function basically just sets the

 with the
        right attributes, and then pass everything inside to
        _build_li, which does the real tough recursive job.

        ---
        h1. Unordered lists

        Unordered lists behave exactly like the ordered lists, and are
        defined using a star:

        pre. * Python
        * Perl
        * PHP

        Becomes:

        pre.

Python

Perl

PHP

        """
        # Get the attributes.
        olattributes = self.parse_params(olparameters, clear)
        liattributes = self.parse_params(liparameters)

        # Remove list depth.
        if text.startswith('*'):
            text = text[1:]

        items = text.split('\n*')

        # Build the open tag.
        open_tag = self.build_open_tag('ul', olattributes) + '\n'

        close_tag = '\n
'

        # Build the list items.
        text = self.build_li(items, liattributes)

        return open_tag + text + close_tag

def
ul
(
self
,
text
,
liparameters
=
,
olparameters
=
,
clear
=
)
:
# Get the attributes.
olattributes
=
self
.
parse_params
(
olparameters
,
clear
)
liattributes
=
self
.
parse_params
(
liparameters
)
# Remove list depth.
if
text
.
startswith
(
'*'
)
:
text
=
text
[
1
:
]
items
=
text
.
split
(
'\n*'
)
# Build the open tag.
open_tag
=
self
.
build_open_tag
(
'ul'
,
olattributes
)
+
'\n'
close_tag
=
'\n</ul>'
# Build the list items.
text
=
self
.
build_li
(
items
,
liattributes
)
return
open_tag
+
text
+
close_tag


def table(self, text, parameters=None, clear=None):
        """Build a table.

        To build a table we split the text in lines to get the
        rows, and split the rows between '|' to get the individual
        cells.

        ---
        h1. Tables

        Making a simple table is as easy as possible:

        pre. |a|b|c|
        |1|2|3|

        Will be processed into:

        pre.

        a
        b
        c

        1
        2
        3

        If you want to customize the @
@ tag, you must use the
        @table@ signature:

        pre. table(class#id)[en]. |a|b|c|
        |1|2|3|

        To customize a row, apply the modifier _before_ the first @|@:

        pre. table. (class)<>|a|b|c|
        |1|2|3|

        Individual cells can by customized by adding the parameters _after_
        the @|@, proceded by a period and a space:

        pre. |(#id). a|b|c|
        |1|2|3|

        The allowed modifiers are:

        dl. {style rule}:A CSS(Cascading Style Sheets) style rule.
        (class) or (#id) or (class#id):A CSS(Cascading Style Sheets) class and/or id attribute.
        ( (one or more):Adds 1em of padding to the left for each '(' character.
        ) (one or more):Adds 1em of padding to the right for each ')' character.
        <:Aligns to the left (floats to left for tables if combined with the ')' modifier).
        >:Aligns to the right (floats to right for tables if combined with the '(' modifier).
        =:Aligns to center (sets left, right margins to 'auto' for tables).
        <>:For cells only. Justifies text.
        ^:For rows and cells only. Aligns to the top.
        ~ (tilde):For rows and cells only. Aligns to the bottom.
        _ (underscore):Can be applied to a table row or cell to indicate a header row or cell.
        \\2 or \\3 or \\4, etc.:Used within cells to indicate a colspan of 2, 3, 4, etc. columns. When you see "\\", think "push forward".
        /2 or /3 or /4, etc.:Used within cells to indicate a rowspan of 2, 3, 4, etc. rows. When you see "/", think "push downward".

        When a cell is identified as a header cell and an alignment is
        specified, that becomes the default alignment for cells below it.
        You can always override this behavior by specifying an alignment
        for one of the lower cells.
        """
        attributes = self.parse_params(parameters, clear, align_type='table')
        #attributes['cellspacing'] = '0'

        # Build the
.
        open_tag = self.build_open_tag('table', attributes) + '\n'
        close_tag = '
'

        output = []
        default_align = {}
        rows = re.split(r'''\n+''', text)
        for row in rows:
            # Get the columns.
            columns = row.split('|')

            # Build the
.
            parameters = columns.pop(0)

            rowattr = self.parse_params(parameters, align_type='table')
            open_tr = self.build_open_tag('tr', rowattr) + '\n'
            output.append(open_tr)

            # Does the row define headers?
            if parameters.count('_'):
                td_tag = 'th'
            else:
                td_tag = 'td'

            col = 0
            for cell in columns[:-1]:
                p = re.compile(r'''(?:%(tattr)s\.\s)?(?P<text>.*)''' % self.res, re.VERBOSE)
                m = p.match(cell)
                if m:
                    c = m.groupdict('')
                    cellattr = self.parse_params(c['parameters'], align_type='table')

                    # Get the width of this cell.
                    width = cellattr.get('colspan', 1)

                    # Is this a header?
                    if c['parameters'].count('_'):
                        td_tag = 'th'

                    # If it is a header, let's set the default alignment.
                    if td_tag == 'th':
                        # Set the default aligment for all cells below this one.
                        # This is a little tricky because this header can have
                        # a colspan set.
                        for i in range(col, col+width):
                            default_align[i] = cellattr.get('align', None)

                    else:
                        # Apply the default align, if any.
                        cellattr['align'] = cellattr.get('align', default_align.get(col, None))

                    open_td = self.build_open_tag(td_tag, cellattr)
                    close_td = '</%s>\n' % td_tag

                    #output.append(open_td + c['text'].strip() + close_td)
                    output.append(open_td + self.inline(c['text'].strip()) + close_td)

                col += width

            output.append('
\n')

        text = open_tag + ''.join(output) + close_tag

        return text


def escape(self, text):
        """Do nothing.

        This is used to match escaped text. Nothing to see here!

        ---
        h1. Escaping

        If you don't want Textile processing a block, you can simply
        enclose it inside @==@:

        pre. p. Regular paragraph

        pre. ==
        Escaped portion -- will not be formatted
        by Textile at all
        ==

        pre. p. Back to normal.

        This can also be used inline, disabling the formatting temporarily:

        pre. p. This is ==*a test*== of escaping.
        """
        return text

def escape ( self , text ) : return text


def itex(self, text):
        """Convert itex to MathML.

        If the itex2mml binary is set, we use it to convert the
        itex to MathML. Otherwise, the text is unprocessed and
        return as is.

        ---
        h1. itex

        Textile can automatically convert itex code to MathML(Mathematical Markup Language)
        for you, if you have the itex2MML binary (you can download it
        from the "Movable Type plugin":http://golem.ph.utexas.edu/~distler/blog/files/itexToMML.tar.gz).

        Block equations should be enclosed inbetween @\[@ and @\]@:

        pre. \[ e^{i\pi} + 1 = 0 \]

        Will be translated to:

        pre. <math xmlns='http://www.w3.org/1998/Math/MathML' mode='display'>
        <msup><mi>e</mi> <mrow><mi>i</mi>
        <mi>&pi;</mi></mrow></msup>
        <mo>+</mo><mn>1</mn><mo>=</mo><mn>0</mn>
        </math>

        Equations can also be displayed inline:

        pre. Euler's formula, $e^{i\pi}+1=0$, ...

        (Note that if you want to display MathML(Mathematical Markup Language)
        your content must be served as @application/xhtml+xml@, which is not
        accepted by all browsers.)
        """
        if itex2mml:
            try:
                text = os.popen("echo '%s' | %s" % (text, itex2mml)).read()
            except:
                pass

        return text

def
itex
(
self
,
text
)
:
if
itex2mml
:
try
:
text
=
os
.
popen
(
"echo '%s' | %s"
%
(
text
,
itex2mml
)
)
.
read
(
)
except
:
pass
return
text


def about(self, text=None):
        """Show PyTextile's functionalities.

        An introduction to PyTextile. Can be called when running the
        main script or if you write the following line:

            'tell me about textile.'

        But keep it a secret!
        """

        about = []
        about.append(textile('h1. This is Textile', head_offset=self.head_offset))
        about.append(textile(__doc__.split('---', 1)[1], head_offset=self.head_offset))

        functions = [(self.split_text, 1),
                     (self.paragraph,  2),
                     (self.pre,        2),
                     (self.bc,         2),
                     (self.blockquote, 2),
                     (self.dl,         2),
                     (self.header,     2),
                     (self.footnote,   2),
                     (self.escape,     2),
                     (self.itex,       2),
                     (self.ol,         2),
                     (self.ul,         2),
                     (self.table,      2),
                     (self.inline,     1),
                     (self.qtags,      2),
                     (self.glyphs,     2),
                     (self.macros,     2),
                     (self.acronym,    2),
                     (self.images,     1),
                     (self.links,      1),
                     (self.sanitize,   1),
                    ]

        for function, offset in functions:
            doc = function.__doc__.split('---', 1)[1]
            doc = doc.split('\n')
            lines = []
            for line in doc:
                line = line.strip()
                lines.append(line)

            doc = '\n'.join(lines)
            about.append(textile(doc, head_offset=self.head_offset+offset))

        about = '\n'.join(about)
        about = about.replace('<br />', '')

        return about

def
about
(
self
,
text
=
)
:
about
=
[
]
about
.
append
(
textile
(
'h1. This is Textile'
,
head_offset
=
self
.
head_offset
)
)
about
.
append
(
textile
(
__doc__
.
split
(
'---'
,
1
)
[
1
]
,
head_offset
=
self
.
head_offset
)
)
functions
=
[
(
self
.
split_text
,
1
)
,
(
self
.
paragraph
,
2
)
,
(
self
.
pre
,
2
)
,
(
self
.
bc
,
2
)
,
(
self
.
blockquote
,
2
)
,
(
self
.
dl
,
2
)
,
(
self
.
header
,
2
)
,
(
self
.
footnote
,
2
)
,
(
self
.
escape
,
2
)
,
(
self
.
itex
,
2
)
,
(
self
.
ol
,
2
)
,
(
self
.
ul
,
2
)
,
(
self
.
table
,
2
)
,
(
self
.
inline
,
1
)
,
(
self
.
qtags
,
2
)
,
(
self
.
glyphs
,
2
)
,
(
self
.
macros
,
2
)
,
(
self
.
acronym
,
2
)
,
(
self
.
images
,
1
)
,
(
self
.
links
,
1
)
,
(
self
.
sanitize
,
1
)
,
]
for
function
,
offset
in
functions
:
doc
=
function
.
__doc__
.
split
(
'---'
,
1
)
[
1
]
doc
=
doc
.
split
(
'\n'
)
lines
=
[
]
for
line
in
doc
:
line
=
line
.
strip
(
)
lines
.
append
(
line
)
doc
=
'\n'
.
join
(
lines
)
about
.
append
(
textile
(
doc
,
head_offset
=
self
.
head_offset
+
offset
)
)
about
=
'\n'
.
join
(
about
)
about
=
about
.
replace
(
'<br />'
,
''
)
return
about


def acronym(self, text):
        """Process acronyms.

        Acronyms can have letters in upper and lower caps, or even numbers,
        provided that the numbers and upper caps are the same in the
        abbreviation and in the description. For example:

            XHTML(eXtensible HyperText Markup Language)
            OPeNDAP(Open source Project for a Network Data Access Protocol)
            L94(Levitus 94)

        are all valid acronyms.

        ---
        h1. Acronyms

        You can define acronyms in your text the following way:

        pre. This is XHTML(eXtensible HyperText Markup Language).

        The resulting code is:

        pre.
<acronym title="eXtensible HyperText Markup Language">XHTML</acronym>

        Acronyms can have letters in upper and lower caps, or even numbers,
        provided that the numbers and upper caps are the same in the
        abbreviation and in the description. For example:

        pre. XHTML(eXtensible HyperText Markup Language)
        OPeNDAP(Open source Project for a Network Data Access Protocol)
        L94(Levitus 94)

        are all valid acronyms.
        """
        # Find the acronyms.
        acronyms = r'''(?P<acronym>[\w]+)\((?P<definition>[^\(\)]+?)\)'''

        # Check all acronyms.
        for acronym, definition in re.findall(acronyms, text):
            caps_acronym = ''.join(re.findall('[A-Z\d]+', acronym))
            caps_definition = ''.join(re.findall('[A-Z\d]+', definition))
            if caps_acronym and caps_acronym == caps_definition:
                text = text.replace('%s(%s)' % (acronym, definition), '<acronym title="%s">%s</acronym>' % (definition, acronym))

        text = html_replace(r'''(^|\s)([A-Z]{3,})\b(?!\()''', r'''\1\2''', text)

        return text


def footnotes(self, text):
        """Add titles to footnotes references.

        This function searches for footnotes references like this [1], and
        adds a title to the link containing the first paragraph of the
        footnote.
        """
        # Search for footnotes.
        p = re.compile(r'''<p class="footnote" id="fn(?P<n>\d+)">(?P=n)(?P<note>.*)
''')
        for m in p.finditer(text):
            n = m.group('n')
            note = m.group('note').strip()

            # Strip HTML from note.
            note = re.sub('<.*?>', '', note)

            # Add the title.
            text = text.replace('' % n, '' % (n, note))

        return text


def macros(self, m):
        """Quick macros.

        This function replaces macros inside brackets using a built-in
        dictionary, and also unicode names if the key doesn't exist.

        ---
        h1. Macros

        Textile has support for character macros, which should be enclosed
        in curly braces. A few useful ones are:

        pre. {C=} or {=C}: euro sign
        {+-} or {-+}: plus-minus sign
        {L-} or {-L}: pound sign.

        You can also make accented characters:

        pre. Expos{e'}

        Becomes:

        pre.
Expos&#233;

        You can also specify Unicode names like:

        pre. {umbrella}
        {white smiling face}
        """
        entity = m.group(1)

        macros = {'c|': '¢',       # cent sign
                  '|c': '¢',       # cent sign
                  'L-': '£',       # pound sign
                  '-L': '£',       # pound sign
                  'Y=': '¥',       # yen sign
                  '=Y': '¥',       # yen sign
                  '(c)': '©',      # copyright sign
                  '<<': '«',       # left-pointing double angle quotation
                  '(r)': '®',      # registered sign
                  '+_': '±',       # plus-minus sign
                  '_+': '±',       # plus-minus sign
                  '>>': '»',       # right-pointing double angle quotation
                  '1/4': '¼',      # vulgar fraction one quarter
                  '1/2': '½',      # vulgar fraction one half
                  '3/4': '¾',      # vulgar fraction three quarters
                  'A`': 'À',       # latin capital letter a with grave
                  '`A': 'À',       # latin capital letter a with grave
                  'A\'': 'Á',      # latin capital letter a with acute
                  '\'A': 'Á',      # latin capital letter a with acute
                  'A^': 'Â',       # latin capital letter a with circumflex
                  '^A': 'Â',       # latin capital letter a with circumflex
                  'A~': 'Ã',       # latin capital letter a with tilde
                  '~A': 'Ã',       # latin capital letter a with tilde
                  'A"': 'Ä',       # latin capital letter a with diaeresis
                  '"A': 'Ä',       # latin capital letter a with diaeresis
                  'Ao': 'Å',       # latin capital letter a with ring above
                  'oA': 'Å',       # latin capital letter a with ring above
                  'AE': 'Æ',       # latin capital letter ae
                  'C,': 'Ç',       # latin capital letter c with cedilla
                  ',C': 'Ç',       # latin capital letter c with cedilla
                  'E`': 'È',       # latin capital letter e with grave
                  '`E': 'È',       # latin capital letter e with grave
                  'E\'': 'É',      # latin capital letter e with acute
                  '\'E': 'É',      # latin capital letter e with acute
                  'E^': 'Ê',       # latin capital letter e with circumflex
                  '^E': 'Ê',       # latin capital letter e with circumflex
                  'E"': 'Ë',       # latin capital letter e with diaeresis
                  '"E': 'Ë',       # latin capital letter e with diaeresis
                  'I`': 'Ì',       # latin capital letter i with grave
                  '`I': 'Ì',       # latin capital letter i with grave
                  'I\'': 'Í',      # latin capital letter i with acute
                  '\'I': 'Í',      # latin capital letter i with acute
                  'I^': 'Î',       # latin capital letter i with circumflex
                  '^I': 'Î',       # latin capital letter i with circumflex
                  'I"': 'Ï',       # latin capital letter i with diaeresis
                  '"I': 'Ï',       # latin capital letter i with diaeresis
                  'D-': 'Ð',       # latin capital letter eth
                  '-D': 'Ð',       # latin capital letter eth
                  'N~': 'Ñ',       # latin capital letter n with tilde
                  '~N': 'Ñ',       # latin capital letter n with tilde
                  'O`': 'Ò',       # latin capital letter o with grave
                  '`O': 'Ò',       # latin capital letter o with grave
                  'O\'': 'Ó',      # latin capital letter o with acute
                  '\'O': 'Ó',      # latin capital letter o with acute
                  'O^': 'Ô',       # latin capital letter o with circumflex
                  '^O': 'Ô',       # latin capital letter o with circumflex
                  'O~': 'Õ',       # latin capital letter o with tilde
                  '~O': 'Õ',       # latin capital letter o with tilde
                  'O"': 'Ö',       # latin capital letter o with diaeresis
                  '"O': 'Ö',       # latin capital letter o with diaeresis
                  'O/': 'Ø',       # latin capital letter o with stroke
                  '/O': 'Ø',       # latin capital letter o with stroke
                  'U`':  'Ù',      # latin capital letter u with grave
                  '`U':  'Ù',      # latin capital letter u with grave
                  'U\'': 'Ú',      # latin capital letter u with acute
                  '\'U': 'Ú',      # latin capital letter u with acute
                  'U^': 'Û',       # latin capital letter u with circumflex
                  '^U': 'Û',       # latin capital letter u with circumflex
                  'U"': 'Ü',       # latin capital letter u with diaeresis
                  '"U': 'Ü',       # latin capital letter u with diaeresis
                  'Y\'': 'Ý',      # latin capital letter y with acute
                  '\'Y': 'Ý',      # latin capital letter y with acute
                  'a`': 'à',       # latin small letter a with grave
                  '`a': 'à',       # latin small letter a with grave
                  'a\'': 'á',      # latin small letter a with acute
                  '\'a': 'á',      # latin small letter a with acute
                  'a^': 'â',       # latin small letter a with circumflex
                  '^a': 'â',       # latin small letter a with circumflex
                  'a~': 'ã',       # latin small letter a with tilde
                  '~a': 'ã',       # latin small letter a with tilde
                  'a"': 'ä',       # latin small letter a with diaeresis
                  '"a': 'ä',       # latin small letter a with diaeresis
                  'ao': 'å',       # latin small letter a with ring above
                  'oa': 'å',       # latin small letter a with ring above
                  'ae': 'æ',       # latin small letter ae
                  'c,': 'ç',       # latin small letter c with cedilla
                  ',c': 'ç',       # latin small letter c with cedilla
                  'e`': 'è',       # latin small letter e with grave
                  '`e': 'è',       # latin small letter e with grave
                  'e\'': 'é',      # latin small letter e with acute
                  '\'e': 'é',      # latin small letter e with acute
                  'e^': 'ê',       # latin small letter e with circumflex
                  '^e': 'ê',       # latin small letter e with circumflex
                  'e"': 'ë',       # latin small letter e with diaeresis
                  '"e': 'ë',       # latin small letter e with diaeresis
                  'i`': 'ì',       # latin small letter i with grave
                  '`i': 'ì',       # latin small letter i with grave
                  'i\'': 'í',      # latin small letter i with acute
                  '\'i': 'í',      # latin small letter i with acute
                  'i^': 'î',       # latin small letter i with circumflex
                  '^i': 'î',       # latin small letter i with circumflex
                  'i"': 'ï',       # latin small letter i with diaeresis
                  '"i': 'ï',       # latin small letter i with diaeresis
                  'n~': 'ñ',       # latin small letter n with tilde
                  '~n': 'ñ',       # latin small letter n with tilde
                  'o`': 'ò',       # latin small letter o with grave
                  '`o': 'ò',       # latin small letter o with grave
                  'o\'': 'ó',      # latin small letter o with acute
                  '\'o': 'ó',      # latin small letter o with acute
                  'o^': 'ô',       # latin small letter o with circumflex
                  '^o': 'ô',       # latin small letter o with circumflex
                  'o~': 'õ',       # latin small letter o with tilde
                  '~o': 'õ',       # latin small letter o with tilde
                  'o"': 'ö',       # latin small letter o with diaeresis
                  '"o': 'ö',       # latin small letter o with diaeresis
                  ':-': '÷',       # division sign
                  '-:': '÷',       # division sign
                  'o/': 'ø',       # latin small letter o with stroke
                  '/o': 'ø',       # latin small letter o with stroke
                  'u`': 'ù',       # latin small letter u with grave
                  '`u': 'ù',       # latin small letter u with grave
                  'u\'': 'ú',      # latin small letter u with acute
                  '\'u': 'ú',      # latin small letter u with acute
                  'u^': 'û',       # latin small letter u with circumflex
                  '^u': 'û',       # latin small letter u with circumflex
                  'u"': 'ü',       # latin small letter u with diaeresis
                  '"u': 'ü',       # latin small letter u with diaeresis
                  'y\'': 'ý',      # latin small letter y with acute
                  '\'y': 'ý',      # latin small letter y with acute
                  'y"': '&#255',        # latin small letter y with diaeresis
                  '"y': '&#255',        # latin small letter y with diaeresis
                  'OE': 'Œ',       # latin capital ligature oe
                  'oe': 'œ',       # latin small ligature oe
                  '*': '•',       # bullet
                  'Fr': '₣',      # french franc sign
                  'L=': '₤',      # lira sign
                  '=L': '₤',      # lira sign
                  'Rs': '₨',      # rupee sign
                  'C=': '€',      # euro sign
                  '=C': '€',      # euro sign
                  'tm': '™',      # trade mark sign
                  '<-': '←',      # leftwards arrow
                  '->': '→',      # rightwards arrow
                  '<=': '⇐',      # leftwards double arrow
                  '=>': '⇒',      # rightwards double arrow
                  '=/': '≠',      # not equal to
                  '/=': '≠',      # not equal to
                  '<_': '≤',      # less-than or equal to
                  '_<': '≤',      # less-than or equal to
                  '>_': '≥',      # greater-than or equal to
                  '_>': '≥',      # greater-than or equal to
                  ':(': '☹',      # white frowning face
                  ':)': '☺',      # white smiling face
                  'spade': '♠',   # black spade suit
                  'club': '♣',    # black club suit
                  'heart': '♥',   # black heart suit
                  'diamond': '♦', # black diamond suit
                 }

        try:
            # Try the key.
            entity = macros[entity]
        except KeyError:
            try:
                # Try a unicode entity.
                entity = unicodedata.lookup(entity)
                entity = entity.encode('ascii', 'xmlcharrefreplace')
            except:
                # Return the unmodified entity.
                entity = '{%s}' % entity

        return entity


def glyphs(self, text):
        """Glyph formatting.

        This function replaces quotations marks, dashes and a few other
        symbol for numerical entities. The em/en dashes use definitions
        comes from http://alistapart.com/articles/emen/.

        ---
        h1. Glyphs

        Textile replaces some of the characters in your text with their
        equivalent numerical entities. These include:

        * Replace single and double primes used as quotation marks with HTML(HyperText Markup Language) entities for opening and closing quotation marks in readable text, while leaving untouched the primes required within HTML(HyperText Markup Language) tags.
        * Replace double hyphens (==--==) with an em-dash (—) entity.
        * Replace triple hyphens (==---==) with two em-dash (——) entities.
        * Replace single hyphens surrounded by spaces with an en-dash (–) entity.
        * Replace triplets of periods (==...==) with an ellipsis (…) entity.
        * Convert many nonstandard characters to browser-safe entities corresponding to keyboard input.
        * Convert ==(TM)==, ==(R)==, and  ==(C)== to ™, ®, and ©.
        * Convert the letter x to a dimension sign: 2==x==4 to 2x4 and 8 ==x== 10 to 8x10.
        """
        glyphs = [(r'''"(?<!\w)\b''', r'''“'''),                              # double quotes
                  (r'''"''', r'''”'''),                                       # double quotes
                  (r"""\b'""", r'''’'''),                                     # single quotes
                  (r"""'(?<!\w)\b""", r'''‘'''),                              # single quotes
                  (r"""'""", r'''’'''),                                       # single single quote
                  (r'''(\b|^)( )?\.{3}''', r'''\1…'''),                       # ellipsis
                  (r'''\b---\b''', r'''——'''),                          # double em dash
                  (r'''\s?--\s?''', r'''—'''),                                # em dash
                  (r'''(\d+)-(\d+)''', r'''\1–\2'''),                         # en dash (1954-1999)
                  (r'''(\d+)-(\W)''', r'''\1—\2'''),                          # em dash (1954--)
                  (r'''\s-\s''', r''' – '''),                                 # en dash
                  (r'''(\d+) ?x ?(\d+)''', r'''\1×\2'''),                      # dimension sign
                  (r'''\b ?(\((tm|TM)\))''', r'''™'''),                       # trademark
                  (r'''\b ?(\([rR]\))''', r'''®'''),                           # registered
                  (r'''\b ?(\([cC]\))''', r'''©'''),                           # copyright
                  (r'''([^\s])\[(\d+)\]''',                                         #
                       r'''\1\2'''),# footnote
                  ]

        # Apply macros.
        text = re.sub(r'''{([^}]+)}''', self.macros, text)

        # LaTeX style quotes.
        text = text.replace('\x60\x60', '“')
        text = text.replace('\xb4\xb4', '”')

        # Linkify URL and emails.
        url = r'''(?=[a-zA-Z0-9./#])                          # Must start correctly
                  ((?:                                        # Match the leading part (proto://hostname, or just hostname)
                      (?:ftp|https?|telnet|nntp)              #     protocol
                      ://                                     #     ://
                      (?:                                     #     Optional 'username:password@'
                          \w+                                 #         username
                          (?::\w+)?                           #         optional :password
                          @                                   #         @
                      )?                                      #
                      [-\w]+(?:\.\w[-\w]*)+                   #     hostname (sub.example.com)
                  )                                           #
                  (?::\d+)?                                   # Optional port number
                  (?:                                         # Rest of the URL, optional
                      /?                                      #     Start with '/'
                      [^.!,?;:"'<>()\[\]{}\s\x7F-\xFF]*       #     Can't start with these
                      (?:                                     #
                          [.!,?;:]+                           #     One or more of these
                          [^.!,?;:"'<>()\[\]{}\s\x7F-\xFF]+   #     Can't finish with these
                          #'"                                 #     # or ' or "
                      )*                                      #
                  )?)                                         #
               '''

        email = r'''(?:mailto:)?            # Optional mailto:
                    ([-\+\w]+               # username
                    \@                      # at
                    [-\w]+(?:\.\w[-\w]*)+)  # hostname
                 '''

        # If there is no html, do a simple search and replace.
        if not re.search(r'''<.*>''', text):
            for glyph_search, glyph_replace in glyphs:
                text = preg_replace(glyph_search, glyph_replace, text)

            # Linkify.
            text = re.sub(re.compile(url, re.VERBOSE), r'''\1''', text)
            text = re.sub(re.compile(email, re.VERBOSE), r'''\1''', text)

        else:
            lines = []
            # Else split the text into an array at <>.
            for line in re.split('(<.*?>)', text):
                if not re.match('<.*?>', line):
                    for glyph_search, glyph_replace in glyphs:
                        line = preg_replace(glyph_search, glyph_replace, line)

                    # Linkify.
                    line = re.sub(re.compile(url, re.VERBOSE), r'''\1''', line)
                    line = re.sub(re.compile(email, re.VERBOSE), r'''\1''', line)

                lines.append(line)

            text = ''.join(lines)

        return text


def qtags(self, text):
        """Quick tags formatting.

        This function does the inline formatting of text, like
        bold, italic, strong and also itex code.

        ---
        h1. Quick tags

        Quick tags allow you to format your text, making it bold,
        emphasized or small, for example. The quick tags operators
        include:

        dl. ==*strong*==:Translates into @strong@.
        ==_emphasis_==:Translates into @emphasis@.
        ==**bold**==:Translates into @bold@.
        ==__italics__==:Translates into @italics@.
        ==++bigger++==:Translates into @<big>bigger</big>@.
        ==--smaller--==:Translates into: @smaller@.
        ==-deleted text-==:Translates into @deleted text@.
        ==+inserted text+==:Translates into @inserted text@.
        ==^superscript^==:Translates into @superscript@.
        ==~subscript~==:Translates into @subscript@.
        ==%span%==:Translates into @span@.
        ==@code@==:Translates into @code@.

        Note that within a "==@==...==@==" section, @<@ and @>@ are
        translated into HTML entities automatically.

        Inline formatting operators accept the following modifiers:

        dl. {style rule}:A CSS(Cascading Style Sheets) style rule.
        [ll]:A language identifier (for a "lang" attribute).
        (class) or (#id) or (class#id):For CSS(Cascading Style Sheets) class and id attributes.
        """
        # itex2mml.
        text = re.sub('\$(.*?)\$', lambda m: self.itex(m.group()), text)

        # Add span tags to upper-case words which don't have a description.
        #text = preg_replace(r'''(^|\s)([A-Z]{3,})\b(?!\()''', r'''\1\2''', text)

        # Quick tags.
        qtags = [('**', 'b',      {'qf': '(?<!\*)\*\*(?!\*)', 'cls': '\*'}),
                 ('__', 'i',      {'qf': '(?<!_)__(?!_)', 'cls': '_'}),
                 ('??', 'cite',   {'qf': '\?\?(?!\?)', 'cls': '\?'}),
                 ('-',  'del',    {'qf': '(?<!\-)\-(?!\-)', 'cls': '-'}),
                 ('+',  'ins',    {'qf': '(?<!\+)\+(?!\+)', 'cls': '\+'}),
                 ('*',  'strong', {'qf': '(?<!\*)\*(?!\*)', 'cls': '\*'}),
                 ('_',  'em',     {'qf': '(?<!_)_(?!_)', 'cls': '_'}),
                 ('++', 'big',    {'qf': '(?<!\+)\+\+(?!\+)', 'cls': '\+\+'}),
                 ('--', 'small',  {'qf': '(?<!\-)\-\-(?!\-)', 'cls': '\-\-'}),
                 ('~',  'sub',    {'qf': '(?<!\~)\~(?!(\\\/~))', 'cls': '\~'}),
                 ('@',  'code',   {'qf': '(?<!@)@(?!@)', 'cls': '@'}),
                 ('%',  'span',   {'qf': '(?<!%)%(?!%)', 'cls': '%'}),
                ]

        # Superscript.
        text = re.sub(r'''(?<!\^)\^(?!\^)(.+?)(?<!\^)\^(?!\^)''', r'''\1''', text)

        # This is from the perl version of Textile.
        for qtag, htmltag, redict in qtags:
            self.res.update(redict)
            p = re.compile(r'''(?:                          #
                                   ^                        # Start of string
                                   |                        #
                                   (?<=[\s>'"])             # Whitespace, end of tag, quotes
                                   |                        #
                                   (?P
[{[])            # Surrounded by [ or {
                                   |                        #
                                   (?<=%(punct)s)           # Punctuation
                               )                            #
                               %(qf)s                       # opening tag
                               %(qattr)s                    # attributes
                               (?P<text>[^%(cls)s\s].*?)    # text
                               (?<=\S)                      # non-whitespace
                               %(qf)s                       #
                               (?:                          #
                                   $                        # End of string
                                   |                        #
                                   (?P<post>[\]}])          # Surrounded by ] or }
                                   |                        #
                                   (?=%(punct)s{1,2}|\s)    # punctuation
                                )                           #
                             ''' % self.res, re.VERBOSE)

            def _replace(m):
                c = m.groupdict('')

                attributes = self.parse_params(c['parameters'])
                open_tag  = self.build_open_tag(htmltag, attributes)
                close_tag = '</%s>' % htmltag

                # Replace < and > inside .
                if htmltag == 'code':
                    c['text'] = c['text'].replace('<', '<')
                    c['text'] = c['text'].replace('>', '>')

                return open_tag + c['text'] + close_tag

            text = p.sub(_replace, text)

        return text

r'''(?:                          #
                                   ^                        # Start of string
                                   |                        #
                                   (?<=[\s>'"])             # Whitespace, end of tag, quotes
                                   |                        #
                                   (?P<pre>[{[])            # Surrounded by [ or {
                                   |                        #
                                   (?<=%(punct)s)           # Punctuation
                               )                            #
                               %(qf)s                       # opening tag
                               %(qattr)s                    # attributes
                               (?P<text>[^%(cls)s\s].*?)    # text
                               (?<=\S)                      # non-whitespace
                               %(qf)s                       #
                               (?:                          #
                                   $                        # End of string
                                   |                        #
                                   (?P<post>[\]}])          # Surrounded by ] or }
                                   |                        #
                                   (?=%(punct)s{1,2}|\s)    # punctuation
                                )                           #
                             '''


def images(self, text):
        """Process images.

        This function process images tags, with or without links. Images
        can have vertical and/or horizontal alignment, and can be resized
        unefficiently using width and height tags.

        ---
        h1. Images

        An image is generated by enclosing the image source in @!@:

        pre. !/path/to/image!

        You may optionally specify an alternative text for the image, which
        will also be used as its title:

        pre. !image.jpg (Nice picture)!

        Becomes:

        pre.

        If you want to make the image point to a link, simply append a
        comma and the URL(Universal Republic of Love) to the image:

        pre. !image.jpg!:http://diveintopython.org

        Images can also be resized. These are all equivalent:

        pre. !image.jpg 10x20!
        !image.jpg 10w 20h!
        !image.jpg 20h 10w!

        The image @image.jpg@ will be resized to width 10 and height 20.

        Modifiers to the @@ tag go after the opening @!@:

        pre. !(class#id)^image.jpg!

        Allowed modifiers include:

        dl. <:Align the image to the left (causes the image to float if CSS options are enabled).
        >:Align the image to the right (causes the image to float if CSS options are enabled).
        - (dash):Aligns the image to the middle.
        ^:Aligns the image to the top.
        ~ (tilde):Aligns the image to the bottom.
        {style rule}:Applies a CSS style rule to the image.
        (class) or (#id) or (class#id):Applies a CSS class and/or id to the image.
        ( (one or more):Pads 1em on the left for each '(' character.
        ) (one or more):Pads 1em on the right for each ')' character.

        Images receive the class "top" when using top alignment, "bottom"
        for bottom alignment and "middle" for middle alignment.
        """
        # Compile the beast.
        p = re.compile(r'''\!               # Opening !
                           %(iattr)s        # Image attributes
                           (?P<src>%(url)s) # Image src
                           \s?              # Optional whitesapce
                           (                #
                               \(           #
                               (?P<alt>.*?) # Optional (alt) attribute
                               \)           #
                           )?               #
                           \s?              # Optional whitespace
                           %(resize)s       # Resize parameters
                           \!               # Closing !
                           (                # Optional link
                               :            #    starts with ':'
                               (?P<link>    #
                               %(url)s      #    link HREF
                               )            #
                           )?               #
                        ''' % self.res, re.VERBOSE)

        for m in p.finditer(text):
            c = m.groupdict('')

            # Build the parameters for the  tag.
            attributes = self.parse_params(c['parameters'], align_type='image')
            attributes.update(c)
            if attributes['alt']:
                attributes['title'] = attributes['alt']

            # Append height and width.
            attributes['width'] = m.groups()[5] or m.groups()[7] or m.groups()[10]
            attributes['height'] = m.groups()[6] or m.groups()[8] or m.groups()[9]

            # Create the image tag.
            tag = self.image(attributes)

            text = text.replace(m.group(), tag)

        return text

# Build the parameters for the <img /> tag.


Process each image.

        This method builds the <img> tag for each image in the text. It's
        separated from the 'images' method so it can be easily overriden when
        subclassing Textiler. Useful if you want to download and/or process
        the images, for example.

def image(self, attributes):
        """Process each image.

        This method builds the  tag for each image in the text. It's
        separated from the 'images' method so it can be easily overriden when
        subclassing Textiler. Useful if you want to download and/or process
        the images, for example.
        """
        link = attributes['link']
        del attributes['link']
        del attributes['parameters']

        # Build the tag.
        tag = self.build_open_tag('img', attributes, single=1)

        if link:
            href = preg_replace('&(?!(#|amp))', '&', link)
            tag = '%s' % (href, tag)

        return tag

def
image
(
self
,
attributes
)
:
link
=
attributes
[
'link'
]
del
attributes
[
'link'
]
del
attributes
[
'parameters'
]
# Build the tag.
tag
=
self
.
build_open_tag
(
'img'
,
attributes
,
single
=
1
)
if
link
:
href
=
preg_replace
(
'&(?!(#|amp))'
,
'&'
,
link
)
tag
=
'%s'
%
(
href
,
tag
)
return
tag


def links(self, text):
        """Process links.

        This function is responsible for processing links. It has
        some nice shortcuts to Google, Amazon and IMDB queries.

        ---
        h1. Links

        A links is done the following way:

        pre. "This is the text link":http://example.com

        The result from this markup is:

        pre.
This is the text link

        You can add an optional @title@ attribute:

        pre. "This is the text link(This is the title)":http://example.com

        The link can be customised as well:

        pre. "(nospam)E-mail me please":mailto:someone@example.com

        You can use either single or double quotes. They must be enclosed in
        whitespace, punctuation or brackets:

        pre. You["gotta":http://example.com]seethis!

        If you are going to reference the same link a couple of times, you
        can define a lookup list anywhere on your document:

        pre. [python]http://www.python.org

        Links to the Python website can then be defined the following way:

        pre. "Check this":python

        There are also shortcuts for Amazon, IMDB(Internet Movie DataBase) and
        Google queries:

        pre. "Has anyone seen this guy?":imdb:Stephen+Fry
        "Really nice book":amazon:Goedel+Escher+Bach
        "PyBlosxom":google
        ["Using Textile and Blosxom with Python":google:python blosxom textile]

        Becomes:

        pre. Has anyone seen this guy?
        Really nice book
        PyBlosxom
        Using Textile and Blosxom with Python
        """
        linkres = [r'''\[                           # [
                       (?P<quote>"|')               # Opening quotes
                       %(lattr)s                    # Link attributes
                       (?P<text>[^"]+?)             # Link text
                       \s?                          # Optional whitespace
                       (?:\((?P<title>[^\)]+?)\))?  # Optional (title)
                       (?P=quote)                   # Closing quotes
                       :                            # :
                       (?P<href>[^\]]+)             # HREF
                       \]                           # ]
                    ''' % self.res,
                   r'''(?P<quote>"|')               # Opening quotes
                       %(lattr)s                    # Link attributes
                       (?P<text>[^"]+?)             # Link text
                       \s?                          # Optional whitespace
                       (?:\((?P<title>[^\)]+?)\))?  # Optional (title)
                       (?P=quote)                   # Closing quotes
                       :                            # :
                       (?P<href>%(url)s)            # HREF
                    ''' % self.res]

        for linkre in linkres:
            p = re.compile(linkre, re.VERBOSE)
            for m in p.finditer(text):
                c = m.groupdict('')

                attributes = self.parse_params(c['parameters'])
                attributes['title'] = c['title'].replace('"', '"')

                # Search lookup list.
                link = self._links.get(c['href'], None) or c['href']

                # Hyperlinks for Amazon, IMDB and Google searches.
                parts = link.split(':', 1)
                proto = parts[0]
                if len(parts) == 2:
                    query = parts[1]
                else:
                    query = c['text']

                query = query.replace(' ', '+')

                # Look for smart search.
                if self.searches.has_key(proto):
                    link = self.searches[proto] % query

                # Fix URL.
                attributes['href'] = preg_replace('&(?!(#|amp))', '&', link)

                open_tag = self.build_open_tag('a', attributes)
                close_tag = ''

                repl = open_tag + c['text'] + close_tag

                text = text.replace(m.group(), repl)

        return text


def format(self, text):
        """Text formatting.

        This function basically defines the order on which the
        formatting is applied.
        """
        text = self.qtags(text)
        text = self.images(text)
        text = self.links(text)
        text = self.acronym(text)
        text = self.glyphs(text)

        return text

def format ( self , text ) : text = self . qtags ( text ) text = self . images ( text ) text = self . links ( text ) text = self . acronym ( text ) text = self . glyphs ( text ) return text


def inline(self, text):
        """Inline formatting.

        This function calls the formatting on the inline text,
        taking care to avoid the escaped parts.

        ---
        h1. Inline

        Inline formatting is applied within a block of text.
        """
        if not re.search(r'''==(.*?)==''', text):
            text = self.format(text)

        else:
            lines = []
            # Else split the text into an array at <>.
            for line in re.split('(==.*?==)', text):
                if not re.match('==.*?==', line):
                    line = self.format(line)
                else:
                    line = line[2:-2]

                lines.append(line)

            text = ''.join(lines)

        return text


Serialize obj as a JSON formatted stream to fp ( a . write () - supporting file - like object ) .

def dump(obj, fp, skipkeys=False, ensure_ascii=True, check_circular=True,
        allow_nan=True, cls=None, indent=None, separators=None,
        encoding='utf-8', default=None, **kw):
    """
    Serialize ``obj`` as a JSON formatted stream to ``fp`` (a
    ``.write()``-supporting file-like object).

    If ``skipkeys`` is ``True`` then ``dict`` keys that are not basic types
    (``str``, ``unicode``, ``int``, ``long``, ``float``, ``bool``, ``None``)
    will be skipped instead of raising a ``TypeError``.

    If ``ensure_ascii`` is ``False``, then the some chunks written to ``fp``
    may be ``unicode`` instances, subject to normal Python ``str`` to
    ``unicode`` coercion rules. Unless ``fp.write()`` explicitly
    understands ``unicode`` (as in ``codecs.getwriter()``) this is likely
    to cause an error.

    If ``check_circular`` is ``False``, then the circular reference check
    for container types will be skipped and a circular reference will
    result in an ``OverflowError`` (or worse).

    If ``allow_nan`` is ``False``, then it will be a ``ValueError`` to
    serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``)
    in strict compliance of the JSON specification, instead of using the
    JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``).

    If ``indent`` is a non-negative integer, then JSON array elements and object
    members will be pretty-printed with that indent level. An indent level
    of 0 will only insert newlines. ``None`` is the most compact representation.

    If ``separators`` is an ``(item_separator, dict_separator)`` tuple
    then it will be used instead of the default ``(', ', ': ')`` separators.
    ``(',', ':')`` is the most compact JSON representation.

    ``encoding`` is the character encoding for str instances, default is UTF-8.

    ``default(obj)`` is a function that should return a serializable version
    of obj or raise TypeError. The default simply raises TypeError.

    To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the
    ``.default()`` method to serialize additional types), specify it with
    the ``cls`` kwarg.
    """
    # cached encoder
    if (skipkeys is False and ensure_ascii is True and
        check_circular is True and allow_nan is True and
        cls is None and indent is None and separators is None and
        encoding == 'utf-8' and default is None and not kw):
        iterable = _default_encoder.iterencode(obj)
    else:
        if cls is None:
            cls = JSONEncoder
        iterable = cls(skipkeys=skipkeys, ensure_ascii=ensure_ascii,
            check_circular=check_circular, allow_nan=allow_nan, indent=indent,
            separators=separators, encoding=encoding,
            default=default, **kw).iterencode(obj)
    # could accelerate with writelines in some versions of Python, at
    # a debuggability cost
    for chunk in iterable:
        fp.write(chunk)


def dumps(obj, skipkeys=False, ensure_ascii=True, check_circular=True,
        allow_nan=True, cls=None, indent=None, separators=None,
        encoding='utf-8', default=None, **kw):
    """
    Serialize ``obj`` to a JSON formatted ``str``.

    If ``skipkeys`` is ``True`` then ``dict`` keys that are not basic types
    (``str``, ``unicode``, ``int``, ``long``, ``float``, ``bool``, ``None``)
    will be skipped instead of raising a ``TypeError``.

    If ``ensure_ascii`` is ``False``, then the return value will be a
    ``unicode`` instance subject to normal Python ``str`` to ``unicode``
    coercion rules instead of being escaped to an ASCII ``str``.

    If ``check_circular`` is ``False``, then the circular reference check
    for container types will be skipped and a circular reference will
    result in an ``OverflowError`` (or worse).

    If ``allow_nan`` is ``False``, then it will be a ``ValueError`` to
    serialize out of range ``float`` values (``nan``, ``inf``, ``-inf``) in
    strict compliance of the JSON specification, instead of using the
    JavaScript equivalents (``NaN``, ``Infinity``, ``-Infinity``).

    If ``indent`` is a non-negative integer, then JSON array elements and
    object members will be pretty-printed with that indent level. An indent
    level of 0 will only insert newlines. ``None`` is the most compact
    representation.

    If ``separators`` is an ``(item_separator, dict_separator)`` tuple
    then it will be used instead of the default ``(', ', ': ')`` separators.
    ``(',', ':')`` is the most compact JSON representation.

    ``encoding`` is the character encoding for str instances, default is UTF-8.

    ``default(obj)`` is a function that should return a serializable version
    of obj or raise TypeError. The default simply raises TypeError.

    To use a custom ``JSONEncoder`` subclass (e.g. one that overrides the
    ``.default()`` method to serialize additional types), specify it with
    the ``cls`` kwarg.
    """
    # cached encoder
    if (skipkeys is False and ensure_ascii is True and
        check_circular is True and allow_nan is True and
        cls is None and indent is None and separators is None and
        encoding == 'utf-8' and default is None and not kw):
        return _default_encoder.encode(obj)
    if cls is None:
        cls = JSONEncoder
    return cls(
        skipkeys=skipkeys, ensure_ascii=ensure_ascii,
        check_circular=check_circular, allow_nan=allow_nan, indent=indent,
        separators=separators, encoding=encoding, default=default,
        **kw).encode(obj)

def
dumps
(
obj
,
skipkeys
=
False
,
ensure_ascii
=
True
,
check_circular
=
True
,
allow_nan
=
True
,
cls
=
,
indent
=
,
separators
=
,
encoding
=
'utf-8'
,
default
=
,
*
*
kw
)
:
# cached encoder
if
(
skipkeys
is
False
and
ensure_ascii
is
True
and
check_circular
is
True
and
allow_nan
is
True
and
cls
is
and
indent
is
and
separators
is
and
encoding
==
'utf-8'
and
default
is
and
not
kw
)
:
return
_default_encoder
.
encode
(
obj
)
if
cls
is
:
cls
=
JSONEncoder
return
cls
(
skipkeys
=
skipkeys
,
ensure_ascii
=
ensure_ascii
,
check_circular
=
check_circular
,
allow_nan
=
allow_nan
,
indent
=
indent
,
separators
=
separators
,
encoding
=
encoding
,
default
=
default
,
*
*
kw
)
.
encode
(
obj
)


Deserialize fp ( a . read () - supporting file - like object containing a JSON document ) to a Python object .

def load(fp, encoding=None, cls=None, object_hook=None, parse_float=None,
        parse_int=None, parse_constant=None, **kw):
    """
    Deserialize ``fp`` (a ``.read()``-supporting file-like object containing
    a JSON document) to a Python object.

    If the contents of ``fp`` is encoded with an ASCII based encoding other
    than utf-8 (e.g. latin-1), then an appropriate ``encoding`` name must
    be specified. Encodings that are not ASCII based (such as UCS-2) are
    not allowed, and should be wrapped with
    ``codecs.getreader(fp)(encoding)``, or simply decoded to a ``unicode``
    object and passed to ``loads()``

    ``object_hook`` is an optional function that will be called with the
    result of any object literal decode (a ``dict``). The return value of
    ``object_hook`` will be used instead of the ``dict``. This feature
    can be used to implement custom decoders (e.g. JSON-RPC class hinting).

    To use a custom ``JSONDecoder`` subclass, specify it with the ``cls``
    kwarg.
    """
    return loads(fp.read(),
        encoding=encoding, cls=cls, object_hook=object_hook,
        parse_float=parse_float, parse_int=parse_int,
        parse_constant=parse_constant, **kw)

def load ( fp , encoding = None , cls = None , object_hook = None , parse_float = None , parse_int = None , parse_constant = None , * * kw ) : return loads ( fp . read ( ) , encoding = encoding , cls = cls , object_hook = object_hook , parse_float = parse_float , parse_int = parse_int , parse_constant = parse_constant , * * kw )


Deserialize s ( a str or unicode instance containing a JSON document ) to a Python object .

def loads(s, encoding=None, cls=None, object_hook=None, parse_float=None,
        parse_int=None, parse_constant=None, **kw):
    """
    Deserialize ``s`` (a ``str`` or ``unicode`` instance containing a JSON
    document) to a Python object.

    If ``s`` is a ``str`` instance and is encoded with an ASCII based encoding
    other than utf-8 (e.g. latin-1) then an appropriate ``encoding`` name
    must be specified. Encodings that are not ASCII based (such as UCS-2)
    are not allowed and should be decoded to ``unicode`` first.

    ``object_hook`` is an optional function that will be called with the
    result of any object literal decode (a ``dict``). The return value of
    ``object_hook`` will be used instead of the ``dict``. This feature
    can be used to implement custom decoders (e.g. JSON-RPC class hinting).

    ``parse_float``, if specified, will be called with the string
    of every JSON float to be decoded. By default this is equivalent to
    float(num_str). This can be used to use another datatype or parser
    for JSON floats (e.g. decimal.Decimal).

    ``parse_int``, if specified, will be called with the string
    of every JSON int to be decoded. By default this is equivalent to
    int(num_str). This can be used to use another datatype or parser
    for JSON integers (e.g. float).

    ``parse_constant``, if specified, will be called with one of the
    following strings: -Infinity, Infinity, NaN, null, true, false.
    This can be used to raise an exception if invalid JSON numbers
    are encountered.

    To use a custom ``JSONDecoder`` subclass, specify it with the ``cls``
    kwarg.
    """
    if (cls is None and encoding is None and object_hook is None and
            parse_int is None and parse_float is None and
            parse_constant is None and not kw):
        return _default_decoder.decode(s)
    if cls is None:
        cls = JSONDecoder
    if object_hook is not None:
        kw['object_hook'] = object_hook
    if parse_float is not None:
        kw['parse_float'] = parse_float
    if parse_int is not None:
        kw['parse_int'] = parse_int
    if parse_constant is not None:
        kw['parse_constant'] = parse_constant
    return cls(encoding=encoding, **kw).decode(s)

def loads ( s , encoding = None , cls = None , object_hook = None , parse_float = None , parse_int = None , parse_constant = None , * * kw ) : if ( cls is None and encoding is None and object_hook is None and parse_int is None and parse_float is None and parse_constant is None and not kw ) : return _default_decoder . decode ( s ) if cls is None : cls = JSONDecoder if object_hook is not None : kw [ 'object_hook' ] = object_hook if parse_float is not None : kw [ 'parse_float' ] = parse_float if parse_int is not None : kw [ 'parse_int' ] = parse_int if parse_constant is not None : kw [ 'parse_constant' ] = parse_constant return cls ( encoding = encoding , * * kw ) . decode ( s )


demjson python - cjson API compatibility hook . Use loads ( s ) instead .

def decode(s):
    """
    demjson, python-cjson API compatibility hook. Use loads(s) instead.
    """
    import warnings
    warnings.warn("simplejson.loads(s) should be used instead of decode(s)",
        DeprecationWarning)
    return loads(s)


demjson python - cjson compatibility hook . Use dumps ( s ) instead .

def encode(obj):
    """
    demjson, python-cjson compatibility hook. Use dumps(s) instead.
    """
    import warnings
    warnings.warn("simplejson.dumps(s) should be used instead of encode(s)",
        DeprecationWarning)
    return dumps(obj)


jsonlib JsonUtils python - json json - py API compatibility hook . Use loads ( s ) instead .

def read(s):
    """
    jsonlib, JsonUtils, python-json, json-py API compatibility hook.
    Use loads(s) instead.
    """
    import warnings
    warnings.warn("simplejson.loads(s) should be used instead of read(s)",
        DeprecationWarning)
    return loads(s)


jsonlib JsonUtils python - json json - py API compatibility hook . Use dumps ( s ) instead .

def write(obj):
    """
    jsonlib, JsonUtils, python-json, json-py API compatibility hook.
    Use dumps(s) instead.
    """
    import warnings
    warnings.warn("simplejson.dumps(s) should be used instead of write(s)",
        DeprecationWarning)
    return dumps(obj)


def iterscan(self, string, idx=0, context=None):
        """
        Yield match, end_idx for each match
        """
        match = self.scanner.scanner(string, idx).match
        actions = self.actions
        lastend = idx
        end = len(string)
        while True:
            m = match()
            if m is None:
                break
            matchbegin, matchend = m.span()
            if lastend == matchend:
                break
            action = actions[m.lastindex]
            if action is not None:
                rval, next_pos = action(m, context)
                if next_pos is not None and next_pos != matchend:
                    # "fast forward" the scanner
                    matchend = next_pos
                    match = self.scanner.scanner(string, matchend).match
                yield rval, matchend
            lastend = matchend

def
iterscan
(
self
,
string
,
idx
=
0
,
context
=
)
:
match
=
self
.
scanner
.
scanner
(
string
,
idx
)
.
match
actions
=
self
.
actions
lastend
=
idx
end
=
len
(
string
)
while
True
:
m
=
match
(
)
if
m
is
:
break
matchbegin
,
matchend
=
m
.
span
(
)
if
lastend
==
matchend
:
break
action
=
actions
[
m
.
lastindex
]
if
action
is
not
:
rval
,
next_pos
=
action
(
m
,
context
)
if
next_pos
is
not
and
next_pos
!=
matchend
:
# "fast forward" the scanner
matchend
=
next_pos
match
=
self
.
scanner
.
scanner
(
string
,
matchend
)
.
match
yield
rval
,
matchend
lastend
=
matchend


encoding determines the encoding used to interpret any str objects decoded by this instance ( utf - 8 by default ) . It has no effect when decoding unicode objects . Note that currently only encodings that are a superset of ASCII work strings of other encodings should be passed in as unicode .

def __init__(self, encoding=None, object_hook=None, parse_float=None,
            parse_int=None, parse_constant=None, strict=True):
        """
        ``encoding`` determines the encoding used to interpret any ``str``
        objects decoded by this instance (utf-8 by default).  It has no
        effect when decoding ``unicode`` objects.

        Note that currently only encodings that are a superset of ASCII work,
        strings of other encodings should be passed in as ``unicode``.

        ``object_hook``, if specified, will be called with the result
        of every JSON object decoded and its return value will be used in
        place of the given ``dict``.  This can be used to provide custom
        deserializations (e.g. to support JSON-RPC class hinting).

        ``parse_float``, if specified, will be called with the string
        of every JSON float to be decoded. By default this is equivalent to
        float(num_str). This can be used to use another datatype or parser
        for JSON floats (e.g. decimal.Decimal).

        ``parse_int``, if specified, will be called with the string
        of every JSON int to be decoded. By default this is equivalent to
        int(num_str). This can be used to use another datatype or parser
        for JSON integers (e.g. float).

        ``parse_constant``, if specified, will be called with one of the
        following strings: -Infinity, Infinity, NaN, null, true, false.
        This can be used to raise an exception if invalid JSON numbers
        are encountered.
        """
        self.encoding = encoding
        self.object_hook = object_hook
        self.parse_float = parse_float
        self.parse_int = parse_int
        self.parse_constant = parse_constant
        self.strict = strict

def __init__ ( self , encoding = None , object_hook = None , parse_float = None , parse_int = None , parse_constant = None , strict = True ) : self . encoding = encoding self . object_hook = object_hook self . parse_float = parse_float self . parse_int = parse_int self . parse_constant = parse_constant self . strict = strict


Return the Python representation of s ( a str or unicode instance containing a JSON document )

def decode(self, s, _w=WHITESPACE.match):
        """
        Return the Python representation of ``s`` (a ``str`` or ``unicode``
        instance containing a JSON document)
        """
        obj, end = self.raw_decode(s, idx=_w(s, 0).end())
        end = _w(s, end).end()
        if end != len(s):
            raise ValueError(errmsg("Extra data", s, end, len(s)))
        return obj

def
decode
(
self
,
s
,
_w
=
WHITESPACE
.
match
)
:
obj
,
end
=
self
.
raw_decode
(
s
,
idx
=
_w
(
s
,
0
)
.
end
(
)
)
end
=
_w
(
s
,
end
)
.
end
(
)
if
end
!=
len
(
s
)
:
raise
ValueError
(
errmsg
(
"Extra data"
,
s
,
end
,
len
(
s
)
)
)
return
obj


Decode a JSON document from s ( a str or unicode beginning with a JSON document ) and return a 2 - tuple of the Python representation and the index in s where the document ended .

def raw_decode(self, s, **kw):
        """
        Decode a JSON document from ``s`` (a ``str`` or ``unicode`` beginning
        with a JSON document) and return a 2-tuple of the Python
        representation and the index in ``s`` where the document ended.

        This can be used to decode a JSON document from a string that may
        have extraneous data at the end.
        """
        kw.setdefault('context', self)
        try:
            obj, end = self._scanner.iterscan(s, **kw).next()
        except StopIteration:
            raise ValueError("No JSON object could be decoded")
        return obj, end

def
raw_decode
(
self
,
s
,
*
*
kw
)
:
kw
.
setdefault
(
'context'
,
self
)
try
:
obj
,
end
=
self
.
_scanner
.
iterscan
(
s
,
*
*
kw
)
.
next
(
)
except
StopIteration
:
raise
ValueError
(
"No JSON object could be decoded"
)
return
obj
,
end


def encode_basestring(s):
    """
    Return a JSON representation of a Python string
    """
    def replace(match):
        return ESCAPE_DCT[match.group(0)]
    return '"' + ESCAPE.sub(replace, s) + '"'

def encode_basestring ( s ) : def replace ( match ) : return ESCAPE_DCT [ match . group ( 0 ) ] return '"' + ESCAPE . sub ( replace , s ) + '"'


Constructor for JSONEncoder with sensible defaults .

def __init__(self, skipkeys=False, ensure_ascii=True,
            check_circular=True, allow_nan=True, sort_keys=False,
            indent=None, separators=None, encoding='utf-8', default=None):
        """
        Constructor for JSONEncoder, with sensible defaults.

        If skipkeys is False, then it is a TypeError to attempt
        encoding of keys that are not str, int, long, float or None.  If
        skipkeys is True, such items are simply skipped.

        If ensure_ascii is True, the output is guaranteed to be str
        objects with all incoming unicode characters escaped.  If
        ensure_ascii is false, the output will be unicode object.

        If check_circular is True, then lists, dicts, and custom encoded
        objects will be checked for circular references during encoding to
        prevent an infinite recursion (which would cause an OverflowError).
        Otherwise, no such check takes place.

        If allow_nan is True, then NaN, Infinity, and -Infinity will be
        encoded as such.  This behavior is not JSON specification compliant,
        but is consistent with most JavaScript based encoders and decoders.
        Otherwise, it will be a ValueError to encode such floats.

        If sort_keys is True, then the output of dictionaries will be
        sorted by key; this is useful for regression tests to ensure
        that JSON serializations can be compared on a day-to-day basis.

        If indent is a non-negative integer, then JSON array
        elements and object members will be pretty-printed with that
        indent level.  An indent level of 0 will only insert newlines.
        None is the most compact representation.

        If specified, separators should be a (item_separator, key_separator)
        tuple.  The default is (', ', ': ').  To get the most compact JSON
        representation you should specify (',', ':') to eliminate whitespace.

        If specified, default is a function that gets called for objects
        that can't otherwise be serialized.  It should return a JSON encodable
        version of the object or raise a ``TypeError``.

        If encoding is not None, then all input strings will be
        transformed into unicode using that encoding prior to JSON-encoding.
        The default is UTF-8.
        """

        self.skipkeys = skipkeys
        self.ensure_ascii = ensure_ascii
        self.check_circular = check_circular
        self.allow_nan = allow_nan
        self.sort_keys = sort_keys
        self.indent = indent
        self.current_indent_level = 0
        if separators is not None:
            self.item_separator, self.key_separator = separators
        if default is not None:
            self.default = default
        self.encoding = encoding

def __init__ ( self , skipkeys = False , ensure_ascii = True , check_circular = True , allow_nan = True , sort_keys = False , indent = None , separators = None , encoding = 'utf-8' , default = None ) : self . skipkeys = skipkeys self . ensure_ascii = ensure_ascii self . check_circular = check_circular self . allow_nan = allow_nan self . sort_keys = sort_keys self . indent = indent self . current_indent_level = 0 if separators is not None : self . item_separator , self . key_separator = separators if default is not None : self . default = default self . encoding = encoding


Implement this method in a subclass such that it returns a serializable object for o or calls the base implementation ( to raise a TypeError ) .

def default(self, o):
        """
        Implement this method in a subclass such that it returns
        a serializable object for ``o``, or calls the base implementation
        (to raise a ``TypeError``).

        For example, to support arbitrary iterators, you could
        implement default like this::

            def default(self, o):
                try:
                    iterable = iter(o)
                except TypeError:
                    pass
                else:
                    return list(iterable)
                return JSONEncoder.default(self, o)
        """
        raise TypeError("%r is not JSON serializable" % (o,))

def
default
(
self
,
o
)
:
raise
TypeError
(
"%r is not JSON serializable"
%
(
o
,
)
)


Return a JSON string representation of a Python data structure .

def encode(self, o):
        """
        Return a JSON string representation of a Python data structure.

        >>> JSONEncoder().encode({"foo": ["bar", "baz"]})
        '{"foo": ["bar", "baz"]}'
        """
        # This is for extremely simple cases and benchmarks.
        if isinstance(o, basestring):
            if isinstance(o, str):
                _encoding = self.encoding
                if (_encoding is not None
                        and not (_encoding == 'utf-8')):
                    o = o.decode(_encoding)
            if self.ensure_ascii:
                return encode_basestring_ascii(o)
            else:
                return encode_basestring(o)
        # This doesn't pass the iterator directly to ''.join() because the
        # exceptions aren't as detailed.  The list call should be roughly
        # equivalent to the PySequence_Fast that ''.join() would do.
        chunks = list(self.iterencode(o))
        return ''.join(chunks)


Encode the given object and yield each string representation as available . For example :: for chunk in JSONEncoder () . iterencode ( bigobject ) : mysocket . write ( chunk )

def iterencode(self, o):
        """
        Encode the given object and yield each string
        representation as available.

        For example::

            for chunk in JSONEncoder().iterencode(bigobject):
                mysocket.write(chunk)
        """
        if self.check_circular:
            markers = {}
        else:
            markers = None
        return self._iterencode(o, markers)

def iterencode ( self , o ) : if self . check_circular : markers = { } else : markers = None return self . _iterencode ( o , markers )


Takes a string with numbers separated by period and possibly with / at end and outputs a string with 3 digit numbers separated by periods .

def fix_thread_string(tstr):
    """
    Takes a string with numbers separated by period and possibly with /
    at end, and outputs a string with 3 digit numbers separated by periods.
    """
    remove_slash = lambda s: s[:-1] if s[-1] == '/' else s
    three_digits = lambda s: "%03d" % int(s)
    return '.'.join( map(three_digits, map(remove_slash, tstr.split('.'))))

def fix_thread_string ( tstr ) : remove_slash = lambda s : s [ : - 1 ] if s [ - 1 ] == '/' else s three_digits = lambda s : "%03d" % int ( s ) return '.' . join ( map ( three_digits , map ( remove_slash , tstr . split ( '.' ) ) ) )


Returns an iterable of blog articles to be imported .

def get_articles(self):
        """Returns an iterable of blog articles to be imported."""
        raise NotImplementedError()

def get_articles ( self ) : raise NotImplementedError ( )


def get_article_tags(self, article):
        """Annotates an article with tags."""
        return article

def get_article_tags ( self , article ) : return article


Returns an iterable of comments associated with an article .

def get_article_comments(self, article):
        """Returns an iterable of comments associated with an article."""
        return []

def get_article_comments ( self , article ) : return [ ]


Returns an iterable of ( src dest ) redirect tuples .

def get_redirects(self):
        """Returns an iterable of (src, dest) redirect tuples."""
        return []