o
    ß8b46  ã                   @   sp   d dl Z ddlmZ ddlmZ G dd„ deƒZG dd„ deƒZG d	d
„ d
eƒZdd„ Z	G dd„ deƒZ
e
ZdS )é    Né   )Úxmlutil)Úlogc                   @   s   e Zd ZdZdd„ ZdS )Ú_XPathSegmenta/  
    Class representing a single 'segment' of an xpath string. For example,
    the xpath:

        ./qemu:foo/bar[1]/baz[@somepro='someval']/@finalprop

    will be split into the following segments:

        #1: nodename=., fullsegment=.
        #2: nodename=foo, nsname=qemu, fullsegment=qemu:foo
        #3: nodename=bar, condition_num=1, fullsegment=bar[1]
        #4: nodename=baz, condition_prop=somepro, condition_val=someval,
                fullsegment=baz[@somepro='somval']
        #5: nodename=finalprop, is_prop=True, fullsegment=@finalprop
    c                 C   sÒ   || _ || _d | _d | _d | _d| jv rA| j d¡ d¡\| _}d|v r8| d¡\}}| d¡| _| d¡| _n	| ¡ rAt|ƒ| _| j 	d¡| _
| j
rS| jdd … | _d | _d| jv rg| j d¡\| _| _d S d S )Nú[ú]ú=ú@ú'r   ú:)ÚfullsegmentÚnodenameÚcondition_propÚcondition_valÚcondition_numÚstripÚsplitÚisdigitÚintÚ
startswithÚis_propÚnsname)Úselfr   ÚcondÚcpropÚcval© r   ú*/usr/share/virt-manager/virtinst/xmlapi.pyÚ__init__   s(   


ÿz_XPathSegment.__init__N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   r   r   r   r      s    r   c                   @   s,   e Zd ZdZdd„ Zedd„ ƒZdd„ ZdS )	Ú_XPathzi
    Helper class for performing manipulations of XPath strings. Splits
    the xpath into segments.
    c                 C   s–   || _ g | _| j  d¡D ]}|dkr| jd d… | _q| j t|ƒ¡ q| jd j| _| jr4| jd jp5d | _| jrB| jd d… | _|  | j¡| _	d S )Nú/z..éÿÿÿÿ)
Ú	fullxpathÚsegmentsr   Úappendr   r   r   ÚpropnameÚjoinÚxpath)r   r&   Úsr   r   r   r   =   s   z_XPath.__init__c                 C   s   d  dd„ | D ƒ¡S )Nr$   c                 s   s    | ]}|j V  qd S ©N)r   )Ú.0r,   r   r   r   Ú	<genexpr>O   s   € z_XPath.join.<locals>.<genexpr>)r*   )r'   r   r   r   r*   M   s   z_XPath.joinc                 C   s   |   | jd d… ¡S )Nr%   )r*   r'   ©r   r   r   r   Úparent_xpathQ   s   z_XPath.parent_xpathN)r   r    r!   r"   r   Ústaticmethodr*   r1   r   r   r   r   r#   8   s    
r#   c                   @   sô   e Zd Zi Ze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„ 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(„ Zd)d*„ Zd+d,„ Zd-d.„ Zd/d0„ Zd1d2„ Zd3d4„ Zd5d6„ Zd7d8„ Z d9S ):Ú_XMLBasec                 C   s   || j |< d S r-   )Ú
NAMESPACES)Úclsr   Úurir   r   r   Úregister_namespaceW   s   z_XMLBase.register_namespacec                 C   ó   t ƒ ‚r-   ©ÚNotImplementedErrorr0   r   r   r   Úcopy_api[   ó   z_XMLBase.copy_apic                 C   r8   r-   r9   ©r   r+   r   r   r   Úcount]   r<   z_XMLBase.countc                 C   r8   r-   r9   )r   r&   r   r   r   Ú_find_   r<   z_XMLBase._findc                 C   r8   r-   r9   ©r   Únoder   r   r   Ú_node_tostringa   r<   z_XMLBase._node_tostringc                 C   r8   r-   r9   r@   r   r   r   Ú_node_get_textc   r<   z_XMLBase._node_get_textc                 C   r8   r-   r9   ©r   rA   Úsetvalr   r   r   Ú_node_set_texte   r<   z_XMLBase._node_set_textc                 C   r8   r-   r9   )r   rA   r)   r   r   r   Ú_node_get_propertyg   r<   z_XMLBase._node_get_propertyc                 C   r8   r-   r9   )r   rA   r)   rE   r   r   r   Ú_node_set_propertyi   r<   z_XMLBase._node_set_propertyc                 C   r8   r-   r9   )r   ÚxpathsegÚ
parentnoder   r   r   Ú	_node_newk   r<   z_XMLBase._node_newc                 C   r8   r-   r9   )r   ÚparentxpathrJ   Únewnoder   r   r   Ú_node_add_childm   r<   z_XMLBase._node_add_childc                 C   r8   r-   r9   )r   rJ   Ú	childnoder   r   r   Ú_node_remove_childo   r<   z_XMLBase._node_remove_childc                 C   r8   r-   r9   )r   r+   rM   r   r   r   Ú_node_replace_childq   r<   z_XMLBase._node_replace_childc                 C   r8   r-   r9   ©r   Úxmlr   r   r   Ú_node_from_xmls   r<   z_XMLBase._node_from_xmlc                 C   r8   r-   r9   r@   r   r   r   Ú_node_has_contentu   r<   z_XMLBase._node_has_contentc                 C   r8   r-   r9   r@   r   r   r   Ú_node_get_namew   r<   z_XMLBase._node_get_namec                 C   r8   r-   r9   r=   r   r   r   Ú
node_cleary   r<   z_XMLBase.node_clearc                 C   r8   r-   r9   rR   r   r   r   Ú_sanitize_xml{   r<   z_XMLBase._sanitize_xmlc                 C   s&   |   |¡}|d u rdS |  |  |¡¡S )NÚ )r?   rX   rB   )r   r+   rA   r   r   r   Úget_xml~   s   
z_XMLBase.get_xmlc                 C   sD   |   |¡}|d u rd S |rdS t|ƒ}|jr|  ||j¡S |  |¡S )NT)r?   r#   r   rG   r)   rC   )r   r+   Úis_boolrA   Úxpathobjr   r   r   Úget_xpath_content„   s   

z_XMLBase.get_xpath_contentc                 C   s|   |   |¡}|du r|  |¡ d S |d u r&|d ur|  ||d ¡ |  |¡ d S |d u r/|  |¡}|du r5d S |  |||¡ d S )NFT)r?   Únode_force_removeÚ_node_set_contentÚ_node_remove_emptyÚ_node_make_stub)r   r+   rE   rA   r   r   r   Úset_xpath_content   s   

z_XMLBase.set_xpath_contentc                 C   s&   |   |¡}|  |¡}|  |||¡ d S r-   )rT   ra   rN   )r   rS   r+   rM   rJ   r   r   r   Únode_add_xml¡   s   

z_XMLBase.node_add_xmlc                 C   s   |   |¡}|  ||¡ dS )zB
        Replace the node at xpath with the passed in xml
        N)rT   rQ   )r   r+   rS   rM   r   r   r   Únode_replace_xml¦   s   
z_XMLBase.node_replace_xmlc                 C   sD   t |ƒ}|  | ¡ ¡}|  |¡}|du s|du rdS |  ||¡ dS )z¢
        Remove the element referenced at the passed xpath, regardless
        of whether it has children or not, and then clean up the XML
        chain
        N)r#   r?   r1   rP   )r   r&   r\   rJ   rO   r   r   r   r^   ­   s   
z_XMLBase.node_force_removec                 C   s2   |   |  d¡¡}||krd S ttdƒ||dœ ƒ‚)NÚ.zSXML did not have expected root element name '%(expectname)s', found '%(foundname)s')Ú
expectnameÚ	foundname)rV   r?   ÚRuntimeErrorÚ_)r   Úexpected_root_nameÚrootnamer   r   r   Úvalidate_root_nameº   s   þÿz_XMLBase.validate_root_namec                 C   sB   t |ƒ}|d urt|ƒ}|jr|  ||j|¡ d S |  ||¡ d S r-   )r#   Ústrr   rH   r)   rF   )r   r+   rA   rE   r\   r   r   r   r_   Ã   s   z_XMLBase._node_set_contentc           	      C   s    t |ƒ}d}|  |¡}|st d| ¡‚|jdd… D ]2}|}|d|j 7 }|  |¡}|dur2|}q|  ||¡}|  |||¡ |}|jrM|  	||j|j
¡ q|S )a`  
        Build all nodes for the passed xpath. For example, if XML is <foo/>,
        and xpath=./bar/@baz, after this function the XML will be:

          <foo>
            <bar baz=''/>
          </foo>

        And the node pointing to @baz will be returned, for the caller to
        do with as they please.

        There's also special handling to ensure that setting
        xpath=./bar[@baz='foo']/frob will create

          <bar baz='foo'>
            <frob></frob>
          </bar>

        Even if <bar> didn't exist before. So we fill in the dependent property
        expression values
        re   z'Did not find XML root node for xpath=%sr   Nz/%s)r#   r?   r   ÚDevErrorr'   r   rK   rN   r   rH   r   )	r   r&   r\   rL   rJ   rI   ÚoldxpathÚtmpnoderM   r   r   r   ra   Ì   s.   
ÿ

ÿ€z_XMLBase._node_make_stubc                 C   sz   t |ƒ}|jdd… }d}|r;t  |¡}| ¡  |}|  |¡}|du r%dS |du r*q|  |¡r1dS |  ||¡ |sdS dS )z·
        Walk backwards up the xpath chain, and remove each element
        if it doesn't have any children or attributes, so we don't
        leave stale elements in the XML
        N)r#   r'   r*   Úpopr?   rU   rP   )r   r&   r\   r'   Úparentr+   Úchildr   r   r   r`   þ   s    


ôz_XMLBase._node_remove_emptyN)!r   r    r!   r4   Úclassmethodr7   r;   r>   r?   rB   rC   rF   rG   rH   rK   rN   rP   rQ   rT   rU   rV   rW   rX   rZ   r]   rb   rc   rd   r^   rl   r_   ra   r`   r   r   r   r   r3   U   s>    
		2r3   c                 C   s   t | o| jdkƒS )NÚtext)ÚboolÚtype)Únr   r   r   Únode_is_text  s   ry   c                   @   s¤   e 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„ 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'S )(Ú_Libxml2APIc                 C   sb   t  | ¡ t d¡ t |¡| _| j ¡ | _| j | jj	¡ | j
 ¡ D ]\}}| j ||¡ q#d S )Nr   )r3   r   Úlibxml2ÚkeepBlanksDefaultÚparseDocÚ_docÚxpathNewContextÚ_ctxÚsetContextNodeÚchildrenr4   ÚitemsÚxpathRegisterNs)r   rS   ÚkeyÚvalr   r   r   r     s   

ÿz_Libxml2API.__init__c                 C   s2   t | dƒsd S | j ¡  d | _| j ¡  d | _d S )Nr~   )Úhasattrr~   ÚfreeDocr€   ÚxpathFreeContextr0   r   r   r   Ú__del__*  s   



z_Libxml2API.__del__c                 C   s   |  d¡sd|v r|d7 }|S )NÚ
)ÚendswithrR   r   r   r   rX   3  s   z_Libxml2API._sanitize_xmlc                 C   s   t | jj ¡ ƒS r-   )rz   r~   r‚   Ú	serializer0   r   r   r   r;   8  ó   z_Libxml2API.copy_apic              
   C   sl   t |ƒj}z| j |¡}W n  ty- } ztjd||dd td|t|ƒf ƒd ‚d }~ww |r4|d p5d S )Nz!fullxpath=%s xpath=%s eval failedT)Úexc_infoz%s %sr   )	r#   r+   r€   Ú	xpathEvalÚ	Exceptionr   Údebugrh   rm   )r   r&   r+   rA   Úer   r   r   r?   ;  s   
ÿ€ýz_Libxml2API._findc                 C   s   t | j |¡ƒS r-   )Úlenr€   r   r=   r   r   r   r>   E  rŽ   z_Libxml2API.countc                 C   s   |  ¡ S r-   )r   r@   r   r   r   rB   H  s   z_Libxml2API._node_tostringc                 C   s   t  |¡jS r-   )r{   r}   r‚   rR   r   r   r   rT   J  s   z_Libxml2API._node_from_xmlc                 C   ó   |j S r-   )Úcontentr@   r   r   r   rC   M  r<   z_Libxml2API._node_get_textc                 C   s    |d ur	t  |¡}| |¡ d S r-   )r   Ú
xml_escapeÚ
setContentrD   r   r   r   rF   O  s   
z_Libxml2API._node_set_textc                 C   s   |  |¡}|r
|jS d S r-   )ÚhasPropr–   )r   rA   r)   Úpropr   r   r   rG   T  s   
ÿz_Libxml2API._node_get_propertyc                 C   sD   |d u r|  |¡}|r| ¡  | ¡  d S d S | |t |¡¡ d S r-   )r™   Ú
unlinkNodeÚfreeNodeÚsetPropr   r—   )r   rA   r)   rE   rš   r   r   r   rH   X  s   
þz_Libxml2API._node_set_propertyc                    sR   t  ˆj¡}ˆjs|S ‡ ‡fdd„}|ƒ }|s"| | jˆj ˆj¡}| |¡ |S )Nc                     sD   ˆ } | r t  |  ¡ ¡D ]}|jˆjkr|  S q|  ¡ } | sd S d S r-   )r   ÚlistifyÚnsDefsÚnamer   Ú
get_parent)rr   Úns©rJ   rI   r   r   Ú_find_parent_nsf  s   ÿüz._Libxml2API._node_new.<locals>._find_parent_ns)r{   ÚnewNoder   r   ÚnewNsr4   ÚsetNs)r   rI   rJ   rM   r¤   r¢   r   r£   r   rK   a  s   ÿ
z_Libxml2API._node_newc                 C   sH   |   |¡}|r"dd„ |jpg D ƒ}|D ]}| |¡ q| d ¡ d S d S )Nc                 S   s   g | ]}|j ‘qS r   ©r    )r.   Úpr   r   r   Ú
<listcomp>x  s    z*_Libxml2API.node_clear.<locals>.<listcomp>)r?   Ú
propertiesÚ	unsetPropr˜   )r   r+   rA   Ú	propnamesr©   r   r   r   rW   u  s   
üz_Libxml2API.node_clearc                 C   s   |j dko
|jp
|jS )NÚelement)rw   r‚   r«   r@   r   r   r   rU   }  s   z_Libxml2API._node_has_contentc                 C   r•   r-   r¨   r@   r   r   r   rV   €  r<   z_Libxml2API._node_get_namec                 C   sZ   |}|  ¡ }t|ƒr| ¡  | ¡  | ¡  | ¡  tdd„ |jD ƒƒr+| d ¡ d S d S )Nc                 S   s   g | ]}t |ƒ‘qS r   )ry   )r.   rx   r   r   r   rª   Ž  s    z2_Libxml2API._node_remove_child.<locals>.<listcomp>)Úget_prevry   r›   rœ   Úallr‚   r˜   )r   rJ   rO   rA   Úwhiter   r   r   rP   ƒ  s   ÿz_Libxml2API._node_remove_childc                 C   sz   |}t | ¡ ƒs!| ¡ }t |ƒrt |j¡}nt d¡}| |¡ | ¡ j}| t d¡¡ | |¡ | t |¡¡ d S )Nr‹   z  )ry   Úget_lastr¯   r{   ÚnewTextr–   ÚaddChild)r   rL   rJ   rM   ÚignoreÚprevsibÚnewlastÚendtextr   r   r   rN   ‘  s   



z_Libxml2API._node_add_childc                 C   s   |   |¡}| |¡ d S r-   )r?   ÚreplaceNode)r   r+   rM   Úoldnoder   r   r   rQ      s   
z_Libxml2API._node_replace_childN)r   r    r!   r   rŠ   rX   r;   r?   r>   rB   rT   rC   rF   rG   rH   rK   rW   rU   rV   rP   rN   rQ   r   r   r   r   rz     s(    	
	rz   )r{   rY   r   Úloggerr   Úobjectr   r#   r3   ry   rz   ÚXMLAPIr   r   r   r   Ú<module>   s   ) B 