o gz@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 ExprtAnyrcastr)r#r4r2r1r3 optimizeconst+s r9opr&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(r:r2r3visitor<s   z_make_binop..visitor)r9r BinExprr)r:rHr2rGr3 _make_binop;s"rKc r;)Nr%r&r'r(r$cs`|jjr|jjvr|dd||j|n|d||j||ddS)Nzenvironment.call_unop(context, r<r=r?)r@rAintercepted_unopsrCr/r'rFrGr2r3rHTs z_make_unop..visitor)r9r UnaryExprr)rJr2rGr3 _make_unopQs" rNFTr'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/rQgetvalue)r'r@rOrPrQrRrS generatorr2r2r3generatees    rZvaluecCs|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 frozensetalldictitemsr[r2r2r3r]}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 rtrHr'r2r2r3find_undeclareds  rxc@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 CallBlockrr2r2r2r3rys$ryc @sheZdZdZ  ddedejddejeddfddZdd d Z dd e ddfd dZ 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-rrr2r2r3rs   zFrame.__init__cCs2ttt|j}|j|j|j |_|S)z!Create a copy of the current one.) r6r8r)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$r)F)rrr__doc__rr6Optionalrgrrrfrr__copy__r2r2r2r3r)s" 3  c@eZdZdZdS)rvz?Exception used by the `UndeclaredNameVisitor` to signal a stop.Nrrrrr2r2r2r3rvrvc@sVeZdZdZd ddZdejddfddZdejddfd d Z dej ddfd d Z dS)DependencyFinderVisitorz.A visitor that collects filter and test calls.r$NcCst|_t|_dSr+)rnfilterstestsr%r2r2r3rs z DependencyFinderVisitor.__init__r'cC|||j|jdSr+) generic_visitraddrOr~r2r2r3 visit_Filter z$DependencyFinderVisitor.visit_FiltercCrr+)rrrrOr~r2r2r3 visit_Testrz"DependencyFinderVisitor.visit_TestcCdS)zStop visiting at blocks.Nr2r~r2r2r3 visit_Block z#DependencyFinderVisitor.visit_Blockr$N) rrrrrr FilterrTestrBlockrr2r2r2r3rs  rc@sPeZdZdZdejeddfddZdej ddfdd Z dej ddfd d Z dS) ruzA 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. rtr$NcCst||_t|_dSr+)rnrtrw)r%rtr2r2r3rs  zUndeclaredNameVisitor.__init__r'cCsL|jdkr|j|jvr|j|j|j|jkrtdS|j|jdS)Nload)ctxrOrtrwrrvdiscardr~r2r2r3 visit_Names  z UndeclaredNameVisitor.visit_NamecCr)zStop visiting a blocks.Nr2r~r2r2r3r!rz!UndeclaredNameVisitor.visit_Block) rrrrr6Iterablerkrr Namerrrr2r2r2r3rus ruc@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@rrOrPrQrRrSr$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@rOrPrQcreated_block_contextrRr,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@rOrPrQrRrSr2r2r3r-s8   zCodeGenerator.__init__cCs |jduSr+)r,rr2r2r3rSvs zCodeGenerator.optimizedmsglinenoz te.NoReturncCst|||j|j)z*Fail with a :exc:`TemplateAssertionError`.)r rOrP)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?)rrCrr2r2r3 end_writes zCodeGenerator.end_writescCs$|||||||dS)z4Simple shortcut for start_write + write + end_write.N)rrCr)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) rrrQrCrrrappendr)r%rr2r2r3rCs zCodeGenerator.writerextracCs|||||dS)z!Combination of newline and write.N)newlinerC)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_keywordr6r8rk)r^rbr2r2r3r`s  z*CodeGenerator.signature..cs|]}|jVqdSr+)keyr^rr2r2r3r`r2r<N=z, *z , **dict({z, **{: z}, **r?}z, **) anyrr*argsrCr/rrdyn_args dyn_kwargsrr[) r%r'r(rkwarg_workaroundargkwargrr[r2r2r3 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 rHr'id_maprt dependencyrOr2r2r3pull_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) rloadsrrrrrget_resolve_funcr rrNotImplementedErrorjoin)r%r(undefstargetactionparamr2r2r3 enter_frameEs" zCodeGenerator.enter_framewith_python_scopecCsF|sg}|jjD]}||q|r!|d|ddSdSdS)Nrr)rr rrr )r%r(rr rr2r2r3 leave_frameUs  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%rOr2r2r3func`szCodeGenerator.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_noderyrn enumeraterrOrrrefrxbodydefaultslen IndexErrorrrdeclare_parameterr{r|r}rrrr rrrpush_parameter_definitionsr/mark_parameter_storedrpop_parameter_definitionsrrr) r%r'r( macro_refexplicit_callerskip_special_paramsridxrrwr%defaultr2r2r3 macro_bodycsz       $      zCodeGenerator.macro_bodyr.c Csrddd|jjD}t|jdd}t|jjdkr|d7}|d|d |d |jd|jd|jd dS) z.rONr ,zMacro(environment, macro, z, (z), z, context.eval_ctx.autoescape)) r r'rgetattrr(rCr|r}r{)r%r.r( arg_tuplerOr2r2r3 macro_defszCodeGenerator.macro_defcCs*d|j}|jdur|d|j}|S)z.Return a human readable position for the node.zline N in )rrO)r%r'rr2r2r3positions  zCodeGenerator.positioncCs*ddd|jD}d|dS)Nr<css"|] \}}|d|VqdSrNr2)r^rOrr2r2r3r`s  z3CodeGenerator.dump_local_context..{r)r r dump_storesrr)r%r(items_kvr2r2r3dump_local_contexts   z CodeGenerator.dump_local_contextcCs,|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.undefinedzcond_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+)rrrDr2r2r3push_context_referencerz$CodeGenerator.push_context_referencecCs|jdSr+)rrCrr2r2r3pop_context_referencesz#CodeGenerator.pop_context_referencecCs |jdS)Nrrrr2r2r3get_context_refs zCodeGenerator.get_context_refcCs |jd}|dkr dS|dS)Nrrresolvez.resolverGrDr2r2r3r s  zCodeGenerator.get_resolve_funccCs|d||dS)Nz .derived(r?)rHr?rr2r2r3derive_contextszCodeGenerator.derive_contextcCs|jsdS||jdvS)z4Checks if a given target is an undeclared parameter.Fr)rrDr2r2r3parameter_is_undeclaredsz%CodeGenerator.parameter_is_undeclaredcCs|jtdS)z+Pushes a new layer for assignment tracking.N)rrrnrr2r2r3push_assign_trackingrz"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 |D]\}}|r}| d |j |}| |d |qr| d|js|js|rt|dkr| d|dddSd tt|}| 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)rrCrrrr(nextiterrr%rr$rCr mapr4)r%r(vars public_namesrOr%r1 names_strr2r2r3pop_assign_tracking sL            z!CodeGenerator.pop_assign_trackingc Cs |dusJdt|j|j}ddlm}m}|jjr"t||}nt|}|d|dd ||j r:dnd}| t j du}|t jD]} | j|jvr^|d | jd | j| |j| j<qJ|t jD]:} | j|jvr| j} ||j| <} d | vr| d d\} }|d | d |d| qk|d| d| qk|d|j|j|dd|ddd||t|}dt|jdvr|jd}||d|j |d|_!|_"|o|j# |_$|r|d|%||&|j|'|j||j(|dd|)|rR|j#s(||d||jjs7|dn|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|)qWd d&d'|jD}|jd(|d)ddd* d+d'|j-D}|d,|dS)-Nzno root frame allowedr )exportedasync_exportedz%from __future__ import generator_stopzfrom 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)z=async for event in parent_template.root_render_func(context):z yield eventblock_)r%superraz = context.super(z, block_r?z_block_vars = {}css|] }|d|VqdS)z: block_Nr2rr2r2r3r`sz/CodeGenerator.visit_Template..z blocks = {r&css"|] \}}|d|VqdS)rNr2rar2r2r3r`s z debug_info = ).rr@rOruntimer[r\rrrr rRfindr Extendsfind_allrrrr ImportedName importnamerrrsplitrrrAr)rxr&rr*r#rrrrrrrrrrrrrr)r%r'r(r-r[r\exported_namesenvenv have_extendsrimport_impaliasmoduleobjr%rOrrw blocks_kv_str debug_kv_strr2r2r3visit_Template9s                       zCodeGenerator.visit_TemplatecCsd}|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|| | |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?zfor event in context.blocks[revent)rrrrrscopedrJrHrequiredrOrr@rrrr)r%r'r(rrr2r2r3rsF      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/templaterCrOrrFr2r2r3 visit_Extendss(      zCodeGenerator.visit_ExtendscCsl|jr |d|d}t|jtjr+t|jjtrd}nt|jjt t fr*d}n t|jtj tj fr7d}|d|d|| |j||d|jd|jrt||d ||d ||d |d }|jr||d ||dn|jjr|dn|dd}|s||d|||jr|dSdS)zHandles includes.rget_or_select_template get_templateselect_templateztemplate = environment.r=r<r?zexcept TemplateNotFound:rrFzUfor event in template.root_render_func(template.new_context(context.get_all(), True, z)):zGfor event in (await template._get_default_module_async())._body_stream:z6yield from template._get_default_module()._body_streamTrvN)ignore_missingrrrTryr Constr[rkrlrmTupleListr/rCrOr with_contextrr?r@rr)r%r'r( func_nameskip_event_yieldr2r2r3 visit_IncludesV        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))rCrr/ryrOrr?)r%r'r(f_namer2r2r3_import_common9szCodeGenerator._import_commoncCst||j|jd||jr|d|jd||||jr6|jds8|d|jddSdSdS)zVisit regular imports.rrPrOrMcontext.exported_vars.discard(r?N)rrr%rrrCr startswithrFr2r2r3 visit_ImportHs 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?rMr rrPrOr<c3s&|]}|dj|VqdSr;)rr%)r^rOr(r2r3r`}s z1CodeGenerator.visit_FromImport..rQrRrz)context.exported_vars.difference_update((rN)rrCrrtrTrlrrr%rr:replacerrrrr(r rVr4) r%r'r( var_namesdiscarded_namesrOror:messagenames_kvrYr2rr3visit_FromImportSs`             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+)rw)r^rr2r2r3r`rz*CodeGenerator.visit_For..r&) for_branchelsetestz(fiter):z async for zfor r9zauto_aiter(fiter)fiter:r rr"z%(reciter, loop_render_func, depth=0):rstorez8Can'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 recursiverxiter_child_nodesrrfr rrr*r#else_rrrrrrrr/rrCrrrrrrOrrr@rrUrr&rrrrdifference_updatestores) r%r'r(r test_frame else_frame extended_looploop_refloop_filter_funcrOiteration_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/rrCrrr&relif_r)r%r'r(if_framerr2r2r3visit_Ifs(        zCodeGenerator.visit_IfcCs||||\}}||jr)|jds|d|jd|d|jd||j|jd| ||dS)NrMrSr?rPrOr) r3rrrOrrCrrr%r8)r%r'r( macro_framer.r2r2r3 visit_Macro*s zCodeGenerator.visit_MacrocCsR|||\}}|d|||||||j|j|dd||dS)Nz caller = T)forward_caller)r3rr8r visit_Callcallr)r%r'r( call_framer.r2r2r3visit_CallBlock4s    zCodeGenerator.visit_CallBlockcCsh|}|j|||||||j||||||j || || |dSr+) rrr#rrrr&rrfilterrr)r%r'r( filter_framer2r2r3visit_FilterBlock<s     zCodeGenerator.visit_FilterBlockcCs||}|j|||t|j|jD]\}}||||| d|||q| |j || |dSNr) rrr#rziptargetsvaluesrr/rCrr&r)r%r'r( with_framerexprr2r2r3 visit_WithGs    zCodeGenerator.visit_WithcCs||||j|dSr+)rr/r'rFr2r2r3visit_ExprStmtSrzCodeGenerator.visit_ExprStmtc@s4eZdZUejejdefed<ejeed<dS)zCodeGenerator._FinalizeInfo.constsrcN)rrrr6rCallablerk__annotations__r2r2r2r3 _FinalizeInfoWs rr[cCst|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. )rkrsr2r2r3_default_finalize[szCodeGenerator._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@r[r$cs |Sr+r2rs)r2 env_finalizer2r3finalizes z.CodeGenerator._make_finalize..finalizer<csj|Sr+)r@rsr2rr%r2r3rr) rrr@rrr eval_contextgetfrom_objr6r7r)r%rrpass_argr2rr3_make_finalizees.  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. )r4r)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-rrrTr TemplateDatarkr)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.rCrrr%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)rCrrr2r2r3_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) Nrurr rz .extend((rr5r?r)rrrrrr rrTr Impossibler Exceptionrrmrr(rrrr/rrCr) r%r'r(rr&childritemvalr2r2r3 visit_Outputs`                zCodeGenerator.visit_OutputcCsF|||||j||d||j|||dSr)rLrr/rrCr'rZrFr2r2r3 visit_Assigns   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?)rLrrrr#rrrr&rr/rrCrrrZr)r%r'r(rr2r2r3visit_AssignBlock#s         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?) rrrrrrrOrr% find_loadrrKrC)r%r'r(r%rr2r2r3r;s*    zCodeGenerator.visit_NamecCsV|j|j}|d|d||d|||d|jddS)Nzif not isinstance(z , Namespace):zMraise TemplateRuntimeError("cannot assign attribute on non-namespace object")rr)rr%rOrrrattr)r%r'r(r%r2r2r3 visit_NSRefTszCodeGenerator.visit_NSRefcCs:||j}t|tr|t|dS|t|dSr+)rr-rTrhrCrkr4)r%r'r(rr2r2r3 visit_Constbs  zCodeGenerator.visit_ConstcCsHz|t||jWdStjy#|d|jdYdSwNz6(Markup if context.eval_ctx.autoescape else identity)(r?)rCr4rr-r rdatarFr2r2r3visit_TemplateDatais  z CodeGenerator.visit_TemplateDatacCs\|dd}t|jD]\}}|r|d|||q ||dkr)ddSddS)Nr=rr<rz,)r?rCr$rrr/r%r'r(r1rr2r2r3 visit_Tupleqs   zCodeGenerator.visit_TuplecCsF|dt|jD]\}}|r|d|||q |ddS)Nrr<rrrr2r2r3 visit_Listzs  zCodeGenerator.visit_ListcCs`|dt|jD]\}}|r|d||j||d||j|q |ddS)Nr<r<rr)rCr$rrr/rr[rr2r2r3 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.rrCr r/)r%r'r(rrr2r2r3 visit_Concats   zCodeGenerator.visit_ConcatcCs>|d||j||jD]}|||q|ddS)Nr=r?)rCr/rops)r%r'r(r:r2r2r3 visit_Compares  zCodeGenerator.visit_ComparecCs*|dt|jd||j|dS)Nr>)rC operatorsr:r/rrFr2r2r3 visit_OperandszCodeGenerator.visit_OperandcCsX|jjr |d|d||j||d|jd|jjr*|ddSdS)N(await auto_await(zenvironment.getattr(r<r?r)r@rrCr/r'rrFr2r2r3 visit_Getattrs  zCodeGenerator.visit_GetattrcCst|jtjr!||j||d||j||ddS|jjr*|d|d||j||d||j||d|jjrR|ddSdS)Nrrrzenvironment.getitem(r<r?r) rTrr Slicer/r'rCr@rrFr2r2r3 visit_Getitems     zCodeGenerator.visit_GetitemcCsd|jdur ||j||d|jdur||j||jdur0|d||j|dSdS)Nr)startr/rCstoprrFr2r2r3 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) Nawait auto_await(r=rrzNo rr]rrr@r<r?)r@rrCrrOrrrrrrrrrr)r%r'r(rr 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.rCrrrFr2r2r3rs&   "zCodeGenerator.visit_FiltercCsB|||d||j|WddS1swYdSrz)rr/r'rFr2r2r3rs"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/rCr:r2r(r'r%r2r3 write_expr2"s z1CodeGenerator.visit_CondExpr..write_expr2r=z if z else r?r)rrCr/expr1r)r%r'r(r r2r r3visit_CondExprs   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@rrCrAr/r'rrrrqr)r%r'r(rr loop_kwargs block_kwargsr2r2r3r5s$    zCodeGenerator.visit_CallcCs"||jd||j|dS)Nr)rCrr/r[rFr2r2r3 visit_KeywordLszCodeGenerator.visit_KeywordcC&|d||j||ddS)NzMarkup(r?rCr/rrFr2r2r3visit_MarkSafeRs zCodeGenerator.visit_MarkSafecCrrrrFr2r2r3visit_MarkSafeIfAutoescapeWs z(CodeGenerator.visit_MarkSafeIfAutoescapecCs|d|jdS)Nz environment.rCrOrFr2r2r3visit_EnvironmentAttribute^z(CodeGenerator.visit_EnvironmentAttributecCs|d|jd|jdS)Nzenvironment.extensions[z].)rC identifierrOrFr2r2r3visit_ExtensionAttributecsz&CodeGenerator.visit_ExtensionAttributecCs||j|jdSr+)rCrrhrFr2r2r3visit_ImportedNamehsz CodeGenerator.visit_ImportedNamecCs||jdSr+rrFr2r2r3visit_InternalNamekrz CodeGenerator.visit_InternalNamecCs|ddS)Nr)rCrFr2r2r3visit_ContextReferencensz$CodeGenerator.visit_ContextReferencecCs|||dSr+)rCrJrFr2r2r3visit_DerivedContextReferencesrz+CodeGenerator.visit_DerivedContextReferencecC|d|dS)Ncontinuer@rFr2r2r3visit_ContinuexrzCodeGenerator.visit_ContinuecCr)Nbreakr@rFr2r2r3 visit_Break{rzCodeGenerator.visit_BreakcCs:|}|j|||||j|||dSr+)rrr#rrr&r)r%r'r( scope_framer2r2r3 visit_Scope~s   zCodeGenerator.visit_ScopecCs|}||d||||d||j||||jdd}|j|| || |j || || dS)Nrz.vars = T)r)rrrJr/rrErrr#rrr&rrF)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/r[rr-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-saverr*r&r/revert)r%r'r( old_ctx_name saved_ctxrr2r2r3visit_ScopedEvalContextModifiers    z-CodeGenerator.visit_ScopedEvalContextModifierNFTrr)r r+)Nr)rr)rrrr6rrkTextIOrfrpropertyrSrgrrr)rrrrr NoderrrrrrCrrrCallrrMappingr7rrrrrrrrrryr3r8r:r?rAr+r-r,rErFrHr rJrKrLrZrUrtrrrerzIncluderImport FromImportrrrForrIfrrr FilterBlockrWithrExprStmtr NamedTupler staticmethodrrrrrr5rrrOutputrAssignr AssignBlockrrrNSRefrrrrrrrrDictrrK visit_Add visit_Sub visit_Mul visit_Divvisit_FloorDiv visit_Pow visit_Mod visit_Andvisit_OrrN visit_Pos visit_Neg visit_Notr9ConcatrComparerOperandrGetattrrGetitemrrrrIteratorrrrCondExprr rKeywordrMarkSaferMarkSafeIfAutoescaperEnvironmentAttributerExtensionAttributerrgr InternalNamerContextReferencerDerivedContextReferencerContinuer!Breakr#Scoper% OverlayScoper&EvalContextModifierr*ScopedEvalContextModifierr/r2r2r2r3r&,s"   I         9+  S     . w++3  7    0    O      )        r0)Frtypingr6 contextlibr functoolsrior itertoolsrr)rr markupsaferrrr exceptionsr idtrackingr r rrrrr,rutilsrrrHr TYPE_CHECKINGtyping_extensionster@rTypeVarrr7rrr9rkrIrKrMrNrUrr1rfrZr]rr3Setrxryr) RuntimeErrorrvrrurrr&r2r2r2r3s                     $     S