o !b^@s.dZddlmZddlZddlZddlmZmZmZddl m Z m Z m Z m Z mZmZddlmZgdZdZGd d d eZGd d d eZGd ddeZGdddeZGdddeZddZdddZdddZGdddeZe eGdddeZ!Gddde!Z"e"j#Z#e"j$Z$e"j%Z%e"j&Z&dS) zBasic templating functionality.)dequeN) numeric_typesStringIOBytesIO)AttrsStreamStreamEventKindSTARTTEXT_ensure) ParseError)ContextDirectiveFactoryTemplate TemplateErrorTemplateRuntimeErrorTemplateSyntaxErrorBadDirectiveErrorzrestructuredtext enc@eZdZdZdddZdS)rz?Base exception class for errors related to template processing.NcCsT|durd}||_|dks|dkrd|j||f}t||||_||_||_dS)a9Create the exception. :param message: the error message :param filename: the filename of the template :param lineno: the number of line in the template at which the error occurred :param offset: the column number at which the error occurred Nzrz%s (%s, line %d))msg Exception__init__filenamelinenooffsetselfmessagerrrr6/usr/lib/python3/dist-packages/genshi/template/base.pyr!s   zTemplateError.__init__Nrr__name__ __module__ __qualname____doc__rrrrr rsrc@r)rz|Exception raised when an expression in a template causes a Python syntax error, or the template is not well-formed. NrcCs>t|tr|jdurt|d|jd}t||||dS)a8Create the exception :param message: the error message :param filename: the filename of the template :param lineno: the number of line in the template at which the error occurred :param offset: the column number at which the error occurred Nz (line %d)) isinstance SyntaxErrorrstrreplacerrrrrr r:s zTemplateSyntaxError.__init__r!r"rrrr r5src@r)rzException raised when an unknown directive is encountered when parsing a template. An unknown directive is any attribute using the namespace for directives, with a local name that doesn't match any registered directive. NrcCst|d|||dS)zCreate the exception :param name: the name of the directive :param filename: the filename of the template :param lineno: the number of line in the template at which the error occurred zbad directive "%s"N)rr)rnamerrrrr rPs zBadDirectiveError.__init__)Nrr"rrrr rHsrc@seZdZdZdS)rzfException raised when an the evaluation of a Python expression in a template causes an error. N)r#r$r%r&rrrr r\src@seZdZdZddZddZddZeZdd Zd d Z d d Z ddZ d!ddZ d!ddZ ddZddZddZddZddZdd ZdS)"r apContainer for template input data. A context provides a stack of scopes (represented by dictionaries). Template directives such as loops can push a new scope on the stack with data that should only be available inside the loop. When the loop terminates, that scope can get popped off the stack again. >>> ctxt = Context(one='foo', other=1) >>> ctxt.get('one') 'foo' >>> ctxt.get('other') 1 >>> ctxt.push(dict(one='frost')) >>> ctxt.get('one') 'frost' >>> ctxt.get('other') 1 >>> ctxt.pop() {'one': 'frost'} >>> ctxt.get('one') 'foo' c sbt|g_jj_jj_g_g_fdd}dfdd }|d||d|dS) zZInitialize the template context with the given keyword arguments as data. cs|vS)z]Return whether a variable with the specified name exists in the expression scope.r)r,rrr definedsz!Context.__init__..definedNcs ||S)zIf a variable of the specified name is defined, return its value. Otherwise, return the provided default value, or ``None``.get)r,defaultr-rr value_ofs z"Context.__init__..value_ofr.r2N) rframespopleftpop appendleftpush_match_templates _choice_stack setdefault)rdatar.r2rr-r r{s     zContext.__init__cCstt|jSr3)reprlistr4r-rrr __repr__szContext.__repr__cCs||dduS)zuReturn whether a variable exists in any of the scopes. :param key: the name of the variable N)_find)rkeyrrr __contains__szContext.__contains__cCs|jD] }||vr ||=qdS)zaRemove a variable from all scopes. :param key: the name of the variable Nr4)rrBframerrr __delitem__s zContext.__delitem__cCs"||\}}|durt||S)aGet a variables's value, starting at the current scope and going upward. :param key: the name of the variable :return: the variable value :raises KeyError: if the requested variable wasn't found in any scope N)rAKeyError)rrBvaluerErrr __getitem__szContext.__getitem__cCs t|S)zReturn the number of distinctly named variables in the context. :return: the number of variables in the context )lenitemsr-rrr __len__s zContext.__len__cCs||jd|<dS)zSet a variable in the current scope. :param key: the name of the variable :param value: the variable value rNrD)rrBrHrrr __setitem__szContext.__setitem__NcCs,|jD]}||vr|||fSq|dfS)a&Retrieve a given variable's value and the frame it was found in. Intended primarily for internal use by directives. :param key: the name of the variable :param default: the default value to return when the variable is not found NrDrrBr1rErrr rAs z Context._findcCs$|jD] }||vr||Sq|S)zGet a variable's value, starting at the current scope and going upward. :param key: the name of the variable :param default: the default value to return when the variable is not found rDrNrrr r0s  z Context.getcs*g|jD] }fdd|D7qS)zlReturn the name of all variables in the context. :return: a list of variable names csg|]}|vr|qSrr.0rBkeysrr z Context.keys..rD)rrErrQr rRs z Context.keyscsfddDS)zReturn a list of ``(name, value)`` tuples for all variables in the context. :return: a list of variables csg|] }||fqSrr/rOr-rr rSsz!Context.items..rQr-rr-r rKsz Context.itemscCs|jd|dS)z-Update the context from the mapping provided.rN)r4update)rmappingrrr rUszContext.updatecCdS)zwPush a new scope on the stack. :param data: the data dictionary to push on the context stack. Nr)rr<rrr r8z Context.pushcCrW)z&Pop the top-most scope from the stack.Nrr-rrr r6rXz Context.popcCs>t}|j|j|j|j|j|j|j|S)z%Create a copy of this Context object.)r r4r6extendr9r:)rctxtrrr copys  z Context.copyr3)r#r$r%r&rr?rChas_keyrFrIrLrMrAr0rRrKrUr8r6r[rrrr r bs$       r cCs,|r|dt||dd|fi|}|S)arApply the given directives to the stream. :param stream: the stream the directives should be applied to :param directives: the list of directives to apply :param ctxt: the `Context` :param vars: additional variables that should be available when Python code is executed :return: the stream with the given directives applied rr@N)iter)stream directivesrZvarsrrr _apply_directivess $racCs(|r||||}|r||S)aEvaluate the given `Expression` object. :param expr: the expression to evaluate :param ctxt: the `Context` :param vars: additional variables that should be available to the expression :return: the result of the evaluation )r8evaluater6)exprrZr`retvalrrr _eval_exprs   recCsN|r |||i|||r%|}||jd|dSdS)zExecute the given `Suite` object. :param suite: the code suite to execute :param ctxt: the `Context` :param vars: additional variables that should be available to the code rN)r8executer6r4rU)suiterZr`toprrr _exec_suite(s   ric@seZdZdZddZdS)DirectiveFactoryMetaz#Meta class for directive factories.cCs>d|vrt|d|d<dd|dD|d<t||||S)Nr_ _dir_by_namecSsg|]}|dqS)r@r)rP directiverrr rS@sz0DirectiveFactoryMeta.__new__.. _dir_order)dicttype__new__)clsr,basesdrrr rp=szDirectiveFactoryMeta.__new__N)r#r$r%r&rprrrr rj:s rjc@s&eZdZdZgZ ddZddZdS)rz]Base for classes that provide a set of template directives. :since: version 0.6 cCs |j|S)zReturn the directive class for the given name. :param name: the directive name as used in the template :return: the directive class :see: `Directive` )rkr0)rr,rrr get_directiveQs zDirectiveFactory.get_directivecCs ||jvr |j|St|jS)aUReturn a key for the given directive class that should be used to sort it among other directives on the same `SUB` event. The default implementation simply returns the index of the directive in the `directives` list. :param dir_cls: the directive class :return: the sort key )rmindexrJ)rdir_clsrrr get_directive_indexZs  z$DirectiveFactory.get_directive_indexN)r#r$r%r&r_rtrwrrrr rEs  rc@seZdZdZedZ edZ edZ edZ dZ e j Z  d#d d Z d d Zd dZddZddZddZeddZddZd$ddZddZddZdd Zd!d"ZdS)%rzAbstract template base class. This class implements most of the template processing model, but does not specify the syntax of templates. EXECEXPRINCLUDESUBNstrictTc Cs|p||_||_||_||_||_||d|_t|t s5t |ds5t|t j r1t |}nt|}z ||||_WdStyV}z t|j|j|j|jd}~ww)aInitialize a template from either a string, a file-like object, or an already parsed markup stream. :param source: a string, file-like object, or markup stream to read the template from :param filepath: the absolute path to the template file :param filename: the path to the template file relative to the search path :param loader: the `TemplateLoader` to use for loading included templates :param encoding: the encoding of the `source` :param lookup: the variable lookup mechanism; either "strict" (the default), "lenient", or a custom lookup class :param allow_exec: whether Python code blocks in templates should be allowed :note: Changed in 0.5: Added the `allow_exec` argument FreadN)filepathrloaderlookup allow_exec _init_filters _init_loader _preparedr(rhasattrsix text_typerr_parse_streamr rrrr) rsourcer~rrencodingrrerrr rs$   zTemplate.__init__cCs|j}g|d<|S)Nfilters)__dict__r[rstaterrr __getstate__s zTemplate.__getstate__cCs||_|dSr3)rrrrrr __setstate__s zTemplate.__setstate__cCsdt|j|jfS)Nz <%s "%s">)ror#rr-rrr r?szTemplate.__repr__cCs|j|jg|_dSr3)_flatten_includerr-rrr rszTemplate._init_filterscCs|jdur>ddlm}|jr0|j|jkr(tj|jdttj|j }n tj |j}nd}|tj |g|_dSdS)Nr)TemplateLoader.) rgenshi.template.loaderrrr~ospathnormpathrJdirnameabspath)rrbasedirrrr rs     zTemplate._init_loadercCs|js||jSr3)r _prepare_selfrr-rrr r^szTemplate.streamcCst)aParse the template. The parsing stage parses the template and constructs a list of directives that will be executed in the render stage. The input is split up into literal output (text that does not depend on the context data) and directives or expressions. :param source: a file-like object containing the XML source of the template, or an XML event stream :param encoding: the encoding of the `source` )NotImplementedError)rrrrrr rs zTemplate._parsecCs(|jst||j||_d|_dSdS)NT)rr>_preparer)rinlinedrrr rs zTemplate._prepare_selfc csddlm}|durt|jf}|D]\}}}|turbg}|d}t|ddddD]\} } } } }| ||| | |\} }| rE|| q,|||}|rY||t |f|fVq|D]}|Vq[q|t ur|\}} }d}t |t j rt|jd d sd}z|jj||d| p|jd }Wn|y|durYnw|dur|j|vr||j|||jD]}|Vq||jd }n|||D]}|Vqd }|rq|r|| t |||f}|||fVq|||fVqdS) zCall the `attach` method of every directive found in the template. :param stream: the event stream of the template rTemplateNotFoundNr@cSs|dS)Nrr)xrrr sz#Template._prepare..)rBF auto_reloadT relative_torq)rrsetr~r{sortedattachappendrr>rzr(r string_typesgetattrrload __class__addrr^discard)rr^rrkindr<posr_ substream_rqrH namespacesrleventhreffallback tmpl_inlinedtmplrrr rsx                zTemplate._preparecOsi}|r&t|dks J|d}|durtdi|}n|}t|ts%Jntdi|}|j}|jD] }|t||fi|}q3t||jS)aApply the template to the given context data. Any keyword arguments are made available to the template as context data. Only one positional argument is accepted: if it is provided, it must be an instance of the `Context` class, and keyword arguments are ignored. This calling style is used for internal processing. :return: a markup event stream representing the result of applying the template to the context data. r@rNr)rJr r(r^rr]r serializer)rargskwargsr`rZr^filter_rrr generates   zTemplate.generatecks|j}g}|j}|j}t|} |D]\}} } |tur\| dr\| \} } g} | D](\}}t|turIdd|j||fi|D}|sDq(d|}| ||fq(|| t | f| fVq|t urt | ||}|durt |t jrwt|| fVqt |trt||| fVqt|dr||t|}n8tt || fVq|tur||t| d| d||}n|turt| ||q|| | fVq|sdS|}q)Nr@cSs,g|]}|dtur|ddur|dqS)rr@N)r )rPrrrr rSNs z%Template._flatten..r'__iter__r) _number_convrr6r]r ror>rjoinrryrer(rrr rrr rr{rarxri)rr^rZr` number_convstackr8r6rr<rtagattrs new_attrsr,rHvaluesresultrrr r=sZ       zTemplate._flattenc ks$ddlm}|D]}|dtur|d\}}}t|tjsCg} |j||fi|D]\} } } | tur8| | q*d dd| D}z!|j j ||dd|pQ|j d} | j |fi|D]}|Vq]Wq |y|d urp|jD] }|t||fi|}qs|D]}|VqYq w|Vq d S) z[Internal stream filter that performs inclusion of external template files. rrr@r'cSsg|]}|dur|qSr3r)rPrrrr rSrTz%Template._include..rN)rrrzr(rrrr rrrrrrrr])rr^rZr`rrrrqrpartssubkindsubdatasubposrrrrr r{s@       zTemplate._include)NNNNr|Tr3)r#r$r%r&rrxryrzr{rrrrrrrr?rrpropertyr^rrrrrrrrrr ris8 '  A >rr3)'r& collectionsrrr genshi.compatrrr genshi.corerrrr r r genshi.inputr __all__ __docformat__rrrrrobjectr rarerirorj add_metaclassrrrxryrzr{rrrr s8   '   #4