B
    ©‰Ad6|  ã               @   s  d Z ddlmZ ddlmZmZmZmZmZm	Z	 ddl
mZ ddlZddlZddlmZ ddlmZ dd	lmZ dd
lmZ ddlZddlmZ ddlmZmZmZ ddlmZ yddl m!Z! W n  e"k
rà   ddl#m!Z! Y nX ddl$Z$ddl%Z%ddl&Z&ddlZddl'Z'G dd„ de(ƒZ)dS )z/
Created : 2015-03-12

@author: Eric Lapouyade
é    )ÚPathLike)ÚAnyÚOptionalÚIOÚUnionÚDictÚSeté   )ÚSubdocN)Úetree)ÚDocument)Ú	parse_xml)ÚXmlPart)ÚRELATIONSHIP_TYPE)ÚEnvironmentÚTemplateÚmeta)ÚTemplateError)Úescapec               @   sÎ  e Zd ZdZdZdZeee e	e
f ddœdd„ZdXed	œd
d„Zdd„ Zdd„ ZdYdd„Zdd„ Zdd„ Zdd„ Zdd„ ZdZdd„Zd[ee	ef ee ddœdd„Zd d!„ Zd\d"d#„Zd$d%„ Zd&d'„ Zd(d)„ Zd*d+„ Z d]d,d-„Z!d.d/„ Z"d^ee	ef ee edd1œd2d3„Z#d4d5„ Z$d6d7„ Z%d_d8d9„Z&e'd:d;„ ƒZ(d<d=„ Z)d>d?„ Z*d@dA„ Z+dBdC„ Z,dDdE„ Z-dFdG„ Z.dHdI„ Z/dJdK„ Z0dLdM„ Z1dNdO„ Z2dPdQ„ Z3eee e	e
f ddRœdSdT„Z4d`ee e5e	 dUœdVdW„Z6e7e6ƒZ8dS )aÚDocxTemplatez= Class for managing docx files as they were jinja2 templates zJhttp://schemas.openxmlformats.org/officeDocument/2006/relationships/headerzJhttp://schemas.openxmlformats.org/officeDocument/2006/relationships/footerN)Útemplate_fileÚreturnc             C   s$   || _ |  ¡  d | _d| _d| _d S )NF)r   Úreset_replacementsÚdocxÚis_renderedÚis_saved)Úselfr   © r   úB/var/www/html/venv/lib/python3.7/site-packages/docxtpl/template.pyÚ__init__'   s
    zDocxTemplate.__init__T)Úreloadc             C   s&   | j r| jr"|r"t| jƒ| _ d| _d S )NF)r   r   r   r   )r   r    r   r   r   Ú	init_docx.   s    zDocxTemplate.init_docxc             C   s$   |   ¡  i | _d | _d| _d| _d S )Niè  F)r!   Úpic_mapÚcurrent_rendering_partÚdocx_ids_indexr   )r   r   r   r   Úrender_init3   s
    zDocxTemplate.render_initc             C   s   t | j|ƒS )N)Úgetattrr   )r   Únamer   r   r   Ú__getattr__:   s    zDocxTemplate.__getattr__Úunicodec             C   s   t j|dddS )Nr)   F)ÚencodingZpretty_print)r   Útostring)r   Úxmlr*   r   r   r   Úxml_to_string=   s    zDocxTemplate.xml_to_stringc             C   s   |   ¡  | jS )N)r!   r   )r   r   r   r   Úget_docxB   s    zDocxTemplate.get_docxc             C   s   |   | jjj¡S )N)r-   r   Ú_elementÚbody)r   r   r   r   Úget_xmlF   s    zDocxTemplate.get_xmlc          	   C   s(   t |dƒ}| |  ¡ ¡ W d Q R X d S )NÚw)ÚopenÚwriter1   )r   ÚfilenameÚfhr   r   r   Ú	write_xmlI   s    zDocxTemplate.write_xmlc       
      C   sf  t jdd|t jd}dd„ }t jd||t jd}dd„ }t jd	||t jd}d
d„ }t jd||t jd}t jdd|t jd}t jdd|t jd}t jdd|t jd}t jdd|t jd}x,dD ]$}dd|i }t j|d|t jd}q¾W x,dD ]$}dd|i }t j|d|t jd}qìW dd„ }t jd||t jd}dd„ }t jd ||t jd}d!d"„ }	t  d#|	|¡}|S )$zÅ Make a lots of cleaning to have a raw xml understandable by jinja2 :
        strip all unnecessary xml tags, manage table cell background color and colspan,
        unescape html entities, etc... z8(?<={)(<[^>]*>)+(?=[\{%\#])|(?<=[%\}\#])(<[^>]*>)+(?=\})Ú )Úflagsc             S   s   t jdd|  d¡t jdS )Nz</w:t>.*?(<w:t>|<w:t [^>]*>)r8   r   )r9   )ÚreÚsubÚgroupÚDOTALL)Úmr   r   r   Ú	striptagsY   s    z)DocxTemplate.patch_xml.<locals>.striptagsz,{%(?:(?!%}).)*|{#(?:(?!#}).)*|{{(?:(?!}}).)*c             S   sR   |   d¡|   d¡ }tjdd|tjd}tjdd|dd}t dd	|   d
¡ |¡S )Nr	   é   z.<w:r[ >](?:(?!<w:r[ >]).)*<w:t></w:t>.*?</w:r>r8   )r9   z<w:gridSpan[^/]*/>)Úcountz(<w:tcPr[^>]*>)z\1<w:gridSpan w:val="{{%s}}"/>é   )r<   r:   r;   r=   )r>   Úcell_xmlr   r   r   Úcolspan`   s    z'DocxTemplate.patch_xml.<locals>.colspanzE(<w:tc[ >](?:(?!<w:tc[ >]).)*){%\s*colspan\s+([^%]*)\s*%}(.*?</w:tc>)c             S   sR   |   d¡|   d¡ }tjdd|tjd}tjdd|dd}t dd	|   d
¡ |¡S )Nr	   r@   z.<w:r[ >](?:(?!<w:r[ >]).)*<w:t></w:t>.*?</w:r>r8   )r9   z<w:shd[^/]*/>)rA   z(<w:tcPr[^>]*>)z7\1<w:shd w:val="clear" w:color="auto" w:fill="{{%s}}"/>rB   )r<   r:   r;   r=   )r>   rC   r   r   r   Úcellbgk   s    z&DocxTemplate.patch_xml.<locals>.cellbgzD(<w:tc[ >](?:(?!<w:tc[ >]).)*){%\s*cellbg\s+([^%]*)\s*%}(.*?</w:tc>)z'<w:t>((?:(?!<w:t>).)*)({{.*?}}|{%.*?%})z<w:t xml:space="preserve">\1\2z({{r\s.*?}}|{%r\s.*?%})zX</w:t></w:r><w:r><w:t xml:space="preserve">\1</w:t></w:r><w:r><w:t xml:space="preserve">z</w:t>(?:(?!</w:t>).)*?{%-z{%z'-%}(?:(?!<w:t[ >]|{%|{{).)*?<w:t[^>]*?>z%})ÚtrÚtcÚpÚrzP<w:%(y)s[ >](?:(?!<w:%(y)s[ >]).)*({%%|{{)%(y)s ([^}%%]*(?:%%}|}})).*?</w:%(y)s>Úyz\1 \2)rF   rG   rH   zG<w:%(y)s[ >](?:(?!<w:%(y)s[ >]).)*({#)%(y)s ([^}#]*(?:#})).*?</w:%(y)s>c             S   s    dd„ }t jd||  ¡ t jdS )Nc             S   s4   d|   d¡ d |   d¡ |   d¡ d |   d¡ S )NzK<w:vMerge w:val="{% if loop.first %}restart{% else %}continue{% endif %}"/>r	   z{% if loop.first %}rB   r@   z{% endif %}é   )r<   )Úm1r   r   r   Úv_merge”   s    (z;DocxTemplate.patch_xml.<locals>.v_merge_tc.<locals>.v_mergez?(</w:tcPr[ >].*?<w:t(?:.*?)>)(.*?)(?:{%\s*vm\s*%})(.*?)(</w:t>))r9   )r:   r;   r<   r=   )r>   rM   r   r   r   Ú
v_merge_tc“   s    
z*DocxTemplate.patch_xml.<locals>.v_merge_tcz6<w:tc[ >](?:(?!<w:tc[ >]).)*?{%\s*vm\s*%}.*?</w:tc[ >]c             S   sn   |   ¡ }dd„ }dd„ }t d|¡rNtjd||tjd}tjdd	|tjd}ntjd
||tjd}d| d S )Nc             S   s&   |   d¡d |   d¡ d |   d¡ S )Nr	   z{{ rB   z * loop.length }}r@   )r<   )rL   r   r   r   Úwith_gridspan¬   s    zADocxTemplate.patch_xml.<locals>.h_merge_tc.<locals>.with_gridspanc             S   s,   d|   d¡ |   d¡ |   d¡ |   d¡ S )Nz'<w:gridSpan w:val="{{ loop.length }}"/>r	   rB   r@   rK   )r<   )Úm2r   r   r   Úwithout_gridspan³   s     zDDocxTemplate.patch_xml.<locals>.h_merge_tc.<locals>.without_gridspanz
w:gridSpanz(w:gridSpan w:val=")(\d+)("))r9   z{%\s*hm\s*%}r8   z?(</w:tcPr[ >].*?<w:t(?:.*?)>)(.*?)(?:{%\s*hm\s*%})(.*?)(</w:t>)z{% if loop.first %}z{% endif %})r<   r:   Úsearchr;   r=   )r>   Zxml_to_patchrO   rQ   r,   r   r   r   Ú
h_merge_tc©   s(    	

z*DocxTemplate.patch_xml.<locals>.h_merge_tcz6<w:tc[ >](?:(?!<w:tc[ >]).)*?{%\s*hm\s*%}.*?</w:tc[ >]c             S   sB   |   d¡ dd¡ dd¡ dd¡ dd	¡ d
d	¡ dd¡ dd¡S )Nr   z&#8216;ú'z&lt;ú<z&gt;ú>u   â€œú"u   â€u   â€˜u   â€™)r<   Úreplace)r>   r   r   r   Ú
clean_tagsÚ   s    
z*DocxTemplate.patch_xml.<locals>.clean_tagsz(?<=\{[\{%])(.*?)(?=[\}%]}))r:   r;   r=   )
r   Úsrc_xmlr?   rD   rE   rJ   ÚpatrN   rS   rY   r   r   r   Ú	patch_xmlM   sD    

.	zDocxTemplate.patch_xmlc       	   
   C   sæ   t  dd|¡}y,|| _|r&| |¡}nt|ƒ}| |¡}W nj tk
r¤ } zLt|dƒr|jd k	rt	|jd dƒ}t
dd„ | ¡ ||d … ƒ|_|‚W d d }~X Y nX t  d	d
|¡}| dd¡ dd¡ dd¡ dd¡}|  |¡}|S )Nz
<w:p([ >])z\n<w:p\1ÚlinenorK   r   c             S   s   t  dd| ¡S )Nz<[^>]+>r8   )r:   r;   )Úxr   r   r   Ú<lambda>ó   ó    z.DocxTemplate.render_xml_part.<locals>.<lambda>é   z\n<w:p([ >])z<w:p\1z{_{z{{z}_}z}}z{_%z{%z%_}z%})r:   r;   r#   Úfrom_stringr   Úrenderr   Úhasattrr]   ÚmaxÚmapÚ
splitlinesZdocx_contextrX   Úresolve_listing)	r   rZ   ÚpartÚcontextÚ	jinja_envÚtemplateZdst_xmlÚexcÚline_numberr   r   r   Úrender_xml_partç   s*    
zDocxTemplate.render_xml_part)rj   rk   r   c             C   sb   ddddddg}|d krt ƒ }x>|D ]6}t| jj|ƒ}| |¡}| |¡}t| jj||ƒ q$W d S )NÚauthorÚcommentsÚ
identifierÚlanguageÚsubjectÚtitle)r   r&   r   Zcore_propertiesrb   rc   Úsetattr)r   rj   rk   Ú
propertiesÚpropÚinitialrl   Úrenderedr   r   r   Úrender_propertiesÿ   s    


zDocxTemplate.render_propertiesc                s8   dd„ ‰‡fdd„‰ ‡ fdd„}t jd||t jd}|S )	Nc             S   sR   |  d¡ dd| | f ¡}| dd|| f ¡}| dd¡}| dd	|| f ¡}|S )
Nr   ú	zB</w:t></w:r><w:r>%s<w:tab/></w:r><w:r>%s<w:t xml:space="preserve">úz:</w:t></w:r></w:p><w:p>%s<w:r>%s<w:t xml:space="preserve">Ú
z'</w:t><w:br/><w:t xml:space="preserve">úze</w:t></w:r></w:p><w:p><w:r><w:br w:type="page"/></w:r></w:p><w:p>%s<w:r>%s<w:t xml:space="preserve">)r<   rX   )Úrun_propertiesÚparagraph_propertiesr>   r,   r   r   r   Úresolve_text  s    z2DocxTemplate.resolve_listing.<locals>.resolve_textc                sJ   t  d| d¡¡‰ˆr ˆ d¡nd‰t jd‡ ‡‡fdd„| d¡t jdS )Nz<w:rPr>.*?</w:rPr>r   r8   z<w:t(?:[^>]*)?>.*?</w:t>c                s   ˆˆˆ | ƒS )Nr   )r^   )r   r‚   r€   r   r   r_   *  r`   zCDocxTemplate.resolve_listing.<locals>.resolve_run.<locals>.<lambda>)r9   )r:   rR   r<   r;   r=   )r   r>   )r‚   )r   r€   r   Úresolve_run&  s
    z1DocxTemplate.resolve_listing.<locals>.resolve_runc                sH   t  d|  d¡¡‰ ˆ r ˆ  d¡nd‰ t jd‡ ‡fdd„|  d¡t jdS )Nz<w:pPr>.*?</w:pPr>r   r8   z<w:r(?:[^>]*)?>.*?</w:r>c                s
   ˆˆ | ƒS )Nr   )r^   )r   rƒ   r   r   r_   1  r`   zIDocxTemplate.resolve_listing.<locals>.resolve_paragraph.<locals>.<lambda>)r9   )r:   rR   r<   r;   r=   )r>   )rƒ   )r   r   Úresolve_paragraph-  s
    z7DocxTemplate.resolve_listing.<locals>.resolve_paragraphz<w:p(?:[^>]*)?>.*?</w:p>)r9   )r:   r;   r=   )r   r,   r„   r   )rƒ   r‚   r   rh     s
    zDocxTemplate.resolve_listingc             C   s*   |   ¡ }|  |¡}|  || jj||¡}|S )N)r1   r\   ro   r   Ú_part)r   rj   rk   r,   r   r   r   Ú	build_xml8  s    
zDocxTemplate.build_xmlc             C   s   | j j}|j}| ||¡ d S )N)r   r/   r0   rX   )r   ÚtreeÚrootr0   r   r   r   Úmap_tree>  s    zDocxTemplate.map_treec             c   s>   x8| j jj ¡ D ]&\}}|j|kr|jjr||jfV  qW d S )N)r   r…   Ú_relsÚitemsÚreltypeÚtarget_partÚblob)r   ÚuriÚrelKeyÚvalr   r   r   Úget_headers_footersC  s    z DocxTemplate.get_headers_footersc             C   s   |   t|jƒ¡S )N)r-   r   rŽ   )r   ri   r   r   r   Úget_part_xmlH  s    zDocxTemplate.get_part_xmlc             C   s"   t  d|t j¡}|r| d¡S dS )Nz <\?xml[^\?]+\bencoding="([^"]+)"r	   zutf-8)r:   ÚmatchÚIr<   )r   r,   r>   r   r   r   Úget_headers_footers_encodingK  s    
z)DocxTemplate.get_headers_footers_encodingc             c   sZ   xT|   |¡D ]F\}}|  |¡}|  |¡}|  |¡}|  ||||¡}|| |¡fV  qW d S )N)r’   r“   r–   r\   ro   Úencode)r   rj   r   rk   r   ri   r,   r*   r   r   r   Úbuild_headers_footers_xmlQ  s    


z&DocxTemplate.build_headers_footers_xmlc             C   sj   | j jj| j}t |j|j||j¡}x.|j	 
¡ D ] \}}| |j|j|j|j¡ q2W || j jj| _d S )N)r   r…   rŠ   r   r   ÚloadZpartnameÚcontent_typeÚpackageÚrelsr‹   Zload_relrŒ   Ú_targetÚrIdÚis_external)r   r   r,   ri   Znew_partrž   Úrelr   r   r   Úmap_headers_footers_xmlY  s
    z$DocxTemplate.map_headers_footers_xmlF)rj   rk   Ú
autoescaper   c       
      C   s¾   |   ¡  |r"|st|d}n||_|  ||¡}|  |¡}|  |¡ |  |¡ |  || j|¡}x|D ]\}}|  	||¡ qbW |  || j
|¡}	x|	D ]\}}|  	||¡ qW |  ||¡ d| _d S )N)r¢   T)r%   r   r¢   r†   Ú
fix_tablesÚfix_docpr_idsr‰   r˜   Ú
HEADER_URIr¡   Ú
FOOTER_URIr{   r   )
r   rj   rk   r¢   Zxml_srcr‡   Úheadersr   r,   Zfootersr   r   r   rc   `  s&    




zDocxTemplate.renderc                sº  t jdd}t j||d}d|jd  d ‰ x†| ˆ d ¡D ]r}| ˆ d ¡}| ˆ d	 ¡}d
}xH| ˆ d ¡D ]6}| ˆ d ¡}	t|ƒ| t|	ƒk rtt|	ƒt|ƒ }qtW |d
krd}
d }x4|D ],}| ˆ d ¡d k	rÆ|
t	| ˆ d ¡ƒ7 }
qÆW |
d
kr|
t|ƒ }|
t|ƒ|  }x<|D ]4}| 
ˆ d ttt	| ˆ d ¡ƒ| | ƒƒ¡ q"W x4t|ƒD ](}t  |ˆ d	 ˆ d tt|ƒƒi¡ qdW | ˆ d	 ¡}t|ƒ}d
}‡ fdd„}x>| ˆ d ¡D ],}| ˆ d ¡}	t ||	d
¡}t||ƒ}qÆW || }|d
kr>d}x8|| d … D ]&}|t	| ˆ d ¡ƒ7 }| |¡ qW | ˆ d	 ¡}d
}t|ƒd
krx|t|ƒ }t|ƒ}x8|D ]0}| 
ˆ d ttt	| ˆ d ¡ƒ| ƒƒ¡ q~W q>W |S )NT)Zrecover)ÚparserÚ{r2   Ú}ÚtblÚtblGridZgridColr   rF   rG   g        c                sN   |  ˆ d ¡}|d krd n|  ˆ d ¡}|d k	rF| t| ˆ d ¡ƒ S | d S )NZtcPrZgridSpanr‘   r	   )ÚfindÚintÚget)ÚtotalÚcellZtc_prZ	grid_span)Únsr   r   Úget_cell_len¹  s
    z-DocxTemplate.fix_tables.<locals>.get_cell_len)r   Z	XMLParserÚ
fromstringÚnsmapÚiterr­   ÚfindallÚlenr¯   ÚfloatÚsetÚstrr®   ÚrangeZ
SubElementÚ	functoolsÚreducere   Úremove)r   r,   r¨   r‡   Útr¬   ÚcolumnsZto_addrI   ÚcellsÚwidthZnew_averageÚcZold_averageÚiZcolumns_lenZcells_len_maxr³   Z	cells_lenZ	to_removeZremoved_widthZcolumns_leftZextra_spacer   )r²   r   r£   Ž  s`    



&

4zDocxTemplate.fix_tablesc             C   s@   x:|j dtjjjdD ]"}|  jd7  _t| jƒ|jd< qW d S )Nz
//wp:docPr)Ú
namespacesr	   Úid)Úxpathr   Úoxmlr²   rµ   r$   r»   Úattrib)r   r‡   Úeltr   r   r   r¤   ä  s    zDocxTemplate.fix_docpr_idsc             C   s   |   ¡  t| |ƒS )N)r!   r
   )r   Zdocpathr   r   r   Ú
new_subdocê  s    zDocxTemplate.new_subdocc          	   C   sD   t | dƒr|  ¡ }nt| dƒ}| ¡ }W d Q R X t |¡d@ }|S )NÚreadÚrbl   ÿÿ )rd   rÍ   r3   ÚbinasciiÚcrc32)Zfile_objÚbufr6   Úcrcr   r   r   Úget_file_crcî  s    

zDocxTemplate.get_file_crcc          	   C   sL   |   |¡}t|dƒr$| ¡ | j|< n$t|dƒ}| ¡ | j|< W dQ R X dS )aý  Replace one media by another one into a docx

        This has been done mainly because it is not possible to add images in
        docx header/footer.
        With this function, put a dummy picture in your header/footer,
        then specify it with its replacement in this function using the file path
        or file-like objects.

        Syntax: tpl.replace_media('dummy_media_to_replace.png','media_to_paste.jpg')
            -- or --
                tpl.replace_media(io.BytesIO(image_stream), io.BytesIO(new_image_stream))

        Note: for images, the aspect ratio will be the same as the replaced image

        Note2: it is important to have the source media file as it is required
                to calculate its CRC to find them in the docx
        rÍ   rÎ   N)rÓ   rd   rÍ   Úcrc_to_new_mediar3   )r   Úsrc_fileÚdst_filerÒ   r6   r   r   r   Úreplace_mediaù  s
    

zDocxTemplate.replace_mediac          	   C   sB   t |dƒr| ¡ | j|< n$t|dƒ}| ¡ | j|< W dQ R X dS )aˆ  Replace embedded picture with original-name given by embedded_file.
           (give only the file basename, not the full path)
           The new picture is given by dst_file (either a filename or a file-like
           object)

        Notes:
            1) embedded_file and dst_file must have the same extension/format
               in case dst_file is a file-like object, no check is done on
               format compatibility
            2) the aspect ratio will be the same as the replaced image
            3) There is no need to keep the original file (this is not the case
               for replace_embedded and replace_media)
        rÍ   rÎ   N)rd   rÍ   Úpics_to_replacer3   )r   Zembedded_filerÖ   r6   r   r   r   Úreplace_pic  s    
zDocxTemplate.replace_picc          	   C   s2   t |dƒ}|  |¡}| ¡ | j|< W dQ R X dS )a  Replace one embedded object by another one into a docx

        This has been done mainly because it is not possible to add images
        in docx header/footer.
        With this function, put a dummy picture in your header/footer,
        then specify it with its replacement in this function

        Syntax: tpl.replace_embedded('dummy_doc.docx','doc_to_paste.docx')

        Note2 : it is important to have the source file as it is required to
                calculate its CRC to find them in the docx
        rÎ   N)r3   rÓ   rÍ   Úcrc_to_new_embedded)r   rÕ   rÖ   r6   rÒ   r   r   r   Úreplace_embedded)  s    
zDocxTemplate.replace_embeddedc          	   C   s(   t |dƒ}| ¡ | j|< W dQ R X dS )a0  Replace one file in the docx file

        First note that a MSWord .docx file is in fact a zip file.

        This method can be used to replace document embedded in the docx template.

        Some embedded document may have been modified by MSWord while saving
        the template : thus replace_embedded() cannot be used as CRC is not the
        same as the original file.

        This method works for embedded MSWord file like Excel or PowerPoint file,
        but won't work for others like PDF, Python or even Text files :
        For these ones, MSWord generate an oleObjectNNN.bin file which is no
        use to be replaced as it is encoded.

        Syntax:

        tpl.replace_zipname(
            'word/embeddings/Feuille_Microsoft_Office_Excel1.xlsx',
            'my_excel_file.xlsx')

        The zipname is the one you can find when you open docx with WinZip,
        7zip (Windows) or unzip -l (Linux). The zipname starts with
        "word/embeddings/". Note that the file is renamed by MSWord,
        so you have to guess a little bit...
        rÎ   N)r3   rÍ   Úzipname_to_replace)r   ZzipnamerÖ   r6   r   r   r   Úreplace_zipname:  s    zDocxTemplate.replace_zipnamec             C   s   i | _ i | _i | _i | _dS )aZ  Reset replacement dictionaries

        This will reset data for image/embedded/zipname replacement

        This is useful when calling several times render() with different
        image/embedded/zipname replacements without re-instantiating
        DocxTemplate object.
        In this case, the right sequence for each rendering will be :
            - reset_replacements(...)
            - replace_zipname(...), replace_media(...) and/or replace_embedded(...),
            - render(...)

        If you instantiate DocxTemplate object before each render(),
        this method is useless.
        N)rÔ   rÚ   rÜ   rØ   )r   r   r   r   r   X  s    zDocxTemplate.reset_replacementsc          
   C   sz  | j s| js| jrvt|dƒr\t ¡ }t|ƒ |¡ | d¡ | d¡ | 	¡  | d¡ nd| }t
 ||¡ t |¡Ê}t |d¡²}xª| ¡ D ]ž}| |j¡}|j| jkrÆ| || j|j ¡ q”|j d¡rô|j| j krô| || j |j ¡ q”|j d¡r&|j| jkr&| || j|j ¡ q”| ||¡ q”W W d Q R X W d Q R X t|dƒs`t
 |¡ t|dƒrv| d¡ d S )NrÍ   r   z %s_docxtpl_before_replace_mediasr2   zword/media/zword/embeddings/)rÔ   rÚ   rÜ   rd   ÚioÚBytesIOr   ÚsaveÚseekÚtruncateÚosÚrenameÚzipfileÚZipFileÚinfolistrÍ   r5   ÚwritestrÚ
startswithÚCRCr¿   )r   Z	docx_fileZtmp_fileZzinZzoutÚitemrÑ   r   r   r   Úpost_processingm  s:    


$
zDocxTemplate.post_processingc             C   s   | j r|  ¡  d S )N)rØ   Ú_replace_pics)r   r   r   r   Úpre_processing’  s    zDocxTemplate.pre_processingc             C   sˆ   dd„ | j D ƒ}| jj}|  ||¡ x8t |j¡D ](\}}|jtj	tj
fkr2|  |j|¡ q2W x$| ¡ D ]\}}|shtd| ƒ‚qhW dS )zRReplaces pictures xml tags in the docx template with pictures provided by the userc             S   s   i | ]
}d |“qS )Fr   )Ú.0Úkeyr   r   r   ú
<dictcomp>š  s    z.DocxTemplate._replace_pics.<locals>.<dictcomp>z)Picture %s not found in the docx templateN)rØ   r   ri   Ú_replace_docx_part_picsÚsixÚ	iteritemsrœ   rŒ   ÚREL_TYPEZHEADERZFOOTERr   r‹   Ú
ValueError)r   Úreplaced_picsri   Zrelidr    Úimg_idZreplacedr   r   r   rí   —  s    zDocxTemplate._replace_picsc             C   s   | j S )N)r"   )r   r   r   r   Úget_pic_map¬  s    zDocxTemplate.get_pic_mapc          	   C   s®  t  |j¡}i }|jdtjjjd}xv|D ]l}d }yH|jd tjjjd kr˜|jdtjjjdd }|jdtjjjd}	t	|	ƒdkr”|	d }qšw,nw,d}
|jd	|
 tjjjdd }|jd
|
 tjjjd}|rà|d }nd}|jd|
 tjjjd}|r|d }nd}|j
| j|j
| jf||< xPt | j¡D ]@\}}||ks`||ks`||kr:||| d _d||< P q:W W q, tk
r˜   w,Y q,X q,W | j |¡ d S )Nz//a:graphic/a:graphicData)rÆ   r   Zpiczpic:pic/pic:blipFill/a:blipr   z@r:embedzpic:pic/pic:nvPicPr/pic:cNvPr/z%s@namez%s@titler8   z%s@descrr	   T)r   r´   rŽ   rÈ   r   rÉ   r²   rµ   rÊ   r¸   rœ   Z
target_refr   ró   rô   rØ   Z_blobÚ	Exceptionr"   Úupdate)r   Zdoc_partr÷   ÚetZpart_mapZgdsÚgdr    ZblipÚdestZnon_visual_propertiesr5   Útitlesru   ZdescriptionsÚdescriptionrø   Zimg_datar   r   r   rò   ¯  sJ    






z$DocxTemplate._replace_docx_part_picsc             C   s   |   ¡  | jjj|tjddS )NT)rŸ   )r!   r   r…   Z	relate_torõ   Z	HYPERLINK)r   Úurlr   r   r   Úbuild_url_idæ  s    zDocxTemplate.build_url_id)r5   r   c             O   sH   | j s| jst| jƒ| _|  ¡  | jj|f|ž|Ž |  |¡ d| _ d S )NT)r   r   r   r   r   rî   rà   rì   )r   r5   ÚargsÚkwargsr   r   r   rà   ë  s    
zDocxTemplate.save)rk   r   c       	      C   sˆ   | j dd |  ¡ }|  |¡}xD| j| jgD ]4}x.|  |¡D ] \}}|  |¡}||  |¡7 }q<W q,W |rn|}ntƒ }| |¡}t	 
|¡S )NF)r    )r!   r1   r\   r¥   r¦   r’   r“   r   Úparser   Zfind_undeclared_variables)	r   rk   r,   r   r   ri   Z_xmlÚenvZparse_contentr   r   r   Ú!get_undeclared_template_variablesõ  s    


z.DocxTemplate.get_undeclared_template_variables)T)r)   )N)N)N)N)NF)N)N)9Ú__name__Ú
__module__Ú__qualname__Ú__doc__r¥   r¦   r   r   Úbytesr»   r   r   Úboolr!   r%   r(   r-   r.   r1   r7   r\   ro   r   r   r   r   r{   rh   r†   r‰   r’   r“   r–   r˜   r¡   rc   r£   r¤   rÌ   ÚstaticmethodrÓ   r×   rÙ   rÛ   rÝ   r   rì   rî   rí   rù   rò   r  rà   r   r  ÚpropertyZundeclared_template_variablesr   r   r   r   r   !   sX   
 
  


 )V
%7
r   )*r  rã   r   Útypingr   r   r   r   r   r   Zsubdocr
   r½   rÞ   Zlxmlr   r   r   Zdocx.opc.oxmlr   Zdocx.opc.partr   Zdocx.oxml.nsZdocx.opc.constantsr   rõ   Zjinja2r   r   r   Zjinja2.exceptionsr   Úhtmlr   ÚImportErrorÚcgir:   ró   rÏ   rå   Úobjectr   r   r   r   r   Ú<module>   s.    