B +[/@srddlmZmZddlmZmZddlmZddlm Z Gddde Z e e e e dd d Z d d Zd S))SequenceHashable)islicechain)Integral)plistcs(eZdZdZdZd=fdd ZeddZedd Ze d d Z d d Z ddZ e Z eddZd>ddZd?ddZe ddZddZddZddZdd Zd!d"Zd#d$Zd%d&Zd'd(Ze d)d*Zd+d,Zd-d.Zd/d0Zd1d2Zd3d4Zd5d6Z e Z!d7d8Z"d9d:Z#d;d<Z$e%j&Z&Z'S)@PDequea Persistent double ended queue (deque). Allows quick appends and pops in both ends. Implemented using two persistent lists. A maximum length can be specified to create a bounded queue. Fully supports the Sequence and Hashable protocols including indexing and slicing but if you need fast random access go for the PVector instead. Do not instantiate directly, instead use the factory functions :py:func:`dq` or :py:func:`pdeque` to create an instance. Some examples: >>> x = pdeque([1, 2, 3]) >>> x.left 1 >>> x.right 3 >>> x[0] == x.left True >>> x[-1] == x.right True >>> x.pop() pdeque([1, 2]) >>> x.pop() == x[:-1] True >>> x.popleft() pdeque([2, 3]) >>> x.append(4) pdeque([1, 2, 3, 4]) >>> x.appendleft(4) pdeque([4, 1, 2, 3]) >>> y = pdeque([1, 2, 3], maxlen=3) >>> y.append(4) pdeque([2, 3, 4], maxlen=3) >>> y.appendleft(4) pdeque([4, 1, 2], maxlen=3) ) _left_list _right_list_length_maxlen __weakref__NcsVtt||}||_||_||_|dk rLt|ts>> pdeque([1, 2]).pop() pdeque([1]) >>> pdeque([1, 2]).pop(2) pdeque([]) >>> pdeque([1, 2]).pop(-1) pdeque([2]) r)popleftr _pop_listsr r maxr r )rcountnew_right_list new_left_listrrrpopis z PDeque.popcCsF|dkr|| St|j|j|\}}t||t|j|d|jS)z Return new deque with leftmost element removed. Otherwise functionally equivalent to pop(). >>> pdeque([1, 2]).popleft() pdeque([2]) r)r0r r+r r r,r r )rr-r/r.rrrr*}s zPDeque.popleftcCs`|}|}xN|dkrV|s|rV|d8}|jr0|j}q |rD|}t}q |j}t}q W||fS)Nrr)restr$r)r"r#r-new_primary_listnew_secondary_listrrrr+s  zPDeque._pop_listscCs|j o|j S)N)r r )rrrr _is_emptyszPDeque._is_emptycCst|tstSt|t|kS)N)rr NotImplementedtuple)rotherrrr__lt__s z PDeque.__lt__cCs&t|tstSt|t|kr"dSdS)NTF)rr r5r6)rr7rrr__eq__s  z PDeque.__eq__cCs tt|S)N)hashr6)rrrr__hash__szPDeque.__hash__cCs|jS)N)r )rrrr__len__szPDeque.__len__cCs(||j|j|\}}}t||||jS)z Return new deque with elem as the rightmost element. >>> pdeque([1, 2]).append(3) pdeque([1, 2, 3]) )_appendr r r r )relemr/r. new_lengthrrrappendsz PDeque.appendcCs(||j|j|\}}}t||||jS)z Return new deque with elem as the leftmost element. >>> pdeque([1, 2]).appendleft(3) pdeque([3, 1, 2]) )r=r r r r )rr>r.r/r?rrr appendleftszPDeque.appendleftcCsd|jdk rN|j|jkrN|jdkr*||dfSt||d\}}||||jfS||||jdfS)Nrr)r r r r+cons)rr"r#r>r2r3rrrr=s   zPDeque._appendcCs,d}x|D]}||}|d7}q W||fS)Nrr)rB)Zthe_listiterabler-r>rrr _extend_lists    zPDeque._extend_listc Cs`t||\}}|}|j|}|jdk rV||jkrV||j}t|||\}}||8}|||fS)N)r rDr r r+) rr"r#rCr2 extend_countr3Z current_lenZpop_lenrrr_extends  zPDeque._extendcCs.||j|j|\}}}t|||j||jS)z Return new deque with all elements of iterable appended to the right. >>> pdeque([1, 2]).extend([3, 4]) pdeque([1, 2, 3, 4]) )rFr r r r r )rrCr.r/rErrrextendsz PDeque.extendcCs.||j|j|\}}}t|||j||jS)a Return new deque with all elements of iterable appended to the left. NB! The elements will be inserted in reverse order compared to the order in the iterable. >>> pdeque([1, 2]).extendleft([3, 4]) pdeque([4, 3, 1, 2]) )rFr r r r r )rrCr/r.rErrr extendlefts zPDeque.extendleftcCs|j||j|S)z Return the number of elements equal to elem present in the queue >>> pdeque([1, 2, 1]).count(1) 2 )r r-r )rr>rrrr-sz PDeque.countc Cs~yt|j||j|jdStk rxy$t|j|j||jdStk rrtd|YnXYnXdS)z Return new deque with first element from left equal to elem removed. If no such element is found a ValueError is raised. >>> pdeque([2, 1, 2]).remove(2) pdeque([1, 2]) rz{0} not found in PDequeN)r r remover r rr$r')rr>rrrrIsz PDeque.removecCst|j|j|jS)z Return reversed deque. >>> pdeque([1, 2, 3]).reverse() pdeque([3, 2, 1]) Also supports the standard python reverse function. >>> reversed(pdeque([1, 2, 3])) pdeque([3, 2, 1]) )r r r r )rrrrr$s zPDeque.reversecCs8||}|dkr&|t||S|t|| S)z Return deque with elements rotated steps steps. >>> x = pdeque([1, 2, 3]) >>> x.rotate(1) pdeque([3, 1, 2]) >>> x.rotate(-2) pdeque([3, 1, 2]) r)r0rHrr$rG)rZstepsZ popped_dequerrrrotate)s z PDeque.rotatecCstt||jffS)N)pdequer(r )rrrr __reduce__9szPDeque.__reduce__cCst|trz|jdk r4|jdkr4tt|||jdS|}|jdk rT||j|j}|j dk rv| |j|j |j}|St|t st dt |j|dkr||jSt||}|dkrtd|t|||jS)Nr)rz-'%s' object cannot be interpreted as an indexrz!pdeque index {0} out of range {1})rslicesteprKr6r startr*r stopr0rrtype__name__rlenr!r')rindexresultZshiftedrrr __getitem__=s$      zPDeque.__getitem__)N)r)r)(rR __module__ __qualname____doc__ __slots__rpropertyrr staticmethodrr%r)__str__rr0r*r+r4r8r9r;r<r@rAr=rDrFrGrHr-rIr$ __reversed__rJrLrVrrT __classcell__rr)rrr sB(                r rNcCsdt|}|dk r|| d}t|}t|d}t|d|}t||ddd}t||||S)a* Return deque containing the elements of iterable. If maxlen is specified then len(iterable) - maxlen elements are discarded from the left to if len(iterable) > maxlen. >>> pdeque([1, 2, 3]) pdeque([1, 2, 3]) >>> pdeque([1, 2, 3, 4], maxlen=2) pdeque([3, 4], maxlen=2) NT)r$)r6rSintrr )rCrtrZpivotrrrrrrK^s  rKcGst|S)z[ Return deque containing all arguments. >>> dq(1, 2, 3) pdeque([1, 2, 3]) )rK)elementsrrrdqqsrd)rN)Z_compatrr itertoolsrrZnumbersrZpyrsistent._plistrobjectr registerrKrdrrrrs  U