o
    W_E`                     @   s\  d 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	 ddl
mZ ddlmZmZmZ dd	lmZ 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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G d d! d!eZG d"d# d#eZ G d$d% d%ej!Z"ed&ej!fe#e"j$Z%dS )'z_
Provides a wrapper around lxml that enables declarative definition of custom
element classes.
    )absolute_import)etreeN)Unicode)OxmlElement)InvalidXmlError)NamespacePrefixedTagnsmapqn)lazypropertyc                 C   s   t j| ddd}t|S )z_
    Serialize *element* to human-readable XML suitable for tests. No XML
    declaration.
    unicodeT)encodingZpretty_print)r   tostring	XmlString)elementxml r   BD:\Projects\ConvertPro\env\Lib\site-packages\docx\oxml\xmlchemy.pyserialize_for_reading   s   r   c                   @   sF   e Zd ZdZedZdd Zdd Zdd Z	d	d
 Z
edd ZdS )r   zg
    Provides string comparison override suitable for serialized XML that is
    useful for tests.
    z)( *</?[\w:]+)(.*?)(/?>)([^<]*</[\w:]+>)?$c                 C   sN   |   }|  }t|t|krdS t||D ]\}}| ||s$ dS qdS )NFT)
splitlineslenzip_eq_elm_strs)selfotherlinesZlines_otherlineZ
line_otherr   r   r   __eq__,   s   zXmlString.__eq__c                 C   s   |  | S N)r   )r   r   r   r   r   __ne__6      zXmlString.__ne__c                 C   s   |  }| }t|S )z
        Return a sequence of attribute strings parsed from *attrs*. Each
        attribute string is stripped of whitespace on both ends.
        )stripsplitsorted)r   attrsZattr_lstr   r   r   	_attr_seq9   s   zXmlString._attr_seqc                 C   sd   |  |\}}}}|  |\}}}	}
||krdS | || |kr$dS ||	kr*dS ||
kr0dS dS )zl
        Return True if the element in *line_2* is XML equivalent to the
        element in *line*.
        FT)_parse_liner$   )r   r   Zline_2frontr#   closetextZfront_2Zattrs_2Zclose_2Ztext_2r   r   r   r   B   s   zXmlString._eq_elm_strsc                    s8   | j |  fddtddD \}}}}||||fS )zo
        Return front, attrs, close, text 4-tuple result of parsing XML element
        string *line*.
        c                    s   g | ]}  |qS r   )group).0nmatchr   r   
<listcomp>Z   s    z)XmlString._parse_line.<locals>.<listcomp>      )_xml_elm_line_pattr-   range)clsr   r&   r#   r'   r(   r   r,   r   r%   S   s    zXmlString._parse_lineN)__name__
__module____qualname____doc__recompiler1   r   r   r$   r   classmethodr%   r   r   r   r   r      s    

	r   c                   @   s   e Zd ZdZdd ZdS )MetaOxmlElementz'
    Metaclass for BaseOxmlElement
    c                 C   s>   t ttttttf}| D ]\}}t||r|	| | qd S r   )
OneAndOnlyOne	OneOrMoreOptionalAttributeRequiredAttribute
ZeroOrMore	ZeroOrOneZeroOrOneChoiceitems
isinstancepopulate_class_members)r3   ZclsnamebasesZclsdictZdispatchablekeyvaluer   r   r   __init__b   s   
zMetaOxmlElement.__init__N)r4   r5   r6   r7   rI   r   r   r   r   r;   ^   s    r;   c                       <   e Zd ZdZ fddZdd Zdd Zedd	 Z  Z	S )
BaseAttributez_
    Base class for OptionalAttribute and RequiredAttribute, providing common
    methods.
    c                       t t|   || _|| _d S r   )superrK   rI   
_attr_name_simple_type)r   	attr_namesimple_type	__class__r   r   rI   q      
zBaseAttribute.__init__c                 C   s   || _ || _|   dS z?
        Add the appropriate methods to *element_cls*.
        N)_element_cls
_prop_name_add_attr_propertyr   element_cls	prop_namer   r   r   rE   v   s   z$BaseAttribute.populate_class_membersc                 C   s$   t | j| jd}t| j| j| dS )z
        Add a read/write ``{prop_name}`` property to the element class that
        returns the interpreted value of this attribute on access and changes
        the attribute value to its ST_* counterpart on assignment.
        N)property_getter_settersetattrrV   rW   r   	property_r   r   r   rX      s   z BaseAttribute._add_attr_propertyc                 C   s   d| j v r
t| j S | j S )N:)rN   r	   r   r   r   r   _clark_name   s   

zBaseAttribute._clark_name)
r4   r5   r6   r7   rI   rE   rX   r\   rd   __classcell__r   r   rR   r   rK   l   s    	
rK   c                       sF   e Zd ZdZd fdd	Zedd Zedd Zed	d
 Z  Z	S )r>   z
    Defines an optional attribute on a custom element class. An optional
    attribute returns a default value when not present for reading. When
    assigned |None|, the attribute is removed.
    Nc                    s   t t| || || _d S r   )rM   r>   rI   _default)r   rP   rQ   defaultrR   r   r   rI      s   
zOptionalAttribute.__init__c                        fdd} j |_|S )t
        Return a function object suitable for the "get" side of the attribute
        property descriptor.
        c                    s&   |   j}|d u r jS  j|S r   )getrd   rf   rO   from_xmlobjZattr_str_valuerc   r   r   get_attr_value   s   z1OptionalAttribute._getter.<locals>.get_attr_value
_docstringr7   r   rn   r   rc   r   r]      s   zOptionalAttribute._getterc                 C      d| j j| jf S )s
        Return the string to use as the ``__doc__`` attribute of the property
        for this attribute.
        z%s type-converted value of ``%s`` attribute, or |None| (or specified default value) if not present. Assigning the default value causes the attribute to be removed from the element.rO   r4   rN   rc   r   r   r   rp      s   zOptionalAttribute._docstringc                        fdd}|S )t
        Return a function object suitable for the "set" side of the attribute
        property descriptor.
        c                    sJ   |d u s	| j kr j| jv r| j j= d S  j|}|  j| d S r   )rf   rd   ZattribrO   to_xmlsetrm   rH   Z	str_valuerc   r   r   set_attr_value   s   
z1OptionalAttribute._setter.<locals>.set_attr_valuer   r   rz   r   rc   r   r^      s   zOptionalAttribute._setterr   )
r4   r5   r6   r7   rI   r\   r]   rp   r^   re   r   r   rR   r   r>      s    

r>   c                   @   s4   e Zd ZdZedd Zedd Zedd ZdS )	r?   a  
    Defines a required attribute on a custom element class. A required
    attribute is assumed to be present for reading, so does not have
    a default value; its actual value is always used. If missing on read,
    an |InvalidXmlError| is raised. It also does not remove the attribute if
    |None| is assigned. Assigning |None| raises |TypeError| or |ValueError|,
    depending on the simple type of the attribute.
    c                    rh   )ri   c                    s4   |   j}|d u rtd j| jf  j|S )Nz1required '%s' attribute not present on element %s)rj   rd   r   rN   tagrO   rk   rl   rc   r   r   rn      s   
z1RequiredAttribute._getter.<locals>.get_attr_valuero   rq   r   rc   r   r]      s   zRequiredAttribute._getterc                 C   rr   )rs   z,%s type-converted value of ``%s`` attribute.rt   rc   r   r   r   rp      s   zRequiredAttribute._docstringc                    ru   )rv   c                    s    j |}|  j| d S r   )rO   rw   rx   rd   ry   rc   r   r   rz      s   z1RequiredAttribute._setter.<locals>.set_attr_valuer   r{   r   rc   r   r^      s   zRequiredAttribute._setterN)r4   r5   r6   r7   r\   r]   rp   r^   r   r   r   r   r?      s    


r?   c                       s   e Zd ZdZd% fdd	Zdd Zdd Zd	d
 Zdd Zdd Z	dd Z
edd Zdd Zdd Zedd Zedd Zedd Zedd Zedd  Zed!d" Zed#d$ Z  ZS )&_BaseChildElementz
    Base class for the child element classes corresponding to varying
    cardinalities, such as ZeroOrOne and ZeroOrMore.
    r   c                    rL   r   )rM   r}   rI   _nsptagname_successors)r   
nsptagname
successorsrR   r   r   rI      rT   z_BaseChildElement.__init__c                 C   s   || _ || _dS )z`
        Baseline behavior for adding the appropriate methods to
        *element_cls*.
        N)rV   rW   rY   r   r   r   rE      s   
z(_BaseChildElement.populate_class_membersc                    *    fdd}d j  |_  j| dS )za
        Add an ``_add_x()`` method to the element class for this child
        element.
        c                    sH   t |  j}| }| D ]
\}}t||| qt |  j}|| |S r   )getattr_new_method_namerC   r_   _insert_method_name)rm   r#   Z
new_methodchildrG   rH   Zinsert_methodrc   r   r   
_add_child  s   z0_BaseChildElement._add_adder.<locals>._add_childSAdd a new ``<%s>`` child element unconditionally, inserted in the correct sequence.N)r~   r7   _add_to_class_add_method_name)r   r   r   rc   r   
_add_adder  s   
z_BaseChildElement._add_adderc                 C   s$   | j }d| j |_| | j| dS )z
        Add a ``_new_{prop_name}()`` method to the element class that creates
        a new, empty element of the correct type, having no attributes.
        zYReturn a "loose", newly created ``<%s>`` element having no attributes, text, or children.N)_creatorr~   r7   r   r   )r   Zcreatorr   r   r   _add_creator  s   z_BaseChildElement._add_creatorc                 C   "   t | jdd}t| j| j| dS )zo
        Add a read-only ``{prop_name}`` property to the element class for
        this child element.
        N)r\   r]   r_   rV   rW   r`   r   r   r   _add_getter(  s   z_BaseChildElement._add_getterc                    r   )zd
        Add an ``_insert_x()`` method to the element class for this child
        element.
        c                    s   | j |g jR   |S r   )insert_element_beforer   rm   r   rc   r   r   _insert_child6  s   z6_BaseChildElement._add_inserter.<locals>._insert_childzYReturn the passed ``<%s>`` element after inserting it as a child in the correct sequence.N)r~   r7   r   r   )r   r   r   rc   r   _add_inserter1  s   z_BaseChildElement._add_inserterc                 C   s*   d| j  }t| jdd}t| j|| dS )z
        Add a read-only ``{prop_name}_lst`` property to the element class to
        retrieve a list of child elements matching this type.
        z%s_lstN)rW   r\   _list_getterr_   rV   )r   r[   ra   r   r   r   _add_list_getter@  s   
z"_BaseChildElement._add_list_getterc                 C   
   d| j  S )Nz_add_%srW   rc   r   r   r   r   I     
z"_BaseChildElement._add_method_namec                    r   )zN
        Add a public ``add_x()`` method to the parent element class.
        c                    s   t |  j}| }|S r   )r   r   )rm   Zprivate_add_methodr   rc   r   r   	add_childQ  s   z6_BaseChildElement._add_public_adder.<locals>.add_childr   N)r~   r7   r   _public_add_method_name)r   r   r   rc   r   _add_public_adderM  s   z#_BaseChildElement._add_public_adderc                 C   s"   t | j|rdS t| j|| dS )zt
        Add *method* to the target class as *name*, unless *name* is already
        defined on the class.
        N)hasattrrV   r_   )r   namemethodr   r   r   r   \  s   z_BaseChildElement._add_to_classc                    ru   )z}
        Return a function object that creates a new, empty element of the
        right type, having no attributes.
        c                    s
   t  jS r   )r   r~   rm   rc   r   r   new_child_elementk  s   
z5_BaseChildElement._creator.<locals>.new_child_elementr   )r   r   r   rc   r   r   e  s   z_BaseChildElement._creatorc                        fdd}d j  |_|S )z
        Return a function object suitable for the "get" side of the property
        descriptor. This default getter returns the child element with
        matching tag name or |None| if not present.
        c                       |  t jS r   )findr	   r~   r   rc   r   r   get_child_elementv     z4_BaseChildElement._getter.<locals>.get_child_elementz0``<%s>`` child element or |None| if not present.r~   r7   r   r   r   rc   r   r]   o  s   z_BaseChildElement._getterc                 C   r   )Nz
_insert_%sr   rc   r   r   r   r   ~  r   z%_BaseChildElement._insert_method_namec                    r   )zm
        Return a function object suitable for the "get" side of a list
        property descriptor.
        c                    r   r   )findallr	   r~   r   rc   r   r   get_child_element_list  r   z>_BaseChildElement._list_getter.<locals>.get_child_element_listzPA list containing each of the ``<%s>`` child elements, in the order they appear.r   )r   r   r   rc   r   r     s   z_BaseChildElement._list_getterc                 C   r   )a  
        add_childElement() is public API for a repeating element, allowing
        new elements to be added to the sequence. May be overridden to
        provide a friendlier API to clients having domain appropriate
        parameter names for required attributes.
        zadd_%sr   rc   r   r   r   r     s   
z)_BaseChildElement._public_add_method_namec                 C   r   Nz
_remove_%sr   rc   r   r   r   _remove_method_name  r   z%_BaseChildElement._remove_method_namec                 C   r   )Nz_new_%sr   rc   r   r   r   r     r   z"_BaseChildElement._new_method_namer   )r4   r5   r6   r7   rI   rE   r   r   r   r   r   r
   r   r   r   r\   r   r]   r   r   r   r   r   re   r   r   rR   r   r}      s6    		
	
	



	
r}   c                   @   sP   e Zd ZdZedd Zdd Zdd Zedd	 Ze	d
d Z
e	dd ZdS )Choicezd
    Defines a child element belonging to a group, only one of which may
    appear as a child.
    c                 C   s   | j S r   )r~   rc   r   r   r   r     s   zChoice.nsptagnamec                 C   s>   || _ || _|| _|   |   |   |   |   dS rU   )rV   _group_prop_namer   r   r   r   r   _add_get_or_change_to_method)r   rZ   Zgroup_prop_namer   r   r   r   rE     s   zChoice.populate_class_membersc                    r   )zl
        Add a ``get_or_change_to_x()`` method to the element class for this
        child element.
        c                    s@   t |  j}|d ur|S t |  j}|  t |  j}| }|S r   )r   rW   _remove_group_method_namer   )rm   r   Zremove_group_method
add_methodrc   r   r   get_or_change_to_child  s   zCChoice._add_get_or_change_to_method.<locals>.get_or_change_to_childzFReturn the ``<%s>`` child, replacing any other group element if found.N)r~   r7   r   _get_or_change_to_method_name)r   r   r   rc   r   r     s   z#Choice._add_get_or_change_to_methodc                 C   s.   d| j v r| j dd }nd}| j |d S )zW
        Calculate property name from tag name, e.g. a:schemeClr -> schemeClr.
        rb   r/   r   N)r~   index)r   startr   r   r   rW     s   
zChoice._prop_namec                 C   r   )Nzget_or_change_to_%sr   rc   r   r   r   r     r   z$Choice._get_or_change_to_method_namec                 C   r   r   )r   rc   r   r   r   r     r   z Choice._remove_group_method_nameN)r4   r5   r6   r7   r\   r   rE   r   rW   r
   r   r   r   r   r   r   r     s    



r   c                       s8   e Zd ZdZ fddZ fddZedd Z  ZS )r<   z?
    Defines a required child element for MetaOxmlElement.
    c                    s   t t| |d  d S r   )rM   r<   rI   )r   r   rR   r   r   rI     s   zOneAndOnlyOne.__init__c                    s   t t| || |   dS rU   )rM   r<   rE   r   rY   rR   r   r   rE     s   
z$OneAndOnlyOne.populate_class_membersc                    r   )j
        Return a function object suitable for the "get" side of the property
        descriptor.
        c                    s*   |  t j}|d u rtd j |S )Nz+required ``<%s>`` child element not present)r   r	   r~   r   r   rc   r   r   r     s   z0OneAndOnlyOne._getter.<locals>.get_child_elementz Required ``<%s>`` child element.r   r   r   rc   r   r]     s   
zOneAndOnlyOne._getter)	r4   r5   r6   r7   rI   rE   r\   r]   re   r   r   rR   r   r<     s    	r<   c                           e Zd ZdZ fddZ  ZS )r=   zc
    Defines a repeating child element for MetaOxmlElement that must appear at
    least once.
    c                    H   t t| || |   |   |   |   |   t|| dS rU   )	rM   r=   rE   r   r   r   r   r   delattrrY   rR   r   r   rE        
z OneOrMore.populate_class_membersr4   r5   r6   r7   rE   re   r   r   rR   r   r=     s    r=   c                       r   )r@   zJ
    Defines an optional repeating child element for MetaOxmlElement.
    c                    r   rU   )	rM   r@   rE   r   r   r   r   r   r   rY   rR   r   r   rE   &  r   z!ZeroOrMore.populate_class_membersr   r   r   rR   r   r@   "  s    r@   c                       rJ   )
rA   z@
    Defines an optional child element for MetaOxmlElement.
    c                    sF   t t| || |   |   |   |   |   |   dS rU   )	rM   rA   rE   r   r   r   r   _add_get_or_adder_add_removerrY   rR   r   r   rE   9  s   z ZeroOrOne.populate_class_membersc                    r   )zf
        Add a ``get_or_add_x()`` method to the element class for this
        child element.
        c                    s*   t |  j}|d u rt |  j}| }|S r   )r   rW   r   )rm   r   r   rc   r   r   get_or_add_childJ  s
   z5ZeroOrOne._add_get_or_adder.<locals>.get_or_add_childz>Return the ``<%s>`` child element, newly added if not present.N)r~   r7   r   _get_or_add_method_name)r   r   r   rc   r   r   E  s
   zZeroOrOne._add_get_or_adderc                    r   )zc
        Add a ``_remove_x()`` method to the element class for this child
        element.
        c                    s   |   j d S r   )
remove_allr~   r   rc   r   r   _remove_childZ  r   z-ZeroOrOne._add_remover.<locals>._remove_childz#Remove all ``<%s>`` child elements.N)r~   r7   r   r   )r   r   r   rc   r   r   U  s
   zZeroOrOne._add_removerc                 C   r   )Nzget_or_add_%sr   rc   r   r   r   r   a  r   z!ZeroOrOne._get_or_add_method_name)
r4   r5   r6   r7   rE   r   r   r
   r   re   r   r   rR   r   rA   5  s    rA   c                       s^   e Zd ZdZdddZ fddZdd Zd	d
 Zedd Z	e
dd Ze
dd Z  ZS )rB   zo
    Correspondes to an ``EG_*`` element group where at most one of its
    members may appear as a child.
    r   c                 C   s   || _ || _d S r   )_choicesr   )r   choicesr   r   r   r   rI   k  s   
zZeroOrOneChoice.__init__c                    sD   t t| || |   | jD ]}||| j| j q|   dS rU   )rM   rB   rE   _add_choice_getterr   rW   r   _add_group_remover)r   rZ   r[   choicerR   r   r   rE   o  s   


z&ZeroOrOneChoice.populate_class_membersc                 C   r   )z
        Add a read-only ``{prop_name}`` property to the element class that
        returns the present member of this group, or |None| if none are
        present.
        N)r\   _choice_getterr_   rV   rW   r`   r   r   r   r   }  s   z"ZeroOrOneChoice._add_choice_getterc                    s$    fdd}d|_   j| dS )ze
        Add a ``_remove_eg_x()`` method to the element class for this choice
        group.
        c                    s    j D ]}| | qd S r   )_member_nsptagnamesr   )rm   tagnamerc   r   r   _remove_choice_group  s   
z@ZeroOrOneChoice._add_group_remover.<locals>._remove_choice_groupz9Remove the current choice group child element if present.N)r7   r    _remove_choice_group_method_name)r   r   r   rc   r   r     s   z"ZeroOrOneChoice._add_group_removerc                    s    fdd}d|_ |S )r   c                    s   | j  j S r   )first_child_found_inr   r   rc   r   r   get_group_member_element  r   z@ZeroOrOneChoice._choice_getter.<locals>.get_group_member_elementzbReturn the child element belonging to this element group, or |None| if no member child is present.)r7   )r   r   r   rc   r   r     s   zZeroOrOneChoice._choice_getterc                 C   s   dd | j D S )z|
        Sequence of namespace-prefixed tagnames, one for each of the member
        elements of this choice group.
        c                 S   s   g | ]}|j qS r   )r   )r*   r   r   r   r   r.     s    z7ZeroOrOneChoice._member_nsptagnames.<locals>.<listcomp>)r   rc   r   r   r   r     s   z#ZeroOrOneChoice._member_nsptagnamesc                 C   r   r   r   rc   r   r   r   r     r   z0ZeroOrOneChoice._remove_choice_group_method_namer   )r4   r5   r6   r7   rI   rE   r   r   r\   r   r
   r   r   re   r   r   rR   r   rB   f  s    



rB   c                       s\   e Zd ZdZeZdd Zdd Zdd Zdd	 Z	e
d
d Z fddZe
dd Z  ZS )_OxmlElementBasez
    Effective base class for all custom element classes, to add standardized
    behavior to all classes in one place. Actual inheritance is from
    BaseOxmlElement below, needed to manage Python 2-3 metaclass declaration
    compatibility.
    c                 C   s   d| j j| jt| f S )Nz<%s '<%s>' at 0x%0x>)rS   r4   _nsptagidrc   r   r   r   __repr__  s   z_OxmlElementBase.__repr__c                 G   s,   |D ]}|  t|}|dur|  S qdS )zd
        Return the first child found with tag in *tagnames*, or None if
        not found.
        N)r   r	   )r   tagnamesr   r   r   r   r   r     s   z%_OxmlElementBase.first_child_found_inc                 G   s.   | j | }|d ur|| |S | | |S r   )r   Zaddpreviousappend)r   elmr   	successorr   r   r   r     s   


z&_OxmlElementBase.insert_element_beforec                 G   s0   |D ]}|  t|}|D ]}| | qqdS )ze
        Remove all child elements whose tagname (e.g. 'a:p') appears in
        *tagnames*.
        N)r   r	   remove)r   r   r   Zmatchingr   r   r   r   r     s   z_OxmlElementBase.remove_allc                 C   s   t | S )z
        Return XML string for this element, suitable for testing purposes.
        Pretty printed for readability and without an XML declaration at the
        top.
        )r   rc   r   r   r   r     s   z_OxmlElementBase.xmlc                    s   t t| j|tdS )z
        Override of ``lxml`` _Element.xpath() method to provide standard Open
        XML namespace mapping (``nsmap``) in centralized location.
        )
namespaces)rM   BaseOxmlElementxpathr   )r   Z	xpath_strrR   r   r   r     s   
z_OxmlElementBase.xpathc                 C   s   t | jS r   )r   Zfrom_clark_namer|   rc   r   r   r   r     s   z_OxmlElementBase._nsptag)r4   r5   r6   r7   r;   Z__metaclass__r   r   r   r   r\   r   r   r   re   r   r   rR   r   r     s    

	r   r   )&r7   Z
__future__r   Zlxmlr   r8   Zdocx.compatr   Z	docx.oxmlr   Zdocx.oxml.exceptionsr   Zdocx.oxml.nsr   r   r	   Zdocx.sharedr
   r   r   typer;   objectrK   r>   r?   r}   r   r<   r=   r@   rA   rB   ZElementBaser   dict__dict__r   r   r   r   r   <module>   s6   	@$51 .E&1LC