Metadata-Version: 1.0
Name: katagami
Version: 0.1.0
Summary: katagami - a very simple xml template engine.
Home-page: http://pypi.python.org/pypi/katagami
Author: chrono-meter@gmx.net
Author-email: chrono-meter@gmx.net
License: PSF
Description: katagami - a very simple xml template engine.
        =============================================
        
        
        # setup...
        >>> def testfile(file):
        ...     if not hasattr(file, 'read'):
        ...         with open(file) as fp:
        ...             result = render(fp)
        ...     else:
        ...         result = render(file)
        ...     if sys.platform != 'cli': # IronPython doesn't implement unicode.
        ...         result = result.encode()
        ...     return result
        >>> def teststr(t):
        ...     return testfile(StringIO('<html><body>%s</body></html>' % t))
        >>> def echo(name, body):
        ...     with open(os.path.join(tmpdir, name), 'w') as fp:
        ...         fp.write(body)
        >>> def echoxml(name, body):
        ...     echo(name, '<html><body>%s</body></html>' % body)
        
        
        Pythonic evaluation
        -------------------
        
        Dump the value (call `eval` with attribute value):
        >>> teststr('''<python value="'hello, world'"/>''')
        '<html><body>hello, world</body></html>'
        
        By the default, xml entities are escaped in `value` attribute of `python` element:
        >>> teststr('''<python value="'&lt;p&gt;hello, world&lt;/p&gt;'" escape="false"/>''')
        '<html><body><p>hello, world</p></body></html>'
        
        
        By the default, exceptions are suppressed:
        >>> teststr('''<python value="not_found"/>''')
        '<html><body></body></html>'
        
        Use `__mode__` for dump exceptions (and see a helpful traceback):
        >>> teststr('''<python __mode__="strict" value="not_found"/>''') # fails in IronPython
        '<html><pre>Traceback (most recent call last):\n  File "&lt;string&gt;", line 1, in Element "body"\n  File "&lt;string&gt;", line 1, in Element "python"\n  File "&lt;string&gt;", line 1, in Element "python" at line 1-1\n    not_found\nNameError: name \'not_found\' is not defined\n</pre></html>'
        
        
        Attribute evaluation (attribute value starts with 'python:'):
        >>> teststr('''<p class="python:'python-expr'">hello, world</p>''')
        '<html><body><p class="python-expr">hello, world</p></body></html>'
        
        
        Pythonic statements
        -------------------
        
        All statements are available in all elements.
        
        `if`, `elif`, `else` statements:
        >>> teststr('''
        ... <p if="0"/>
        ... <p elif="0"/>
        ... <p else="">output here</p>
        ... ''')
        '<html><body><p>output here</p></body></html>'
        
        
        `for` statement (attribute value is Pythonic for style):
        >>> teststr('''<p for_="i, j in enumerate(range(3))"><python value="i, j"/></p>''')
        '<html><body><p>(0, 0)</p><p>(1, 1)</p><p>(2, 2)</p></body></html>'
        
        
        `while` statement:
        >>> teststr('''
        ... <python><![CDATA[ i = [1, 2, 3] ]]></python>
        ... <p while="i">
        ...     <python value="i[0]"/>
        ...     <python><![CDATA[ i = i[1:] ]]></python>
        ... </p>
        ... ''')
        '<html><body><p>1</p><p>2</p><p>3</p></body></html>'
        
        
        `except` statement:
        >>> teststr('''
        ... <python except="StandardError as e"><![CDATA[ not_found ]]></python>
        ... <python value="e"/>
        ... <python except="StandardError"><![CDATA[ not_found ]]></python>
        ... ''')
        "<html><body>name 'not_found' is not defined</body></html>"
        
        
        `with` statement:
        >>> echo('msg.txt', 'hello, world')
        >>> teststr('''
        ... <python with="open(r'%s') as fp">
        ...     <p><python value="fp.read()"/></p>
        ...     <p><python value="fp.closed"/></p>
        ... </python>
        ... <p><python value="fp.closed"/></p>
        ... ''' % os.path.join(tmpdir, 'msg.txt'))
        '<html><body><p>hello, world</p><p>False</p><p>True</p></body></html>'
        
        Multi items are supported (ex. 'with a, b: pass').
        >>> echo('msg2.txt', 'hello, world')
        >>> teststr('''
        ... <python with="open(r'%s') as fp, open(r'%s') as fp2">
        ...     <p><python value="fp.read()"/></p>
        ...     <p><python value="fp2.read()"/></p>
        ... </python>
        ... ''' % (os.path.join(tmpdir, 'msg.txt'), os.path.join(tmpdir, 'msg2.txt')))
        '<html><body><p>hello, world</p><p>hello, world</p></body></html>'
        
        
        `def` statement (give context by keyword arguments):
        >>> teststr('''
        ... <p def="myfunc">hello, <python value="msg"/></p>
        ... <python value="myfunc(msg='world')" escape="false"/>
        ... ''')
        '<html><body><p>hello,world</p></body></html>'
        
        
        Embedded python script
        ----------------------
        
        `CDATA` is required and `write` is function:
        >>> teststr('''
        ... <python><![CDATA[
        ...     write('<p>hello, world</p>')
        ... ]]></python>
        ... ''')
        '<html><body><p>hello, world</p></body></html>'
        
        and escape xml entities:
        >>> teststr('''
        ... <python><![CDATA[
        ...     write('<p>', 'hello, world', '</p>', escape=True)
        ... ]]></python>
        ... ''')
        '<html><body>&lt;p&gt;hello, world&lt;/p&gt;</body></html>'
        
        
        Include python script file:
        >>> echo('sub-script.py', '''write('hello, world')''')
        >>> echoxml('template.html', '''
        ...     <p><python src="sub-script.py"/></p>
        ... ''')
        >>> testfile(os.path.join(tmpdir, 'template.html'))
        '<html><body><p>hello, world</p></body></html>'
        
        and share variables:
        >>> echo('sub-script.py', '''
        ... global msg 
        ... msg = 'hello, world'
        ... msg2 = 'hello, world'
        ... global myfunc
        ... def myfunc(name):
        ...     return 'hello, ' + name
        ... ''')
        >>> echoxml('template.html', '''
        ...     <python src="sub-script.py"/>
        ...     <p><python value="msg"/></p>
        ...     <p>
        ...         <python value="msg2" __mode__="strict" except="NameError as e"/>
        ...         <python value="e"/>
        ...     </p>
        ...     <p><python value="myfunc('world')"/></p>
        ... ''')
        >>> testfile(os.path.join(tmpdir, 'template.html'))
        "<html><body><p>hello, world</p><p>name 'msg2' is not defined</p><p>hello, world</p></body></html>"
        
        
        Include another template
        ------------------------
        
        Simply, include all elements:
        >>> echoxml('sub-template.html', '<p>hello, world</p>')
        >>> echoxml('template.html', '<python template="sub-template.html"/>')
        >>> testfile(os.path.join(tmpdir, 'template.html'))
        '<html><body><html><body><p>hello, world</p></body></html></body></html>'
        
        Then include a part of elements:
        >>> echoxml('sub-template.html', '<p id="myid">hello, world</p>')
        >>> echoxml('template.html',
        ...      '<python template="sub-template.html" fragment="myid"/>')
        >>> testfile(os.path.join(tmpdir, 'template.html'))
        '<html><body><p id="myid">hello, world</p></body></html>'
        
        And share variables:
        >>> echoxml('sub-template.html', '''
        ...     <p id="myid">hello, world</p>
        ...     <python><![CDATA[
        ...         global msg
        ...         msg = 'hello, world'
        ...     ]]></python>
        ...     <p def="global myfunc"><python value="text"/></p>
        ... ''')
        >>> echoxml('template.html', '''
        ...     <python template="sub-template.html" fragment="myid"/>
        ...     <p><python value="msg"/></p>
        ...     <python value="myfunc(text='hello, world')" escape="false"/>
        ... ''')
        >>> testfile(os.path.join(tmpdir, 'template.html'))
        '<html><body><p id="myid">hello, world</p><p>hello, world</p><p>hello, world</p></body></html>'
        
        
        Techniques and notices
        ----------------------
        
        This module is wrote under assuming that sys.setdefaultencoding('utf-8').
        
        This module works with null xml namespace, but doesn't remove any namespace:
        >>> testfile(StringIO('''<?xml version="1.0"?>
        ... <root xmlns    = "http://default-namespace.org/"
        ...       xmlns:py = "http://www.python.org/ns/">
        ...     <py:elem1 py:if="0"/>
        ...     <elem2 xmlns="" />
        ...     <py:elem3 if="0"/>
        ... </root>'''))
        '<?xml version="1.0"?>\n<root xmlns="http://default-namespace.org/" xmlns:py="http://www.python.org/ns/"><py:elem1 py:if="0"/><elem2 xmlns=""/></root>'
        
        
        The namespace is flat like python module and nested in function:
        >>> teststr('''
        ... <python><![CDATA[ a = b = 0 ]]></python>
        ... <python def="myfunc"><![CDATA[
        ...     global a
        ...     write('a = %d\\n' % a)
        ...     write('b = %d\\n' % b)
        ...     a = b = 1
        ... ]]></python>
        ... <python value="myfunc()"/>
        ... <python value="a, b"/>
        ... ''')
        '<html><body>a = 0\nb = 0\n(1, 0)</body></html>'
        
        
        By the default, White spaces and comments are stripped:
        >>> teststr('''<p><!-- comment --> hello, world </p>''')
        '<html><body><p>hello, world</p></body></html>'
        
        Use `direct` mode:
        >>> teststr('''<p __mode__="direct"><!-- comment --> hello, world </p>''')
        '<html><body><p><!-- comment --> hello, world </p></body></html>'
        
        
        The attribute order is important:
        >>> teststr('''
        ... <p if="0" for_="i in range(2)"><python value="i"/></p>
        ... <p for_="i in range(2)" if="i > 0"><python value="i"/></p>
        ... ''')
        '<html><body><p>1</p></body></html>'
        
        
        If you need closing tag such as `textarea`, then write below:
        >>> teststr('''<textarea><python/></textarea>''')
        '<html><body><textarea></textarea></body></html>'
        
        
        Entities will not be expanded:
        >>> teststr('''&nbsp;&unknown_entity;''')
        '<html><body>&nbsp;&unknown_entity;</body></html>'
        
        
        Special variables are available in some cases:
         * __file__ = str -> path of file (template or script)
         * __noloop__ = bool -> whether loop statements executed
                                (and when not `strict` mode)
         * _ = object -> temporary value when extracting variables
        
        Special utility functions are available, see default_namespace.
        
        Special string codecs:
         * percent, uri - known as encodeURIComponent, decodeURIComponent
         * xml - escape '<', '>', '&'
        
        For more information, see `Element` class implementation.
        
Platform: UNKNOWN
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Python Software Foundation License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 2.7
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content :: CGI Tools/Libraries
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Text Processing :: Markup :: HTML
Classifier: Topic :: Text Processing :: Markup :: XML
