;ņ
d³d?c           @   s¼  d  Z  d Z d Z d k Z d k Z d k Z d k l Z l Z y e	 e
 e f Wn( e j
 o d Z	 d Z
 d   Z n Xe i d  Z d	 Z d
 Z e i d  Z d   Z d f  d     YZ d Z d e f d     YZ d f  d     YZ h  d d <d d <d d <d d <d d <d d <d  d! <d" d# <d$ d% <d& d' <d( d) <d* d+ <d, d- <d. d/ <Z d0   Z e d1 j o- e   \ Z Z e d j o d2 e GHqøn d S(3   s  A simple, lightweight system for manipulating HTML (and XML, informally)
using a Pythonic object model.  `PyMeld` is a single Python module,
_PyMeld.py_.    This beta version requires Python 2.2 or above, but the
final production version may work with previous releases of Python (with
slightly limited features) if there's sufficient demand.

*Features:*

 o Allows program logic and HTML to be completely separated - a graphical
   designer can design the HTML in a visual HTML editor, without needing to
   deal with any non-standard syntax or non-standard attribute names.  The
   program code knows nothing about XML or HTML - it just deals with objects
   and attributes like any other piece of Python code.

 o Designed with common HTML-application programming tasks in mind.
   Populating an HTML form with a record from a database is a one-liner
   (using the `%` operator - see below).  Building an HTML table from a set
   of records is just as easy, as shown in the example below.

 o No special requirements for the HTML/XML (or just one: attribute values
   must be quoted) - so you can use any editor, and your HTML/XML doesn't
   need to be strictly valid.

 o Works by string substitution, rather than by decomposing and rebuilding the
   markup, hence has no impact on the parts of the page you don't manipulate.

 o Does nothing but manipulating HTML/XML, hence fits in with any other Web
   toolkits you're using.

 o Tracebacks always point to the right place - many Python/HTML mixing
   systems use exec or eval, making bugs hard to track down.


*Quick overview*

A `PyMeld.Meld` object represents an XML document, or a piece of one.
All the elements in a document with `id=name` attributes are made available
by a Meld object as `object.name`.  The attributes of elements are available
in the same way.  A brief example is worth a thousand words:

>>> from PyMeld import Meld
>>> xhtml = '''<html><body>
... <textarea id="message" rows="2" wrap="off">Type your message.</textarea>
... </body></html>
... '''
>>> page = Meld(xhtml)                # Create a Meld object from XHTML.
>>> print page.message                # Access an element within the document.
<textarea id="message" rows="2" wrap="off">Type your message.</textarea>
>>> print page.message.rows           # Access an attribute of an element.
2
>>> page.message = "New message."     # Change the content of an element.
>>> page.message.rows = 4             # Change an attribute value.
>>> del page.message.wrap             # Delete an attribute.
>>> print page                        # Print the resulting page.
<html><body>
<textarea id="message" rows="4">New message.</textarea>
</body></html>

So the program logic and the HTML are completely separated - a graphical
designer can design the HTML in a visual XHTML editor, without needing to
deal with any non-standard syntax or non-standard attribute names.  The
program code knows nothing about XML or HTML - it just deals with objects and
attributes like any other piece of Python code.  Populating an HTML form with
a record from a database is a one-liner (using the `%` operator - see below).
Building an HTML table from a set of records is just as easy, as shown in the
example below:


*Real-world example:*

Here's a data-driven example populating a table from a data source, basing the
table on sample data put in by the page designer.  Note that in the real world
the HTML would normally be a larger page read from an external file, keeping
the data and presentation separate, and the data would come from an external
source like an RDBMS.  The HTML could be full of styles, images, anything you
like and it would all work just the same.

>>> xhtml = '''<html><table id="people">
... <tr id="header"><th>Name</th><th>Age</th></tr>
... <tr id="row"><td id="name">Example name</td><td id="age">21</td></tr>
... </table></html>
... '''
>>> doc = Meld(xhtml)
>>> templateRow = doc.row.clone()  # Take a copy of the template row, then
>>> del doc.row                    # delete it to make way for the real rows.
>>> for name, age in [("Richie", 30), ("Dave", 39), ("John", 78)]:
...      newRow = templateRow.clone()
...      newRow.name = name
...      newRow.age = age
...      doc.people += newRow
>>> print re.sub(r'</tr>\s*', '</tr>\n', str(doc))  # Prettify the output
<html><table id="people">
<tr id="header"><th>Name</th><th>Age</th></tr>
<tr id="row"><td id="name">Richie</td><td id="age">30</td></tr>
<tr id="row"><td id="name">Dave</td><td id="age">39</td></tr>
<tr id="row"><td id="name">John</td><td id="age">78</td></tr>
</table></html>

Note that if you were going to subsequently manipulate the table, using
PyMeld or JavaScript for instance, you'd need to rename each `row`, `name`
and `age` element to have a unique name - you can do that by assigning
to the `id` attribute but I've skipped that to make the example simpler.

As the example shows, the `+=` operator appends content to an element -
appending `<tr>` elements to a `<table>` in this case.


*Shortcut: the % operator*

Using the `object.id = value` syntax for every operation can get tedious, so
there are shortcuts you can take using the `%` operator.  This works just like
the built-in `%` operator for strings.  The example above could have been
written like this:

>>> for name, age in [("Richie", 30), ("Dave", 39), ("John", 78)]:
...      doc.people += templateRow % (name, age)

The `%` operator, given a single value or a sequence, assigns values to
elements with `id`s in the order that they appear, just like the `%` operator
for strings.  Note that there's no need to call `clone()` when you're using
`%`, as it automatically returns a modified clone (again, just like `%` does
for strings).  You can also use a dictionary:

>>> print templateRow % {'name': 'Frances', 'age': 39}
<tr id="row"><td id="name">Frances</td><td id="age">39</td></tr>

The `%` operator is really useful when you have a large number of data items
- for example, populating an HTML form with a record from an RDBMS becomes a
one-liner.

Note that these examples are written for clarity rather than performance, and
don't necessarily scale very well - using `+=` to build up a result in a loop
is inefficient, and PyMeld's `%` operator is slower than Python's built-in
one.  See `toFormatString()` in the reference manual for ways to speed up this
kind of code.


*Element content*

When you refer to a named element in a document, you get a Meld object
representing that whole element:

>>> page = Meld('<html><span id="x">Hello world</span></html>')
>>> print page.x
<span id="x">Hello world</span>

If you just want to get the content of the element as string, use the
`_content` attribute:

>>> print page.x._content
Hello world

You can also assign to `_content`, though that's directly equivalent to
assigning to the tag itself:

>>> page.x._content = "Hello again"
>>> print page
<html><span id="x">Hello again</span></html>
>>> page.x = "Goodbye"
>>> print page
<html><span id="x">Goodbye</span></html>

The only time that you need to assign to `_content` is when you've taken a
reference to an element within a document:

>>> x = page.x
>>> x._content = "I'm back"
>>> print page
<html><span id="x">I'm back</span></html>

Saying `x = "I'm back"` would simply re-bind `x` to the string `"I'm back"`
without affecting the document.


*Version and license*

This is version 2.1.1 Beta of PyMeld, Copyright (c) 2003 Entrian Solutions.
It is released under the terms of the Sleepycat License (see the top of
_PyMeld.py_), which allows Open Source products to freely redistribute it
in source or binary form.  Commercial licensing is available for a fee;
contact _richie@entrian.com_ for more information.

Version 1.0 had a different API which is now deceased.  If you need advice
on upgrading your code to use the new API (which should be trivial), or
you need a copy of PyMeld 1.0, please contact _richie@entrian.com_.
s
   2.1.1 betas"   Richie Hindle <richie@entrian.com>N(   s
   StringTypes   UnicodeTypei   i    c         C   s
   |  Sd  S(   N(   s   x(   s   x(    (    s	   PyMeld.pys   boolō   s    s  (?ix)                 # Case-insensitive, verbose
    <(?P<tag>\w+)                                # Tag opens; capture its name
    (?:\s+\w+=(?P<quote1>["']).*?(?P=quote1))*   # Attributes
    \s*/?>                                       # Tag closes
    s¦  (?ix)                          # Case-insensitive, verbose
    <(?P<tag>\w+)                                # Tag opens; capture its name
    (?:\s+\w+=(?P<quote1>["']).*?(?P=quote1))*   # Attributes preceding 'id'
    \s+id=(?P<quote2>["'])(?P<id>%s)(?P=quote2)  # The 'id' tag
    (?:\s+\w+=(?P<quote3>["']).*?(?P=quote3))*   # Attributes following 'id'
    \s*/?>                                       # Tag closes
    sS   (?ix)
   (?P<space>\s+)
   (?P<name>%s)=(?P<quote>["'])(?P<value>.*?)(?P=quote)
   s.   (?i)\s+id=(?P<quote>["'])(?P<id>.*?)(?P=quote)c         C   s   t  |  } d } t i | |  } | } xQ | oI | } | | i	   d d 7} t i | d | | | | i
   ! } q+ W| Sd S(   s   Work around a possible RE bug:
    > m = re.search(r"<\w+(?:\s\w+='.*?')*\sid='x'>", "<A a='b'><B c='d' id='x'>")
    > m.span()
    (0, 25)
    i    i   s   .N(   s   openIDTagREs   ids   thisREs   starts   res   searchs   texts   matchs	   prevMatchs   spans   end(   s   ids   texts   thisREs	   prevMatchs   starts   match(    (    s	   PyMeld.pys   _findIDMatch  s     
 ,s   _MarkupHolderc           B   s    t  Z d  Z d   Z d   Z RS(   s\   Keeps hold of the markup string, so that it can be shared between
    multiple Meld objects.c         C   s   d |  _ | |  _ d  S(   Ni    (   s   selfs   counts   s(   s   selfs   s(    (    s	   PyMeld.pys   __init__&  s    	c         C   s6   | |  i | <| d j o |  i d |  i d <n d  S(   Ns   si   s   count(   s   values   selfs   __dict__s   names   count(   s   selfs   names   value(    (    s	   PyMeld.pys   __setattr__*  s    (   s   __name__s
   __module__s   __doc__s   __init__s   __setattr__(    (    (    s	   PyMeld.pys   _MarkupHolder#  s    	s+   You can't modify this read-only Meld objects   ReadOnlyErrorc           B   s   t  Z d  Z RS(   s3   Raised if you try to modify a readonly Meld object.(   s   __name__s
   __module__s   __doc__(    (    (    s	   PyMeld.pys   ReadOnlyError1  s    s   Meldc           B   s³   t  Z d  Z e d  Z d   Z e d  Z d   Z d   Z	 d   Z
 d   Z d   Z d	   Z d
   Z e d  Z d d  Z d   Z d   Z d   Z d   Z d   Z RS(   s  Represents an XML document, or a fragment of one.  Pass XML/XHTML
    source to the constructor.  You can then access all the elements with
    `id="name"` attributes as `object.name`, and all the attributes of the
    outermost element as `object.attribute`.c         C   sl   | |  _ | t j	 oR t | t  p t | t  o% t |  |  _	 d |  _
 t |  _ qh t d  n d S(   sH   Creates a `Meld` from XML source.  `readonly` does what it
        says.i’’’’s&   Melds must be constructed from stringsN(   s   readonlys   selfs	   _readonlys   sources   Nones
   isinstances
   StringTypes   UnicodeTypes   _MarkupHolders   _markups   _lastUpdates   _names	   TypeError(   s   selfs   sources   readonly(    (    s	   PyMeld.pys   __init__<  s     	 	c         C   sE   t  t |  i  } |  i | _ d | _ | | _ | i	 |  | Sd S(   s  Alternative constructor for internal use: makes a child Meld
        for a named element.  `start` is a shortcut - everywhere where this
        is used, we've already found the starting position of the child
        element as a side effect of determining that the element exists.i’’’’N(   s   Melds   Nones   selfs	   _readonlys	   newObjects   _markups   _lastUpdates   names   _names   _updatePositionss   start(   s   selfs   names   starts	   newObject(    (    s	   PyMeld.pys
   _makeChildL  s     		c         C   sž  |  i |  i i j o d Sn |  i t j oa t i t |  i i	  } | o t d  n | i d  |  _ | i   |  _ | i   |  _ n® | t j oL t |  i |  i i	  } | i d  |  _ | i   |  _ | i   |  _ nU t i t |  i i	 |  } | i d  |  _ | | i   |  _ | | i   |  _ |  i i	 |  i } d } d } xn ot i d |  i | |  } t i d |  i | |  } | o |  i |  _ |  _ Pq^| op | d j oA |  i | | i   d |  _ |  i | | i   d |  _ Pqę| d } | | i   d } q^| i   d | i   d j  o" | d } | | i   d } q^| d } | d j oA |  i | | i   d |  _ |  i | | i   d |  _ Pq^| | i   d } qeW|  i i |  _ d S(   s“   Finds the start and end positions of the start and end tag in
        the markup.  If the caller happens to know where the start tag starts,
        he can pass it in to save time.Ns)   This isn't any form of markup I recognizes   tagi   i    s   (?i)<%s(>|\s)s	   (?i)</%s>(   s   selfs   _lastUpdates   _markups   counts   _names   Nones   res   searchs	   openTagREs   ss   matchs
   ValueErrors   groups   _tagNames   starts
   _openStarts   ends   _openEnds   _findIDMatchs   rests   depths   poss	   openMatchs
   closeMatchs   _closeStarts	   _closeEnds   span(   s   selfs   starts	   openMatchs   rests   poss   depths
   closeMatchs   match(    (    s	   PyMeld.pys   _updatePositionsY  s\      
!

c         C   sV   |  i   |  i i |  i |  i !} t | |  } | o |  i | i
   Sn t Sd S(   sM   Returns the start position of the element with the given ID,
        or None.N(   s   selfs   _updatePositionss   _markups   ss   _openEnds   _closeStarts   subsets   _findIDMatchs   nodeIDs   matchs   starts   None(   s   selfs   nodeIDs   subsets   match(    (    s	   PyMeld.pys   _findElementFromID¤  s     
c         C   sM   | i d d  } | i d d  i d d  } t i d d |  } | Sd	 S(
   sX   Minimally quotes an attribute value, using `&quot;`, `&amp;`,
        `&lt;` and `&gt;`.s   "s   &quot;s   <s   &lt;s   >s   &gt;s   &(?![a-zA-Z0-9]+;)s   &amp;N(   s   values   replaces   res   sub(   s   selfs   value(    (    s	   PyMeld.pys   _quoteAttributeÆ  s
     c         C   s>   | i d d  i d d  } | i d d  i d d  Sd	 S(
   s:   Unquotes an attribute value quoted by `_quoteAttribute()`.s   &quot;s   "s   &amp;s   &s   &lt;s   <s   &gt;s   >N(   s   values   replace(   s   selfs   value(    (    s	   PyMeld.pys   _unquoteAttribute·  s     c         C   s  | d j o% |  i   |  i i |  i |  i !SnD | d d j o2 y |  i | SWqu t j
 o t	 |  qu Xn |  i   |  i
 |  } | t j	 o |  i | |  Sn |  i i |  i |  i !} t i t | |  } | o |  i | i d   Sn t	 d |  d S(   sŚ  `object.<name>`, if this Meld contains an element with an `id`
        attribute of `name`, returns a Meld representing that element.

        Otherwise, `object.<name>` returns the value of the attribute with
        the given name, as a string.  If no such attribute exists, an
        AttributeError is raised.

        `object._content` returns the content of the Meld, not including
        the enclosing `<element></element>`, as a string.

        >>> p = Meld('<p style="one">Hello <b id="who">World</b></p>')
        >>> print p.who
        <b id="who">World</b>
        >>> print p.style
        one
        >>> print p._content
        Hello <b id="who">World</b>
        >>> print p.who._content
        World
        s   _contenti    s   _s   values    No element or attribute named %rN(   s   names   selfs   _updatePositionss   _markups   ss   _openEnds   _closeStarts   __dict__s   KeyErrors   AttributeErrors   _findElementFromIDs   starts   Nones
   _makeChilds
   _openStarts   openTags   res   searchs   attributeREs   matchs   _unquoteAttributes   group(   s   selfs   names   starts   matchs   openTag(    (    s	   PyMeld.pys   __getattr__¼  s$     

c         C   s  | d d j o
 | d j o | |  i | <d Sn |  i o t t  n |  i   t | t	  p t | t
  o t |  } n | d j o6 |  i i |  i  | |  i i |  i |  i _ d Sn |  i |  } | t j	 ol |  i | |  } |  i i | i | i !| j o d Sn |  i i | i  | |  i i | i |  i _ n&|  i i |  i |  i !}
 t i t | |
  } |  i |  } | o | i   \ } } | i! d  } |
 |  d | i! d  | i! d  | | | f |
 | } |  i i |  i  | |  i i |  i |  i _ nS |  i d	 t$ |  i%  }	 d
 | | f } |  i i |	  | |  i i |	 |  i _ t( i) |  d j o | |  _* n d S(   s5  `object.<name> = value` sets the XML content of the element with an
        `id` of `name`, or if no such element exists, sets the value of the
        `name` attribute on the outermost element.  If the attribute is not
        already there, a new attribute is created.

        >>> p = Meld('<p style="one">Hello <b id="who">World</b></p>')
        >>> p.who = "Richie"
        >>> p.style = "two"
        >>> p.align = "center"
        >>> p.who.id = "newwho"
        >>> print p
        <p align="center" style="two">Hello <b id="newwho">Richie</b></p>
        i    s   _s   _contentNs   quotes   %s%s=%s%s%ss   spaces   namei   s    %s="%s"s   id(+   s   names   values   selfs   __dict__s	   _readonlys   ReadOnlyErrors   READ_ONLY_MESSAGEs   _updatePositionss
   isinstances
   StringTypes   UnicodeTypes   strs   _markups   ss   _openEnds   _closeStarts   _findElementFromIDs   starts   Nones
   _makeChilds   childs
   _openStarts	   _closeEnds   openTags   res   searchs   attributeREs   attributeMatchs   _quoteAttributes   escapedValues   spans   attributeStarts   attributeEnds   groups   quotes
   newOpenTags   lens   _tagNames   newAttributePoss   newAttributes   strings   lowers   _name(   s   selfs   names   values
   newOpenTags   attributeEnds   attributeMatchs   attributeStarts   escapedValues   starts   newAttributePoss   openTags   quotes   newAttributes   child(    (    s	   PyMeld.pys   __setattr__å  s>     

!. 2;2(c   	      C   s­  | d j o< |  i   |  i i |  i  |  i i |  i |  i _ d Sn | d d j o5 y |  i | =d SWq t j
 o t	 |  q Xn |  i
 o t t  n |  i   |  i |  } | t j	 oD |  i | |  } |  i i | i  |  i i | i |  i _ d Sn |  i i |  i |  i !} t i t | |  } | oV | i   \ } } | |  | | } |  i i |  i  | |  i i |  i |  i _ n t	 d |  d S(   są   Deletes the named element or attribute from the `Meld`:

        >>> p = Meld('<p style="one">Hello <b id="who">World</b></p>')
        >>> del p.who
        >>> del p.style
        >>> print p
        <p>Hello </p>
        s   _contentNi    s   _s    No element or attribute named %r(   s   names   selfs   _updatePositionss   _markups   ss   _openEnds   _closeStarts   __dict__s   KeyErrors   AttributeErrors	   _readonlys   ReadOnlyErrors   READ_ONLY_MESSAGEs   _findElementFromIDs   starts   Nones
   _makeChilds   childs
   _openStarts	   _closeEnds   openTags   res   searchs   attributeREs   attributeMatchs   spans   attributeStarts   attributeEnds
   newOpenTag(	   s   selfs   names
   newOpenTags   attributeEnds   starts   attributeMatchs   childs   attributeStarts   openTag(    (    s	   PyMeld.pys   __delattr__$  s4     
*


*2c         C   sÖ  |  i   } | i   t | d  o t | i  o | i   } | i   } nW t | d  o t	 | t
  p t	 | t  o t } t |  } n t } | g } | oµ xt | |  D] \ }	 } t	 | t
  p t	 | t  o t |  } n | i |	  } | t j	 oD | i |	 |  }
 | i i |
 i  | | i i |
 i | i _ qæ qæ Wnk| i   | i } x| o| i   } t	 | t
  p t	 | t  o t |  } n | i i | | i !} t d |  } | o t  d  n | i | i! d  | | i    }
 | i i |
 i  | | i i |
 i | i _ t" |  |
 i |
 i } | i | 7_ | i$ | 7_$ |
 i$ | } qzW| i i | | i !} t d |  } | o t  d  n | Sd S(   sĪ  `object % value`, `object % sequence`, or `object % dictionary` all
        mimic the `%` operator for strings:

        >>> xml = '<x><y id="greeting">Hello</y> <z id="who">World</z></x>'
        >>> x = Meld(xml)
        >>> print x % ("Howdy", "everybody")
        <x><y id="greeting">Howdy</y> <z id="who">everybody</z></x>
        >>> print x % {'who': 'all'}
        <x><y id="greeting">Hello</y> <z id="who">all</z></x>

        Assignment for sequences happens in the same order that nodes with
        'id' attributes appear in the document, not including the top-level
        node (because if the top-level node were included, you'd only ever
        be able to assign to that and nothing else):

        >>> xml = '''<a id="a">
        ... <b>  <!-- `b` has no ID, hence is ignored. -->
        ...     <c id="c">First one</c>
        ...     <d id="d">Second one</d>
        ... </b>
        ... <e id="e">Third one; the content includes 'f':
        ...     <f id="f">Removed when 'e' is assigned to</f>
        ... </e>
        ... </a>'''
        >>> a = Meld(xml)
        >>> print a % ('One, with a <z id="new">new</z> node', 'Two', 'Three')
        <a id="a">
        <b>  <!-- `b` has no ID, hence is ignored. -->
            <c id="c">One, with a <z id="new">new</z> node</c>
            <d id="d">Two</d>
        </b>
        <e id="e">Three</e>
        </a>

        Giving the wrong number of elements to `%` raises the same exceptions
        as the builtin string `%` operator.  Unlike the builtin `%` operator,
        dictionaries don't need to specify all the keys:

        >>> print x % "Howdy"
        Traceback (most recent call last):
        ...
        TypeError: not enough arguments
        >>> print x % ("Howdy", "everybody", "everywhere")
        Traceback (most recent call last):
        ...
        TypeError: not all arguments converted
        >>> print x % {"greeting": "Howdy"}
        <x><y id="greeting">Howdy</y> <z id="who">World</z></x>
        s   valuess   __getitem__s   [^'"]*s   not all arguments converteds   ids   not enough argumentsN(%   s   selfs   clones   news   _updatePositionss   hasattrs   valuess   callables   keyss   sequences
   isinstances
   StringTypes   UnicodeTypes   Nones   lists   zips   keys   values   strs   _findElementFromIDs   starts
   _makeChilds   childs   _markups   ss   _openEnds   _closeStarts   reverses   poss   pops   subsets   _findIDMatchs   matchs	   TypeErrors   groups   lens	   addedSizes	   _closeEnd(   s   selfs   valuess   subsets   sequences   poss   starts   news   matchs   keyss   keys   childs	   addedSizes   value(    (    s	   PyMeld.pys   __mod__O  sT    1 
 1	 !:
	 !%.c         C   sŗ   |  i   |  i i |  i |  i !} t i d |  } h  } x" | D] \ } } d | | | <qB Wt |  |  } t i | d d  } | o t i d d |  Sn t i d d |  Sd	 S(
   sO	  Converts a Meld object to a string, with the contents of any tags
        with `id` attributes replaced with `%s` or `%(id)s`.  This lets you
        use Python's built-in `%` operator rather than PyMeld's, which can
        speed things up considerably when you're looping over a lot of data.
        Here's the example from the main documentation, speeded up by using
        `toFormatString()` and by avoiding repeated use of the `+=` operator:

        >>> xhtml = '''<html><table id="people">
        ... <tr id="header"><th>Name</th><th>Age</th></tr>
        ... <tr id="row"><td id="name">Example</td><td id="age">21</td></tr>
        ... </table></html>
        ... '''
        >>> doc = Meld(xhtml)
        >>> rowFormat = doc.row.toFormatString()
        >>> rows = []
        >>> for name, age in [("Richie", 30), ("Dave", 39), ("John", 78)]:
        ...      rows.append(rowFormat % (name, age))
        >>> doc.people = '\n' + doc.header + ''.join(rows)
        >>> print re.sub(r'</tr>\s*', '</tr>\n', str(doc))  # Prettify
        <html><table id="people">
        <tr id="header"><th>Name</th><th>Age</th></tr>
        <tr id="row"><td id="name">Richie</td><td id="age">30</td></tr>
        <tr id="row"><td id="name">Dave</td><td id="age">39</td></tr>
        <tr id="row"><td id="name">John</td><td id="age">78</td></tr>
        </table></html>

        So the inner loop no longer contains any PyMeld calls at all - it only
        manipulates strings and lists.  Here's what `doc.row.toFormatString()`
        actually returns - note that this is a string, not a PyMeld object:

        >>> print doc.row.toFormatString()
        <tr id="row"><td id="name">%s</td><td id="age">%s</td></tr>

        You can ask for a format string that expects a dictionary rather than
        a tuple using the `useDict` parameter:

        >>> print doc.row.toFormatString(useDict=True)
        <tr id="row"><td id="name">%(name)s</td><td id="age">%(age)s</td></tr>

        If your markup contains `%` symbols, they are correctly quoted in the
        resulting format string:

        >>> doc = Meld("<html><p>10% <span id='drink'>gin</span>.</p></html>")
        >>> print doc.toFormatString()
        <html><p>10%% <span id='drink'>%s</span>.</p></html>
        >>> print doc.toFormatString() % 'vodka'
        <html><p>10% <span id='drink'>vodka</span>.</p></html>
        s   \bid=(["\'])([^"\']+)\1s   :PyMeldMarker'%s':s   %s   %%s   :PyMeldMarker'([^']+)':s   %(\1)ss   :PyMeldMarker'[^']+':s   %sN(   s   selfs   _updatePositionss   _markups   ss   _openEnds   _closeStarts   contents   res   findalls   quotesAndKeyss   keysToMarkerss   unusedQuotes   keys   strs   formats   strings   replaces   useDicts   sub(   s   selfs   useDicts   unusedQuotes   quotesAndKeyss   keys   keysToMarkerss   formats   content(    (    s	   PyMeld.pys   toFormatString»  s    0 
 i    c         C   s4   |  i   |  i i |  i |  i !} t | |  Sd S(   sf  Creates a clone of a `Meld`, for instance to change an attribute
        without affecting the original document:

        >>> p = Meld('<p style="one">Hello <b id="who">World</b></p>')
        >>> q = p.clone()
        >>> q.who = "Richie"
        >>> print q.who
        <b id="who">Richie</b>
        >>> print p.who
        <b id="who">World</b>
        N(	   s   selfs   _updatePositionss   _markups   ss
   _openStarts	   _closeEnds   markups   Melds   readonly(   s   selfs   readonlys   markup(    (    s	   PyMeld.pys   clone  s     
c         C   s`   t  | t  o' | i   | i i | i | i !} n |  i   |  i i |  i |  i !| Sd S(   só  `object1 + object2` turns both objects into strings and returns the
        concatenation of the strings:

        >>> a = Meld('<html><span id="x">1</span></html>')
        >>> b = Meld('<html><span id="y">2</span></html>')
        >>> c = Meld('<html><span id="z">3</span></html>')
        >>> print a + b
        <html><span id="x">1</span></html><html><span id="y">2</span></html>
        >>> print a.x + b.y + c.z
        <span id="x">1</span><span id="y">2</span><span id="z">3</span>
        N(	   s
   isinstances   others   Melds   _updatePositionss   _markups   ss
   _openStarts	   _closeEnds   self(   s   selfs   other(    (    s	   PyMeld.pys   __add__  s     

c         C   s)   |  i   | |  i i |  i |  i !Sd S(   s   See `__add__`N(   s   selfs   _updatePositionss   others   _markups   ss
   _openStarts	   _closeEnd(   s   selfs   other(    (    s	   PyMeld.pys   __radd__&  s     
c         C   s   |  i o t t  n t | t  o' | i   | i i	 | i
 | i !} n |  i   |  i i	 |  i  | |  i i	 |  i |  i _	 |  Sd S(   s  `object1 += object2` appends a string or a clone of a Meld to
        the end of another Meld's content.  This is used to build things
        like HTML tables, which are collections of other objects (eg. table
        rows).  See *Real-world example* in the main documentation.N(   s   selfs	   _readonlys   ReadOnlyErrors   READ_ONLY_MESSAGEs
   isinstances   others   Melds   _updatePositionss   _markups   ss
   _openStarts	   _closeEnds   _closeStart(   s   selfs   other(    (    s	   PyMeld.pys   __iadd__-  s     


.c         C   s+   |  i   t |  i i |  i |  i ! Sd S(   sė   Returns the XML that this `Meld` represents.  Don't call
        this directly - instead convert a `Meld` to a string using
        `str(object)`.  `print` does this automatically, which is why
        none of the examples calls `str`.N(   s   selfs   _updatePositionss   strs   _markups   ss
   _openStarts	   _closeEnd(   s   self(    (    s	   PyMeld.pys   __str__>  s     
c         C   s+   |  i   t |  i i |  i |  i ! Sd S(   s9  Returns the XML that this `Meld` represents.  Don't call
        this directly - instead convert a `Meld` to unicode using
        `unicode(object)`.  `print` does this automatically, which is why
        none of the examples calls `str`.  Note that PyMeld's ability to
        handle Unicode is largely untested.N(   s   selfs   _updatePositionss   unicodes   _markups   ss
   _openStarts	   _closeEnd(   s   self(    (    s	   PyMeld.pys   __unicode__G  s     
(   s   __name__s
   __module__s   __doc__s   Falses   __init__s
   _makeChilds   Nones   _updatePositionss   _findElementFromIDs   _quoteAttributes   _unquoteAttributes   __getattr__s   __setattr__s   __delattr__s   __mod__s   toFormatStrings   clones   __add__s   __radd__s   __iadd__s   __str__s   __unicode__(    (    (    s	   PyMeld.pys   Meld6  s$    	K				)	?	+	lG					s   entities and charrefss%  
>>> page = Meld('''<html><body>&bull; This "and&#160;that"...
... <span id="s" title="&quot;Quoted&quot; & Not">x</span></body></html>''')
>>> print page.s.title
"Quoted" & Not
>>> page.s.title = page.s.title     # Accept liberally, produce strictly.
>>> print page
<html><body>&bull; This "and&#160;that"...
<span id="s" title="&quot;Quoted&quot; &amp; Not">x</span></body></html>
>>> page.s.title = page.s.title + " <>"
>>> print page.s.title
"Quoted" & Not <>
>>> print page.s
<span id="s" title="&quot;Quoted&quot; &amp; Not &lt;&gt;">x</span>
s   assigning to _contentsĻ   
>>> page = Meld('''<html><span id="s">Old</span></html>''')
>>> page.s._content = "New"
>>> print page
<html><span id="s">New</span></html>
>>> page._content = "All new"
>>> print page
<html>All new</html>
s   deleting _contents   
>>> page = Meld('''<html><span id="s">Old</span></html>''')
>>> del page.s._content
>>> print page
<html><span id="s"></span></html>
s!   constructing from an unknown typesm   
>>> page = Meld(1)
Traceback (most recent call last):
...
TypeError: Melds must be constructed from strings
s"   accessing a non-existent attributes;  
>>> page = Meld('<html><body id="body"></body></html>')
>>> print page.spam
Traceback (most recent call last):
...
AttributeError: No element or attribute named 'spam'
>>> del page.spam
Traceback (most recent call last):
...
AttributeError: No element or attribute named 'spam'
>>> print page.body.spam    # For non-container Melds
Traceback (most recent call last):
...
AttributeError: No element or attribute named 'spam'
>>> del page.body.spam      # For non-container Melds
Traceback (most recent call last):
...
AttributeError: No element or attribute named 'spam'
s   add new thingssŅ   
>>> page = Meld('''<html><textarea id="empty"></textarea></html>''')
>>> page.empty = "Not any more"
>>> page.empty.cols = 60
>>> print page
<html><textarea cols="60" id="empty">Not any more</textarea></html>
s   readonlys3  
>>> page = Meld('''<html><span id='no'>No!</span></html>''', readonly=True)
>>> page.no = "Yes?"
Traceback (most recent call last):
...
ReadOnlyError: You can't modify this read-only Meld object

>>> page.no.attribute = "Yes?"
Traceback (most recent call last):
...
ReadOnlyError: You can't modify this read-only Meld object

>>> page.no += "More?"
Traceback (most recent call last):
...
ReadOnlyError: You can't modify this read-only Meld object

>>> del page.no
Traceback (most recent call last):
...
ReadOnlyError: You can't modify this read-only Meld object
s   copy from one to anothersB  
>>> a = Meld('<html><span id="one">One</span></html>')
>>> b = Meld('<html><span id="two">Two</span></html>')
>>> a.one = b.two
>>> print a
<html><span id="one"><span id="two">Two</span></span></html>
>>> b.two = "New"
>>> print a  # Checking for side-effects
<html><span id="one"><span id="two">Two</span></span></html>
s   mixed-type add, radd and iaddså   
>>> a = Meld('<html><span id="one">1</span></html>')
>>> print a.one + "x"
<span id="one">1</span>x
>>> print "x" + a.one
x<span id="one">1</span>
>>> a.one += "y<z></z>"
>>> print a
<html><span id="one">1y<z></z></span></html>
s   unicodesO  
>>> u = Meld(u'<html><span id="one">One</span></html>')
>>> a = Meld('<html><span id="two">Two</span></html>')
>>> u.one = a.two
>>> print repr(unicode(u))
u'<html><span id="one"><span id="two">Two</span></span></html>'
>>> a.two = Meld(u'<x a="Unicode Value"/>')
>>> print a
<html><span id="two"><x a="Unicode Value"/></span></html>
s   private attributessi  
>>> page = Meld('<html>x</html>')
>>> page._private = "Spam"
>>> print repr(page._private)
'Spam'
>>> print page
<html>x</html>
>>> del page._private
>>> print repr(page._private)
Traceback (most recent call last):
...
AttributeError: _private
>>> del page._private
Traceback (most recent call last):
...
AttributeError: _private
>>> print page
<html>x</html>
s	   no markups   
>>> page = Meld("Hello world")
>>> print page.spam
Traceback (most recent call last):
...
ValueError: This isn't any form of markup I recognize
s   nestings¹  
>>> page = Meld('''<html>
... <span id="all">Hello
...     <span id="who">World
...         <span id='extra'>and friends</span>
...     </span>!
...     <span id="goodbye">Goodbye</span>
... </span>
... </html>''')
>>> print page.all
<span id="all">Hello
    <span id="who">World
        <span id='extra'>and friends</span>
    </span>!
    <span id="goodbye">Goodbye</span>
</span>
>>> print page.extra
<span id='extra'>and friends</span>
s   re-bugs   
>>> page = Meld("<A a='a'><B b='b'><C c='c' id='x'></C></B></A>")
>>> print page.x    # Was "<B b='b'><C c='c' id='x'></C></B>"
<C c='c' id='x'></C>
c          C   s   d k  } y d k l } | i d  Wn t j
 o t } n Xd k }  | i |   } | o | i	   } | i   n | Sd S(   s   Tests the `PyMeld` module, performing code coverage analysis if
    `Entrian.Coverage` is available.  Returns `(failed, total)`, a la
    `doctest.testmod`.N(   s   Coverages   PyMeld(   s   doctests   Entrians   Coverages   starts   ImportErrors   Falses   PyMelds   testmods   results   getAnalysiss   analysiss   printAnalysis(   s   PyMelds   analysiss   doctests   Coverages   result(    (    s	   PyMeld.pys   test  s     		s   __main__s   All %d tests passed.(   s   __doc__s   __version__s
   __author__s   syss   strings   res   typess
   StringTypes   UnicodeTypes   Trues   Falses   bools	   NameErrors   compiles	   openTagREs   openIDTagREs   attributeREs   idREs   _findIDMatchs   _MarkupHolders   READ_ONLY_MESSAGEs	   Exceptions   ReadOnlyErrors   Melds   __test__s   tests   __name__s   faileds   total(   s   totals   Melds
   StringTypes	   openTagREs   faileds   res   bools   attributeREs   __version__s   Trues   openIDTagREs   strings   READ_ONLY_MESSAGEs
   __author__s   syss   tests   __test__s   _MarkupHolders   _findIDMatchs   Falses   idREs   UnicodeTypes   ReadOnlyError(    (    s	   PyMeld.pys   ?å   s6   	’ ’ !ŗ	!