U
    dRf/                     @   s   d Z ddlmZ ddlZddlZddlZddlZddlmZ ddl	m
Z
 e
jde
jde
jde
jd	e
jd
e
jde
jde
jde
jde
jde
jde
jdiZdd e D ZdZdd Zdd ZG dd deZG dd deZdS )z
Transport for json protocol that apache thrift files will understand
unfortunately, thriftpy2's TJSONProtocol is not compatible with apache's
    )absolute_importN)TProtocolBase)TTypetfi8i16i32i64dblstrZreclstsetmapc                 C   s   i | ]\}}||qS  r   .0kvr   r   B/tmp/pip-unpacked-wheel-jqs7l_7o/thriftpy2/protocol/apache_json.py
<dictcomp>"   s      r      c                 C   sL   t  }t| ts| f} | D ](}t|tr8|t| q|| qt|S )z
    isinstance() can accept a bunch of really annoying different types:
        * a single type
        * a tuple of types
        * an arbitrary nested tree of tuples
    Return a flattened tuple of the given argument.
    )list
isinstancetupleextendflattenappend)Zsuitable_for_isinstancetypesthingr   r   r   r   '   s    	

r   c                 C   s$   t jd dkr t| tr |  S | S )z
    Ensure that the variable is something that we can encode with b64encode
    python3 needs bytes, python2 needs string
    r      )sysversion_infor   r   encode)valr   r   r   _ensure_b64_encode<   s    r$   c                   @   s   e Zd Zedd ZdS )TApacheJSONProtocolFactoryc                 C   s   t | S N)TApacheJSONProtocol)transr   r   r   get_protocolG   s    z'TApacheJSONProtocolFactory.get_protocolN)__name__
__module____qualname__staticmethodr)   r   r   r   r   r%   F   s   r%   c                   @   sj   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dZdd Zdd ZdS )r'   z;
    Protocol that implements the Apache JSON Protocol
    c                 C   s   t | | d | _d S r&   )r   __init___req)selfr(   r   r   r   r.   Q   s    zTApacheJSONProtocol.__init__c                 C   s   d}d}d}t | jdr@z| j }W qW n tk
r>   Y nX | jd}||7 }|dkrl|dsl| }|s|dkr|d7 }n|d	kr|d8 }|dkrqq|rt|d
| _	nd | _	d S )N    r   Fgetvaluer      "s   \"   [   ]utf8)
hasattrr(   r2   	Exceptionreadendswithjsonloadsdecoder/   )r0   dataZl_bracesZ	in_stringZnew_datar   r   r   
_load_dataU   s.    

zTApacheJSONProtocol._load_datac                 C   s   | j s|   | j dd S )Nr      )r/   r?   r0   r   r   r   read_message_begins   s    z&TApacheJSONProtocol.read_message_beginc                 C   s   d S r&   r   rA   r   r   r   read_message_endx   s    z$TApacheJSONProtocol.read_message_endc                 C   s   d S r&   r   )r0   ttyper   r   r   skip{   s    zTApacheJSONProtocol.skipc                 C   s   d S r&   r   rA   r   r   r   write_message_end~   s    z%TApacheJSONProtocol.write_message_endc                 C   s   || _ || _|| _d S r&   )apirD   seqid)r0   namerD   rH   r   r   r   write_message_begin   s    z'TApacheJSONProtocol.write_message_beginc                 C   s>   t | j| j| j| |g}tj|dd}| j|	d dS )z
        Write json to self.trans following apache style jsonification of `obj`

        :param obj: A thriftpy2 object
        :return:
        ),:)
separatorsr6   N)
VERSIONrG   rD   rH   _thrift_to_dictr;   dumpsr(   writer"   )r0   objdocZjson_strr   r   r   write_struct   s    z TApacheJSONProtocol.write_structNc                    sH  t |ds|dk	r@t|tr@t|dkr@|d dd tD }|d tjksbt|trt|d  t|gfdd|D  S |d tj	kst|t
rd tj	kr|d  |d }n|d  |d }t  t| t| fd	d
| D gS tjks|d tjkr@tjtjkr@tt|dS t|trTt|S |tjks|t|tr|d tjkrtjtjkrtt|dS |S i }|j D ]\}}|dd \}}	ttrވft||	}
|
dk	r|tjkrt| |
i||< q|tjtjfkr`t| td  t|
gfdd|
D  i||< n|tj	krtd   ttd trd d nd  }t|  |t|
fdd
|
 D gi||< nn|tjkrtjtjkrt| tt|
di||< n2|tjkr0t| t|
i||< nt| |
i||< q|S )aH  
        Convert a thriftpy2 into an apache conformant dict, eg:

        >>> {0: {'rec': {1: {'str': "304"}, 14: {'rec': {1: {'lst': ["rec", 0]}}}}}}

        >>> {"0":{"rec":{"1":{"str":"284"},"14":{"rec":{"1":{"lst":
        >>>  ["rec",2,{"1":{"i32":12345.0},"2":{"i32":2.0},"3":{"str":"Testing notifications"},"4":{"tf":1}},
              {"1":{"i32":567809.0},"2":{"i32":2.0},"3":{"str":"Other test"},"4":{"tf":0}}]}}}}}}

        :param thrift_obj: the thing we want to make into a dict
        :param item_type: the type of the item we are to convert
        :return:
        thrift_specNr   c                 S   s    g | ]}t |d rtjn|qS )rU   )r7   r   STRUCT)r   tr   r   r   
<listcomp>   s     z7TApacheJSONProtocol._thrift_to_dict.<locals>.<listcomp>r   c                    s   g | ]}  |d  qS r   rO   r   r   )r0   to_typer   r   rX      s     r   c                    s*   i | ]"\}} |  |d  qS rY   rZ   r   )key_typer0   r\   r   r   r      s   
z7TApacheJSONProtocol._thrift_to_dict.<locals>.<dictcomp>ascii   c                    s   g | ]}  |qS r   rZ   r[   r0   specr   r   rX      s     c                    s*   i | ]"\}}  |d    |qS )r   rZ   r   ra   r   r   r      s   )r7   r   r   lenr   r   LISTr   CTYPESMAPdictitemsBINARYSTRINGbase64	b64encoder$   r=   boolintrU   getattrrV   rO   SETBOOL)r0   Z
thrift_obj	item_typeZflat_key_valZval_typeresult	field_idxrU   rD   
field_namer#   r   )r]   r0   rb   r\   r   rO      s    

 *


  &
( 

 
 
 z#TApacheJSONProtocol._thrift_to_dictc              
      s  t |tttttjtjfs"|dkr|tj	tj
tjtjfkrBt|S |tjkrbtjtjkrbt|S |tjkrddddd|  S t |trt|S |S t |tr|d }|d  |tjkrʈ| S |tjtjfkr fdd|d	d D S |tjkr fd
d|d  D S i }|j}| D ]Z\}}|t| d }| D ]0\}	}
t|	 }d tjkrtjtjkr|dd}t|d }|dkr|dd|  7 }t|||< n|tjkr|
d	 ||< n|tjtjfkrfdd|
d	d D ||< nh|tjkrfd	 d d	 d fdd|
d  D ||< n tttttttd|	 |
||< qVq0t|dr|f |S | D ]\}}t||| q|S dS )z
        Convert an apache thrift dict (where key is the type, value is the data)

        :param data: the dict data
        :param base_type: the type we are going to convert data to
        :return:
        NTF)truefalse10r   r   c                    s   g | ]} | qS r   _dict_to_thriftr[   rr   r0   r   r   rX     s     z7TApacheJSONProtocol._dict_to_thrift.<locals>.<listcomp>r   c                    s.   i | ]&\}} | d   | d qS )r   r   rz   r   r|   r   r   r     s   z7TApacheJSONProtocol._dict_to_thrift.<locals>.<dictcomp>r`   r    r@   =c                    s   g | ]}  |d  qS )r   rz   r[   )r0   rU   r   r   rX     s     c                    s&   i | ]\}} |  |qS r   rz   r   )key_specr0   val_specr   r   r     s   
 )r   r   r   r   r	   r
   r   __call__) r   r   rn   floatrm   sixstring_typesbinary_typer   ZI08I16I32I64ri   rj   rk   	b64decoderq   lowerr   rV   r{   rd   rp   rf   rh   rU   JTYPESgetrc   r7   setattr)r0   r>   Z	base_typeZcontainer_typers   Z	base_specrt   r#   ru   ZftypevaluerD   Zbin_datamr   r   r   )rr   r   r0   rU   r   r   r{      s    	"





"
	
z#TApacheJSONProtocol._dict_to_thriftc                 C   s   |  | jd |S )a  
        Read the next struct into obj, usually the argument from an incoming request
        Only really used to read the arguments off a request into whatever we want
        see thriftpy2.thrift.TProcessor.process_in for how this class will be used

        Will turn the contents of self.req[4] into the args of obj,
        ie. self.req[4]["1"] must be rendered into obj.thrift_spec

        :param obj:
        :return:
        r@   )r{   r/   )r0   rR   r   r   r   read_struct4  s    zTApacheJSONProtocol.read_struct)N)r*   r+   r,   __doc__r.   r?   rB   rC   rE   rF   rJ   rT   rO   r{   r   r   r   r   r   r'   L   s   
SPr'   ) r   
__future__r   r;   rk   r    r   Zthriftpy2.protocolr   Zthriftpy2.thriftr   rq   ZBYTEr   r   r   ZDOUBLErj   ri   rV   rd   rp   rf   re   rh   r   rN   r   r$   objectr%   r'   r   r   r   r   <module>   sL               
