n9eYddlmZmZddlmZmZddlmZddlZddl m Z m Z ddl m Z e dd Zd Zd Zed z ZeeZd ZdZGddeZGdde eeZedeggZej3eej2eej2eddZ ddlZej8j;dreZn"ddlmZej3e edZ"y#e!$reZYdZ"ywxYw))abstractmethodABCMeta)SequenceHashable)IntegralN)TypeVarGeneric transformT_coT) covariantc6t|jdS)N1)bincount)vals 5/usr/lib/python3/dist-packages/pyrsistent/_pvector.py _bitcountr s s8>>#  cx||jt|tr|jS|SN)tolist isinstancePVector)votheroperators rcompare_pvectorr s- AHHJ*UG2L  XXRW XXrc"||St||Sr)slice)indexstops r_index_or_slicer%s |  rc$eZdZdZdZfdZdZdZdZdZ dZ d Z d Z d Z d Zd ZdZdZdZeZdZdZdZdZdZdZdZGddeZdZdZdZe dZ!dZ"dZ#d Z$d!Z%d"Z&d#Z'd$Z(d%Z)d&Z*d'Z+d*d(Z,d)Z-xZ.S)+ PythonPVectorzd Support structure for PVector that implements structural sharing for vectors using a trie. )_count_shift_root_tail _tail_offset __weakref__ctt| |}||_||_||_||_|jt|j z |_|Sr) superr'__new__r(r)r*r+lenr,)clsrshiftroottailself __class__s rr0zPythonPVector.__new__%sP]C05    !KK#djj/9 rc|jSr)r(r6s r__len__zPythonPVector.__len__0s {{rc"t|trL|j|j|j|St j |j|S|dkr||jz }tj|||tzSNr) rr"startr$step_EMPTY_PVECTORextendrr(r' _node_forBIT_MASKr6r#s r __getitem__zPythonPVector.__getitem__3s eU #{{"uzz'9ejj>P "((u)=> > 19 T[[ E&&tU3EH4DEErc$|j|Sr)r@r6rs r__add__zPythonPVector.__add__Cs{{5!!rcRdjt|jS)Nz pvector({0}))formatstrrr9s r__repr__zPythonPVector.__repr__Fs$$S%788rc"|jSr)rKr9s r__str__zPythonPVector.__str__Is}}rc4t|jSr)iterrr9s r__iter__zPythonPVector.__iter__LsDKKM""rc&|j| Sr)__eq__rFs r__ne__zPythonPVector.__ne__Qs;;u%%%rc||uxsCt|dxr|jt|k(xrt||tj S)Nr:)hasattrr(r1r reqrFs rrRzPythonPVector.__eq__Ts\u}H !:!Xt{{cRWj?X!H^mnrty|D|G|G_H Hrc8t||tjSr)r rgtrFs r__gt__zPythonPVector.__gt__WtUHKK88rc8t||tjSr)r rltrFs r__lt__zPythonPVector.__lt__ZrZrc8t||tjSr)r rgerFs r__ge__zPythonPVector.__ge__]rZrc8t||tjSr)r rlerFs r__le__zPythonPVector.__le__`rZrc|dks|turtS|dk(r|Stj||jzSNrr)r?r@rr6timess r__mul__zPythonPVector.__mul__cs> A:/! ! A:K$$UT[[]%:;;rcr|r$|tz}|D]}|j|||y|j|yr)SHIFT _fill_listr@)r6noder3the_listns rrkzPythonPVector._fill_listns;  UNE 45(3 4 OOD !rcg}|j|j|j||j|j|S)zK The fastest way to convert the vector into a python list. )rkr*r)r@r+)r6rms rrzPythonPVector.tolistvs6  DKK: #rc4t|jS)z8 Returns the content as a python tuple. )tuplerr9s r_totuplezPythonPVector._totuplesT[[]##rc4t|jSr)hashrrr9s r__hash__zPythonPVector.__hash__sDMMO$$rct||Srr r6transformationss rr zPythonPVector.transforms//rc0t|jffSr)pvectorrr9s r __reduce__zPythonPVector.__reduce__s(((rct|dzr td|j}tdt|dD]}||dz|||<|j S)Nz)mset expected an even number of argumentsrr)r1 TypeErrorevolverrange persistent)r6argsris rmsetzPythonPVector.msetsg t9q=GH H,,.q#d)Q' )A#AaCyGDG  )!!##rc^eZdZdZdZdZdZdZdZdZ dZ d Z d Z d Z d Zd ZdZy)PythonPVector.Evolver) r(r)r*r+r, _dirty_nodes _extra_tail _cached_leafs _orig_pvectorc&|j|yr)_resetr6rs r__init__zPythonPVector.Evolver.__init__s KKNrct|ts!tdt|jz|dkr%||j t |jzz }|j |cxkr%|j t |jzkrnn|j||j z Stj|||tzS)N-'%s' object cannot be interpreted as an indexr) rrr~type__name__r(r1rr'rArBrCs rrDz!PythonPVector.Evolver.__getitem__seX. ORVW\R]RfRf fggqys4+;+;'<<<{{eIdkkC8H8H4I&II'' (;<< **478HI Irc|j|_|j|_|j|_|j|_|j|_i|_i|_g|_||_yr) r(r)r*r+r,rrrrrs rrzPythonPVector.Evolver._resetsZ((DK((DKDJDJ !D  "D !#D !D !"D rc<|jj||Sr)rappend)r6elements rrzPythonPVector.Evolver.appends    # #G ,Krc<|jj||Sr)rr@)r6iterables rr@zPythonPVector.Evolver.extends    # #H -Krc|||<|Sr)r6r#rs rsetzPythonPVector.Evolver.setsDKKrc8t|ts!tdt|jz|dkr%||j t |jzz }d|cxkr|j krnn|jj|tz }|r |||tz<y||jk\rt|j|jvr\t!|j|_d|jt|j<|j|j|tz <||j|tz<y|j#|j$|j&|||_y|j |cxkr%|j t |jzkr nn||j||j z <y||j t |jzk(r|jj)|yt+d|)NrrTIndex out of range: )rrr~rrr(r1rrgetrjrBr,idr+rlist_do_setr)r*r IndexError)r6r#rrls r __setitem__z!PythonPVector.Evolver.__setitem__seX. ORVW\R]RfRf fggqys4+;+;'<<<E'DKK'))--eun=-0D)*d///$**~T->->>%)$**%5 <@))"TZZ.9=AZZ**5E>:36DJJux/0!%dkk4::uc!RDJK c$:J:J6K(KK8;  !45$++D,<,<(===  '', U!DEErc,t||jvr|}n#t|}d|jt|<|dk(r$|||tz<||j|t z <|S||z tz}|j |t z ||||||<|S)NTr)rrrrBrrjrr6levelrlrrret sub_indexs rrzPythonPVector.Evolver._do_sets$x4,,,4j-1!!"S'*z$'AL!14""1:. J%Z83 !%eemT)_aQT!UIJrc ||=|SrrrCs rdeletezPythonPVector.Evolver.deletesU Krc,|jr{t|j|j|j|j j }|j|j|jt||_|j|=yr) rr'r(r)r*r+rr@rrr?)r6keyls r __delitem__z!PythonPVector.Evolver.__delitem__sh!!!$++t{{DJJ SZZ\))* N+#$   %rc|j}|jr`t|j|j|j |j j|j}|j||Sr) ris_dirtyr'r(r)r*r+r@rr)r6results rrz PythonPVector.Evolver.persistentsY''F}}&t{{DKKTZZX__`d`p`pq F#MrcF|jt|jzSr)r(r1rr9s rr:zPythonPVector.Evolver.__len__s;;T%5%5!66 6rcHt|jxs |jSr)boolrrr9s rrzPythonPVector.Evolver.is_dirtys))=T-=-=> >rN)r __module__ __qualname__ __slots__rrDrrr@rrrrrrr:rrrrEvolverrsMF   J #    F4    &  7 ?rrc,tj|Sr)r'rr9s rrzPythonPVector.evolver s$$T**rc tt|ts!tdt|jz|dkr||j z }d|cxkr|j krnn||j k\rMt|j}|||tz<t|j |j|j|St|j |j|j|j|j|||jS||j k(r|j|Std|)Nrrr)rrr~rrr(r,rr+rBr'r)r*rrr)r6rrnew_tails rrzPythonPVector.set s !X&KdSTgN^N^^_ _ q5  A  DKK D%%% +),X&$T[[$++tzz8TT dkk4<< UYU_U_abdg;hjnjtjtu u  ;;s# #Q899rct|}|dk(r|||tz<|S||z tz}|j|tz ||||||<|Sr<)rrBrrjrs rrzPythonPVector._do_set%s\4j A: #CH   ex/I!\\%%-i!SQC N rcd|cxkr|jkr\nnY||jk\r |jS|j}t |j dt D]}|||z tz}|Std|)Nrr) r(r,r+r*rr)rjrBr) pvector_likerrlrs rrAzPythonPVector._node_for/s  'L'' 'L---#)))%%D|22Av> 5Q%Z834 5KQ899rcH|j}|jtz d|jzkDr?|j|j |j|j g}|tz }||fS|j |j|j|j }||fSNr)r)r(rjr* _new_pathr+ _push_tail)r6 new_shiftnew_roots r_create_new_rootzPythonPVector._create_new_root=sKK  KK5 Q$++%5 6 DNN4;; $KLH  I""t{{DJJ KH""rcBt|jtkrUt|j}|j |t |j dz|j|j|S|j\}}t |j dz|||gSr) r1r+ BRANCH_FACTORrrr'r(r)r*r)r6rrrrs rrzPythonPVector.appendIs} tzz?] *DJJ'H OOC  q$++tzz8T T#335)T[[1_iC5IIrcD|dk(r|S|j|tz |gSr<)rrj)r6rrls rrzPythonPVector._new_pathSs& A:Kuu}d344rcL|j\|_|_g|_yr)rr*r)r+r9s r_mutating_insert_tailz#PythonPVector._mutating_insert_tailYs "&"7"7"9 DK rctt|jz }||||z}|jj|t|}|xj|z c_||zSr)rr1r+r@r()r6offsetsequence max_delta_lendelta delta_lens r_mutating_fill_tailz!PythonPVector._mutating_fill_tail]sY%DJJ7  67 % J  y  !!rcd}t|}||krD|j||}t|jtk(r|j ||krD|j t|jz |_yr<)r1rr+rrr(r,)r6rr sequence_lens r_mutating_extendzPythonPVector._mutating_extendesk8} |#--fh?F4::-/**,|# !KK#djj/9rct|tr|jn t|}|r*|j |d}|j |dd|S|Sre)rr'rrrr)r6objr new_vectors rr@zPythonPVector.extendosR'sM:CJJLS  QqT*J  ' '!" .  rc6t|}|tk(r|j||S|jdz |z tz}t ||kDr"|j |tz |||||<|S|j|j|tz ||S)z if parent is leaf, insert node, else does it map to an existing child? -> node_to_insert = push node one more level else alloc new path return node_to_insert placed in copy of parent r)rrjrr(rBr1rr)r6rparent tail_noderrs rrzPythonPVector._push_tailzs6l E> JJy !JkkAo%/8; v; "!__UU]F9>%%-;< rcJ|jj|g|i|Sr)rr#r6valuerkwargss rr#zPythonPVector.indexs%"t{{}""5:4:6::rc@|jj|Sr)rrr6rs rrzPythonPVector.counts{{}""5))rcf|j}|t||=tj|Sr)rr%r?r@)r6r#r$rs rrzPythonPVector.deletes- KKM oeT* +$$Q''rcn|j}|j|tj|Sr)rremover?r@)r6rrs rrzPythonPVector.removes) KKM $$Q''rr)/rrr__doc__rr0r:rDrGrKrMrPrSrRrYr]r`rcrh__rmul__rkrrrrur r{robjectrrrr staticmethodrArrrrrrr@rr#rrr __classcell__)r7s@rr'r'sVI F "9# &H9999<H"$ %0)$n?&n?`+:0 : : #J5 ": .;*( (rr'ceZdZdZedZedZedZedZedZ edZ edZ ed Z ed Z ed Zed Zed ZedZeddZedZy)ra Persistent vector implementation. Meant as a replacement for the cases where you would normally use a Python list. Do not instantiate directly, instead use the factory functions :py:func:`v` and :py:func:`pvector` to create an instance. Heavily influenced by the persistent vector available in Clojure. Initially this was more or less just a port of the Java code for the Clojure vector. It has since been modified and to some extent optimized for usage in Python. The vector is organized as a trie, any mutating method will return a new vector that contains the changes. No updates are done to the original vector. Structural sharing between vectors are applied where possible to save space and to avoid making complete copies. This structure corresponds most closely to the built in list type and is intended as a replacement. Where the semantics are the same (more or less) the same function names have been used but for some cases it is not possible, for example assignments. The PVector implements the Sequence protocol and is Hashable. Inserts are amortized O(1). Random access is log32(n) where n is the size of the vector. The following are examples of some common operations on persistent vectors: >>> p = v(1, 2, 3) >>> p2 = p.append(4) >>> p3 = p2.extend([5, 6, 7]) >>> p pvector([1, 2, 3]) >>> p2 pvector([1, 2, 3, 4]) >>> p3 pvector([1, 2, 3, 4, 5, 6, 7]) >>> p3[5] 6 >>> p.set(1, 99) pvector([1, 99, 3]) >>> cy)z/ >>> len(v(1, 2, 3)) 3 Nrr9s rr:zPVector.__len__rcy)z Get value at index. Full slicing support. >>> v1 = v(5, 6, 7, 8) >>> v1[2] 7 >>> v1[1:3] pvector([6, 7]) NrrCs rrDzPVector.__getitem__rrcy)zm >>> v1 = v(1, 2) >>> v2 = v(3, 4) >>> v1 + v2 pvector([1, 2, 3, 4]) NrrFs rrGzPVector.__add__rrcy)zY >>> v1 = v(1, 2) >>> 3 * v1 pvector([1, 2, 1, 2, 1, 2]) Nrrfs rrhzPVector.__mul__rrcy)zo >>> v1 = v(1, 2, 3) >>> v2 = v(1, 2, 3) >>> hash(v1) == hash(v2) True Nrr9s rruzPVector.__hash__rrcy)a~ Create a new evolver for this pvector. The evolver acts as a mutable view of the vector with "transaction like" semantics. No part of the underlying vector i updated, it is still fully immutable. Furthermore multiple evolvers created from the same pvector do not interfere with each other. You may want to use an evolver instead of working directly with the pvector in the following cases: * Multiple updates are done to the same vector and the intermediate results are of no interest. In this case using an evolver may be a more efficient and easier to work with. * You need to pass a vector into a legacy function or a function that you have no control over which performs in place mutations of lists. In this case pass an evolver instance instead and then create a new pvector from the evolver once the function returns. The following example illustrates a typical workflow when working with evolvers. It also displays most of the API (which i kept small by design, you should not be tempted to use evolvers in excess ;-)). Create the evolver and perform various mutating updates to it: >>> v1 = v(1, 2, 3, 4, 5) >>> e = v1.evolver() >>> e[1] = 22 >>> _ = e.append(6) >>> _ = e.extend([7, 8, 9]) >>> e[8] += 1 >>> len(e) 9 The underlying pvector remains the same: >>> v1 pvector([1, 2, 3, 4, 5]) The changes are kept in the evolver. An updated pvector can be created using the persistent() function on the evolver. >>> v2 = e.persistent() >>> v2 pvector([1, 22, 3, 4, 5, 6, 7, 8, 10]) The new pvector will share data with the original pvector in the same way that would have been done if only using operations on the pvector. Nrr9s rrzPVector.evolverrrcy)aY Return a new vector with elements in specified positions replaced by values (multi set). Elements on even positions in the argument list are interpreted as indexes while elements on odd positions are considered values. >>> v1 = v(1, 2, 3) >>> v1.mset(0, 11, 2, 33) pvector([11, 2, 33]) Nr)r6rs rrz PVector.mset(rrcy)a Return a new vector with element at position i replaced with val. The original vector remains unchanged. Setting a value one step beyond the end of the vector is equal to appending. Setting beyond that will result in an IndexError. >>> v1 = v(1, 2, 3) >>> v1.set(1, 4) pvector([1, 4, 3]) >>> v1.set(3, 4) pvector([1, 2, 3, 4]) >>> v1.set(-1, 4) pvector([1, 2, 4]) Nr)r6rrs rrz PVector.set5rrcy)z Return a new vector with val appended. >>> v1 = v(1, 2) >>> v1.append(3) pvector([1, 2, 3]) Nr)r6rs rrzPVector.appendFrrcy)z Return a new vector with all values in obj appended to it. Obj may be another PVector or any other Iterable. >>> v1 = v(1, 2, 3) >>> v1.extend([4, 5]) pvector([1, 2, 3, 4, 5]) Nr)r6rs rr@zPVector.extendPrrcy)z Return first index of value. Additional indexes may be supplied to limit the search to a sub range of the vector. >>> v1 = v(1, 2, 3, 4, 3) >>> v1.index(3) 2 >>> v1.index(3, 3, 5) 4 Nrrs rr#z PVector.index[rrcy)z Return the number of times that value appears in the vector. >>> v1 = v(1, 4, 3, 4) >>> v1.count(4) 2 Nrrs rrz PVector.counthrrcy)a Transform arbitrarily complex combinations of PVectors and PMaps. A transformation consists of two parts. One match expression that specifies which elements to transform and one transformation function that performs the actual transformation. >>> from pyrsistent import freeze, ny >>> news_paper = freeze({'articles': [{'author': 'Sara', 'content': 'A short article'}, ... {'author': 'Steve', 'content': 'A slightly longer article'}], ... 'weather': {'temperature': '11C', 'wind': '5m/s'}}) >>> short_news = news_paper.transform(['articles', ny, 'content'], lambda c: c[:25] + '...' if len(c) > 25 else c) >>> very_short_news = news_paper.transform(['articles', ny, 'content'], lambda c: c[:15] + '...' if len(c) > 15 else c) >>> very_short_news.articles[0].content 'A short article' >>> very_short_news.articles[1].content 'A slightly long...' When nothing has been transformed the original data structure is kept >>> short_news is news_paper True >>> very_short_news is news_paper False >>> very_short_news.articles[0] is news_paper.articles[0] True Nrrws rr zPVector.transformrrrNcy)z Delete a portion of the vector by index or range. >>> v1 = v(1, 2, 3, 4, 5) >>> v1.delete(1) pvector([1, 3, 4, 5]) >>> v1.delete(1, 3) pvector([1, 4, 5]) Nr)r6r#r$s rrzPVector.deleterrcy)z Remove the first occurrence of a value from the vector. >>> v1 = v(1, 2, 3, 2, 1) >>> v2 = v1.remove(1) >>> v2 pvector([2, 3, 2, 1]) >>> v2.remove(1) pvector([2, 3, 2]) Nrrs rrzPVector.removerrr)rrrrrr:rDrGrhrurrrrr@r#rr rrrrrrrs5'R            - - ^                  6        rr) metaclassc,tj|S)z Create a new persistent vector containing the elements in iterable. >>> v1 = pvector([1, 2, 3]) >>> v1 pvector([1, 2, 3]) )r?r@)rs rpython_pvectorrs   **rPYRSISTENT_NO_C_EXTENSIONrzct|S)z Create a new persistent vector containing all parameters to this function. >>> v1 = v(1, 2, 3) >>> v1 pvector([1, 2, 3]) r)elementss rrrs 8 r)r)#abcrrcollections.abcrrnumbersrrtypingrr pyrsistent._transformationsr r rrrBrjr r%rr'rr?registerrosenvironrrzpvectorcr ImportErrorrrrrr s '.#1v& 1 (Y@(F@(D D gdmgD Nq%R0''+   zz~~12 $gi)  G s+AC33D?D