o !bk@sZdZddlZddlmZmZddlmZddlmZm Z m Z m Z m Z ddl mZmZmZgdZdZGd d d eZeeGd d d eZd dZGdddeZGdddeZGdddeZGdddeZGdddeZGdddeZGdddeZGdddeZ Gdd d eZ!Gd!d"d"eZ"Gd#d$d$eZ#Gd%d&d&eZ$dS)'z2Implementation of the various template directives.N)QNameStream)Path)TemplateRuntimeErrorTemplateSyntaxErrorEXPR_apply_directives _eval_expr) Expression_ast_parse) AttrsDirectiveChooseDirectiveContentDirective DefDirective ForDirective IfDirectiveMatchDirectiveOtherwiseDirectiveReplaceDirectiveStripDirective WhenDirective WithDirectivezrestructuredtext enc@seZdZdZddZdS) DirectiveMetaz#Meta class for template directives.cCs$|dd|d<t||||S)N directivetagname)lowerreplacetype__new__)clsnamebasesdr%)getattrr,sourcerr')r1r,r%r%r&__repr__bs zDirective.__repr__c Csjz|r t||j||jdpdWSty4}z|jd||jf7_t||j|||jp-dd}~ww)zpParses the given expression, raising a useful error message when a syntax error is encountered. lookupN% in expression "%s" of "%s" directiver)r filepathrG SyntaxErrormsgrrr6)r!r,r3r5r6errr%r%r&r/hs   zDirective._parse_exprNNr-r-)r-r-) r'r(r)r* __slots__r7 classmethodr<rBrEr/r%r%r%r&r+'s   r+cs$fdd|ffdd S)zTakes the AST representation of an assignment, and returns a function that applies the assignment of a given value to a dictionary. cs:t|tjrtfdd|jDSt|tjr|jSdS)Ncsg|]}|qSr%r%).0child_namesr%r& }z/_assignment.._names..) isinstancer TupletupleeltsNameid)noderRr%r&rS{s  z_assignment.._namescsBt|turtt|D] }|||||q dS|||<dSr.)rrXrangelen)datar2namesidx)_assignr%r&rbs  z_assignment.._assignr%)astr%)rbrSr& _assignmentws rdc@eZdZdZgZddZdS)r a_Implementation of the ``py:attrs`` template directive. The value of the ``py:attrs`` attribute should be a dictionary or a sequence of ``(name, value)`` tuples. The items in that dictionary or sequence are added as attributes to the element: >>> from genshi.template import MarkupTemplate >>> tmpl = MarkupTemplate('''
    ...
  • Bar
  • ...
''') >>> print(tmpl.generate(foo={'class': 'collapse'}))
  • Bar
>>> print(tmpl.generate(foo=[('class', 'collapse')]))
  • Bar
If the value evaluates to ``None`` (or any other non-truth value), no attributes are added: >>> print(tmpl.generate(foo=None))
  • Bar
c "fdd}t||S)Nc3st\}\}}}tj}|r>t|tr,ztt|}Wnty+g}Yn wt|ts5|}|dd|DO}|||f|fVD]}|VqHdS)NcSs2g|]\}}t||durt|pdfqSr.)rsix text_typestrip)rPnvr%r%r&rTs z>AttrsDirective.__call__.._generate..) nextr r,rVriter StopIterationlistitems)kindtagattribr;attrseventr@r1r:rAr%r& _generates&   z*AttrsDirective.__call__.._generaterr1r:r?r@rArwr%rvr&rBszAttrsDirective.__call__Nr'r(r)r*rNrBr%r%r%r&r s r c@ eZdZdZgZeddZdS)raImplementation of the ``py:content`` template directive. This directive replaces the content of the element with the result of evaluating the value of the ``py:content`` attribute: >>> from genshi.template import MarkupTemplate >>> tmpl = MarkupTemplate('''
    ...
  • Hello
  • ...
''') >>> print(tmpl.generate(bar='Bye'))
  • Bye
cCs`t|turtd|jg|ddR|j||g|ddR}d|dt||f|dgfS)Nz3The content directive can not be used as an elementr8rr-)rdictrrIr/rr!r3r:r2r4r;r,r%r%r&r<s  zContentDirective.attachNr'r(r)r*rNrOr<r%r%r%r&rs rcsFeZdZdZgdZd ddZefddZd d Zd d Z Z S)raImplementation of the ``py:def`` template directive. This directive can be used to create "Named Template Functions", which are template snippets that are not actually output during normal processing, but rather can be expanded from expressions in other places in the template. A named template function can be used just like a normal Python function from template expressions: >>> from genshi.template import MarkupTemplate >>> tmpl = MarkupTemplate('''
...

... ${greeting}, ${name}! ...

... ${echo('Hi', name='you')} ...
''') >>> print(tmpl.generate(bar='Bye'))

Hi, you!

If a function does not require parameters, the parenthesis can be omitted in the definition: >>> tmpl = MarkupTemplate('''
...

... Hello, world! ...

... ${helloworld()} ...
''') >>> print(tmpl.generate(bar='Bye'))

Hello, world!

)r"args star_args dstar_argsdefaultsNr-c Cst|d||||t|j}g|_d|_d|_i|_t|t j r|j j |_ |jD]}tt dr.functionr-)ror"r'frames)r1r:r?r@rArr%rr&rB+s zDefDirective.__call__cCsdt|j|jfSNz <%s "%s">)rr'r"r1r%r%r&rEKszDefDirective.__repr__Nr-r- r'r(r)r*rNr7rOr<rBrE __classcell__r%r%rr&rs(   rcsFeZdZdZddgZdddZefdd Zd d Zd d Z Z S)raImplementation of the ``py:for`` template directive for repeating an element based on an iterable in the context data. >>> from genshi.template import MarkupTemplate >>> tmpl = MarkupTemplate('''
    ...
  • ${item}
  • ...
''') >>> print(tmpl.generate(items=[1, 2, 3]))
  • 1
  • 2
  • 3
assignfilenameNr-cCspd|vr td|j|||dd\}}t|d}d|}t|jdj|_|j|_ t ||||||dS)Nz in z'"in" keyword missing in "for" directiver8execziter(%s)r) rrIsplitr rirdrr2rrr+r7)r1r2r3r4r5r6rrcr%r%r&r7^s  zForDirective.__init__cr)Neach)rr|rrrr<r9rr%r&r<irzForDirective.attachc ksrt|j||}|durdS|j}i}t|}|D]}|||||t||||D]} | Vq,|qdSr.)r r,rrorrr) r1r:r?r@rAiterablerritemrur%r%r&rBps   zForDirective.__call__cCdt|jSNz<%s>rr'rr%r%r&rEzForDirective.__repr__rrr%r%rr&rOs  rcs0eZdZdZgZefddZddZZS)raImplementation of the ``py:if`` template directive for conditionally excluding elements from being output. >>> from genshi.template import MarkupTemplate >>> tmpl = MarkupTemplate('''
... ${bar} ...
''') >>> print(tmpl.generate(foo=True, bar='Hello'))
Hello
crNtest)rr|rrrr<r9rr%r&r<rzIfDirective.attachcKs$t|j||}|rt||||SgSr.)r r,r)r1r:r?r@rAr2r%r%r&rBszIfDirective.__call__ r'r(r)r*rNrOr<rBrr%r%rr&rs  rc@sBeZdZdZgdZ  d ddZeddZd d Zd d Z dS)raImplementation of the ``py:match`` template directive. >>> from genshi.template import MarkupTemplate >>> tmpl = MarkupTemplate('''
... ... Hello ${select('@name')} ... ... ...
''') >>> print(tmpl.generate())
Hello Dude
)pathr4hintsNr-cCs<t|d||||t||j||_|pi|_|pd|_dS)Nr%)r+r7rrIrr4r)r1r2r3rr4r5r6r%r%r&r7s zMatchDirective.__init__cCsg}t|tur:|dddkr|d|dddkr&|d|dddkr5|d |d }|||t||g|d dR|fS) Nbufferrfalse not_bufferedoncetrue match_once recursive not_recursiverr8)rr|rrr frozenset)r!r3r:r2r4r;rr%r%r&r<s      zMatchDirective.attachcKs0|j|jjdd|jt||j|j|fgS)NT)ignore_context)_match_templatesrrrrorr4r>r%r%r&rBs zMatchDirective.__call__cCsdt|j|jjfSr)rr'rrDrr%r%r&rEszMatchDirective.__repr__rM) r'r(r)r*rNr7rOr<rBrEr%r%r%r&rs   rc@r{)ra=Implementation of the ``py:replace`` template directive. This directive replaces the element with the result of evaluating the value of the ``py:replace`` attribute: >>> from genshi.template import MarkupTemplate >>> tmpl = MarkupTemplate('''
... Hello ...
''') >>> print(tmpl.generate(bar='Bye'))
Bye
This directive is equivalent to ``py:content`` combined with ``py:strip``, providing a less verbose way to achieve the same effect: >>> tmpl = MarkupTemplate('''
... Hello ...
''') >>> print(tmpl.generate(bar='Bye'))
Bye
cCsbt|tur |d}|std|jg|ddR|j||g|ddR}dt||fgfS)Nr2z%missing value for "replace" directiver8)rr|rrrIr/rr}r%r%r&r<s   zReplaceDirective.attachNr~r%r%r%r&rs rc@re)raImplementation of the ``py:strip`` template directive. When the value of the ``py:strip`` attribute evaluates to ``True``, the element is stripped from the output >>> from genshi.template import MarkupTemplate >>> tmpl = MarkupTemplate('''
...
foo
...
''') >>> print(tmpl.generate())
foo
Leaving the attribute value empty is equivalent to a truth value. This directive is particulary interesting for named template functions or match templates that do not generate a top-level element: >>> tmpl = MarkupTemplate('''
...
... ${what} ...
... ${echo('foo')} ...
''') >>> print(tmpl.generate())
foo
c rf)Nc3sRjr tjrtt}D]}|V|}qdSD]}|Vq!dSr.)r,r rl)previousrurvr%r&rwsz*StripDirective.__call__.._generaterxryr%rvr&rBs zStripDirective.__call__Nrzr%r%r%r&rs rcs4eZdZdZddgZefddZddZZS)raImplementation of the ``py:choose`` directive for conditionally selecting one of several body elements to display. If the ``py:choose`` expression is empty the expressions of nested ``py:when`` directives are tested for truth. The first true ``py:when`` body is output. If no ``py:when`` directive is matched then the fallback directive ``py:otherwise`` will be used. >>> from genshi.template import MarkupTemplate >>> tmpl = MarkupTemplate('''
... 0 ... 1 ... 2 ...
''') >>> print(tmpl.generate())
1
If the ``py:choose`` directive contains an expression, the nested ``py:when`` directives are tested for equality to the ``py:choose`` expression: >>> tmpl = MarkupTemplate('''
... 1 ... 2 ...
''') >>> print(tmpl.generate())
2
Behavior is undefined if a ``py:choose`` block contains content outside a ``py:when`` or ``py:otherwise`` block. Behavior is also undefined if a ``py:otherwise`` occurs before ``py:when`` blocks. matchedr2crr)rr|rrrr<r9rr%r&r<QrzChooseDirective.attachcks^dt|jdg}|jrt|j|||d<|j|t||||D]}|Vq"|jdS)NF)boolr,r _choice_stackrrr)r1r:r?r@rAinforur%r%r&rBXs zChooseDirective.__call__rr%r%rr&r(s &rcs<eZdZdZdgZd ddZefddZd d ZZ S) rzImplementation of the ``py:when`` directive for nesting in a parent with the ``py:choose`` directive. See the documentation of the `ChooseDirective` for usage. rNr-cCs t|||||||j|_dSr.r+r7rIrr0r%r%r&r7j zWhenDirective.__init__crr)rr|rrrr<r9rr%r&r<nrzWhenDirective.attachcKs|jo|jd}|std|jgt|dddR|dr"gS|js;|ds;td|jgt|dddR|drU|d}|jrP|t|j||k}nt|}n tt|j||}||d<|sfgSt||||S)Nr-z>"when" directives can only be used inside a "choose" directiverr8rz?either "choose" or "when" directive must have a test expression)rrrrlr,r rr)r1r:r?r@rArr2rr%r%r&rBus2 zWhenDirective.__call__r) r'r(r)r*rNr7rOr<rBrr%r%rr&rbs rc@s(eZdZdZdgZd ddZddZdS) rzImplementation of the ``py:otherwise`` directive for nesting in a parent with the ``py:choose`` directive. See the documentation of `ChooseDirective` for usage. rNr-cCs t|d|||||j|_dSr.rr0r%r%r&r7rzOtherwiseDirective.__init__cKsZ|jo|jd}|std|jgt|dddR|dr"gSd|d<t||||S)Nr-zEan "otherwise" directive can only be used inside a "choose" directiverr8rT)rrrrlr)r1r:r?r@rArr%r%r&rBszOtherwiseDirective.__call__r)r'r(r)r*rNr7rBr%r%r%r&rs   rcsDeZdZdZdgZd ddZefddZd d Zd d Z Z S)raImplementation of the ``py:with`` template directive, which allows shorthand access to variables and expressions. >>> from genshi.template import MarkupTemplate >>> tmpl = MarkupTemplate('''
... $x $y $z ...
''') >>> print(tmpl.generate(x=42))
42 7 52
rANr-c Cst|d||||g|_|}z3t|d}|jD]'}t|tjs*t d|j |||j dd|j Dt |j|j ||jdfqWdStyi}z|jd||jf7_t ||j |||jpbdd}~ww)Nrz8only assignment allowed in value of the "with" directivecSsg|]}t|qSr%)rd)rPrjr%r%r&rTrUz*WithDirective.__init__..rFrHr)r+r7rArir rrVr AssignrrIrtargetsr r2rGrJrKrr6) r1r2r3r4r5r6rcr\rLr%r%r&r7s2       zWithDirective.__init__cr)NrA)rr|rrrr<r9rr%r&r<rzWithDirective.attachc ksfi}|||jD]\}}t|||}|D]} | ||qq t||||D]} | Vq'|dSr.)rrAr rr) r1r:r?r@rAframerr,r2rrur%r%r&rBs    zWithDirective.__call__cCrrrrr%r%r&rErzWithDirective.__repr__rrr%r%rr&rs  r)%r*rg genshi.corerr genshi.pathrgenshi.template.baserrrrr genshi.template.evalr r r __all__ __docformat__rr add_metaclassobjectr+rdr rrrrrrrrrrrr%r%r%r&s0  O5v42'/:.