o
    i1g                     @   s&  d dl Z d dlT ddlmZ e eZdZe Z	e Z
G dd dZG d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d!d" Zd#d$ ZdS )%    N)*   )JsonPathLexerc                   @   H   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S )JSONPathz
    The base class for JSONPath abstract syntax; those
    methods stubbed here are the interface to supported
    JSONPath semantics.
    c                 C      t  )a  
        All `JSONPath` types support `find()`, which returns an iterable of `DatumInContext`s.
        They keep track of the path followed to the current location, so if the calling code
        has some opinion about that, it can be passed in here as a starting point.
        NotImplementedErrorselfdata r   W/home/ubuntu/.local/lib/python3.10/site-packages/ddtrace/vendor/jsonpath_ng/jsonpath.pyfind      zJSONPath.findc                 C   s
   |  |S N)r   r
   r   r   r   find_or_create      
zJSONPath.find_or_createc                 C   r   )z~
        Returns `data` with the specified path replaced by `val`. Only updates
        if the specified path exists.
        r   r   r   valr   r   r   update"   r   zJSONPath.updatec                 C   s   |  ||S r   )r   r   r   r   r   update_or_create*      zJSONPath.update_or_createc                 C   r   )aM  
        Returns `data` with the specified path filtering nodes according
        the filter evaluation result returned by the filter function.

        Arguments:
            fn (function): unary function that accepts one argument
                and returns bool.
            data (dict|list|tuple): JSON object to filter.
        r   r   fnr   r   r   r   filter-   s   zJSONPath.filterc                 C   s>   t | ts
t | tr|S t |tr| S t |tr|S t| |S )zP
        Equivalent to Child(self, next) but with some canonicalization
        )
isinstanceThisRootChild)r   childr   r   r   r    :   s   


zJSONPath.childc                 C   s   t |tr|S t|t d dS Npathcontext)r   DatumInContextr   )r   valuer   r   r   
make_datumG   s   
zJSONPath.make_datumN)__name__
__module____qualname____doc__r   r   r   r   r   r    r'   r   r   r   r   r      s    r   c                   @   sV   e Zd ZdZedd ZdddZdd Zed	d
 Z	edd Z
dd Zdd ZdS )r%   a  
    Represents a datum along a path from a context.

    Essentially a zipper but with a structure represented by JsonPath,
    and where the context is more of a parent pointer than a proper
    representation of the context.

    For quick-and-dirty work, this proxies any non-special attributes
    to the underlying datum, but the actual datum can (and usually should)
    be retrieved via the `value` attribute.

    To place `datum` within another, use `datum.in_context(context=..., path=...)`
    which extends the path. If the datum already has a context, it places the entire
    context within that passed in, so an object can be built from the inside
    out.
    c                 C   s   t || r|S | |S r   )r   )clsr   r   r   r   wrap_   s   
zDatumInContext.wrapNc                 C   s4   || _ |pt | _|d u rd | _d S t|| _d S r   )r&   r   r#   r%   r-   r$   )r   r&   r#   r$   r   r   r   __init__f   s   "zDatumInContext.__init__c                 C   s<   t |}| jrt | j| j|j||ddS t | j||dS )Nr"   )r&   r#   r$   )r%   r-   r$   r&   r#   
in_contextr   r$   r#   r   r   r   r/   k   s   
zDatumInContext.in_contextc                 C   s    | j d u r| jS | j j| jS r   )r$   r#   	full_pathr    r   r   r   r   r1   s   s    zDatumInContext.full_pathc              
   C   sN   zt t| jt }W n tttfy   | j}Y nw | jr%| jj	
|S |S )zI
        Looks like a path, but with ids stuck in when available
        )Fieldsstrr&   auto_id_field	TypeErrorAttributeErrorKeyErrorr#   r$   id_pseudopathr    )r   
pseudopathr   r   r   r9   w   s   
zDatumInContext.id_pseudopathc                 C      d| j j| j| j| jf S )Nz!%s(value=%r, path=%r, context=%r))	__class__r(   r&   r#   r$   r2   r   r   r   __repr__      zDatumInContext.__repr__c                 C   s.   t |to|j| jko|j| jko| j|jkS r   )r   r%   r&   r#   r$   r   otherr   r   r   __eq__      .zDatumInContext.__eq__)NN)r(   r)   r*   r+   classmethodr-   r.   r/   propertyr1   r9   r=   rA   r   r   r   r   r%   N   s    



r%   c                   @   sV   e Zd ZdZdddZedd Zedd Zed	d
 Zdd Z	dd Z
dd ZdS )AutoIdForDatuma  
    This behaves like a DatumInContext, but the value is
    always the path leading up to it, not including the "id",
    and with any "id" fields along the way replacing the prior
    segment of the path

    For example, it will make "foo.bar.id" return a datum
    that behaves like DatumInContext(value="foo.bar", path="foo.bar.id").

    This is disabled by default; it can be turned on by
    settings the `auto_id_field` global to a value other
    than `None`.
    Nc                 C   s   || _ |pt| _dS )aW  
        Invariant is that datum.path is the path from context to datum. The auto id
        will either be the id in the datum (if present) or the id of the context
        followed by the path to the datum.

        The path to this datum is always the path to the context, the path to the
        datum, and then the auto id field.
        N)datumr5   id_field)r   rF   rG   r   r   r   r.      s   	zAutoIdForDatum.__init__c                 C   s   t | jjS r   )r4   rF   r9   r2   r   r   r   r&      s   zAutoIdForDatum.valuec                 C      | j S r   )rG   r2   r   r   r   r#         zAutoIdForDatum.pathc                 C   rH   r   rF   r2   r   r   r   r$      rI   zAutoIdForDatum.contextc                 C      d| j j| jf S )Nz%s(%r))r<   r(   rF   r2   r   r   r   r=         zAutoIdForDatum.__repr__c                 C   s   t | jj||dS )Nr$   r#   )rE   rF   r/   r0   r   r   r   r/         zAutoIdForDatum.in_contextc                 C   s"   t |to|j| jko| j|jkS r   )r   rE   rF   rG   r?   r   r   r   rA         "zAutoIdForDatum.__eq__r   )r(   r)   r*   r+   r.   rD   r&   r#   r$   r=   r/   rA   r   r   r   r   rE      s    



rE   c                   @   r   )r   z
    The JSONPath referring to the "root" object. Concrete syntax is '$'.
    The root is the topmost datum without any context attached.
    c                 C   sH   t |tst|t d dgS |jd u rt|jd t dgS t |jS )Nr"   rM   )r   r%   r   r$   r&   r   r
   r   r   r   r      s
   

z	Root.findc                 C      |S r   r   r   r   r   r   r         zRoot.updatec                 C      ||r|S d S r   r   r   r   r   r   r         zRoot.filterc                 C      dS N$r   r2   r   r   r   __str__   rQ   zRoot.__str__c                 C   rT   )NzRoot()r   r2   r   r   r   r=      rQ   zRoot.__repr__c                 C   
   t |tS r   )r   r   r?   r   r   r   rA      r   zRoot.__eq__c                 C      t dS rU   hashr2   r   r   r   __hash__      zRoot.__hash__Nr(   r)   r*   r+   r   r   r   rW   r=   rA   r\   r   r   r   r   r      s    	r   c                   @   r   )r   zN
    The JSONPath referring to the current datum. Concrete syntax is '@'.
    c                 C   s   t |gS r   )r%   r-   r   rF   r   r   r   r      r   z	This.findc                 C   rP   r   r   r   r   r   r   r      rQ   zThis.updatec                 C   rR   r   r   r   r   r   r   r      rS   zThis.filterc                 C   rT   )Nz`this`r   r2   r   r   r   rW      rQ   zThis.__str__c                 C   rT   )NzThis()r   r2   r   r   r   r=      rQ   zThis.__repr__c                 C   rX   r   )r   r   r?   r   r   r   rA      r   zThis.__eq__c                 C   rY   )NthisrZ   r2   r   r   r   r\      r]   zThis.__hash__Nr^   r   r   r   r   r      s    r   c                   @   s`   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 Zdd ZdS )r   zi
    JSONPath that first matches the left, then the right.
    Concrete syntax is <left> '.' <right>
    c                 C      || _ || _d S r   leftrightr   rc   rd   r   r   r   r.        
zChild.__init__c                        fdd j |D S )z
        Extra special case: auto ids do not have children,
        so cut it off right now rather than auto id the auto id
        c                    s,   g | ]}t |ts j|D ]}|qqS r   )r   rE   rd   r   ).0subdatasubmatchr2   r   r   
<listcomp>  s    

zChild.find.<locals>.<listcomp>rc   r   r_   r   r2   r   r     s   

z
Child.findc                 C   s&   | j |D ]
}| j|j| q|S r   )rc   r   rd   r   r&   r   r   r   rF   r   r   r   r        zChild.updatec                 C   sL   t |}g }| j|D ]}t|trq| j|D ]}|| qq|S r   )r%   r-   rc   r   r   rE   rd   append)r   rF   
submatchesri   rj   r   r   r   r     s   

zChild.find_or_createc                 C   s*   | j |D ]
}| j|j| qt|S r   )rc   r   rd   r   r&   _clean_list_keysrm   r   r   r   r   !  s   zChild.update_or_createc                 C   s&   | j |D ]
}| j||j q|S r   )rc   r   rd   r   r&   r   r   r   rF   r   r   r   r   &  rn   zChild.filterc                 C   "   t |to| j|jko| j|jkS r   )r   r   rc   rd   r?   r   r   r   rA   +  rO   zChild.__eq__c                 C      d| j | jf S )Nz%s.%srb   r2   r   r   r   rW   .  rS   zChild.__str__c                 C      d| j j| j| jf S Nz
%s(%r, %r)r<   r(   rc   rd   r2   r   r   r   r=   1     zChild.__repr__c                 C      t | j| jfS r   r[   rc   rd   r2   r   r   r   r\   4  rS   zChild.__hash__N)r(   r)   r*   r+   r.   r   r   r   r   r   rA   rW   r=   r\   r   r   r   r   r      s    r   c                   @   8   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d ZdS )Parentz
    JSONPath that matches the parent node of the current match.
    Will crash if no such parent exists.
    Available via named operator `parent`.
    c                 C   s   t |}|jgS r   )r%   r-   r$   r_   r   r   r   r   ?  s   
zParent.findc                 C   rX   r   )r   r|   r?   r   r   r   rA   C  r   zParent.__eq__c                 C   rT   )Nz`parent`r   r2   r   r   r   rW   F  rQ   zParent.__str__c                 C   rT   )NzParent()r   r2   r   r   r   r=   I  rQ   zParent.__repr__c                 C   rY   )NparentrZ   r2   r   r   r   r\   L  r]   zParent.__hash__N)	r(   r)   r*   r+   r   rA   rW   r=   r\   r   r   r   r   r|   8  s    r|   c                   @   r   )Wherez
    JSONPath that first matches the left, and then
    filters for only those nodes that have
    a match on the right.

    WARNING: Subject to change. May want to have "contains"
    or some other better word for it.
    c                 C   ra   r   rb   re   r   r   r   r.   Z  rf   zWhere.__init__c                    rg   )Nc                    s   g | ]
} j |r|qS r   )rd   r   )rh   ri   r2   r   r   rk   _  s    zWhere.find.<locals>.<listcomp>rl   r
   r   r2   r   r   ^  r>   z
Where.findc                 C   "   |  |D ]	}|j|| q|S r   r   r#   r   rm   r   r   r   r   a     zWhere.updatec                 C   s$   |  |D ]
}|j||j q|S r   )r   r#   r   r&   rr   r   r   r   r   f  s   zWhere.filterc                 C   rt   )Nz%s where %srb   r2   r   r   r   rW   k  rS   zWhere.__str__c                 C   s"   t |to|j| jko|j| jkS r   )r   r~   rc   rd   r?   r   r   r   rA   n  rO   zWhere.__eq__c                 C   ry   r   rz   r2   r   r   r   r\   q  rS   zWhere.__hash__N)r(   r)   r*   r+   r.   r   r   r   rW   rA   r\   r   r   r   r   r~   P  s    	r~   c                   @   sX   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 ZdS )Descendantsz{
    JSONPath that matches first the left expression then any descendant
    of it which matches the right expression.
    c                 C   ra   r   rb   re   r   r   r   r.   z  rf   zDescendants.__init__c                    s<   j |}t|ts|g} fdd  fdd|D S )Nc                    sr   j  }t jtr fddtdt jD }nt jtr1 fdd j D }ng }|t| S )Nc                    2   g | ]}t  j|  t|d D ]}|qqS rM   r%   r&   Index)rh   irj   rF   match_recursivelyr   r   rk         
z?Descendants.find.<locals>.match_recursively.<locals>.<listcomp>r   c                    r   r   )r%   r&   r3   )rh   fieldrj   r   r   r   rk     r   )	rd   r   r   r&   listrangelendictkeys)rF   right_matchesrecursive_matchesr   r   rJ   r   r     s   z+Descendants.find.<locals>.match_recursivelyc                    s   g | ]} |D ]}|qqS r   r   )rh   
left_matchrj   )r   r   r   rk     s    
z$Descendants.find.<locals>.<listcomp>)rc   r   r   r   )r   rF   left_matchesr   r   r   r   ~  s   

zDescendants.findc                 C   rT   NFr   r2   r   r   r   is_singular  rQ   zDescendants.is_singularc                    sD    j |}t|ts|g} fdd|D ]}|j q|S )Nc                    s   t | tst | tsd S  j|  t | tr*tdt| D ]}| |  qd S t | tr<|  D ]
}| |  q3d S d S Nr   )r   r   r   rd   r   r   r   r   r   r   r   r   update_recursivelyr   r   r   r        

z.Descendants.update.<locals>.update_recursivelyrc   r   r   r   r&   )r   r   r   r   rj   r   r   r   r        
zDescendants.updatec                    sD   j |}t|ts|g} fdd |D ]} |j q|S )Nc                    s   t | tst | tsd S j|  t | tr*tdt| D ]} | |  qd S t | tr<|  D ]
} | |  q3d S d S r   )r   r   r   rd   r   r   r   r   r   filter_recursivelyr   r   r   r   r     r   z.Descendants.filter.<locals>.filter_recursivelyr   )r   r   r   r   rj   r   r   r   r     r   zDescendants.filterc                 C   rt   )Nz%s..%srb   r2   r   r   r   rW     rS   zDescendants.__str__c                 C   rs   r   )r   r   rc   rd   r?   r   r   r   rA     rO   zDescendants.__eq__c                 C   ru   rv   rw   r2   r   r   r   r=     rx   zDescendants.__repr__c                 C   ry   r   rz   r2   r   r   r   r\     rS   zDescendants.__hash__N)r(   r)   r*   r+   r.   r   r   r   r   rW   rA   r=   r\   r   r   r   r   r   t  s    $r   c                   @   r{   )Unionas  
    JSONPath that returns the union of the results of each match.
    This is pretty shoddily implemented for now. The nicest semantics
    in case of mismatched bits (list vs atomic) is to put
    them all in a list, but I haven't done that yet.

    WARNING: Any appearance of this being the _concatenation_ is
    coincidence. It may even be a bug! (or laziness)
    c                 C   ra   r   rb   re   r   r   r   r.     rf   zUnion.__init__c                 C   rT   r   r   r2   r   r   r   r     rQ   zUnion.is_singularc                 C   s   | j || j| S r   )rc   r   rd   r
   r   r   r   r     s   z
Union.findc                 C   rs   r   )r   r   rc   rd   r?   r   r   r   rA     rO   zUnion.__eq__c                 C   ry   r   rz   r2   r   r   r   r\     rS   zUnion.__hash__N	r(   r)   r*   r+   r.   r   r   rA   r\   r   r   r   r   r     s    	r   c                   @   r{   )	IntersectaL  
    JSONPath for bits that match *both* patterns.

    This can be accomplished a couple of ways. The most
    efficient is to actually build the intersected
    AST as in building a state machine for matching the
    intersection of regular languages. The next
    idea is to build a filtered data and match against
    that.
    c                 C   ra   r   rb   re   r   r   r   r.     rf   zIntersect.__init__c                 C   rT   r   r   r2   r   r   r   r     rQ   zIntersect.is_singularc                 C   r   r   r   r
   r   r   r   r     s   zIntersect.findc                 C   rs   r   )r   r   rc   rd   r?   r   r   r   rA     rO   zIntersect.__eq__c                 C   ry   r   rz   r2   r   r   r   r\     rS   zIntersect.__hash__Nr   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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 )r3   z
    JSONPath referring to some field of the current object.
    Concrete syntax ix comma-separated field names.

    WARNING: If '*' is any of the field names, then they will
    all be returned.
    c                 G   
   || _ d S r   )fields)r   r   r   r   r   r.   '  r   zFields.__init__c              	   C   sn   |t krt| S z"| j|t}|tu r!|ri  | j|< }nW d S t|t|| dW S  ttfy6   Y d S w r!   )	r5   rE   r&   getNOT_SETr%   r3   r6   r7   )rF   r   createfield_valuer   r   r   get_field_datum*  s   zFields.get_field_datumc                 C   sN   d| j vr| j S zt|j }td u r|W S |tf W S  ty&   Y dS w )Nr   r   )r   tupler&   r   r5   r7   )r   rF   r   r   r   r   reified_fields9  s   
zFields.reified_fieldsc                 C      | j |ddS NFr   
_find_baser_   r   r   r   r   C     zFields.findc                 C   r   NTr   r   r_   r   r   r   r   F  r   zFields.find_or_createc                    s4   t  fddD }dd |D S )Nc                    s   g | ]	} | qS r   )r   )rh   r   r   rF   r   r   r   rk   K  s    z%Fields._find_base.<locals>.<listcomp>c                 S   s   g | ]}|d ur|qS r   r   )rh   fdr   r   r   rk   M  s    )r%   r-   r   )r   rF   r   
field_datar   r   r   r   I  s
   
zFields._find_basec                 C      | j ||ddS r   _update_baser   r   r   r   r   O  rS   zFields.updatec                 C   r   r   r   r   r   r   r   r   R  rS   zFields.update_or_createc                 C   sr   |d ur7|  t|D ]*}|r||vri ||< t|tur6||v r6t|dr2||| ||||< q|||< q|S N__call__)r   r%   r-   typeboolhasattr)r   r   r   r   r   r   r   r   r   U  s   
zFields._update_basec                 C   s@   |d ur|  t|D ]}||v r||| r|| q|S r   )r   r%   r-   pop)r   r   r   r   r   r   r   r   a  s   
zFields.filterc                 C   s   dd | j D }d|S )Nc                 3   s@    | ] t  fd dtjD rdt  d nt V  qdS )c                    s   g | ]}| v qS r   r   )rh   lfr   r   rk   n  s    z,Fields.__str__.<locals>.<genexpr>.<listcomp>'N)anyr   literalsr4   )rh   r   r   r   	<genexpr>n  s    (
z!Fields.__str__.<locals>.<genexpr>,)r   join)r   fields_as_strr   r   r   rW   i  s   
zFields.__str__c                 C   s   d| j jdtt| jf S )Nz%s(%s)r   )r<   r(   r   mapreprr   r2   r   r   r   r=   s     zFields.__repr__c                 C   s   t |tot| jt|jkS r   )r   r3   r   r   r?   r   r   r   rA   v  r   zFields.__eq__c                 C   s   t t| jS r   )r[   r   r   r2   r   r   r   r\   y  r   zFields.__hash__N)r(   r)   r*   r+   r.   staticmethodr   r   r   r   r   r   r   r   r   rW   r=   rA   r\   r   r   r   r   r3     s"    


r3   c                   @   sx   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 Zdd Zdd Zdd Zdd ZdS )r   aQ  
    JSONPath that matches indices of the current datum, or none if not large enough.
    Concrete syntax is brackets.

    WARNING: If the datum is None or not long enough, it will not crash but will not match anything.
    NOTE: For the concrete syntax of `[*]`, the abstract syntax is a Slice() with no parameters (equiv to `[:]`
    c                 C   r   r   index)r   r   r   r   r   r.     r   zIndex.__init__c                 C   r   r   r   r_   r   r   r   r     r   z
Index.findc                 C   r   r   r   r_   r   r   r   r     r   zIndex.find_or_createc                 C   sb   t |}|r|ji krt|j|_| |j |jr/t|j| jkr/t |j| j | |dgS g S r!   )r%   r-   r&   _create_list_key
_pad_valuer   r   )r   rF   r   r   r   r   r     s   

zIndex._find_basec                 C   r   r   r   r   r   r   r   r     rS   zIndex.updatec                 C   r   r   r   r   r   r   r   r     rS   zIndex.update_or_createc                 C   sd   |r|i kr
t |}| | t|dr$||| j || j|| j< |S t|| jkr0||| j< |S r   )r   r   r   r   r   r   )r   r   r   r   r   r   r   r     s   


zIndex._update_basec                 C   s   ||| j  r|| j  |S r   )r   r   r   r   r   r   r     s   zIndex.filterc                 C   s   t |to
| j|jkS r   )r   r   r   r?   r   r   r   rA     rx   zIndex.__eq__c                 C   s
   d| j  S )Nz[%i]r   r2   r   r   r   rW     r   zIndex.__str__c                 C   rK   )Nz%s(index=%r))r<   r(   r   r2   r   r   r   r=     rL   zIndex.__repr__c                 C   s>   t || jkr| jt | d }|dd t|D 7 }d S d S )Nr   c                 S   s   g | ]}i qS r   r   )rh   __r   r   r   rk     s    z$Index._pad_value.<locals>.<listcomp>)r   r   r   )r   r&   padr   r   r   r     s   zIndex._pad_valuec                 C   s
   t | jS r   )r[   r   r2   r   r   r   r\     r   zIndex.__hash__N)r(   r)   r*   r+   r.   r   r   r   r   r   r   r   rA   rW   r=   r   r\   r   r   r   r   r   }  s    r   c                   @   sR   e Zd ZdZd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 )Slicea  
    JSONPath matching a slice of an array.

    Because of a mismatch between JSON and XML when schema-unaware,
    this always returns an iterable; if the incoming data
    was not a list, then it returns a one element list _containing_ that
    data.

    Consider these two docs, and their schema-unaware translation to JSON:

    <a><b>hello</b></a> ==> {"a": {"b": "hello"}}
    <a><b>hello</b><b>goodbye</b></a> ==> {"a": {"b": ["hello", "goodbye"]}}

    If there were a schema, it would be known that "b" should always be an
    array (unless the schema were wonky, but that is too much to fix here)
    so when querying with JSON if the one writing the JSON knows that it
    should be an array, they can write a slice operator and it will coerce
    a non-array value to an array.

    This may be a bit unfortunate because it would be nice to always have
    an iterator, but dictionaries and other objects may also be iterable,
    so this is the compromise.
    Nc                 C   s   || _ || _|| _d S r   startendstep)r   r   r   r   r   r   r   r.     s   
zSlice.__init__c                    s   t    js
g S t jtst jtst jtr*| t  jg j j	dS | j
d u rH| jd u rH| jd u rH fddtdt jD S  fddtdt j| j
| j| j D S )Nr"   c                    $   g | ]}t  j| t| d qS r"   r   rh   r   rJ   r   r   rk        $ zSlice.find.<locals>.<listcomp>r   c                    r   r   r   r   rJ   r   r   rk     r   )r%   r-   r&   r   r   intr4   r   r#   r$   r   r   r   r   r   r_   r   rJ   r   r     s   
$.z
Slice.findc                 C   r   r   r   rm   r   r   r   r     r   zSlice.updatec                 C   sL   	 t |}| |D ]}|j||}t ||k r nq
|t |kr%	 |S qr   )r   r   r#   r   )r   r   r   lengthrF   r   r   r   r     s   zSlice.filterc                 C   sZ   | j d u r| jd u r| jd u rdS d| j pd| jrd| j nd| jr)d| j f S df S )Nz[*]z[%s%s%s] z:%dr   r2   r   r   r   rW     s   
zSlice.__str__c                 C   r;   )Nz%s(start=%r,end=%r,step=%r))r<   r(   r   r   r   r2   r   r   r   r=   
  r>   zSlice.__repr__c                 C   s.   t |to|j| jko| j|jko|j| jkS r   )r   r   r   r   r   r?   r   r   r   rA     rB   zSlice.__eq__c                 C   s   t | j| j| jfS r   )r[   r   r   r   r2   r   r   r   r\     rN   zSlice.__hash__)NNN)r(   r)   r*   r+   r.   r   r   r   rW   r=   rA   r\   r   r   r   r   r     s    
r   c                 C   s   i g | t < }|S )zf
    Adds a list to a dictionary by reference and returns the list.

    See `_clean_list_keys()`
    )LIST_KEY)dict_new_listr   r   r   r     s   r   c                 C   sl   t | trt| D ]
\}}t|| |< q	| S t | tr4t| v r%t| t S |  D ]
\}}t|| |< q)| S )z
    Replace {LIST_KEY: ['foo', 'bar']} with ['foo', 'bar'].

    >>> _clean_list_keys({LIST_KEY: ['foo', 'bar']})
    ['foo', 'bar']

    )r   r   	enumeraterq   r   r   items)struct_indr&   keyr   r   r   rq     s   

rq   )logging	itertoolslexerr   	getLoggerr(   loggerr5   objectr   r   r   r%   rE   r   r   r   r|   r~   r   r   r   r3   r   r   r   rq   r   r   r   r   <module>   s.    
>?1"=$t_ER
