
    W'Fgt                     @   S SK r S SKrS SKrS SKrS SKrSSKJr  SSKJr  SSK	J
r
  \" S\R                  ;   5      r/ r/ r " S S\5      r " S	 S
\5      r\" 5       r " S S\5      r " S S\5      r " S S\5      r " S S\5      r " S S\5      r " S S\5      rg)    N   )log)XMLAPI)xmlutilVIRTINST_TEST_SUITEc                   @    \ rS rSrSrSrSrSrSrSr	Sr
SrS rS rS	rg)
XMLManualAction   zO
Helper class for tracking and performing the user requested manual
XML action
r         Nc                    SS jnU R                   (       a!  U" U R                   [        R                  5      $ U R                  (       a!  U" U R                  [        R                  5      $ U R
                  nU R                  (       a  U R                  nO1S[        U5      ;  a  [        SU-  5      eUR                  SS5      u  p#U" U[        R                  U5      $ )Nc                 
    XU4$ N )xavs      ./usr/share/virt-manager/virtinst/xmlbuilder.py_ret+XMLManualAction._process_args.<locals>._ret,   s    !9    =z4%s: Setting xpath must be in the form of XPATH=VALUEr   r   )xpath_deleter	   ACTION_DELETExpath_createACTION_CREATE	xpath_setxpath_valuestr
ValueErrorrsplit
ACTION_SET)selfr   xpathvals       r   _process_argsXMLManualAction._process_args+   s    	 ))?+H+HII))?+H+HII""C#e*$ J  c1-JEE?55s;;r   c                    U R                   (       d4  U R                  (       d#  U R                  (       d  U R                  (       d  g U R	                  5       u  p#nUR                  S5      (       a  UR                  U5      nX0R                  :X  a  SnOX0R                  :X  a  SnOU=(       d    S nUR                  R                  X%5        g )N.FT)r   r   r   r   r&   
startswithmake_abs_xpathr   r   xmlapiset_xpath_content)r#   xmlstater$   actionvaluesetvals         r   performXMLManualAction.perform?   s    !!!!  #113uC  ++E2E'''F)))F]dF))%8r   r   )__name__
__module____qualname____firstlineno____doc__r   r   r"   r   r   r   r   r&   r2   __static_attributes__r   r   r   r	   r	      s6     MMJLLKI<(9r   r	   c                   6    \ rS rSrSrS rS rS rS rS r	Sr
g	)
_XMLPropertyCacheS   zb
Cache lookup tables mapping classes to their associated
XMLProperty and XMLChildProperty classes
c                      0 U l         0 U l        g r   _name_to_prop_prop_to_namer#   s    r   __init___XMLPropertyCache.__init__X   s    r   c                 r   [        U5      S-   UR                  -   nX0R                  ;  a  0 n[        [        R                  U5      S S 5       HJ  nUR                  R                  5        H)  u  pg[        Xr5      (       d  M  XtU'   X`R                  U'   M+     ML     X@R                  U'   U R                  U   $ )N-)
r   r4   r?   reversedtypemro__dict__items
isinstancer@   )r#   cls
checkclass	cachenameretckeyr%   s           r   _get_prop_cache!_XMLPropertyCache._get_prop_cache\   s    HsNZ%8%88	...CdhhsmCR01 !

 0 0 2HC!#22#&C25**3/ !3 2
 -0y)!!),,r   c                 B    U R                  UR                  [        5      $ r   )rS   	__class__XMLPropertyr#   insts     r   get_xml_props_XMLPropertyCache.get_xml_propsh   s    ##DNNK@@r   c                 B    U R                  UR                  [        5      $ r   )rS   rV   XMLChildPropertyrX   s     r   get_child_props!_XMLPropertyCache.get_child_propsk   s    ##DNN4DEEr   c                      U R                   U   $ r   )r@   )r#   propinsts     r   get_prop_name_XMLPropertyCache.get_prop_namen   s    !!(++r   r>   N)r4   r5   r6   r7   r8   rB   rS   rZ   r^   rb   r9   r   r   r   r;   r;   S   s"     
-AF,r   r;   c                   .    \ rS rSrSrSS jrS rS rSrg)	_XMLChildListu   z
Little wrapper for a list containing XMLChildProperty output.
This is just to insert a dynamically created add_new() function
which instantiates and appends a new child object
c                     [         R                  U 5        Xl        X0l        X@l        U H  nU R                  U5        M     g r   )listrB   _childclass_xmlbuilder_is_xmlappend)r#   
childclasscopylist
xmlbuilderis_xmlis         r   rB   _XMLChildList.__init__{   s4    d%%AKKN r   c                 t    SnU R                   (       a  U R                  R                  4nU R                  " U6 $ )z.
Instantiate a new child object and return it
r   )rk   rj   connri   )r#   argss     r   new_XMLChildList.new   s5     <<$$))+D&&r   c                     U R                  5       nU R                  (       a  U R                  R                  U5        U$ U R	                  U5        U$ )z:
Instantiate a new child object, append it, and return it
)rv   rk   rj   	add_childrl   )r#   objs     r   add_new_XMLChildList.add_new   sD     hhj<<&&s+ 
 KK
r   )ri   rk   rj   N)T)	r4   r5   r6   r7   r8   rB   rv   r{   r9   r   r   r   re   re   u   s    
'	r   re   c                   *    \ rS rSrS r\S 5       rSrg)_XMLPropertyBase   c                 :    S U l         [        R                  XUS9  g )N)fgetfset)	_propnamepropertyrB   )r#   r   r   s      r   rB   _XMLPropertyBase.__init__   s    $5r   c                 p    U R                   (       d  [        R                  U 5      U l         U R                   $ )z
The variable name associated with this XMLProperty. So with
a definition like

    foo = XMLProperty("./@bar")

and this will return "foo".
)r   
_PropCacherb   rA   s    r   propname_XMLPropertyBase.propname   s'     ~~'55d;DN~~r   )r   N)r4   r5   r6   r7   rB   r   r   r9   r   r   r   r~   r~      s    6  r   r~   c                   X    \ rS rSrSrSS jrS rS rS rS r	S r
S	 rS
 rS rS rSrg)r]      aN  
Property that points to a class used for parsing a subsection of
of the parent XML. For example when we deligate parsing
/domain/cpu/feature of the /domain/cpu class.

@child_class: XMLBuilder class this property is tracking. So for
    guest.devices.disk this is DeviceDisk
@relative_xpath: Relative location where the class is rooted compared
    to its xmlbuilder root path. So if xmlbuilder is ./foo and we
    want to track ./foo/bar/baz instances, set relative_xpath=./bar
@is_single: If True, this represents an XML node that is only expected
    to appear once, like <domain><cpu>
c                 h    Xl         X0l        X l        [        R	                  X R
                  S 5        g r   )child_class	is_singlerelative_xpathr~   rB   _fget)r#   r   r   r   s       r   rB   XMLChildProperty.__init__   s'    &",!!$

D9r   c                 P    S[        U R                  5      < S[        U 5      < S3$ )Nz<XMLChildProperty  >)r   r   idrA   s    r   __repr__XMLChildProperty.__repr__   s    -01A1A-BBtHMMr   c                     U R                   UR                  ;  a*  U R                  (       d  / UR                  U R                   '   UR                  U R                      $ r   )r   
_propstorer   r#   ro   s     r   _getXMLChildProperty._get   sC    ==
 5 55dnn35J!!$--0$$T]]33r   c                     U R                   (       a  U R                  U5      $ [        U R                  U R                  U5      U5      $ r   )r   r   re   r   r   s     r   r   XMLChildProperty._fget   s<    >>99Z((T--!YYz2') 	)r   c                     U R                   (       a   U R                  U5      R                  5         g U R                  U5      S S   H  nUR                  U5        M     g r   )r   r   clearremove_childr#   ro   rz   s      r   r   XMLChildProperty.clear   sD    >>IIj!'')yy,Q/'', 0r   c                 D    U R                  U5      R                  X25        g r   )r   insert)r#   ro   newobjidxs       r   r   XMLChildProperty.insert   s    		*$$S1r   c                 D    U R                  U5      R                  U5        g r   )r   rl   )r#   ro   r   s      r   rl   XMLChildProperty.append   s    		*$$V,r   c                 D    U R                  U5      R                  U5        g r   )r   remover   s      r   r   XMLChildProperty.remove   s    		*$$S)r   c                 4    X!R                   U R                  '   g r   r   r   r   s      r   setXMLChildProperty.set   s    /2dmm,r   c                 :    U R                   S-   UR                  -   $ )N/)r   XML_NAME)r#   rj   rz   s      r   get_prop_xpathXMLChildProperty.get_prop_xpath   s    ""S(3<<77r   )r   r   r   N)r)   F)r4   r5   r6   r7   r8   rB   r   r   r   r   r   rl   r   r   r   r9   r   r   r   r]   r]      s:    :N4
)-2-*38r   r]   c                   ^    \ rS rSr  SS jrS rS rS rS rS r	S r
S	 rS
 rS rS rSrg)rW      c                    Xl         U R                   (       d  [        R                  " S5      eX l        X0l        X@l        XPl        X`l        [        S U R                  U R                  U R
                  U R                  4 5       5      nUS:  a  [        R                  " S5      eSU l	        [        (       a  [        R                  U 5        [        R                  X R                  U R                   5        g)a  
Set a XMLBuilder class property that maps to a value in an XML
document, indicated by the passed xpath. For example, for a
<domain><name> the definition may look like:

  name = XMLProperty("./name")

When building XML from scratch (virt-install), 'name' works
similar to a regular class property(). When parsing and editing
existing guest XML, we  use the xpath value to get/set the value
in the parsed XML document.

:param xpath: xpath string which maps to the associated property
              in a typical XML document
:param name: Just a string to print for debugging, only needed
    if xpath isn't specified.
:param is_bool: Whether this is a boolean property in the XML
:param is_int: Whether this is an integer property in the XML
:param is_yesno: Whether this is a yes/no property in the XML
:param is_onoff: Whether this is an on/off property in the XML
:param do_abspath: If True, run os.path.abspath on the passed value
z"XMLProperty: xpath must be passed.c              3   J   #    U  H  n[        [        U5      5      v   M     g 7fr   )intbool).0rq   s     r   	<genexpr>'XMLProperty.__init__.<locals>.<genexpr>	  s%      21 *+DG1s   !#r   z$Conflict property converter options.FN)_xpathr   DevError_is_bool_is_int	_is_yesno	_is_onoff_do_abspathsum_is_tracked_trackprops	_allpropsrl   r~   rB   gettersetter)r#   r$   is_boolis_intis_yesnois_onoff
do_abspath	conflictss           r   rB   XMLProperty.__init__   s    2 {{""#GHH!!% 212 2	 q=""#IJJ ;T"!!$T[[Ar   c                 P    S[        U R                  5      < S[        U 5      < S3$ )Nz<XMLProperty r   r   )r   r   r   rA   s    r   r   XMLProperty.__repr__  s    (+DKK(8"T(CCr   c                    U R                   (       a  [        U5      $ U R                  (       a(  Ub%   0 nS[        U5      ;   a  SUS'   [	        U40 UD6nU$ U R                  (       a  US:X  a  SnU$ US:X  a  SnU$ Un U$ U R                  (       a  US	:X  a  SnU$ US
:X  a  SnU$ Un U$ UnU$ ! [
         a$  n[        R                  " SU5        Un S nAU$ S nAff = f)N0x   basez%Error converting XML value to int: %syesTnoFonoff)
r   r   r   r   r   r    r   debugr   r   )r#   r%   	intkwargsrP   es        r   _convert_get_valueXMLProperty._convert_get_value  s   ==9\\co	3s8#(*If%#++( 
! ^^e| 
  
  
 ^^d{ 
 
 
  
 C
'  		A1E" 
's   "B. .
C8CCc                 h   U R                   (       a$  Ub!  [        R                  R                  U5      nU$ U R                  (       a  USL a  SnU$ USL a  SnU$ U R
                  (       a  USL a  SnU$ USL a  SnU$ U R                  (       a%  Ub"  0 nS[        U5      ;   a  SUS	'   [        U40 UD6nU$ )
NTr   Fr   r   r   r   r   r   )	r   ospathabspathr   r   r   r   r   )r#   r%   r   s      r   _convert_set_valueXMLProperty._convert_set_value=  s    ''//#&C  
 ^^d{ 
  
 ^^d{ 
  
 \\coIs3x$&	&!c'Y'C
r   c                 p    UR                   nU R                  U;   a  X0R                  	 X#U R                  '   g)z
This stores the value in XMLBuilder._propstore
dict as propname->value. This saves us from having to explicitly
track every variable.
Nr   )r#   ro   r%   	propstores       r   _nonxml_fsetXMLProperty._nonxml_fsetQ  s1     ))	==I%--(#&$-- r   c                 N    UR                   R                  U R                  S5      $ )zJ
The flip side to nonxml_fset, fetch the value from
XMLBuilder._propstore
N)r   getr   r   s     r   _nonxml_fgetXMLProperty._nonxml_fget]  s!    
 $$((==r   c                 b    UR                   nU R                  U;   a  U R                  US 5        g g r   )r   r   r   )r#   ro   r   s      r   r   XMLProperty.cleard  s,    ))	==I%KK
D) &r   c                    [         (       a-  U R                  (       d  [        R                  U 5        SU l        U R                  UR
                  ;   a  U R                  U5      nOU R                  U5      nU R                  U5      $ )a7  
Fetch value at user request. If we are parsing existing XML and
the user hasn't done a 'set' yet, return the value from the XML,
otherwise return the value from propstore

If this is a built from scratch object, we never pull from XML
since it's known to the empty, and we may want to return
a 'default' value
T)	r   r   
_seenpropsrl   r   r   r   _get_xmlr   )r#   ro   r%   s      r   r   XMLProperty.gettero  sh     ;t//d##D==J111##J/C--
+C&&s++r   c                     UR                   R                  U R                  5      nUR                   R                  R	                  X R
                  5      $ )z:
Actually fetch the associated value from the backing XML
)	_xmlstater+   r   r,   get_xpath_contentr   )r#   ro   r$   s      r   r   XMLProperty._get_xml  sD     $$33DKK@##**<<}}& 	&r   c                     [         (       a-  U R                  (       d  [        R                  U 5        SU l        U R	                  U5      nU R                  X5        g)z~
Set the value at user request. This just stores the value
in propstore. Setting the actual XML is only done at
get_xml time.
TN)r   r   r   rl   r   r   )r#   ro   r%   r1   s       r   r   XMLProperty.setter  sE     ;t//d##D((-*-r   c                     UR                   R                  U R                  5      nUR                   R                  R	                  X25        g)z3
Actually set the passed value in the XML document
N)r   r+   r   r,   r-   )r#   ro   r1   r$   s       r   _set_xmlXMLProperty._set_xml  s8     $$33DKK@##55eDr   )r   r   r   r   r   r   r   N)FFFFF)r4   r5   r6   r7   rB   r   r   r   r   r   r   r   r   r   r   r9   r   r   r   rW   rW      sC    GL!-B`D>(
'>*,(&.Er   rW   c                   >    \ rS rSrS rS rS rS rS rS r	S r
S	rg
)	_XMLStatei  c                    Xl         SU l        SU R                   ;   a?  U R                   R                  S5      S   nSU< S[        R                  U   < S3U l        U=(       d    SU l        U=(       a    UR                  5       =(       d    SU l        S U l        U(       + =(       a    U(       + U l	        U R                  X#5        g )N :r   z xmlns:z='')
_root_name
_namespacesplitr   
NAMESPACES_relative_object_xpath	abs_xpath_parent_xpathr,   is_buildparse)r#   	root_nameparsexmlparentxmlstaterelative_object_xpathnss         r   rB   _XMLState.__init__  s    #$//!&&s+A.B24f6G6G6KLDO
 '<&Ar# 9~779A>@ 	 $;^);

8,r   c                 j   U(       a6  UR                   =(       d    U R                   U l         UR                  U l        g U(       d  SU R                  < U R                  < S3nOPU R                  (       a?  SU;  a9  UR	                  SU R                  -   SU R                  -   U R                  -   5      n [        U5      U l        U R                   (       d8  U R                  R                  U R                  R                  S5      S   5        g g ! [         a    [        R                  " SU5        e f = f)N<z/>xmlnszError parsing xml=
%sr  rF   )r  r,   r  r  replacer   	Exceptionr   r   validate_root_namer  )r#   r  r  s      r   r  _XMLState.parse  s    *33Dt}}DM(//DK $(OOT__EH__!8''doo(=$//)DOO;=H	 *DK
 }}KK**4??+@+@+Eb+IJ 	  	II.9	s   5D #D2c                 $    U=(       d    SU l         g Nr  )r
  r#   r$   s     r   set_relative_object_xpath#_XMLState.set_relative_object_xpath  s    &+kr#r   c                 $    U=(       d    SU l         g r  )r  r  s     r   set_parent_xpath_XMLState.set_parent_xpath  s    "[br   c                 @    UR                  S5      (       a  USS  nX-   $ )Nr)   r   )r*   )r#   x1x2s      r   _join_xpath_XMLState._join_xpath  s#    ==ABBwr   c                 r    U R                  U R                  =(       d    SU R                  =(       d    S5      $ )Nr)   )r'  r  r
  rA   s    r   r  _XMLState.abs_xpath  s0     2 2 9c++2s4 	4r   c                 T    U R                  U R                  5       =(       d    SU5      $ )z
Convert a relative xpath to an absolute xpath. So for DeviceDisk
that's part of a Guest, accessing driver_name will do convert:
    ./driver/@name
to an absolute xpath like:
    ./devices/disk[3]/driver/@name
r)   )r'  r  r  s     r   r+   _XMLState.make_abs_xpath  s#      0 7C??r   )r  r  r
  r  r  r,   N)r4   r5   r6   r7   rB   r  r  r"  r'  r  r+   r9   r   r   r   r  r    s'    -.K.2)
4@r   r  c                       \ rS rSrSr/ rSrSr\S 5       r	\S 5       r
  SS jrS rS	 rS
 rS rSS jrS rS rS rS rS rS rS rS S jrS rS rS!S jrS rS rS rS rS r Sr!g)"
XMLBuilderi  z6
Base for all classes which build or parse domain XML
NFc                 0    [         R                  " X5        g r   )r   register_namespace)nsnameuris     r   r0  XMLBuilder.register_namespace  s    !!&.r   c                     S/nU(       d  [        [        S5      U -  5      eU H$  nX1;  a  M
  [        S5      XUS.-  n[        U5      e   g )Nr   z#A name must be specified for the %szD%(objecttype)s name '%(name)s' can not contain '%(char)s' character.)
objecttypenamechar)r    _)
name_labelr%   forbidrQ   msgs        r   validate_generic_name XMLBuilder.validate_generic_name   sf     QDE    A| , -#-AFGC S/! r   c                    Xl         U R                  (       aX  UR                  SS5      R                  S5      nSR	                  U Vs/ s H  oU[
        R                  ;   d  M  UPM     sn5      n[        R                  " 5       U l	        [        U R                  X#U5      U l        U R                  5         U R                  5         [        [         / U SS9U l        gs  snf )z
Initialize state

:param conn: VirtinstConnection to validate device against
:param parsexml: Optional XML string to parse

The rest of the parameters are for internal use only
asciiignorer  F)rp   N)rt   _XML_SANITIZEencodedecodejoinstring	printablecollectionsOrderedDictr   r  r   r   _validate_xmlbuilder_initial_child_parsere   r	   xml_actions)r#   rt   r  r  r  rQ   s         r   rB   XMLBuilder.__init__  s     	w9@@IHww8M8aF<L<L7L8MNH%113"4==#+#8: 	!!#!!#(T%9  Ns   C#Cc                    U R                   R                  S-   n[        U R                   US5      (       a  g U R                  5       nU R	                  5       nU R
                   H(  nXB;  d  M
  XC;  d  M  [        R                  " SU-  5      e   / nUR                  5        HQ  nUR                  U;   a#  [        R                  " SUR                  -  5      eUR                  UR                  5        MS     [        U R                   US5        g )N_xmlbuilder_validatedFz'key '%s' must be xml prop or child propz'can't register duplicate child_class=%sT)rV   r4   getattr_all_xml_props_all_child_props_XML_PROP_ORDERr   r   valuesr   rl   setattr)r#   cachekeyxmlprops
childpropsrR   childclasses	childprops          r   rI  XMLBuilder._validate_xmlbuilder,  s    >>**-DD4>>8U33&&(**,
''C"s'<&&ACGI I (
 #**,I$$4&&A!--./ / 	 5 56 - 	$/r   c                 (   [        U R                  5       R                  5       5       H  nUR                  nUR	                  X5      nUR
                  (       a/  U" U R                  U R                  US9nUR                  X5        M`  U R                  R                  R                  U R                  R                  U5      5      n[        U5       H:  nSUS-   -  nU" U R                  U R                  X7-   S9nUR                  X5        M<     M     g )N)r  r  [%d]r   )rh   rQ  rS  r   r   r   rt   r   r   r,   countr+   rangerl   )r#   xmlpropr   	prop_pathrz   	nodecountr   idxstrs           r   rJ  XMLBuilder._initial_child_parseC  s     D113::<=G!--K..tAI  !$))#'>>*35 D&--33--i8:IY'37+!$))#'>>+4+=@ t) ( >r   c                     SU R                   R                  R                  S5      S   < SU R                  < S[	        U 5      < S3$ )Nr  r)   rF   r   r   )rV   r4   r  r   r   rA   s    r   r   XMLBuilder.__repr__Z  s6    #~~66<<SA"E#}}bh8 	8r   c                    U R                   R                  nU R                   R                  (       a  UR                  5       nU R	                  U5        UR                  U R                   R                  S5      5      nU(       d  U$ UR                  5       R                  5       S   nUR                  S5      (       d-  UR                  S5      (       a  UR                  S5      S   U-   nUR                  S5      (       d  US-  nU$ )z!
Return XML string of the object
r)   rF   r   r  r   
)r   r,   r  copy_api_add_parse_bitsget_xmlr+   rstrip
splitlinesr*   r  endswith)r#   r,   rP   lastlines       r   rj  XMLBuilder.get_xmlc  s     &&>>""__&FV$nnT^^::3?@J::<**,R0~~c""x':':3'?'?..%a(3.C||D!!4KC
r   c                 \   [        U R                  5       R                  5       5      nU[        U R                  5       R                  5       5      -  nU H  nUR	                  U 5        M     [        [        R                  " SU R                  R                  5       5      5      nU(       d  U(       a>  U R                  R                  R                  U R                  R                  5       5        gU R                  R                  R                  U R                  R                  5       5        g)z
Wipe out all properties of the object

:param leave_stub: if True, don't unlink the top stub node,
    see virtinst/cli usage for an explanation
z^.*\[\d+\]$N)rh   rP  rS  rQ  r   r   rematchr   r  r,   
node_clearnode_force_remove)r#   
leave_stubpropspropis_childs        r   r   XMLBuilder.cleary  s     T((*1134d++-44677DJJt  1I1I1KLMz NN!!,,T^^-E-E-GHNN!!33DNN4L4L4NOr   c                     g)zE
Validate any set values and raise an exception if there's
a problem
Nr   rA   s    r   validateXMLBuilder.validate  s    r   c                     Ung)z%
Encode any default values if needed
Nr   )r#   guestr@  s      r   set_defaultsXMLBuilder.set_defaults  s	     r   c                 6    U R                   R                  5       $ )z
Return the location of the object in the XML document. This is
basically the absolute xpath, but the value returned should be
treated as opaque, it's just for cross XML comparisons. Used
in virt-manager code
)r   r  rA   s    r   
get_xml_idXMLBuilder.get_xml_id  s     ~~''))r   c                     U R                   R                  5       nSU;  a  g[        UR                  SS5      S   R	                  S5      5      S-
  $ )z
This is basically the offset parsed out of the object's xpath,
minus 1. So if this is the fifth <disk> in a <domain>, ret=4.
If this is the only <cpu> in a domain, ret=0.
[r   r   ])r   r  r   r!   stripr  s     r   get_xml_idxXMLBuilder.get_xml_idx  sL     ((*e5<<Q'*0056::r   c                 ,    [         R                  U 5      $ )zA
Return a list of all XMLProperty instances that this class has.
)r   rZ   rA   s    r   rP  XMLBuilder._all_xml_props  s     ''--r   c                 ,    [         R                  U 5      $ )zF
Return a list of all XMLChildProperty instances that this class has.
)r   r^   rA   s    r   rQ  XMLBuilder._all_child_props  s     ))$//r   c                     U R                  5       nS n[        UR                  5       5       H(  nUR                  (       a  M  XR                  L d  M&  Un  O   U(       d  [
        R                  " SU-  5      eU$ )Nz-Didn't find child property for child_class=%s)rQ  rh   rS  r   r   r   r   )r#   r   rV  rP   r_  s        r   _find_child_propXMLBuilder._find_child_prop  sr    ((*HOO-.G  111 / ""?+MO O
r   c                 J   U R                   R                  U5        US:w  a  U R                   R                  U5        U R                  5        HS  n[        R
                  " [        X/ 5      5       H,  nUR                  U R                   R                  5       5        M.     MU     g)z-
Change the object hierarchy's cached xpaths
rF   N)	r   r"  r  rQ  r   listifyrO  _set_xpathsr  )r#   parent_xpathr  r   ps        r   r  XMLBuilder._set_xpaths  sx     	''5 B&NN445JK--/H__WTR%@Adnn6689 B 0r   c                    0 nU R                  5       R                  5        H  u  p#[        R                  " [	        X5      5       H{  nSnUR
                  (       d(  UR                  nXa;  a  SX'   X==   S-  ss'   SX   -  nUR                  X5      nUR                  U R                  R                  5       Xu-   5        M}     M     g)z
Walk the list of child properties and make sure their
xpaths point at their particular element. Needs to be called
whenever child objects are added or removed
r  r   r   r\  N)rQ  rK   r   r  rO  r   rV   r   r  r   r  )r#   	typecountr   r_  rz   rb  
class_typer`  s           r   _set_child_xpathsXMLBuilder._set_child_xpaths  s     	!%!6!6!8!>!>!@Hwt'>?((!$J!201	-)Q.)#i&;;F#224=	 8 8 :!*, @ "Ar   c                     U R                   R                  " U0 UD6  U R                  5        HF  n[        R                  " [        X/ 5      5       H  nUR                  SU R                   5        M!     MH     g)zB
Set new backing XML objects in ourselves and all our child props
N)r   r  rQ  r   r  rO  _parse_with_children)r#   ru   kwargsr   r  s        r   r  XMLBuilder._parse_with_children  s]     	d-f---/H__WTR%@A&&tT^^< B 0r   c                 b   U R                  UR                  5      nUR                  5       nUc  UR                  X5        OUR	                  XU5        U R                  5         UR                  R                  (       d  UR                  R                  5       R                  SS5      S   nSUR                  R                  5       R                  S5      -  nU R                  R                  R                  [        R                  " XFS-  5      U5        UR                  SU R                  5        g)z
Insert the passed XMLBuilder object into our XML document. The
object needs to have an associated mapping via XMLChildProperty
Nr   r   r   r   r   )r  rV   rj  rl   r   r  r   r  r  r!   r]  r,   node_add_xmltextwrapindentr  )r#   rz   r   r_  xml	use_xpathr  s          r   ry   XMLBuilder.add_child  s    
 ''6kkm;NN4%NN4c*  }}%%//188a@CI00288==FNN!!..OOC#6	C  t~~6r   c                 b   U R                  UR                  5      nUR                  X5        UR                  R	                  5       nUR                  5       nUR                  SS5        UR                  US5        U R                  R                  R                  U5        U R                  5         g)z_
Remove the passed XMLBuilder object from our XML document, but
ensure its data isn't altered.
N)r  rV   r   r   r  rj  r  r  r,   rt  r  )r#   rz   r_  r$   r  s        r   r   XMLBuilder.remove_child  s    
 ''6t!'')kkmd#  d+//6 r   c                    U R                   R                  (       d  UR                  5       nSUR                  S5      -  n[        R
                  " UR                  5       US-  5      R                  5       nU R                   R                  R                  X55        gUR                  5       nU R                  U5        U R                  X&S9  g)a  
Replace the origobj child with the newobj. For is_build, this
replaces the objects, but for !is_build this only replaces the
XML and keeps the object references in place. This is hacky and
it's fixable but at time or writing it doesn't matter for
our usecases.
r   r   r   )r   N)r   r  r  r]  r  r  rj  r  r,   node_replace_xmlr  r   ry   )r#   origobjr   r$   r  r  origidxs          r   replace_childXMLBuilder.replace_child  s     ~~&&&&(ES))F//&.."2FSLAGGICNN!!225>))+Gg&NN6N/r   c                 @    [        X5      (       a  gXR                  ;  $ )z<
Return True if the property name has never had a value set
F)rO  r   )r#   r   s     r   _prop_is_unsetXMLBuilder._prop_is_unset1  s     4""..r   c                    U R                   R                  5       nU R                  R                  n XR                  l        U R	                  5       X0R                  l        X l         $ ! X0R                  l        X l         f = f)zN
Callback that adds the implicitly tracked XML properties to
the backing xml.
)r   copyr   r,   _do_add_parse_bits)r#   r,   origpropstoreorigapis       r   ri  XMLBuilder._add_parse_bits>  sb    
 ,,...''	,$*NN!**,$+NN!+O %,NN!+Os   A( (B c                 4   U R                  5       nU R                  5       nU R                   Vs/ s H  o3U;  d  M
  UPM     nn[        U R                  5       HF  nXT;   a%  UR                  U5        UR                  SU5        M-  XR;   d  M4  UR                  SU5        MH     [        [        UR                  5       5      5       H  nXT;  d  M
  UR                  U5        M     U H|  nXQ;   a"  X   R                  X R                  U   5        M*  XR;   d  M1  [        R                  " [        X5      5       H(  nUR                  U R                   R"                  5        M*     M~     U R$                   H  nUR'                  U R                   5        M      g s  snf )Nr   )rP  rQ  r   rG   rR  r   r   sortedrh   keysrl   r   r   r  rO  ri  r   r,   rK  r2   )r#   rV  rW  r  do_orderrR   rz   manualactions           r   r  XMLBuilder._do_add_parse_bitsL  s>   &&(**,
  $F!:2EAFD001C$3'"3' 2 $z012C"$ 3
 C&&t__S-AB""??74+=>C''(=(=> ?	  !,,L  0 -) Gs
   	FF)r   r   rt   rK  )NNN)F)rF   r   )"r4   r5   r6   r7   r8   rR  r   rA  staticmethodr0  r<  rB   rI  rJ  r   rj  r   r{  r  r  r  rP  rQ  r  r  r  r  ry   r   r  r  ri  r  r9   r   r   r   r.  r.    s    
 O H M/ / " "" '+<@940.*.8,P.*	; .0	:,*=70!0$/,1r   r.  )rG  r   rq  rE  r  loggerr   r,   r   r  r   r   environr   r   r   objectr	   r;   r   rh   re   r   r~   r]   rW   r  r.  r   r   r   <module>r     s     	 	      (BJJ67	
39f 39l, ,>  
 D  Fx (68' 68rxE" xEvF@ F@R~1 ~1r   