o |nh!@sdZddlZddlmZddlmZddlmZddl m Z ddl m Z ddlmZdd lmZd d lmZd d lmZd d lmZd dlmZd dlmZd dlmZd dlmZd dlmZd dlmZd dlmZd dlm Z d dl!m"Z"ej#rddl$Z%d dl&m'Z'ej(dej)dej*fdZ+dddddd d!d"d#Z,d$e+d%e+fd&d'Z-d(e.d%ej)d)ej/d*gdffd+d,Z0d(e.d%ej)d)ej1d*gdffd-d.Z2  / 0dNd1ej3d2d3d4ej4e.d5ej4e.d6ej4ej5d7e6d8e6d%ej4e.fd9d:Z7d;ej*d%e6fdej9ej:d?ej9e.d%ej;e.fd@dAZGdEdFdFe?Z@GdGdHdHe"ZAGdIdJdJe"ZBGdKdLdLeCZDGdMd)d)e"ZEdS)Oz0Compiles nodes from the parser into Python code.N)contextmanager)update_wrapper)StringIO)chain) iskeyword)escape)Markup)nodes)TemplateAssertionError)Symbols)VAR_LOAD_ALIAS)VAR_LOAD_PARAMETER)VAR_LOAD_RESOLVE)VAR_LOAD_UNDEFINED) EvalContext) Optimizer)_PassArg)concat) NodeVisitor) EnvironmentF.)boundz==z!=>z>=.new_func)r ExprtAnyr)r#r4r2r1r3 optimizeconst-s r8opr&r)c (tdddtjdtddffdd }|S)Nr%r&r'r(r$cs|jjr'|jjvr'|dd||j||d||j|n|d||j||dd||j||ddS)Nz environment.call_binop(context, , ( )) environment sandboxedintercepted_binopswriter/leftrightr%r'r(r9r2r3visitor>s   z_make_binop..visitor)r8r BinExprr)r9rGr2rFr3 _make_binop=s"rJc r:)Nr%r&r'r(r$cs`|jjr|jjvr|dd||j|n|d||j||ddS)Nzenvironment.call_unop(context, r;r<r>)r?r@intercepted_unopsrBr/r'rErFr2r3rGUs z_make_unop..visitor)r8r UnaryExprr)rIr2rFr3 _make_unopRs" rMFTr'r?rnamefilenamestream defer_init optimizedcCsHt|tjs td|||||||}|||dur"|jSdS)z+Generate the python source for a node tree.z Can't compile non template nodesN) isinstancer Template TypeErrorcode_generator_classr/rPgetvalue)r'r?rNrOrPrQrR generatorr2r2r3generatees    rYvaluecCs|dus |tus |turdSt|ttttttt hvrdSt|t t t t hvr0tdd|DSt|turAtdd|DSdS)z)Does the node have a safe representation?NTcss|]}t|VqdSr+ has_safe_repr).0vr2r2r3 sz has_safe_repr..css$|] \}}t|o t|VqdSr+r[r]kr^r2r2r3r_s"F)NotImplementedEllipsistypeboolintfloatcomplexrangestrrtuplelistset frozensetalldictitemsrZr2r2r3r\}s r\r namescCs<t|}z|D]}||qW|jStyY|jSw)zCheck if the names passed are accessed undeclared. The return value is a set of all the undeclared names from the sequence of names found. )UndeclaredNameVisitorr/ VisitorExit undeclared)r rsrGr'r2r2r3find_undeclareds  rwc@s,eZdZdejejejfddfddZdS)MacroRefr'r$NcCs||_d|_d|_d|_dSNF)r'accesses_calleraccesses_kwargsaccesses_varargsr%r'r2r2r3__init__s zMacroRef.__init__) __name__ __module__ __qualname__r6Unionr Macro CallBlockr~r2r2r2r3rxs$rxc @sheZdZdZ  ddedejddejeddfddZdd d Z dd e ddfddZ dddZ e Z dS)r)z&Holds compile time information for us.Nr-parentlevelr$cCs~||_||_|durt|d|_d|_d|_d|_nt|j|d|_|j|_|j|_|j|_d|_d|_d|_ d|_ d|_ dS)NrF) r-rr symbolsrequire_output_checkbufferblocktoplevel rootlevel loop_frame block_frame soft_frame)r%r-rrr2r2r3r~s   zFrame.__init__te.SelfcCs*t|j}|j|j|j|_|S)z!Create a copy of the current one.)object__new__ __class____dict__updatercopyr%rvr2r2r3rs  z Frame.copyFisolatedcCs&|r t|j|jjddSt|j|S)zReturn an inner frame.r r)r)r-rr)r%rr2r2r3inners z Frame.innercCs|}d|_d|_|S)a&Return a soft frame. A soft frame may not be modified as standalone thing as it shares the resources with the frame it was created of, but it's not a rootlevel frame any longer. This is only used to implement if-statements and conditional expressions. FT)rrrrr2r2r3softsz Frame.soft)NN)r$rF)rrr__doc__rr6Optionalrfr~rrerr__copy__r2r2r2r3r)s" 3  c@eZdZdZdS)ruz?Exception used by the `UndeclaredNameVisitor` to signal a stop.Nrrrrr2r2r2r3ruruc@sVeZdZdZd ddZdejddfddZdejddfd d Z dej ddfd d Z dS)DependencyFinderVisitorz.A visitor that collects filter and test calls.r$NcCst|_t|_dSr+)rmfilterstestsr%r2r2r3r~s z DependencyFinderVisitor.__init__r'cC|||j|jdSr+) generic_visitraddrNr}r2r2r3 visit_Filter z$DependencyFinderVisitor.visit_FiltercCrr+)rrrrNr}r2r2r3 visit_Testrz"DependencyFinderVisitor.visit_TestcCdS)zStop visiting at blocks.Nr2r}r2r2r3 visit_Block z#DependencyFinderVisitor.visit_Blockr$N) rrrrr~r FilterrTestrBlockrr2r2r2r3rs  rc@sPeZdZdZdejeddfddZdej ddfdd Z dej ddfd d Z dS) rtzA visitor that checks if a name is accessed without being declared. This is different from the frame visitor as it will not stop at closure frames. rsr$NcCst||_t|_dSr+)rmrsrv)r%rsr2r2r3r~s  zUndeclaredNameVisitor.__init__r'cCsL|jdkr|j|jvr|j|j|j|jkrtdS|j|jdS)Nload)ctxrNrsrvrrudiscardr}r2r2r3 visit_Names  z UndeclaredNameVisitor.visit_NamecCr)zStop visiting a blocks.Nr2r}r2r2r3r!rz!UndeclaredNameVisitor.visit_Block) rrrrr6Iterablerjr~r Namerrrr2r2r2r3rts rtc@r) CompilerExitzRaised if the compiler encountered a situation where it just doesn't make sense to further process the code. Any block that raises such an exception is not further processed. Nrr2r2r2r3r%rrc@s eZdZU   ddddejedejedejejd ed ed dfd d Ze d efddZ dede d dfddZ d efddZ ded dfddZ ddeded dfddZdddZdd e d dfd!d"Zdded#ejejd dfd$d%Zded dfd&d'Z dd(eded#ejejd dfd)d*Zd+ejejded dfd,d-Zd.ed dfd/d0Z 1dd.ed#ejejd2e d dfd3d4Zdd#ejejd2e d dfd5d6Z dd#ejejejej fded7ejej!eej"fd dfd8d9Z#d+ejejd dfd:d;Z$ded dfded dfd?d@Z&ddCedDed efdEdFZ'ded efdGdHZ(d#ejej)ej*fded ej+ee,ffdIdJZ-dKe,ded dfdLdMZ.d#ejd efdNdOZ/ded efdPdQZ0ddRdSZ1ded dfdTdUZ2ddVdWZ3dXed dfdYdZZ4dXed dfd[d\Z5dd]d^Z6d efd_d`Z7d efdadbZ8ded efdcddZ9dXed efdedfZ:ddgdhZ;ded dfdidjZ< dd#ej=dejed dfdkdlZ>d#ej?ded dfdmdnZ@d#ejAded dfdodpZBd#ejCded dfdqdrZDd#ejejEejFfded dfdsdtZGd#ejEded dfdudvZHd#ejFded dfdwdxZId#ejJded dfdydzZKd#ejLded dfd{d|ZMd#ej)ded dfd}d~ZNd#ej*ded dfddZOd#ejPded dfddZQd#ejRded dfddZSd#ejTded dfddZUGdddejVZWeXdej"d ej"fddZYdZZejeWe[d<d eWfddZ\dejej"d efddZ]d#ej^dedeWd efddZ_d#ej^dedeWd dfddZ`d#ej^dedeWd dfddZad#ejbded dfddZcd#ejdded dfddZed#ejfded dfddZgd#ejhded dfddZid#ejjded dfddZkd#ejlded dfddZmd#ejnded dfddZod#ej+ded dfddZpd#ejqded dfddZrd#ejsded dfddZteudZveudZweudZxeudZyeudZzeudZ{eudZ|eudZ}eudZ~edZedZedZed#ejded dfddZed#ejded dfddZd#ejded dfddZed#ejded dfddZed#ejded dfddZd#ejded dfdd„Zed#ejejej fdeded ejdfddńZed#ejded dfddDŽZed#ej ded dfddɄZed#ejded dfdd˄Ze dd#ejdeded dfdd΄Zd#ejded dfddЄZd#ejded dfdd҄Zd#ejded dfddԄZd#ejded dfddքZd#ejded dfdd؄Zd#ejded dfddڄZd#ejded dfdd܄Zd#ejded dfddބZd#ejded dfddZd#ejded dfddZd#ejded dfddZd#ejded dfddZd#ejded dfddZd#ejded dfddZd#ejded dfddZdS)r&NFTr?rrNrOrPrQrRr$cCs|durt}||_||_||_||_d|_||_d|_|r#t||_i|_ i|_ d|_ d|_ d|_ i|_i|_g|_d|_d|_d|_d|_d|_d|_g|_g|_dg|_dS)NFrr Tcontext)rr?rNrOrPcreated_block_contextrQr,rimport_aliasesblocksextends_so_farhas_known_extends code_linenorr debug_info_write_debug_info _new_lines _last_line _first_write_last_identifier _indentation _assign_stack_param_def_block_context_reference_stack)r%r?rNrOrPrQrRr2r2r3r~-s8   zCodeGenerator.__init__cCs |jduSr+)r,rr2r2r3rRvs zCodeGenerator.optimizedmsglinenoz te.NoReturncCst|||j|j)z*Fail with a :exc:`TemplateAssertionError`.)r rNrO)r%rrr2r2r3fail|zCodeGenerator.failcCs|jd7_d|jS)zGet a new unique identifier.r t_)rrr2r2r3temporary_identifiers z"CodeGenerator.temporary_identifierr(cCs ||_||jddS)z7Enable buffering for the frame from that point onwards.z = []N)rr writeliner%r(r2r2r3rs zCodeGenerator.bufferforce_unescapedcCs|sF|jjr6|d||d|jd||d||d|jd|dS|jjrF|d|jddS|d|jddS)z(Return the buffer contents of the frame.zif context.eval_ctx.autoescape:zreturn Markup(concat())else:zreturn concat(r>N)r-r.rindentroutdent autoescape)r%r(rr2r2r3return_buffer_contentss  z$CodeGenerator.return_buffer_contentscCs|jd7_dS)zIndent by one.r Nrrr2r2r3rrzCodeGenerator.indentr stepcCs|j|8_dS)zOutdent by step.Nr)r%rr2r2r3rrzCodeGenerator.outdentr'cCs2|jdur |d|dS||jd|dS)z%Yield or write into the frame buffer.Nyield .append()rr)r%r(r'r2r2r3 start_writes zCodeGenerator.start_writecCs|jdur |ddSdS)z1End the writing process started by `start_write`.Nr>)rrBrr2r2r3 end_writes zCodeGenerator.end_writescCs$|||||||dS)z4Simple shortcut for start_write + write + end_write.N)rrBr)r%rr(r'r2r2r3 simple_writes  zCodeGenerator.simple_writer cCs<z|d|D]}|||qWdStyYdSw)zVisit a list of nodes as block in a frame. If the current frame is no buffer a dummy ``if 0: yield None`` is written automatically. passN)rr/r)r%r r(r'r2r2r3 blockvisits  zCodeGenerator.blockvisitxcCs|jr8|js)|jd|j|j|j7_|jdur)|j|j|jfd|_d|_|jd|jd|_|j|dS)z&Write a string into the output stream. NFz r) rrrPrBrrrappendr)r%rr2r2r3rBs zCodeGenerator.writerextracCs|||||dS)z!Combination of newline and write.N)newlinerB)r%rr'rr2r2r3rs zCodeGenerator.writelinecCsBt|jd||_|dur|j|jkr|j|_|j|_dSdSdS)z/Add one or more newlines before the next write.r N)maxrrrr)r%r'rr2r2r3rs  zCodeGenerator.newline extra_kwargsc Cstddtdd|jD|pdD}|jD] }|d|||q|sP|jD] }|d|||q*|durP|D]\}}|d|d|q@|jr_|d||j||r|jdurl|d n|d |jD]}||j d ||j ||dqt|dur|D]\}}||d |dq|jdur|d ||j||d dS|ddS|jdur|d||j|dSdS)a+Writes a function call to the stream for the current node. A leading comma is added automatically. The extra keyword arguments may not include python keywords otherwise a syntax error could occur. The extra keyword arguments should be given as python dict. css |] }ttt|VqdSr+)is_python_keywordr6castrj)r]rar2r2r3r_s  z*CodeGenerator.signature..cs|]}|jVqdSr+)keyr]rr2r2r3r_r2r;N=z, *z , **dict({z, **{: z}, **r>}z, **) anyrr*argsrBr/rqdyn_args dyn_kwargsrrZ) r%r'r(rkwarg_workaroundargkwargrrZr2r2r3 signaturesH              zCodeGenerator.signaturec Cs t}|D]}||q|j|jdf|j|jdffD]h\}}}t|D]^}||vr0|||<|d||||d|d|d||d||d|d ||d ||d |d d d|d||q$qd S)aFind all filter and test names used in the template and assign them to variables in the compiled namespace. Checking that the names are registered with the environment is done when compiling the Filter and Test nodes. If the node is in an If or CondExpr node, the check is done at runtime instead. .. versionchanged:: 3.0 Filters and tests in If and CondExpr nodes are checked at runtime instead of compile time. rrtry:z = environment.[]zexcept KeyError:z @internalcodedef z (*unused):zraise TemplateRuntimeError("No N named z found.")) rr/rrsortedrrrr)r%r rGr'id_maprs dependencyrNr2r2r3pull_dependenciess<          zCodeGenerator.pull_dependenciesc Csg}|jjD]<\}\}}|tkrq|tkr(||d|d|dq|tkr7||d|q|tkrA| |qt d|rT|d |ddSdS)N = r<r>zunknown load instruction = missing) rloadsrqrrrget_resolve_funcr rrNotImplementedErrorjoin)r%r(undefstargetactionparamr2r2r3 enter_frameHs" zCodeGenerator.enter_framewith_python_scopecCsF|sg}|jjD]}||q|r!|d|ddSdSdS)Nrr )rr rrr )r%r(rrrr2r2r3 leave_frameXs  zCodeGenerator.leave_frameasync async_value sync_valuecCs|jjr|S|Sr+)r?is_async)r%rrr2r2r3 choose_async`zCodeGenerator.choose_asynccCs|d|S)Nr)r)r%rNr2r2r3funccszCodeGenerator.funcc Cs|}|j|t|}d}t}g}t|jD] \}}|jdkr%|}|jdvr0||j| |j |jqt |j d} d| vrr|durfz |j |t|jWntye|d|jYn w| |jdd|_d| vrd|vr| |jdd|_d| vrd|vr| |jdd|_d |_|j|||d d d |d ||||||||t|jD]V\}}|j |j} |d| d|z |j |t|j} Wnty || d|jd|jdYnw|| d|| ||| | q|!|"|j ||j#|dd|j$|dd| ||fS)z/Dump the function def of a macro or call block.Ncaller)r*varargs)rr*rzhWhen defining macros or call blocks the special "caller" argument must be omitted or be given a default.Tr*rFmacror<r;):if is missing:z = undefined("parameter z was not provided", name=r>r)rr)%rr analyze_noderxrm enumeraterrNrrrefrwbodydefaultslen IndexErrorrrdeclare_parameterrzr{r|rrrr rrrpush_parameter_definitionsr/mark_parameter_storedrpop_parameter_definitionsrrr) r%r'r( macro_refexplicit_callerskip_special_paramsridxrrvr&defaultr2r2r3 macro_bodyfsz       $      zCodeGenerator.macro_bodyr/c Csrddd|jjD}t|jdd}t|jjdkr|d7}|d|d |d |jd|jd|jd dS) z.rNNr ,zMacro(environment, macro, z, (z), z, context.eval_ctx.autoescape)) r r'rgetattrr)rBr{r|rz)r%r/r( arg_tuplerNr2r2r3 macro_defszCodeGenerator.macro_defcCs*d|j}|jdur|d|j}|S)z.Return a human readable position for the node.zline N in )rrN)r%r'rr2r2r3positions  zCodeGenerator.positioncCs*ddd|jD}d|dS)Nr;css"|] \}}|d|VqdSrNr2)r]rNrr2r2r3r_s  z3CodeGenerator.dump_local_context..{r)r r dump_storesrq)r%r(items_kvr2r2r3dump_local_contexts   z CodeGenerator.dump_local_contextcCs6|d|d|d|d|ddS)zWrites a common preamble that is used by root and block functions. Primarily this sets up common local helpers and enforces a generator through a dead branch. z$resolve = context.resolve_or_missingz!undefined = environment.undefinedzconcat = environment.concatzcond_expr_undefined = Undefinedzif 0: yield NoneNrrr2r2r3 write_commonss    zCodeGenerator.write_commonscCs|j|jdS)aQPushes all parameter targets from the given frame into a local stack that permits tracking of yet to be assigned parameters. In particular this enables the optimization from `visit_Name` to skip undefined expressions for parameters in macros as macros can reference otherwise unbound parameters. N)rrrdump_param_targetsrr2r2r3r,sz(CodeGenerator.push_parameter_definitionscCs|jdS)z+Pops the current parameter definitions set.N)rpoprr2r2r3r.sz'CodeGenerator.pop_parameter_definitionsrcCs|jr |jd|dSdS)zMarks a parameter in the current parameter definitions as stored. This will skip the enforced undefined checks. rN)rrr%rr2r2r3r-sz#CodeGenerator.mark_parameter_storedcCs|j|dSr+)rrrEr2r2r3push_context_referencerz$CodeGenerator.push_context_referencecCs|jdSr+)rrDrr2r2r3pop_context_referencesz#CodeGenerator.pop_context_referencecCs |jdS)Nrrrr2r2r3get_context_refs zCodeGenerator.get_context_refcCs |jd}|dkr dS|dS)Nrrresolvez.resolverHrEr2r2r3r s  zCodeGenerator.get_resolve_funccCs|d||dS)Nz .derived(r>)rIr@rr2r2r3derive_contextszCodeGenerator.derive_contextcCs|jsdS||jdvS)z4Checks if a given target is an undeclared parameter.Fr)rrEr2r2r3parameter_is_undeclaredsz%CodeGenerator.parameter_is_undeclaredcCs|jtdS)z+Pushes a new layer for assignment tracking.N)rrrmrr2r2r3push_assign_tracking rz"CodeGenerator.push_assign_trackingcCs|j}|js|js|jr|sdSdd|D}t|dkrWtt|}|j |}|jr;| d|d|dS|jrK| d|d|dS| d|d|n>|jr`| d n|jri| d n| d t t |D]\}}|r| d |j |}| |d |qt| d|js|js|rt|dkr| d|dddSd ttt |}| d|ddSdSdSdS)zoPops the topmost level for assignment tracking and updates the context variables if necessary. NcSs g|] }|dddkr|qS)Nr _r2rr2r2r3 s z5CodeGenerator.pop_assign_tracking..r z _loop_vars[] = z _block_vars[ context.vars[z_loop_vars.update({z_block_vars.update({context.vars.update({r;r})context.exported_vars.add(rr>zcontext.exported_vars.update((r)rrDrrrr)nextiterrr&rr%rrBr mapr5)r%r(vars public_namesrNr&r2 names_strr2r2r3pop_assign_trackingsL            z!CodeGenerator.pop_assign_trackingc Cs8|dusJdt|j|j}ddlm}ddlm}|jjr&t||}nt|}|dd ||j r9dnd}| t j du}|t jD]} | j|jvr]|d | jd | j| |j| j<qI|t jD]:} | j|jvr| j} ||j| <} d | vr| d d\} }|d | d |d| qj|d| d| qj|d|j|j|dd|ddd||t|}dt|jdvr|jd}||d|j |d|_!|_"|o|j# |_$|r|d|%||&|j|'|j||j(|dd|)|rh|j#s'||d||jjs6|dn)|d|d||d||d |)|)|d!|)d|j# |j*D]\}} ||d"|d|d| d||t|}d|_+t| jd#}d|vr|jd}||dd$|vr|jd$}||d%|d&|d'|j | ||_,|d(|%||&| j|'| j||j(|dd|)qmd d)d*|jD}|jd+|d,ddd- d.d*|j-D}|d/|dS)0Nzno root frame allowedr )async_exported)exportedzfrom jinja2.runtime import r;rz, environment=environmentzblock z defined twice.zfrom z import z as zimport zname = rootz(context, missing=missingr )rr%rz = TemplateReference(context)Tzparent_template = Noner#if parent_template is not None:z4yield from parent_template.root_render_func(context)z0agen = parent_template.root_render_func(context)rzasync for event in agen:z yield eventzfinally: await agen.aclose()block_)r%superrbz = context.super(z, block_r>z_block_vars = {}css|] }|d|VqdS)z: block_Nr2rr2r2r3r_sz/CodeGenerator.visit_Template..z blocks = {r&css"|] \}}|d|VqdS)rNr2r`r2r2r3r_s z debug_info = ).rr?rNruntimer\r]rrrr rQfindr Extendsfind_allrrrr ImportedName importnamerrrsplitrrrBr)rwr'rr+r$rrrrrrrrrrqrrr)r%r'r(r-r\r]exported_namesenvenv have_extendsrimport_impaliasmoduleobjr&rNrrv blocks_kv_str debug_kv_strr2r2r3visit_Template=s                            zCodeGenerator.visit_TemplatecCsPd}|jr|jr dS|jdkr|d||d7}|jr%||}n|}|jrJ|d|j d|||d|j d|| |j j sb|j durb|d |j d |d |n?|d |j d |d |d |||d|||d|| | |d|dd| |dS)z.Call a block and register it for the template.rNif parent_template is None:r zif len(context.blocks[z]) <= 1:z+raise TemplateRuntimeError("Required block z not found")zyield from context.blocks[z][0](r>zgen = context.blocks[rfor event in gen:event finally: await gen.aclose() gen.close())rrrrrscopedrKrIrequiredrNrr?rrrr)r%r'r(rrr2r2r3rsL       zCodeGenerator.visit_BlockcCs|js |d|j|jdkr*|js|d||d|jr&t||d|| |j || d|j d|d||d ||j rYd |_|jd 7_d S) zCalls the extender.z,cannot use extend from a non top-level scoperr`z5raise TemplateRuntimeError("extended multiple times")z+parent_template = environment.get_template(r;r>z9for name, parent_block in parent_template.blocks.items():z8context.blocks.setdefault(name, []).append(parent_block)Tr N)rrrrrrrrrr/templaterBrNrrEr2r2r3 visit_Extendss(      zCodeGenerator.visit_Extendscs|jr dd}t|jtjr+t|jjtrd}nt|jjt t fr*d}n t|jtj tj fr7d}d|d| |jdjd|jrtd d d dfdd }|jrdddd|dddnjjrd|nd|jr͈d Sd S)zHandles includes.rget_or_select_template get_templateselect_templateztemplate = environment.r<r;r>zexcept TemplateNotFound:rrr$Ncs ddS)Nrx)rrrr2r(r%r2r3 loop_body-s  z.CodeGenerator.visit_Include..loop_bodyzNgen = template.root_render_func(template.new_context(context.get_all(), True, rrwryrzr{zGfor event in (await template._get_default_module_async())._body_stream:z6yield from template._get_default_module()._body_streamr)ignore_missingrrrSr~r ConstrZrjrkrlTupleListr/rBrNr with_contextr@rr?r)r%r'r( func_namerr2rr3 visit_Includes^       zCodeGenerator.visit_IncludecCs||dd||j||d|jd|jr7d|d}||d||ddS|d |dd dS) Nawait zenvironment.get_template(r;z). make_module_asyncz(context.get_all(), True, r>_get_default_modulez (context))rBrr/r~rNrr@)r%r'r(f_namer2r2r3_import_commonLszCodeGenerator._import_commoncCst||j|jd||jr|d|jd||||jr6|jds8|d|jddSdSdS)zVisit regular imports.rrQrPrNcontext.exported_vars.discard(r>N)rrr&rrrBr startswithrEr2r2r3 visit_Import[s zCodeGenerator.visit_Importc s|||d||g}g}|jD]k}t|tr#|\}}n|}|j|d|d|dj|d| | | dd dd }d |d |}|j|d |d |d| j r|||ds||q|rt|dkr|d}|d|dj|ndfdd|D} |d| d|rt|dkr|d|dddSdtt|} |d| ddSdS)zVisit named imports.zincluded_template = z = getattr(included_template, z , missing)r!r"r=z{{rz}}z9the template {included_template.__name__!r} (imported on z%) does not export the requested name z = undefined(fz, name=r>rNr rrQrPr;c3s&|]}|dj|VqdSr<)rr&)r]rNr(r2r3r_s z1CodeGenerator.visit_FromImport..rRrSrz)context.exported_vars.difference_update((rN)rrBrrsrSrkrrr&rr;replacerrrrr)r rWr5) r%r'r( var_namesdiscarded_namesrNrpr;messagenames_kvrZr2rr3visit_FromImportfs`             zCodeGenerator.visit_FromImportc Cs||}d|_|}|}|jp)dt|jdddvp)tdd|tjD}d}|r4|j d}|j j |dd |j rG|j j |d d |j r|}|j j |d d |||d |j |||||d d||j||d||dd|d||d|j ||j ||d||d||j||d|j|dd|jr||dd|||||j|_|r||d|tjD]} | jdkr| jdkr|d| jq|j r|} || d||d d|||j||r8|d|d|ddn|d|j rI||d|jrS|d n!|jj r`|s`|d!||j!||jj rt|st|d"|j r}|d"|jr|d#n ||rd$nd||||d%|"|j#||j r|| d&||j||jo|j d|j r|d| d||||"|j |||||jr,|$|||%||||d'd(|jj r|d!||j!||jj r"|d"|d)|&||j'r<|j'd*(|j j)dSdS)+NTloop)r')only)rcsrr+)r|)r]rr2r2r3r_rz*CodeGenerator.visit_For..r') for_branchelsetestz(fiter):z async for zfor r:zauto_aiter(fiter)fiter:r!rr#z%(reciter, loop_render_func, depth=0):r storez8Can't assign to special loop variable in for-loop targetz = 1r;Asyncz LoopContext(r<reciterz auto_aiter(r>z&, undefined, loop_render_func, depth):z , undefined):z_loop_vars = {}z = 0rzloop(z, loop)r)*rr recursiverwiter_child_nodesrrgr rrr+r$else_rrrrrrrr/rrBrrrrrrNrrr?rrVrr'rrrrdifference_updatestores) r%r'r(r test_frame else_frame extended_looploop_refloop_filter_funcrNiteration_indicatorr2r2r3 visit_Fors                           zCodeGenerator.visit_ForcCs|}|d|||j||d|||j|||j D]#}|d|||j||d|||j||q(|j re|d|||j ||dSdS)Nr!rzelif r) rrr/rrBrrr'relif_r)r%r'r(if_framerr2r2r3visit_If(s(        zCodeGenerator.visit_IfcCs||||\}}||jr)|jds|d|jd|d|jd||j|jd| ||dS)NrNrTr>rQrPr) r4rrrNrrBrrr&r9)r%r'r( macro_framer/r2r2r3 visit_Macro=s zCodeGenerator.visit_MacrocCsR|||\}}|d|||||||j|j|dd||dS)Nz caller = T)forward_caller)r4rr9r visit_Callcallr)r%r'r( call_framer/r2r2r3visit_CallBlockGs    zCodeGenerator.visit_CallBlockcCsh|}|j|||||||j||||||j || || |dSr+) rrr$rrrr'rrfilterrr)r%r'r( filter_framer2r2r3visit_FilterBlockOs     zCodeGenerator.visit_FilterBlockcCs||}|j|||t|j|jD]\}}||||| d|||q| |j || |dS)Nr) rrr$rziptargetsvaluesrr/rBrr'r)r%r'r( with_framerexprr2r2r3 visit_WithZs    zCodeGenerator.visit_WithcCs||||j|dSr+)rr/r'rEr2r2r3visit_ExprStmtfrzCodeGenerator.visit_ExprStmtc@s4eZdZUejejdefed<ejeed<dS)zCodeGenerator._FinalizeInfo.constsrcN)rrrr6rCallablerj__annotations__r2r2r2r3 _FinalizeInfojs rrZcCst|S)zThe default finalize function if the environment isn't configured with one. Or, if the environment has one, this is called on that function's output for constants. )rjrrr2r2r3_default_finalizenszCodeGenerator._default_finalize _finalizecsjdurjSj}d}jjrYd}jjtjdtjdtjdit}d}|dur?dt j dt j ffdd }n||d }|dkrYdt j dt j ffd d } ||_jS) aBuild the finalize function to be used on constants and at runtime. Cached so it's only created once for all output nodes. Returns a ``namedtuple`` with the following attributes: ``const`` A function to finalize constant data at compile time. ``src`` Source code to output around nodes to be evaluated at runtime. Nzenvironment.finalize(rcontext.eval_ctxr?rZr$cs |Sr+r2rr)r3 env_finalizer2r3finalizes z.CodeGenerator._make_finalize..finalizer;csj|Sr+)r?rrr3rr%r2r3rr) rrr?rrr eval_contextgetfrom_objr6r7r)r%rrpass_argr2rr3_make_finalizexs.  zCodeGenerator._make_finalizegroupcCs tt|S)zGiven a group of constant values converted from ``Output`` child nodes, produce a string to write to the template module source. )r5r)r%rr2r2r3_output_const_reprs z CodeGenerator._output_const_reprrcCs:||j}|jjrt|}t|tjrt|S||S)aCTry to optimize a child of an ``Output`` node by trying to convert it to constant, finalized data at compile time. If :exc:`Impossible` is raised, the node is not constant and will be evaluated at runtime. Any other exception will also be evaluated at runtime for easier debugging. ) as_constr-rrrSr TemplateDatarjr)r%r'r(rrr2r2r3_output_child_to_consts   z$CodeGenerator._output_child_to_constcCsP|jjr |dn|jjr|dn|d|jdur&||jdSdS)zXOutput extra source code before visiting a child of an ``Output`` node. z1(escape if context.eval_ctx.autoescape else str)(zescape(zstr(N)r-r.rBrrr%r'r(rr2r2r3_output_child_pres    zCodeGenerator._output_child_precCs&|d|jdur|ddSdS)zWOutput extra source code after visiting a child of an ``Output`` node. r>N)rBrrr2r2r3_output_child_posts  z CodeGenerator._output_child_postc Cs|jr|jrdS|d||}g}|jD]A}z|js*t|tjs*t | |||}Wntj t fyC| |Yqw|rUt|dt rU|d |q| |gq|jdur~t|dkrq||jdn ||jd||D]P}t|t r||}|jdur|d|q||dq|jdur|d|n||||||||||||||jdur|dq|jdur||t|dkrdnd |jr|dSdS) Nrvrr rz .extend((rr6r>r)rrrrrr rrSr Impossibler Exceptionrrlrr)rrrr/rrBr) r%r'r(rr'childritemvalr2r2r3 visit_Outputs`                zCodeGenerator.visit_OutputcCs|t}|tjD]+}|j|vrq ||j|j|j}| d|d| | d| q | || |j||d| |j|||dS)Nzif not isinstance(z , Namespace):zMraise TemplateRuntimeError("cannot assign attribute on non-namespace object")r)rMrmrgr NSRefrNrrr&rrrrr/rrBr'r[)r%r'r( seen_refsnsrefr&r2r2r3 visit_Assign.s$     zCodeGenerator.visit_AssigncCs||}d|_|j|||||||j|| || |j || d|j dur@||j |n | d|jd| d||||dS)NFz9 = (Markup if context.eval_ctx.autoescape else identity)(concat(r>)rMrrrr$rrrr'rr/rrBrrr[r)r%r'r(rr2r2r3visit_AssignBlockMs         zCodeGenerator.visit_AssignBlockc Cs|jdkr|js|js|jr|jr|jd|j|j|j}|jdkrM|j |}|dur;|dt kr;| |rM| d|jd|d|ddS| |dS) Nrrrrz(undefined(name=z) if z is missing else r>) rrrrrrrNrr& find_loadrrLrB)r%r'r(r&rr2r2r3res*    zCodeGenerator.visit_NamecCs*|j|j}||d|jddS)Nrr)rr&rNrattr)r%r'r(r&r2r2r3 visit_NSRef~szCodeGenerator.visit_NSRefcCs:||j}t|tr|t|dS|t|dSr+)rr-rSrgrBrjr5)r%r'r(rr2r2r3 visit_Consts  zCodeGenerator.visit_ConstcCsHz|t||jWdStjy#|d|jdYdSwNz6(Markup if context.eval_ctx.autoescape else identity)(r>)rBr5rr-r rdatarEr2r2r3visit_TemplateDatas  z CodeGenerator.visit_TemplateDatacCs\|dd}t|jD]\}}|r|d|||q ||dkr)ddSddS)Nr<rr;rz,)r>rBr%rqr/r%r'r(r2rr2r2r3 visit_Tuples   zCodeGenerator.visit_TuplecCsF|dt|jD]\}}|r|d|||q |ddS)Nrr;rrrr2r2r3 visit_Lists  zCodeGenerator.visit_ListcCs`|dt|jD]\}}|r|d||j||d||j|q |ddS)Nr=r;rr)rBr%rqr/rrZrr2r2r3 visit_Dicts   zCodeGenerator.visit_Dict+-*/z//z**%andorznot cCs`|jjrd}n |jjrd}nd}||d|jD] }||||dq|ddS)Nz8(markup_join if context.eval_ctx.volatile else str_join) markup_joinstr_joinz((r;r)r-r.rrBr r/)r%r'r(rrr2r2r3 visit_Concats   zCodeGenerator.visit_ConcatcCs>|d||j||jD]}|||q|ddS)Nr<r>)rBr/rops)r%r'r(r9r2r2r3 visit_Compares  zCodeGenerator.visit_ComparecCs*|dt|jd||j|dS)Nr=)rB operatorsr9r/rrEr2r2r3 visit_OperandszCodeGenerator.visit_OperandcCsX|jjr |d|d||j||d|jd|jjr*|ddSdS)N(await auto_await(zenvironment.getattr(r;r>r)r?rrBr/r'rrEr2r2r3 visit_Getattrs  zCodeGenerator.visit_GetattrcCst|jtjr!||j||d||j||ddS|jjr*|d|d||j||d||j||d|jjrR|ddSdS)Nrrrzenvironment.getitem(r;r>r) rSrr Slicer/r'rBr?rrEr2r2r3 visit_Getitems     zCodeGenerator.visit_GetitemcCsd|jdur ||j||d|jdur||j||jdur0|d||j|dSdS)Nr)startr/rBstoprrEr2r2r3 visit_Slices     zCodeGenerator.visit_Slice is_filterccs|jjr |d|r!||j|jd|jj|j}n||j|jd|jj|j}|durQ|jsQ|r@dnd}|d|d|jd|j t j dt j d t jd it |}|durn||d dV||||d |jjr|d dSdS)Nrr<rrzNo rr^rrr?r;r>r)r?rrBrrNrrrrrrrrrr)r%r'r(r r type_namerr2r2r3_filter_test_commons6    z!CodeGenerator._filter_test_commoncCs|||dZ|jdur||j|n4|jjr(|d|jd|jdn)|jjr7|d|jdn"|d|jdWddSWddSWddSWddS1sdwYdS)NTz(Markup(concat(z.)) if context.eval_ctx.autoescape else concat(rzMarkup(concat(rr>)rr'r/r-r.rBrrrEr2r2r3r,s&   "zCodeGenerator.visit_FiltercCsB|||d||j|WddS1swYdSry)rr/r'rEr2r2r3r=s"zCodeGenerator.visit_Testcshdfdd }djdjd|ddS) Nr$cs8jdurjdSdddS)Nz1cond_expr_undefined("the inline if-expression on z6 evaluated to false and no else section was defined."))expr2r/rBr;r2r(r'r%r2r3 write_expr2Fs z1CodeGenerator.visit_CondExpr..write_expr2r<z if z else r>r)rrBr/expr1r)r%r'r(rr2rr3visit_CondExprBs   zCodeGenerator.visit_CondExprrcCs|jjr |d|jjr|dn|d||j||r%ddind}|jr.ddini}|jr7ddini}|rE|j|fi|n |sI|rQt |fi|}| ||||d|jjrh|ddSdS) Nrzenvironment.call(context, z context.call(r _loop_vars _block_varsr>r) r?rrBr@r/r'rrrrpr)r%r'r(rr loop_kwargs block_kwargsr2r2r3rYs$    zCodeGenerator.visit_CallcCs"||jd||j|dS)Nr)rBrr/rZrEr2r2r3 visit_KeywordpszCodeGenerator.visit_KeywordcC&|d||j||ddS)NzMarkup(r>rBr/rrEr2r2r3visit_MarkSafevs zCodeGenerator.visit_MarkSafecCrrrrEr2r2r3visit_MarkSafeIfAutoescape{s z(CodeGenerator.visit_MarkSafeIfAutoescapecCs|d|jdS)Nz environment.rBrNrEr2r2r3visit_EnvironmentAttributez(CodeGenerator.visit_EnvironmentAttributecCs|d|jd|jdS)Nzenvironment.extensions[z].)rB identifierrNrEr2r2r3visit_ExtensionAttributesz&CodeGenerator.visit_ExtensionAttributecCs||j|jdSr+)rBrrirEr2r2r3visit_ImportedNamesz CodeGenerator.visit_ImportedNamecCs||jdSr+rrEr2r2r3visit_InternalNamerz CodeGenerator.visit_InternalNamecCs|ddS)Nr)rBrEr2r2r3visit_ContextReferencesz$CodeGenerator.visit_ContextReferencecCs|||dSr+)rBrKrEr2r2r3visit_DerivedContextReferencerz+CodeGenerator.visit_DerivedContextReferencecC|d|dS)NcontinuerArEr2r2r3visit_ContinuerzCodeGenerator.visit_ContinuecCr&)NbreakrArEr2r2r3 visit_BreakrzCodeGenerator.visit_BreakcCs:|}|j|||||j|||dSr+)rrr$rrr'r)r%r'r( scope_framer2r2r3 visit_Scopes   zCodeGenerator.visit_ScopecCs|}||d||||d||j||||jdd}|j|| || |j || || dS)Nrz.vars = T)r)rrrKr/rrFrrr$rrr'rrG)r%r'r(rr+r2r2r3visit_OverlayScopes      z CodeGenerator.visit_OverlayScopec Csr|jD]3}|d|jd||j|z |j|j}Wntjy-d|j_ Yqwt |j|j|qdS)Nzcontext.eval_ctx.rT) optionsrrr/rZrr-r rr.setattr)r%r'r(keywordrr2r2r3visit_EvalContextModifiers  z'CodeGenerator.visit_EvalContextModifiercCsh|}|j}||d||||jD]}|||q|j||d|ddS)Nz = context.eval_ctx.save()zcontext.eval_ctx.revert(r>)rr-saverr1r'r/revert)r%r'r( old_ctx_name saved_ctxrr2r2r3visit_ScopedEvalContextModifiers    z-CodeGenerator.visit_ScopedEvalContextModifierNFTrr)r r+)Nr)rr)rrrr6rrjTextIOrer~propertyrRrfrrr)rrrrr NoderrrrrrBrrrCallrrMappingr7rrrrrrrrrrxr4r9r;r@rBr,r.r-rFrGrIr rKrLrMr[rTrurrrfrIncluderImport FromImportrrrForrIfrrr FilterBlockrWithrExprStmtr NamedTupler staticmethodrrrrrr5rrrOutputrAssignr AssignBlockrrrrrrrrrrrrDictrrJ visit_Add visit_Sub visit_Mul visit_Divvisit_FloorDiv visit_Pow visit_Mod visit_Andvisit_OrrM visit_Pos visit_Neg visit_Notr8ConcatrComparerOperandrGetattrrGetitemrrr rIteratorrrrCondExprrrKeywordrMarkSaferMarkSafeIfAutoescaperEnvironmentAttributerExtensionAttributer!rhr" InternalNamer#ContextReferencer$DerivedContextReferencer%Continuer(Breakr*Scoper, OverlayScoper-EvalContextModifierr1ScopedEvalContextModifierr6r2r2r2r3r&,s"   I         9.  S     . z1*:  7    0    O      )        r7)Frtypingr6 contextlibr functoolsrior itertoolsrr0rr markupsaferrrr exceptionsr idtrackingr r rrrrr,rutilsrrrGr TYPE_CHECKINGtyping_extensionster?rTypeVarrr7rrr8rjrHrJrLrMrTrr8rerYr\rr:Setrwrxr) RuntimeErrorrurrtrrr&r2r2r2r3s                     $     S