U
    c:                  
   @   sj  d Z ddlmZ dZeZddlmZ zddlmZ	 W n  e
k
rT   ddlmZ	 Y nX ddlZddlZddlmZ edZze W n   eZY nX ze W n   eZY nX d3ddZdd Zg Zd4d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!d5d$d%Z"d&d' Z#d(d) Z$d6d*d+Z%d7d,d-Z&d8d.d/Z'd0d#d0d	d0e!d	d0d1d0f
d2dZ(dS )9a  
Converts a Python dictionary or other native data type into a valid XML string.

Supports item (`int`, `float`, `long`, `decimal.Decimal`, `bool`, `str`, `unicode`, `datetime`, `none` and other number-like objects) and collection (`list`, `set`, `tuple` and `dict`, as well as iterable and dict-like objects) data types, with arbitrary nesting for the collections. Items with a `datetime` type are converted to ISO format strings. Items with a `None` type become empty XML elements.

This module works with both Python 2 and 3.
    )unicode_literalsz1.7.16)randint)IterableN)parseString	dicttoxmlFdicttoxml.logc                 C   sT   | rBdd l }td|  tj|tjd tdt|j    ntjtj	d d S )Nr   z*Debug mode is on. Events are logged at: %s)filenamelevelz
Logging session starts: %s)r	   )
datetimeprintloggingbasicConfigINFOLOGinfostrtodayWARNING)debugr   r
    r   -/tmp/pip-unpacked-wheel-y5vxa37i/dicttoxml.py	set_debug,   s    r   c                 C   s6   t d| f  zt| dW S    t|  Y S X dS )zConverts strings with non-ASCII characters to unicode for LOG.
    Python 3 doesn't have a `unicode()` function, so `unicode()` is an alias
    for `str()`, but `str()` doesn't take a second argument, hence this kludge.
    zInside unicode_me(). val = "%s"utf-8N)r   r   unicodevalr   r   r   
unicode_me8   s
    r   順 ?B c                 C   s&   t d| ||f  d| t||f S )zReturns a random integerz6Inside make_id(). element = "%s", start="%s", end="%s"%s_%s)r   r   r   )elementstartendr   r   r   make_idF   s    r#   c                 C   sJ   t d| f  t| }d}|rB|tkr8d}t| qt| }qtd S )z'Returns a unique id for a given elementz&Inside get_unique_id(). element = "%s"TF)r   r   r#   idsappend)r    this_iddupr   r   r   get_unique_idL   s    
r)   c                 C   s  t d| t| jf  t| jdkr4t d dS t| jdkrPt d dS t| jdkrlt d d	S t| jd
krt d dS t| jdkrt d dS t| tjrt d dS t| trt d dS t| trt d dS t dt| j  t| jS )z0Returns the data type for the xml type attributez3Inside get_xml_type(). val = "%s", type(val) = "%s"ZNoneTypez2type(val).__name__ == 'NoneType', returning 'null'nullboolz.type(val).__name__ == 'bool', returning 'bool')r   r   z8type(val).__name__ in ('str', unicode'), returning 'str'r   )intlongz5type(val).__name__ in ('int', long'), returning 'int'r,   floatz0type(val).__name__ == 'float', returning 'float'z3isinstance(val, numbers.Number), returning 'number'numberz'isinstance(val, dict), returning 'dict'dictz+isinstance(val, iterable), returning 'list'listztype not found, returning '%s')	r   r   type__name__
isinstancenumbersNumberr0   iterabler   r   r   r   get_xml_typeZ   s6    









r8   c                 C   sn   t d| t| f  t| ttfkrjt| } | dd} | dd} | dd} | dd	} | d
d} | S )Nz0Inside escape_xml(). s = "%s" and type(s) = "%s"&z&amp;"z&quot;'z&apos;<z&lt;>z&gt;)r   r   r2   r   r   r   replace)sr   r   r   
escape_xml   s    r@   c                 C   s@   t d| f  ddd |  D }d|dkr6dnd|f S )z2Returns an attribute string in the form key="val" z$Inside make_attstring(). attr = "%s" c                 S   s   g | ]\}}d ||f qS )z%s="%s"r   ).0kvr   r   r   
<listcomp>   s     z#make_attrstring.<locals>.<listcomp>z%s%s )r   r   joinitems)attr
attrstringr   r   r   make_attrstring   s    rK   c                 C   sH   t dt|   d| | f }zt| W dS  tk
rB   Y dS X dS )z%Checks that a key is a valid XML namez'Inside key_is_valid_xml(). Testing "%s"z3<?xml version="1.0" encoding="UTF-8" ?><%s>foo</%s>TFN)r   r   r   r   	Exception)keyZtest_xmlr   r   r   key_is_valid_xml   s    rN   c                 C   s   t dt| t|f  t| } t|}t| r:| |fS t|  rRd|  |fS zdtt|  |fW S  tk
r|   Y nX t| 	ddr| 	dd|fS | |d< d} | |fS )z)Tests an XML name and fixes it if invalidz=Inside make_valid_xml_name(). Testing key "%s" with attr "%s"zn%srA   _namerM   )
r   r   r   r@   rN   r   isdigitr.   
ValueErrorr>   )rM   rI   r   r   r   make_valid_xml_name   s&     rS   c                 C   s,   t d| f  t| dd} d|  d S )z"Wraps a string into CDATA sectionszInside wrap_cdata(). val = "%s"z]]>z]]]]><![CDATA[>z	<![CDATA[)r   r   r   r>   r   r   r   r   
wrap_cdata   s    rT   c                 C   s   t d| f  dS )Nz)Inside default_item_func(). parent = "%s"item)r   r   parentr   r   r   default_item_func   s    rX   rootc                 C   s   t dt| jt| f  ||}t| tkr>t|| ||S | dkrTt|| ||S t| t	j
spt| ttfkr~t|| ||S t| drt||  ||S t| trt| |||||S t| trt| |||||S td| t| jf dS )zcRoutes the elements of an object to the right function to convert them
    based on their data typez-Inside convert(). obj type is: "%s", obj="%s"N	isoformatUnsupported data type: %s (%s))r   r   r2   r3   r   r+   convert_boolconvert_noner4   r5   r6   r   r   
convert_kvhasattrrZ   r0   convert_dictr7   convert_list	TypeError)objr%   	attr_type	item_funccdatarW   	item_namer   r   r   convert   s    


rh   c                 C   s  t dt| jt| f  g }|j}||}|  D ]\}	}
t dt|	t|
t|
jf  |sji nddt| i}t|	|\}	}t|
t	kr|t
|	|
||| q6t|
tjst|
ttfkr|t|	|
||| q6t|
dr|t|	|
 ||| q6t|
t	kr&|t
|	|
||| q6t|
trl|rDt|
|d< |d|	t|t|
||	||||	f  q6t|
tr|rt|
|d< |d|	t|t|
||	||||	f  q6|
dkr|t|	|
||| q6td	|
t|
jf q6d
|S )z#Converts a dict into an XML string.z2Inside convert_dict(): obj type is: "%s", obj="%s"zALooping inside convert_dict(): key="%s", val="%s", type(val)="%s"idz%srZ   r2   <%s%s>%s</%s>Nr[   rF   )r   r   r2   r3   r   r&   rH   r)   rS   r+   r\   r4   r5   r6   r   r   r^   r_   rZ   r0   r8   rK   r`   r7   ra   r]   rb   rG   )rc   r%   rW   rd   re   rf   outputaddlinerg   rM   r   rI   r   r   r   r`      s`        


 
r`   c                 C   s  t d g }|j}||}|r(t|}	t| D ]\}
}t dt||t|jf  |s`i ndd|	|
d f i}t|t	j
st|ttfkr|t||||| q0t|dr|t|| ||| q0t|tkr|t||||| q0t|trB|s |d|t|||||||f  n |d|t|||||||f  q0t|tr|s||d	|t|t|||||||f  n&|d
|t|t|||||||f  q0|dkr|t|d||| q0td|t|jf q0d|S )z#Converts a list into an XML string.zInside convert_list()zCLooping inside convert_list(): item="%s", item_name="%s", type="%s"ri   r      rZ   <%s>%s</%s>z<%s type="dict">%s</%s>z<%s %s>%s</%s>z<%s type="list"%s>%s</%s>Nr[   rF   )r   r   r&   r)   	enumerater   r2   r3   r4   r5   r6   r   r   r^   r_   rZ   r+   r\   r0   r`   r7   rK   ra   r]   rb   rG   )rH   r%   rW   rd   re   rf   rk   rl   rg   r'   irU   rI   r   r   r   ra   '  sh    
  


 
 

 
ra   c                 C   sx   t dt| t|t|jf  |dkr.i }t| |\} }|rLt||d< t|}d| ||dkrjt|nt	|| f S )z/Converts a number or string into an XML elementz;Inside convert_kv(): key="%s", val="%s", type(val) is: "%s"Nr2   rj   T)
r   r   r   r2   r3   rS   r8   rK   rT   r@   rM   r   rd   rf   rI   rJ   r   r   r   r^   j  s"       r^   c                 C   sl   t dt| t|t|jf  |dkr.i }t| |\} }|rLt||d< t|}d| |t|	 | f S )z&Converts a boolean into an XML elementz=Inside convert_bool(): key="%s", val="%s", type(val) is: "%s"Nr2   rj   )
r   r   r   r2   r3   rS   r8   rK   r   lowerrq   r   r   r   r\     s    r\   c                 C   sf   t dt| t|t|t|f  |dkr2i }t| |\} }|rPt||d< t|}d| || f S )z)Converts a null value into an XML elementzBInside convert_none(): key="%s". val="%s", attr_type="%s", attr=%sNr2   z<%s%s></%s>)r   r   r   r   rS   r8   rK   rq   r   r   r   r]     s    r]   TzUTF-8c                 C   s   t dt| jt| f  g }|j}|dkrx|dkrT|dkrH|d n|d|	  |d|t| |||||d|f  n|t| ||||dd |
dkrd|S d|d	S )
ay  Converts a python object into XML.
    Arguments:
    - root specifies whether the output is wrapped in an XML root element
      Default is True
    - custom_root allows you to specify a custom root element.
      Default is 'root'
    - ids specifies whether elements get unique ids.
      Default is False
    - attr_type specifies whether elements get a data type attribute.
      Default is True
    - item_func specifies what function should generate the element name for
      items in a list.
      Default is 'item'
    - cdata specifies whether string values should be wrapped in CDATA sections.
      Default is False
    z0Inside dicttoxml(): type(obj) is: "%s", obj="%s"TFz<?xml version="1.0" ?>z$<?xml version="1.0" encoding="%s" ?>rn   rV   rF   r   )	r   r   r2   r3   r   r&   rh   rG   encode)rc   rY   Zcustom_rootxml_declarationr%   rd   re   rf   Zinclude_encodingencodingZreturn_bytesrk   rl   r   r   r   r     s"    


)Fr   )r   r   )rY   )FN)FN)FN))__doc__
__future__r   __version__versionrandomr   collections.abcr   r7   ImportErrorcollectionsr5   r   Zxml.dom.minidomr   	getLoggerr   r   r   r-   r,   r   r   r%   r#   r)   r8   r@   rK   rN   rS   rT   rX   rh   r`   ra   r^   r\   r]   r   r   r   r   r   <module>   sb   




( 
?C


