B
    AdS                 @   s  d dl mZ d dlmZ d dlmZ d dlmZ d dlmZ	 d dl
mZ d dlmZ d dlmZ d d	lmZ d d
lmZ d dlmZ d dlmZ d dlm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ZdZ d!ed d!ed d!ed d!ed d!ed dZ"dZ#dd Z$dd Z%d d! Z&edZ'e'd"d#d$ Z(G d%d& d&e)Z*G d'd( d(e)Z+G d)d* d*e+Z,G d+d, d,e-Z.G d-d. d.e+Z/dS )/    )format_datetime)deepcopy)datetime)CONTENT_TYPE)RELATIONSHIP_TYPE)serialize_part_xml)PackURI)Part)	parse_xml)CT_CoreProperties)NS)word_to_python_date_format)xpath)FunctionNamespace)QName)binary_type)	text_typeNz&{D5CDD505-2E9C-101B-9397-08002B2CF9AE}z<vt:lpwstr xmlns:vt="{}"/>vtz<vt:i4 xmlns:vt="{}"/>z<vt:bool xmlns:vt="{}"/>z<vt:filetime xmlns:vt="{}"/>z<vt:r8 xmlns:vt="{}"/>)textintboolr   float   c             C   s   t | tr&ttd }| rdnd|_nt | trHttd }t| |_nt | trjttd }t| |_n|t | trttd }| 	d|_nXt | trttd }| |_n:t | t
r| d	} ttd }| |_ntd
t| |S )Nr   truefalser   r   r   z%Y-%m-%dT%H:%M:%SZr   zutf-8zUnsupported type {})
isinstancer   r
   CUSTOM_PROPERTY_TYPESr   r   r   r   r   strftimer   decode	TypeErrorformattype)valueel r$   H/var/www/html/venv/lib/python3.7/site-packages/docxcompose/properties.pyvalue2vt!   s*    






r&   c             C   s   t | j}|dkr*| j dkr$dS dS nV|dkr<t| jS |dkrNt| jS |dkrbt| jS |dkrz| jrv| jS d	S | jS d S )
Nr   r   TF)i1i2i4r   Zui1Zui2Zui4Zuint)Zr4r8Zfiletimelpwstr )r   	localnamer   lowerr   r   r   Z_parse_W3CDTF_to_datetime)elementtagr$   r$   r%   vt2value:   s    


r1   c             C   s   t | j}|dkS )N)ZbstrZlpstrr+   )r   r-   )propertyr0   r$   r$   r%   is_text_propertyM   s    
r3   z
lower-casec             C   s   dd |D S )Nc             S   s   g | ]}|  qS r$   )r.   ).0r#   r$   r$   r%   
<listcomp>Y   s    zlower_case.<locals>.<listcomp>r$   )contextar$   r$   r%   
lower_caseW   s    r8   c               @   s   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	dd Z
dd Zdd Zd+ddZdd Zdd Zdd Zdd Zdd  Zd,d!d"Zd-d#d$Zd%d& Zd'd( Zd)d* ZdS ).CustomPropertieszvCustom doc properties stored in ``/docProps/custom.xml``.
       Allows updating of doc properties in a document.
    c             C   sj   || _ d | _d | _|  | _y|jjtj}W n" t	k
rR   t
|  | _Y nX || _t
|j| _d S )N)docpart_elementget_doc_languagelanguagepackageZpart_related_byRTCUSTOM_PROPERTIESKeyErrorr
   _part_templateblob)selfr:   r;   r$   r$   r%   __init__`   s    
zCustomProperties.__init__c             C   s   t ddS )NZdocxcomposeztemplates/custom.xml)pkg_resourcesresource_string)rE   r$   r$   r%   rC   n   s    zCustomProperties._part_templatec             C   sh   | j d krVtd}t|tjt| j| jj j| _ | jj j	| j t
j t| j j| _nt| j| j _d S )Nz/docProps/custom.xml)r;   r   r	   CTZOFC_CUSTOM_PROPERTIESr   r<   r:   r?   Z	relate_tor@   rA   r
   rD   Z_blob)rE   Zpartnamer$   r$   r%   _update_partr   s    
zCustomProperties._update_partc             C   s2   t | jd| }|s"t|t|d d S )zGet the value of a property.z&.//cp:property[lower-case(@name)="{}"]r   )r   r<   r    r.   rB   r1   )rE   keypropsr$   r$   r%   __getitem__~   s    zCustomProperties.__getitem__c             C   sZ   t | jd| }|s*| || dS |d d }t|}| || |   dS )zSet the value of a property.z&.//cp:property[lower-case(@name)="{}"]Nr   )	r   r<   r    r.   addr&   	getparentreplacerJ   )rE   rK   r"   rL   value_elZnew_value_elr$   r$   r%   __setitem__   s    zCustomProperties.__setitem__c             C   sp   t | jd| }|s"t||d  |d  t}x&| jD ]}|dt	| |d7 }qDW | 
  dS )zDelete a property.z&.//cp:property[lower-case(@name)="{}"]r   pid   N)r   r<   r    r.   rB   rO   removeMIN_PIDsetr   rJ   )rE   rK   rL   rS   propr$   r$   r%   __delitem__   s    zCustomProperties.__delitem__c                sf   t | jjd}|t | jjjd dtd   fdd|D }|rb|d j  }|ddS d	S )
zWe actually should determine the correct language for each field.
        Instead we simply determine the language from the first w:lang tag in
        the document, and if None are found, from the w:lang tag in the default
        style.
        z	.//w:langz	{{{}}}valwc                s   g | ]} |  kr|qS r$   )keys)r4   r0   )latin_lang_keyr$   r%   r5      s    z5CustomProperties.get_doc_language.<locals>.<listcomp>r   -_N)	r   r:   r/   extendstylesr    r   attribrP   )rE   Z	lang_tagsr>   r$   )r\   r%   r=      s    z!CustomProperties.get_doc_languagec             C   sF   t | jd| }|s"t|t|d d r<d| |< n| |= dS )zVDelete key for non text-properties, set key to empty string for
        text.
        z&.//cp:property[lower-case(@name)="{}"]r   r,   N)r   r<   r    r.   rB   r3   )rE   rK   rL   r$   r$   r%   nullify   s    
zCustomProperties.nullifyc             C   s&   t | jd| }|rdS dS d S )Nz&.//cp:property[lower-case(@name)="{}"]TF)r   r<   r    r.   )rE   itemrL   r$   r$   r%   __contains__   s    zCustomProperties.__contains__Nc             C   s"   y| | S  t k
r   |S X d S )N)rB   )rE   rK   defaultr$   r$   r%   get   s    zCustomProperties.getc             C   s   dd t | jdD }|r(t|d }nt}tdtd }|dt |d| |d	t	| t
|}|| | j| |   d
S )zAdd a property.c             S   s   g | ]}t |qS r$   )r   )r4   rS   r$   r$   r%   r5      s    z(CustomProperties.add.<locals>.<listcomp>z.//cp:property/@pidrT   z<cp:property xmlns:cp="{}"/>cpZfmtidnamerS   N)r   r<   maxrV   r
   r    r   rW   CUSTOM_PROPERTY_FMTIDr   r&   appendrJ   )rE   rh   r"   ZpidsrS   rX   rQ   r$   r$   r%   rN      s    
zCustomProperties.addc             C   s(   | j d krg S t| j d}dd |D S )Nz.//cp:propertyc             S   s   g | ]}| d qS )rh   )rf   )r4   rX   r$   r$   r%   r5      s    z)CustomProperties.keys.<locals>.<listcomp>)r<   r   )rE   rL   r$   r$   r%   r[      s    
zCustomProperties.keysc             C   s(   | j d krg S t| j d}dd |D S )Nz.//cp:propertyc             S   s   g | ]}t |d  qS )r   )r1   )r4   rX   r$   r$   r%   r5      s    z+CustomProperties.values.<locals>.<listcomp>)r<   r   )rE   rL   r$   r$   r%   values   s    
zCustomProperties.valuesc             C   s(   | j d krg S t| j d}dd |D S )Nz.//cp:propertyc             S   s"   g | ]}| d t|d fqS )rh   r   )rf   r1   )r4   rX   r$   r$   r%   r5      s    z*CustomProperties.items.<locals>.<listcomp>)r<   r   )rE   rL   r$   r$   r%   items   s    
zCustomProperties.itemsc             C   s&   x |  D ]\}}| || q
W d S )N)rm   rW   )rE   
propertiesrh   r"   r$   r$   r%   set_properties  s    zCustomProperties.set_propertiesc             C   s   g }x^| j jD ]R}|j|j|j|j|j|jg}x0|D ](}|jr4|j	s4|
| j|jj|d q4W qW |
| j| j jj|d |S )zpThis method searches for all doc-properties in the document and
        in section headers and footers.
        )rh   )r:   sectionsZfirst_page_headerheaderZeven_page_headerZfirst_page_footerfooterZeven_page_footerZ_has_definitionZis_linked_to_previousr_   _find_docprops_inr;   r/   body)rE   rh   docpropssectionZall_header_footers	containerr$   r$   r%   find_docprops_in_document  s    

z*CustomProperties.find_docprops_in_documentc                sT   t |d}dd |D }t |d}|dd |D   d k	rPt fdd|}|S )Nz2.//w:fldSimple[contains(@w:instr, 'DOCPROPERTY ')]c             S   s   g | ]}t |qS r$   )SimpleField)r4   Zsfield_noder$   r$   r%   r5   *  s    z6CustomProperties._find_docprops_in.<locals>.<listcomp>z*.//w:instrText[contains(.,'DOCPROPERTY ')]c             S   s   g | ]}t |qS r$   )ComplexField)r4   Zcfield_noder$   r$   r%   r5   1  s    c                s
   | j  kS )N)rh   )rX   )rh   r$   r%   <lambda>4      z4CustomProperties._find_docprops_in.<locals>.<lambda>)r   r_   filter)rE   r/   rh   Zsfield_nodesru   Zcfield_nodesr$   )rh   r%   rs   $  s    z"CustomProperties._find_docprops_inc             C   sL   |   }t|  }x2|D ]*}||j}|dkr4q|j|| jd qW dS )z)Update all the document's doc-properties.N)r>   )rx   dictrm   rf   rh   updater>   )rE   ru   Zavailable_docpropsdocpropr"   r$   r$   r%   
update_all7  s    
zCustomProperties.update_allc             C   s,   |  |}x|D ]}|j|| jd qW dS )z=Update all instances of a given doc-property in the document.)r>   N)rx   r   r>   )rE   rh   r"   ru   r   r$   r$   r%   r   B  s    

zCustomProperties.updatec             C   s$   |  |}x|D ]}|  qW dS )z0Remove the property fields but keep their value.N)rx   replace_field_with_value)rE   rh   ru   r   r$   r$   r%   dissolve_fieldsH  s    

z CustomProperties.dissolve_fields)N)N)N)__name__
__module____qualname____doc__rF   rC   rJ   rM   rR   rY   r=   rb   rd   rf   rN   r[   rl   rm   ro   rx   rs   r   r   r   r$   r$   r$   r%   r9   \   s*   	


r9   c               @   sT   e Zd ZdZejdejdZdd ZdddZ	dd	d
Z
dd Zdd Zdd ZdS )	FieldBasezEClass used to represent a docproperty field in the document.xml.
    zZDOCPROPERTY +"{0,1}([^\\]*?)"{0,1} +(?:\\\@ +"{0,1}([^\\]*?)"{0,1} +){0,1}\\\* MERGEFORMAT)flagsc             C   s4   || _ |  \| _| _| jr*t| j| _nd| _d S )Nshort)node_parse_fieldname_and_formatrh   date_formatr   )rE   
field_noder$   r$   r%   rF   W  s
    zFieldBase.__init__Nc             C   sP   t |tr|rdS dS t |trD|d k	r8t|| j|dS t|| jS t|S d S )NYN)locale)r   r   r   r   r   r   )rE   r"   r>   r$   r$   r%   _format_value_  s    

zFieldBase._format_valuec             C   s
   t  dS )z; Sets the value of the docproperty in the document
        N)NotImplementedError)rE   r"   r>   r$   r$   r%   r   i  s    zFieldBase.updatec             C   s
   t  dS )zS Removes the field from the document, replacing it with
        its value.
        N)r   )rE   r$   r$   r%   r   n  s    z"FieldBase.replace_field_with_valuec             C   s
   t  d S )N)r   )rE   r$   r$   r%   _get_fieldname_stringt  s    zFieldBase._get_fieldname_stringc             C   s$   | j |  }|d krdS | S )N)NN) fieldname_and_format_search_exprsearchr   groups)rE   matchr$   r$   r%   r   w  s
    
z%FieldBase._parse_fieldname_and_format)N)N)r   r   r   r   recompileUNICODEr   rF   r   r   r   r   r   r$   r$   r$   r%   r   P  s   



r   c               @   s8   e Zd ZdZded Zdd ZdddZd	d
 Z	dS )ry   z Represents a simple field, i.e. <w:fldSimple> node in the
    document.xml, its body containing the value of the field.
    self.node here is the <w:fldSimple> node.
    z{{{}}}instrrZ   c             C   s   | j j| j S )N)r   ra   	attr_name)rE   r$   r$   r%   r     s    z!SimpleField._get_fieldname_stringNc             C   s(   t | jd}|r$| j||d|d _d S )Nz.//w:t)r>   r   )r   r   r   r   )rE   r"   r>   r   r$   r$   r%   r     s    zSimpleField.updatec             C   sD   | j  }t|| j }t| j d }|| j  ||| d S )Nr   )r   rO   listindexr   rU   insert)rE   parentr   w_rr$   r$   r%   r     s
    
z$SimpleField.replace_field_with_value)N)
r   r   r   r   r    r   r   r   r   r   r$   r$   r$   r%   ry     s
   
ry   c               @   s   e Zd ZdZdS )InvalidComplexFieldzNThis exception is raised when a complex field cannot
    be handled correctly.N)r   r   r   r   r$   r$   r$   r%   r     s   r   c                   s   e Zd ZdZdZdZdZdZ fddZdd	 Z	e
d
d Ze
dd Zdd Ze
dd Zdd Zdd ZdddZdd Z  ZS )rz   a2   Represents a complex field, i.e. a several <w:r> nodes delimited by runs
    containing <w:fldChar w:fldCharType="begin"/> and <w:fldChar w:fldCharType="end"/>.
    In these fields, the actual value is stored in <w:r> nodes that come after a
    <w:r><w:fldChar w:fldCharType="separate"/></w:r> node.
    z=./preceding-sibling::w:r/w:fldChar[@w:fldCharType="begin"]/..z;./following-sibling::w:r/w:fldChar[@w:fldCharType="end"]/..z@./following-sibling::w:r/w:fldChar[@w:fldCharType="separate"]/..zw:instrTextc                s*   |  | _| j  | _tt| | d S )N)rO   r   w_psuperrz   rF   )rE   r   )	__class__r$   r%   rF     s    
zComplexField.__init__c                sx     }|dk	rj|njj  fddjD }g }x|D ]}|t|j qJW ddd |D S )zThe field name can be split up in several instrText runs
        so we look for all the instrText nodes between the begin and either
        separate or end runs
        Nc                s    g | ]}j | k r|qS r$   )r   r   )r4   run)lastrE   r$   r%   r5     s    z6ComplexField._get_fieldname_string.<locals>.<listcomp>r,   c             S   s   g | ]
}|j qS r$   )r   )r4   Zeachr$   r$   r%   r5     s    )	get_separate_runr   r   end_run_runsr_   r   XPATH_TEXTSjoin)rE   separate_runrunsZtextsr   r$   )r   rE   r%   r     s    
z"ComplexField._get_fieldname_stringc             C   s&   t | j| j}|sd}t||d S )Nz1Complex field without begin node is not supported)r   r   XPATH_PRECEDING_BEGINSr   )rE   Zbeginsmsgr$   r$   r%   	begin_run  s
    zComplexField.begin_runc             C   s8   t | ds2t| j| j}|s(d}t||d | _| jS )N_end_runz/Complex field without end node is not supportedr   )hasattrr   r   XPATH_FOLLOWING_ENDSr   r   )rE   Zendsr   r$   r$   r%   r     s    

zComplexField.end_runc             C   s@   t | j| j}|sdS |d }| j|| j| jk s<dS |S )zThe ooxml format standard says that the separate node is optional,
        so we check whether we find one in our complex field, otherwise
        we return None.Nr   )r   r   XPATH_FOLLOWING_SEPARATESr   r   r   )rE   Z	separatesseparater$   r$   r%   r     s    zComplexField.get_separate_runc             C   s   t | jdS )Nz./following-sibling::w:r)r   r   )rE   r$   r$   r%   r     s    zComplexField._runsc                sF   j j  }|dkr"g S j | fddjD S )zW
        Get run fields after <w:r><w:fldChar w:fldCharType="separate"/></w:r>
        Nc                s0   g | ](}j |krj | k r|qS r$   )r   r   )r4   r   )	end_indexrE   separate_indexr$   r%   r5     s    z4ComplexField.get_runs_for_update.<locals>.<listcomp>)r   r   r   r   r   )rE   r   r$   )r   rE   r   r%   get_runs_for_update  s    z ComplexField.get_runs_for_updatec                sv     }|dkr6jj  fddjD }n"j|fddjD }|dj |j |S )z
        Get all <w:r> nodes between <w:fldChar w:fldCharType="begin"/>
        and <w:fldChar w:fldCharType="separate"/> including boundaries,
        plus the <w:fldChar w:fldCharType="end"/> node
        Nc                s    g | ]}j | k r|qS r$   )r   r   )r4   r   )r   rE   r$   r%   r5     s    zEComplexField.get_runs_to_replace_field_with_value.<locals>.<listcomp>c                s    g | ]} j |kr|qS r$   )r   r   )r4   r   )rE   r   r$   r%   r5      s    r   )r   r   r   r   r   r   r   rk   )rE   r   r   r$   )r   rE   r   r%   $get_runs_to_replace_field_with_value  s    z1ComplexField.get_runs_to_replace_field_with_valueNc             C   s6  |   }|r|d }t|d}|r6| j||d|d _x|dd  D ]}|| qDW x|dd  D ]}t|d}|rd| j| qdW nt| j}t|dd }	|	d	t
d d t| j}
|
t|
dd  td		t
d }| j||d|_|
| | j| j}| j|d | | j|d
 |
 d S )Nr   z.//w:t)r>   rT   z	w:fldCharz{{{}}}fldCharTyperZ   r   z<w:t xmlns:w="{}"></w:t>r   )r   r   r   r   rU   r   r   r   rW   r    r   r
   rk   r   r   r   )rE   r"   r>   Zruns_after_separateZ	first_w_rr   Zunnecessary_w_tr   r   Z
w_fld_charZ	value_runZdocprop_indexr$   r$   r%   r     s.    
	



zComplexField.updatec             C   s&   |   }x|D ]}| j| qW d S )N)r   r   rU   )rE   Zruns_to_remover   r$   r$   r%   r   >  s    
z%ComplexField.replace_field_with_value)N)r   r   r   r   r   r   r   r   rF   r   r2   r   r   r   r   r   r   r   r   __classcell__r$   r$   )r   r%   rz     s   

8rz   )0Zbabel.datesr   copyr   r   Zdocx.opc.constantsr   rI   r   r@   Zdocx.opc.oxmlr   Zdocx.opc.packurir   Zdocx.opc.partr	   Z	docx.oxmlr
   Zdocx.oxml.corepropsr   Zdocxcompose.utilsr   r   r   Z
lxml.etreer   r   sixr   r   rG   r   rj   r    r   rV   r&   r1   r3   nsr8   objectr9   r   ry   	Exceptionr   rz   r$   r$   r$   r%   <module>   sH    u/