Metadata-Version: 1.0
Name: katagami
Version: 0.3.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...skip to next chapter:
        
            >>> def renderString_(t):
            ...     return renderString('<html xmlns:py="http://pypi.python.org/pypi/katagami" py:feature="strip-space"><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 xmlns:py="http://pypi.python.org/pypi/katagami" py:feature="strip-space"><body>%s</body></html>' % body)
        
        
        Pythonic evaluation
        -------------------
        
        scriping
        ~~~~~~~~
        
        `CDATA` is required and use `print`:
        
            >>> renderString_('''
            ... <py:script><![CDATA[
            ...     print '<p>hello, world</p>'
            ... ]]></py:script>
            ... ''')
            '<html><body><p>hello, world</p>\n</body></html>'
        
        
        Include python script file:
        
            >>> echo('sub-script.py', '''print "hello, world"''')
            >>> echoxml('template.html', '''
            ...     <p><py:script src="sub-script.py"/></p>
            ... ''')
            >>> renderFile(os.path.join(tmpdir, 'template.html'))
            '<html><body><p>hello, world\n</p></body></html>'
        
        
        evaluate XML attributes, textContent, innerXML
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        
        XML attributes (attribute value starts with XML namespace):
        
            >>> renderString_('''<p class="py:'python-expr'">hello, world</p>''')
            '<html><body><p class="python-expr">hello, world</p></body></html>'
        
        textContent:
        
            >>> renderString_('''<p py:text="'hello, world'"/>''')
            '<html><body><p>hello, world</p></body></html>'
        
        innerXML:
        
            >>> renderString_('''<div py:content="'hello, world&lt;hr/&gt;'"/>''')
            '<html><body><div>hello, world<hr/></div></body></html>'
        
        
        Python syntax as XML attributes
        -------------------------------
        
        `if`, `elif`, `else` statements
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        
            >>> renderString_('''
            ... <p py:if="0"/>
            ... <p py:elif="0"/>
            ... <p py:else="">output here</p>
            ... ''')
            '<html><body><p>output here</p></body></html>'
        
        
        loop statements
        ~~~~~~~~~~~~~~~
        
        `for` statement (attribute value is Pythonic `for` style):
        
            >>> renderString_('''<p py:for="i, j in enumerate(range(3))" py:text="i, j"/>''')
            '<html><body><p>(0, 0)</p><p>(1, 1)</p><p>(2, 2)</p></body></html>'
        
        `for`'s `else` is not supported.
        
        
        `while` statement:
        
            >>> renderString_('''
            ... <py:script><![CDATA[ i = [1, 2, 3] ]]></py:script>
            ... <p py:while="i">
            ...     <py:_ py:text="i[0]"/>
            ...     <py:script><![CDATA[ i = i[1:] ]]></py:script>
            ... </p>
            ... ''')
            '<html><body><p>1</p><p>2</p><p>3</p></body></html>'
        
        `while`'s `else` is not supported.
        
        
        And there is special variable named `__loop__`, it is loop counter:
        
            >>> renderString_('''
            ... <p py:for="i in range(0)" py:text="i"/>
            ... <p py:if="not __loop__">no for loop</p>
            ... <p py:while="0"/>
            ... <p py:if="not __loop__">no while loop</p>
            ... ''')
            '<html><body><p>no for loop</p><p>no while loop</p></body></html>'
        
        
        `try` statement
        ~~~~~~~~~~~~~~~~~~
        
            >>> renderString_('''
            ... <p py:try="" py:text="not_found"/>
            ... <p py:except="NameError as e" py:text="e"/>
            ... <p py:try="" py:text="'try'"/>
            ... <p py:except="" py:text="e"/>
            ... <p py:else="">no error</p>
            ... ''')
            "<html><body><p>name 'not_found' is not defined</p><p>try</p><p>no error</p></body></html>"
        
        
        `with` statement
        ~~~~~~~~~~~~~~~~
        
            >>> echo('msg.txt', 'hello, world')
            >>> renderString_('''
            ... <py:_ py:with="open(r'%s') as fp">
            ...     <p py:text="fp.read()"/>
            ...     <p py:text="fp.closed"/>
            ... </py:_>
            ... <p py:text="fp.closed"/>
            ... ''' % 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')
            >>> renderString_('''
            ... <py:_ py:with="open(r'%s') as fp, open(r'%s') as fp2">
            ...     <p py:text="fp.read()"/>
            ...     <p py:text="fp2.read()"/>
            ... </py:_>
            ... ''' % (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 the context by keyword arguments:
        
            >>> renderString_('''
            ... <p py:def="myfunc">hello, <py:_ py:text="msg"/></p>
            ... <py:_ py:content="myfunc(msg='world')"/>
            ... ''')
            '<html><body><p>hello,world</p></body></html>'
        
        
        Include another template
        ------------------------
        
        Simply, include all elements:
        
            >>> echoxml('sub-template.html', '<p>hello, world</p>')
            >>> echoxml('template.html', '<py:include src="sub-template.html"/>')
            >>> renderFile(os.path.join(tmpdir, 'template.html'))
            '<html><body><html><body><p>hello, world</p></body></html></body></html>'
        
        XUL like XML overlay:
        
            >>> echoxml('sub-template.html', '''
            ... <p py:insertbefore="myid">before</p>
            ... <p py:replace="myid">hello, world</p>
            ... <p py:insertafter="myid">after</p>
            ... ''')
            >>> echoxml('template.html', '''
            ...     <py:overlay src="sub-template.html"/>
            ...     <p id="myid"/>
            ... ''')
            >>> renderFile(os.path.join(tmpdir, 'template.html'))
            '<html><body><p>before</p><p id="myid">hello, world</p><p>after</p></body></html>'
        
        `id` attribute is automatically set from `replace` attribute's value.
        
        And special variable named `__file__` means that pathname of template file:
        
            >>> echoxml('sub-template.html', '<p py:replace="fragment" py:text="os.path.basename(__file__)"/>')
            >>> echoxml('template.html', '''
            ... <py:script><![CDATA[ import os ]]></py:script>
            ... <p py:text="os.path.basename(__file__)"/>
            ... <py:overlay src="sub-template.html"/>
            ... <p id="fragment"/>
            ... ''')
            >>> renderFile(os.path.join(tmpdir, 'template.html'))
            '<html><body><p>template.html</p><p id="fragment">sub-template.html</p></body></html>'
        
        
        namespace (scope)
        -----------------
        
        The namespace is flat like python module and nested in function:
        
            >>> renderString_('''
            ... <py:script><![CDATA[ a = b = 0 ]]></py:script>
            ... <py: py:def="myfunc">
            ...     <py:script><![CDATA[
            ...         global a
            ...         print 'a=%d,' % a
            ...         print 'b=%d,' % b
            ...         a = b = 1
            ...     ]]></py:script>
            ... </py:>
            ... <py: py:text="myfunc()"/>
            ... (a, b)=<py: py:text="a, b"/>
            ... ''')
            '<html><body>a=0,\nb=0,\n(a, b)=(1, 0)</body></html>'
        
        
        In included script file:
        
            >>> echo('sub-script.py', '''
            ... global msg
            ... msg = 'hello, world'
            ... msg2 = 'hello, world'
            ... global myfunc
            ... def myfunc(name):
            ...     return 'hello, ' + name
            ... ''')
            >>> echoxml('template.html', '''
            ...     <py:script src="sub-script.py"/>
            ...     <p py:text="msg"/>
            ...     <p py:try="" py:text="msg2"/>
            ...     <p py:except="NameError as e" py:text="e"/>
            ...     <p py:text="myfunc('world')"/>
            ... ''')
            >>> renderFile(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>"
        
        
        In included template file:
        
            >>> echoxml('sub-template.html', '''
            ...     <p py:replace="myid">hello, world</p>
            ...     <py:script><![CDATA[
            ...         global msg
            ...         msg = 'hello, world'
            ...     ]]></py:script>
            ...     <p py:def="global myfunc" py:text="text"/>
            ... ''')
            >>> echoxml('template.html', '''
            ...     <py:overlay src="sub-template.html"/>
            ...     <p id="myid"/>
            ...     <p py:text="msg"/>
            ...     <py: py:content="myfunc(text='hello, world')"/>
            ... ''')
            >>> renderFile(os.path.join(tmpdir, 'template.html'))
            '<html><body><p id="myid">hello, world</p><p>hello, world</p><p>hello, world</p></body></html>'
        
        
        Features
        --------
        
        strip-space
        ~~~~~~~~~~~
        
            >>> renderString('''<html xmlns:py="http://pypi.python.org/pypi/katagami"
            ...                       py:feature="strip-space"><body>
            ...     <p> spaces after tag or before tag are stripped. </p>
            ... </body></html>''')
            '<html><body><p>spaces after tag or before tag are stripped.</p></body></html>'
        
        
        strip-comment
        ~~~~~~~~~~~~~
        
            >>> renderString('''<html xmlns:py="http://pypi.python.org/pypi/katagami"
            ...                       py:feature="strip-space strip-comment"><body>
            ...     <!-- comment will be strippd. -->
            ... </body></html>''')
            '<html><body></body></html>'
        
        
        entity-variable
        ~~~~~~~~~~~~~~~
        
        Expand entity starts with special xmlns prefix:
        
            >>> renderString('''<html xmlns:py="http://pypi.python.org/pypi/katagami"
            ...                       py:feature="strip-space entity-variable"><body>
            ...     <py:script><![CDATA[
            ...         msg = 'hello,world'
            ...     ]]></py:script>
            ...     &py:msg;
            ... </body></html>''')
            '<html><body>hello,world</body></html>'
        
        
        compile-coffeescript
        ~~~~~~~~~~~~~~~~~~~~
        
        If CoffeeScrip compiler (coffee) is installed and `compile-cofeescript`
        feature flag is set, template engine converts
        '<script type="text/coffeescript"/>' to
        '<script type="application/javascript"/>' by coffee. But `src` attributes is
        not supported.
        
        
        compile-scss
        ~~~~~~~~~~~~
        
        If pyScss (http://pypi.python.org/pypi/pyScss) is installed and `compile-scss`
        feature flag is set, template engine converts '<style type="text/scss"/>' to
        '<style type="text/css"/>' by pyScss.
        
        
        Encoding
        --------
        
        Template engine detects file encoding and encodes to unicode for inner use,
        returns unicode or decoded str. Python script file encoding is PEP 0263 style,
        XML file encoding is XML header ('<?xml encoding="NAME"?>').
        
        
        Techniques and notices
        ----------------------
        
        This module is wrote under assuming that sys.setdefaultencoding('utf-8').
        
        
        The attribute order is important:
        
            >>> renderString_('''
            ... <p py:if="0" py:for="i in range(2)" py:text="i"/>
            ... <p py:for="i in range(2)" py:if="i > 0" py:text="i"/>
            ... ''')
            '<html><body><p>1</p></body></html>'
        
        
        If you need closing tag, then write below (This trick is not required for
        `html`'s `textarea`):
        
            >>> renderString_('''
            ... <textarea></textarea>
            ... <div></div>
            ... <div><py:/></div>
            ... ''')
            '<html><body><textarea></textarea><div/><div></div></body></html>'
        
        
        Entities will not be expanded:
        
            >>> renderString_('''&nbsp;&unknown_entity;''')
            '<html><body>&nbsp;&unknown_entity;</body></html>'
        
        
        All unsupported tags will be stripped:
        
            >>> renderString_('''<py:unknownTag/><py:>not strip</py:>''')
            '<html><body>not strip</body></html>'
        
        But unsupported attributes will occur exception:
        
            >>> renderString_('''<p py:unknown_attr_0123456789=""/>''')
            Traceback (most recent call last):
            ...
            SyntaxError: unknown statement unknown_attr_0123456789
        
        
        Special variables are available in some cases:
         * __file__ = str -> path of file (template or script)
         * __noloop__ = bool -> whether loop statements executed
         * _ = 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.
        
        History
        -------
        * 0.3.0 change specification (required xmlns, for_ -> for, remove python tag,
                add script tag, add include tag, add text attribute, add content
                attribute, add overlay tag, add insertbefore attribute, add
                insertafter attribute, add replace attribute), this version is not
                compatible with version 0.2.0
        * 0.2.0 change exception handling, fix encoding handling
        * 0.1.2 fix encoding handling, add new commandline handling
        * 0.1.1 update document for PyPI
        * 0.1.0 first release
        
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
