U
    h                      @   sJ   d Z zddlmZ W n  ek
r4   ddlmZ Y nX G dd deZdS )zpasslib.utils.compat._ordered_dict -- backport of collections.OrderedDict for py26

taken from stdlib-suggested recipe at http://code.activestate.com/recipes/576693/

this should be imported from passlib.utils.compat.OrderedDict, not here.
    )	get_identc                   @   s   e Zd ZdZdd ZejfddZejfddZdd	 Zd
d Z	dd Z
d0ddZdd Zdd Zdd Zdd Zdd Zdd Zdd ZeZe Zefdd Zd1d"d#Zi fd$d%Zd&d' Zd(d) Zed2d*d+Zd,d- Zd.d/ Zd!S )3OrderedDictz)Dictionary that remembers insertion orderc                 O   sn   t |dkrtdt | z
| j W n6 tk
r\   g  | _}||dg|dd< i | _Y nX | j|| dS )zInitialize an ordered dictionary.  Signature is the same as for
        regular dictionaries, but keyword arguments are not recommended
        because their insertion order is arbitrary.

           z$expected at most 1 arguments, got %dN)len	TypeError_OrderedDict__rootAttributeError_OrderedDict__map_OrderedDict__update)selfargskwdsroot r   H./venv/lib/python3.8/site-packages/passlib/utils/compat/_ordered_dict.py__init__   s    

zOrderedDict.__init__c                 C   sF   || kr6| j }|d }|||g |d<  |d< | j|< || || dS )z!od.__setitem__(i, y) <==> od[i]=yr   r   N)r   r	   )r   keyvalueZdict_setitemr   lastr   r   r   __setitem__)   s
     zOrderedDict.__setitem__c                 C   s0   || | | j |\}}}||d< ||d< dS )z od.__delitem__(y) <==> del od[y]r   r   N)r	   pop)r   r   Zdict_delitem	link_prev	link_nextr   r   r   __delitem__3   s    
zOrderedDict.__delitem__c                 c   s.   | j }|d }||k	r*|d V  |d }qdS )zod.__iter__() <==> iter(od)r      Nr   r   r   Zcurrr   r   r   __iter__<   s
    
zOrderedDict.__iter__c                 c   s.   | j }|d }||k	r*|d V  |d }qdS )z#od.__reversed__() <==> reversed(od)r   r   Nr   r   r   r   r   __reversed__D   s
    
zOrderedDict.__reversed__c                 C   sd   z@| j  D ]}|dd= q| j}||dg|dd< | j   W n tk
rT   Y nX t|  dS )z.od.clear() -> None.  Remove all items from od.N)r	   
itervaluesr   clearr   dict)r   Znoder   r   r   r   r    L   s    zOrderedDict.clearTc                 C   s|   | st d| j}|r8|d }|d }||d< ||d< n |d }|d }||d< ||d< |d }| j|= t| |}||fS )zod.popitem() -> (k, v), return and remove a (key, value) pair.
        Pairs are returned in LIFO order if last is true or FIFO order if false.

        zdictionary is emptyr   r   r   )KeyErrorr   r	   r!   r   )r   r   r   linkr   r   r   r   r   r   r   popitemX   s     
zOrderedDict.popitemc                 C   s   t | S )zod.keys() -> list of keys in od)listr   r   r   r   keysq   s    zOrderedDict.keysc                    s    fdd D S )z#od.values() -> list of values in odc                    s   g | ]} | qS r   r   .0r   r&   r   r   
<listcomp>w   s     z&OrderedDict.values.<locals>.<listcomp>r   r&   r   r&   r   valuesu   s    zOrderedDict.valuesc                    s    fdd D S )z.od.items() -> list of (key, value) pairs in odc                    s   g | ]}| | fqS r   r   r(   r&   r   r   r*   {   s     z%OrderedDict.items.<locals>.<listcomp>r   r&   r   r&   r   itemsy   s    zOrderedDict.itemsc                 C   s   t | S )z0od.iterkeys() -> an iterator over the keys in od)iterr&   r   r   r   iterkeys}   s    zOrderedDict.iterkeysc                 c   s   | D ]}| | V  qdS )z2od.itervalues -> an iterator over the values in odNr   r   kr   r   r   r      s    zOrderedDict.itervaluesc                 c   s   | D ]}|| | fV  qdS )z=od.iteritems -> an iterator over the (key, value) items in odNr   r/   r   r   r   	iteritems   s    zOrderedDict.iteritemsc                  O   s   t | dkr tdt | f n| s,td| d }d}t | dkrL| d }t|trn|D ]}|| ||< qZn<t|dr| D ]}|| ||< qn|D ]\}}|||< q| D ]\}}|||< qdS )	a  od.update(E, **F) -> None.  Update od from dict/iterable E and F.

        If E is a dict instance, does:           for k in E: od[k] = E[k]
        If E has a .keys() method, does:         for k in E.keys(): od[k] = E[k]
        Or if E is an iterable of items, does:   for k, v in E: od[k] = v
        In either case, this is followed by:     for k, v in F.items(): od[k] = v

        r   z8update() takes at most 2 positional arguments (%d given)z,update() takes at least 1 argument (0 given)r   r   r   r'   N)r   r   
isinstancer!   hasattrr'   r,   )r   r   r   otherr   r   r   r   r   update   s(    	


zOrderedDict.updatec                 C   s0   || kr| | }| |= |S || j kr,t||S )zod.pop(k[,d]) -> v, remove specified key and return the corresponding value.
        If key is not found, d is returned if given, otherwise KeyError is raised.

        )_OrderedDict__markerr"   )r   r   defaultresultr   r   r   r      s    
zOrderedDict.popNc                 C   s   || kr| | S || |< |S )zDod.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in odr   )r   r   r7   r   r   r   
setdefault   s    zOrderedDict.setdefaultc                 C   s^   t | t f}||krdS d||< z.| s:d| jjf W S d| jj|  f W S ||= X dS )zod.__repr__() <==> repr(od)z...r   z%s()z%s(%r)N)id
_get_ident	__class____name__r,   )r   Z_repr_runningZcall_keyr   r   r   __repr__   s    zOrderedDict.__repr__c                    sX    fdd D }t   }t t D ]}||d q(|rL j|f|fS  j|ffS )z%Return state information for picklingc                    s   g | ]}| | gqS r   r   )r)   r0   r&   r   r   r*      s     z*OrderedDict.__reduce__.<locals>.<listcomp>N)varscopyr   r   r<   )r   r,   Z	inst_dictr0   r   r&   r   
__reduce__   s    zOrderedDict.__reduce__c                 C   s
   |  | S )z!od.copy() -> a shallow copy of od)r<   r&   r   r   r   r@      s    zOrderedDict.copyc                 C   s   |  }|D ]}|||< q
|S )zOD.fromkeys(S[, v]) -> New ordered dictionary with keys from S
        and values equal to v (which defaults to None).

        r   )clsiterabler   dr   r   r   r   fromkeys   s    
zOrderedDict.fromkeysc                 C   s6   t |tr*t| t|ko(|  | kS t| |S )zod.__eq__(y) <==> od==y.  Comparison to another OD is order-sensitive
        while comparison to a regular mapping is order-insensitive.

        )r2   r   r   r,   r!   __eq__r   r4   r   r   r   rF      s    
 zOrderedDict.__eq__c                 C   s
   | |k S )Nr   rG   r   r   r   __ne__   s    zOrderedDict.__ne__)T)N)N)r=   
__module____qualname____doc__r   r!   r   r   r   r   r    r$   r'   r+   r,   r.   r   r1   r5   r
   objectr6   r   r9   r>   rA   r@   classmethodrE   rF   rH   r   r   r   r   r      s4   
	



	r   N)rK   threadr   r;   ImportErrorZdummy_threadr!   r   r   r   r   r   <module>   s
   