)uyc{ hddlZddlZddlZddlZddlZddlmZddlm Z ddlm Z ddl m Z m Z mZddlmZmZmZddlmZmZmZmZmZmZmZmZmZmZmZmZm Z m!Z!m"Z"ddl#m$Z$m%Z%dd l&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z, dd l-m.Z.m/Z/m0Z0m1Z1m2Z2m3Z3m4Z4m5Z5m6Z6m7Z7m8Z8m9Z9m:Z:m;Z;mZ>dd l#m?Z?m@Z@mAZAmBZBmCZCmDZDmEZEmFZFe=r4e4ee ege@fZGe4eHge.e1d e@ffZIe)dZJndZGdZIdZJn#eK$r e=sdZ:dZ;YnwxYwGdde6eAZLejMdkse=rejNe>ZOnGdde6e>ZOGdde6e@e?feOdZPGdde6e>ZQGddeQe>e6e>e@fZRdZSGddeRePe@e?fe@fZTd ZUd!ZVd"ZWd#ZXGd$d%ZYGd&d'eYZZGd(d)eYZ[Gd*d+eYZ\Gd,d-eYZ]Gd.d/eYZ^Gd0deYZ_d1Z` dTd3Zad4ZbejMdkse=rejj<eBe>fZcn Gd5d6ejj<e6e>eZcGd7d8e6e>ece>ZdGd9d:edeHeZeGd;deZfGd=d>efe>ZgGd?d@efeHeeZhGdAdBeYeeeZiGdCdDeiZjGdEdFeiZkGdGdHeYZle eeZZme ee^Zne e[e\Zoe e_eieijpIZqdJZreTe"eUe]edKerZseTe!eWe]eeerZteTe!eXe]eeerZudLZvdMZwdNZxdOZyd2d2dPdQdRZze{dSkrddl|Z|e|j}dSdS)UN)ABC) TracebackType) ReferenceType)combine_into_replacementBufferingIteratorlen_check_iterator)FormatterContentToken%one_value_per_line_trailing_separator format_field) Deb822TokenDeb822ValueToken'Deb822SemanticallySignificantWhiteSpaceDeb822SpaceSeparatorTokenDeb822CommentTokenDeb822WhitespaceTokenDeb822ValueContinuationTokenDeb822NewlineAfterValueTokenDeb822CommaTokenDeb822FieldNameTokenDeb822FieldSeparatorTokenDeb822ErrorTokentokenize_deb822_filecomma_split_tokenizerwhitespace_split_tokenizer)AmbiguousDeb822FieldKeyErrorSyntaxOrParseError) resolve_ref LinkedListLinkedListNode OrderedSet_strIdefault_field_sort_key)IterableIteratorListUnionDictOptionalCallableAnyGenericTypeTupleIOcastoverloadMapping TYPE_CHECKING)T)STVETE ParagraphKeyTokenOrElement CommentishParagraphKeyBaseFormatterCallbackr Deb822KeyValuePairElementc|SN)tvs >/usr/lib/python3/dist-packages/debian/_deb822_repro/parsing.pyrC5sAcdSr>r?)fs rBrCrC6sTrDc^eZdZdZdZdZdZedZej dZdZ dS) ValueReferenceafReference to a value inside a Deb822 paragraph This is useful for cases where want to modify values "in-place" or maybe conditionally remove a value after looking at it. ValueReferences can be invalidated by various changes or actions performed to the underlying provider of the value reference. As an example, sorting a list of values will generally invalidate all ValueReferences related to that list. The ValueReference will raise validity issues where it detects them but most of the time it will not notice. As a means to this end, the ValueReference will *not* keep a strong reference to the underlying value. This enables it to detect when the container goes out of scope. However, keep in mind that the timeliness of garbage collection is implementation defined (e.g., pypy does not use ref-counting). )_node_render_value_factory_removal_handler_mutation_notifiercptj||_||_||_||_||_dSr>)weakrefrefrIrJrKrLrM)selfnoderender value_factoryremoval_handlermutation_notifiers rB__init__zValueReference.__init__Os:[&&  + /"3rDc||jtd|}|td|S)Nz(Cannot use ValueReference after remove()z-ValueReference is invalid (garbage collected))rI RuntimeError)rQrRs rB _resolve_nodezValueReference._resolve_node\sA : IJJ Jzz|| <NOO O rDcZ||jS)z Resolve the reference into a str)rJrZvaluerQs rBr\zValueReference.valuegs%||D..006777rDc|||_|j|dSdS)aUpdate the reference value Updating the value via this method will *not* invalidate the reference (or other references to the same container). This can raise an exception of the new value does not follow the requirements for the referenced values. As an example, values in whitespace separated lists cannot contain spaces and would trigger an exception. N)rKrZr\rMrQ new_values rBr\zValueReference.valuemsO&*%8%8%C%C"  " .  # # % % % % % / .rDc~|td|d|_dS)zRemove the underlying value This will invalidate the ValueReference (and any other ValueReferences pointing to that exact value). The validity of other ValueReferences to that container remains unaffected. zLinkedListNode[TokenOrElement]N)rLr/rZrIr]s rBremovezValueReference.remove}s: d#CTEWEWEYEYZZ[[[ rDN) __name__ __module__ __qualname____doc__ __slots__rWrZpropertyr\setterrbr?rDrBrHrH9s$aI 4 4 4   88X8  \ & &\ &     rDrH) ceZdZdZdZdS)%_Deb822ParsedTokenList_ContextManagerc|Sr>r?r]s rB __enter__z/_Deb822ParsedTokenList_ContextManager.__enter__sKrDcdSr>r?)rQexc_typeexc_valexc_tbs rB__exit__z._Deb822ParsedTokenList_ContextManager.__exit__s4rDN)rcrdrerortr?rDrBrmrms2        rDrmceZdZdZdZdZfdZedZdZ dZ d#d Z d Z d Z d Zd ZdZdZdZdZedZdZdZdZdZ d$dZdZdZdZdZdZdddd Zdd!d"Z xZ!S)%Deb822ParsedTokenListc||_t||_||_||_||_||_t|||_||_ d|_ t|_ d|_ d|_|jsJ|jj}|0t!|t"r|jdSdSdS)NTF)_kvpair_elementr _token_list_vtype_stype_str2value_parser_default_separator_factory_parser_to_value_factoryrKrJ$_format_preserve_original_formattingr _formatter_changed._Deb822ParsedTokenList__continuation_line_chartail isinstancerpop) rQkvpair_elementinterpreted_value_elementvtypestypestr2value_parserdefault_separator_factoryrS last_tokens rBrWzDeb822ParsedTokenList.__init__s .%&?@@  !1*C'67GOO 481? (,%%*  !j=Y&Z&Z !   " " " " " " ! ! !rDc#>KfdjDEd{VdS)Nc3BK|]}|VdSr>)rJ.0rArQs rB z1Deb822ParsedTokenList.__iter__..s->>DLLOO>>>>>>rD) value_partsr]s`rB__iter__zDeb822ParsedTokenList.__iter__s<>>>>T-=>>>>>>>>>>>>rDc@tt|dduSr>)nextiterr]s rB__bool__zDeb822ParsedTokenList.__bool__sDJJ%%T11rDc||jr|t|||Sr>)r _update_fieldsuperrt)rQrqrrrs __class__s rBrtzDeb822ParsedTokenList.__exit__s@       ww'6:::rDc#>KfdjDEd{VdS)Nc3FK|]}t|j|VdSr>)rrzrs rBrz4Deb822ParsedTokenList.value_parts..s4NN!:a3M3MNANNNNNNrDryr]s`rBrz!Deb822ParsedTokenList.value_partss?ONNNt/NNNNNNNNNNNNrDcd|_dSNT)rr]s rB _mark_changedz#Deb822ParsedTokenList._mark_changeds  rDc#bKfdjDEd{VdS)aIterate over all values in the list (as ValueReferences) This is useful for doing inplace modification of the values or even streaming removal of field values. It is in general also more efficient when more than one value is updated or removed. c3K|]S}t|jjtt d|jjjjVTdS)zLinkedListNode[VE]N) rr\rzrHr/rJrK _remove_noder)rnrQs rBrz>Deb822ParsedTokenList.iter_value_references..s{  !'4;// N %q ) ) L               rDN)ry iter_nodesr]s`rBiter_value_referencesz+Deb822ParsedTokenList.iter_value_referencessk    #..00             rDTc|}|jrd}d|_||j||r0|js+|jt ddSdSdSNFT )r} is_whitespacer,_append_continuation_line_token_if_necessaryryappendr)rQspace_after_separatorseparator_tokens rBappend_separatorz&Deb822ParsedTokenList.append_separators99;;  ( *$) !  99;;; 000  @)F @   # #$9#$>$> ? ? ? ? ? @ @ @ @rDc|j}|jD]Y}t|j|rB||j|kr$|||_d|_dSZtd)zReplace the first instance of a value with another This method will *not* affect the validity of ValueReferences. Tz!list.replace(x, y): x not in listN) rzryrrr\rJrKr ValueError)rQ orig_valuer`rrRs rBreplacezDeb822ParsedTokenList.replaces  $//11 B BD$*e,, dj1I1IZ1W1W!00;; $ @AA ArDc|j}|jD]9}t|j|r"||j|kr|}n:t d||S)zRemove the first instance of a value Removal will invalidate ValueReferences to the value being removed. ValueReferences to other values will be unaffected. zlist.remove(x): x not in list)rzryrrr\rJrr)rQr\rrRnode_to_removes rBrbzDeb822ParsedTokenList.remove s $//11 > >D$*e,, dj1I1IU1R1R!%<== =  000rDcl|j}d|_d}d}d}d}|dD]<}|j}t |t r |jrd}(t ||r|}n=|dD]<} | j} t | t r | jrd}(t | |r| }n=|||j dS||sd} n ||sd} n|du} | r |} |j } n |j } |} | | |j_ | | |j_ tj| | dS)NTF skip_current)rzr iter_previousr\rr is_comment iter_nextryclear next_node previous_node head_node tail_noder link_nodes)rQrrfirst_value_on_lhsfirst_value_on_rhscomment_before_previous_valuecomment_before_next_value past_node past_token future_node future_tokendelete_lhs_of_nodefirst_remain_lhsfirst_remain_rhss rBrz"Deb822ParsedTokenList._remove_nodes  v"!(-%$)!'5545HH  I"J*k22 z7L 04-*e,, %." *333FF  K&,L, 44 9P ,0),.. %0"   %*<*D   " " $ $ $ F  )2O )!%    +4M +!&   "44!?   21 -7  -; 1   #)9D  &  #)9D  &!"24DEEEEErDcZ||}||dSr>)rK append_value)rQr\vts rBrzDeb822ParsedTokenList.appends/   ' ' "rDc|j}|r_d}|j}|j}t|D](}t ||rd}nt ||rn)|r|n'|jtd|d|_ ||dSr) ryr{rzreversedrrrrrr)rQrrneeds_separatorrrr@s rBrz"Deb822ParsedTokenList.append_values&  @#OKEKEk**  a''&*OEa''E (%%'''   # #$9#$>$> ? ? ? 99;;; 2rDcp|jj}|duo&|dSN )ryrconvert_to_textendswithrQrs rB_previous_is_newlinez*Deb822ParsedTokenList._previous_is_newlines7$4ID$8$8$:$:$C$CD$I$IIrDc|rtd|jt dS)Nz9Cannot add a newline after a token that ends on a newline)rrryrrr]s rBappend_newlinez$Deb822ParsedTokenList.append_newlinesJ  $ $ & & ZXYY Y  < > >?????rDc|jj}|'|ds|t t |}|j|dSr)ryrrrrr_format_commentr)rQ comment_textr comment_tokens rBappend_commentz$Deb822ParsedTokenList.append_commentst$ >tDD<    ! ! !*?<+H+HII   .....rDcz|j}|1d}|jD] }t|tr |j}n!||_|SNr)rryrrtext)rQchartokens rB_continuation_line_charz-Deb822ParsedTokenList._continuation_line_chars[, <D)  e%ABB :DE-1D ) rDc|jj}|U|dr0|jt |jdSdSdSr)ryrrrrrrrs rBrzBDeb822ParsedTokenList._append_continuation_line_token_if_necessarysi$   4 4 6 6 ? ? E E    # #$@A]$^$^ _ _ _ _ _    rDc<|d|_dSr)_enable_reformattingrr]s rBreformat_when_finishedz,Deb822ParsedTokenList.reformat_when_finisheds !!### rDcd|_dS)NFrr]s rBrz*Deb822ParsedTokenList._enable_reformattings49111rDcd|_dSrrr]s rBno_reformatting_when_finishedz3Deb822ParsedTokenList.no_reformatting_when_finisheds48111rDFc8||_d|_|r d|_dSdS)alUse a custom formatter when formatting the value :param formatter: A formatter (see debian._deb822_repro.formatter.format_field for details) :param force_reformat: If True, always reformat the field even if there are no (other) changes performed. By default, fields are only reformatted if they are changed. FTN)rrr)rQ formatterforce_reformats rBvalue_formatterz%Deb822ParsedTokenList.value_formatters0$491  ! DMMM ! !rDcT|jrd|_|jdS)zGLike list.clear() - removes all content (including comments and spaces)TN)ryrrr]s rBrzDeb822ParsedTokenList.clears1   ! DM      rDc#K|jD]6}t|tr|Ed{V2|V7dSr>)ryr Deb822Element iter_tokens)rQtes rB_iter_content_as_tokensz-Deb822ParsedTokenList._iter_content_as_tokenssd"  B"m,, >>++++++++++   rDc|}|j|j|jfd}t |j|jjtj |j |S)Nc3^Kd}D]}t|trQ|jrtj|jV:t|r|j}tj|Vht|sJ|}tj|VdS)N) rr rr rrrr value_token)rrr token_listrs rB _token_iterzNDeb822ParsedTokenList._generate_reformatted_field_content.._token_itersD B Bb+.. B}J3A"'JJJJJJ#B..J!w3CDIIIII%b%00000--//D/;DAAAAAA B BrD) r}rzr{ryr rrx field_namer rr)rQrrrrrs @@@rB#_generate_reformatted_field_contentz9Deb822ParsedTokenList._generate_reformatted_field_contents99;;  %  B B B B B B BDO 0;1A/BVWW'KMM rDcddd|DS)Nrc3$K|] }|jV dSr>rrr@s rBrz@Deb822ParsedTokenList._generate_field_content..s$FF!qvFFFFFFrD)joinrr]s rB_generate_field_contentz-Deb822ParsedTokenList._generate_field_contents/wwFFt'C'C'E'EFFFFFFrDc|j}|j}|j}|j}d}|D]}d}|js |jsn|rtd|t|tr|jrtd| ds| |j r,|}d||f}n|}|d} n|dzg} t%t'| } | } | rtd |zt+t'| } t| t,sJ| |} | J| j|_d|_dS) NFTzUField must be completely empty or have content (i.e. non-whitespace and non-comments)z Fields must not end on a commentr:keependsz: $Syntax error in new field value for )rxrryrrrrrrr rrrrrrr splitlinesparse_deb822_filerfind_first_error_elementr'Deb822NoDuplicateFieldsParagraphElementget_kvpair_element value_elementr)rQrrrr had_tokensr@ value_textr new_content deb822_file error_token paragraphnew_kvpair_elements rBrz#Deb822ParsedTokenList._update_field s-#. %  --// K KAJ<   K "JKKK  $ ,, E E !CDDD''))22488 &##%%%8 B!99;; xxZ 899??AA//4/88KK &-.K([(9(9:: !::<<  RCjPQQ Qk**++ )%LMMMMM&99*EE!---'9'G$ rDNkeyreversec d}|j}|j fd}g}|jD]}|j}t |t r |jr||}*t ||rVg} |9|dD]"} | |urn| | j#| || fd}| ||d|_ |j d} | j} |D]\}} | r'd} | r" fd| D} |nq| s1t! fd| Ds|d | r|n'|j t%d |j| ||dS) a^Sort the elements (abstract values) in this list. This method will sort the logical values of the list. It will attempt to preserve comments associated with a given value where possible. Whether space and separators are preserved depends on the contents of the field as well as the formatting settings. Sorting (without reformatting) is likely to leave you with "awkward" whitespace. Therefore, you almost always want to apply reformatting such as the reformat_when_finished() method. Sorting will invalidate all ValueReferences. Nc^r|dS|dSNrr)xrs rBkey_funcz5Deb822ParsedTokenList.sort_elements..key_funchs3 !s1Q4yy Q4'')) )rDFrrTc4g|]}t||Sr?rrr!rs rB z7Deb822ParsedTokenList.sort_elements..s(PPPa:a;O;OPPPPrDc38K|]}t|VdSr>r$r%s rBrz6Deb822ParsedTokenList.sort_elements..s-5]5]qjE6J6J5]5]5]5]5]5]rD)rr)rzr{ryrr\rr rrrsortrrr}rranyrrextendr)rQrrcomment_start_noderr"partsrRr\comments keep_node first_valueseparator_is_spacers ` @rB sort_elementsz#Deb822ParsedTokenList.sort_elementsRsp$"   * * * * * $//11 * *DJE%-- %2B %-)-&%'' *%1%7%A%Au%A%U%U99 $,,!E  8888 eX.///%)" x 111      !<<>>L$ % %OE8 H# * QPPP8PPPH''))))G#5]5]5]5]T\5]5]5]2]2]G )))FFFH''))))$++,A#,F,FGGG   # #H - - -   e $ $ $ $/ % %rDrc H|jfd|d<|jdi|dS)a\Sort the values (rendered as str) in this list. This method will sort the logical values of the list. It will attempt to preserve comments associated with a given value where possible. Whether space and separators are preserved depends on the contents of the field as well as the formatting settings. Sorting (without reformatting) is likely to leave you with "awkward" whitespace. Therefore, you almost always want to apply reformatting such as the reformat_when_finished() method. Sorting will invalidate all ValueReferences. Nc,|Sr>r?)rrrSs rBrCz,Deb822ParsedTokenList.sort..sss66"::rDrr?)rJr1)rQrkwargsrSs ` @rBr(zDeb822ParsedTokenList.sortsF& ?\F66666F5M$$V$$$$$rDTF)"rcrdrerWrrrtrhrrrrrrbrrrrrrrrrrrrrrrrrr1r( __classcell__rs@rBrvrvsI!#!#!#F???222;;;;;OOXO   $ @ @ @ @ B B B111"rFrFrFh .JJJ @@@ ///  X ```  :::999 (-!!!!$!!!8GGG000f#N%N%N%N%N%d%%%%%%%%%rDrvzDeb822ParsedTokenList[VE, ST]ceZdZ ddZdS)InterpretationTctr>NotImplementedError)rQrdiscard_comments_on_reads rB interpretzInterpretation.interpret "!rDNr6)rcrdrer@r?rDrBr;r;s-,0""""""rDr;cDeZdZfdZ ddZdZdZdZ ddZxZ S) !GenericContentBasedInterpretationcdt||_||_dSr>)rrW _tokenizer _value_parser)rQ tokenizer value_parserrs rBrWz*GenericContentBasedInterpretation.__init__s0 #)rDTctr>r=rQrrr?s rB_high_level_interpretationz)rFrr )rQbuffered_iteratorrHrs rB _parse_streamz/GenericContentBasedInterpretation._parse_streamsc ) &  E%!122 "l5*;<<<<<<   rDc#rK|j}||Ed{VdSr>)rr _parse_str)rQkvpaircontents rB _parse_kvpairz/GenericContentBasedInterpretation._parse_kvpairsF &6688??7+++++++++++rDc#Kt|}tt||||}t||||Ed{VdS)N) content_len)lenrrrErO)rQrSrVbiters rBrQz,GenericContentBasedInterpretation._parse_strs'll !"4W59__W5M5MAL#O#O#OPP&g&*&8&8&?&?2=((( ( ( ( ( ( ( ( ( (rDcg}|||||||SN)r?)r*rTrK)rQrr?rs rBr@z+GenericContentBasedInterpretation.interpretsP  $,,^<<===..~/9H`/11 1rDr6) rcrdrerWrKrOrTrQr@r8r9s@rBrCrCs*****=A""""   ,,, ( ( (,0 1 1 1 1 1 1 1 1rDrCcfd}|S)Nc|dkrtdt|}t|d}t|d}|Jd|zdz|7tjd|}t|t |s^t |tr|js|j rtdd}t||j | t| t|ksKJd t| t| |S) NrzThe empty string is not a valuez.Bad parser - it returned None (or no TE) for ""z The input "{v}" should have been exactly one element, but the parser provided at least two. This can happen with unnecessary leading/trailing whitespace or including commas the value for a comma list. rAz._value_factorys 77>?? ?&&))__ *d # # *d # #~~ORSSVYY~~~ >/#!  S// !"e$$ P"k** a  aAQ a !_```.CSZZ!2ZNNOO O2%%''((CFF222 ,,2F2--//00A-3--322  rDr?)rirrKs`` rBr~r~s*: rDc(eZdZfdZ ddZxZS)ListInterpretationct||||_||_||_||_dSr>)rrWrzr{r}_render_factory)rQrGrHrrrrender_factoryrs rBrWzListInterpretation.__init__*sC L111  *C'-rDTc zt|||j|j|j|j||Sr>)rvrzr{rQr}rmrJs rBrKz-ListInterpretation._high_level_interpretation9sC %   K K O  +  !9 : :   rDr6)rcrdrerWrKr8r9s@rBrkrk(sR . . . . .$=A        rDrkc"t|gSr>)Deb822ParsedValueElement)r_s rB_parse_whitespace_list_valuersJs #UG , ,,rDc,t|tSr>)rrr^s rB_is_comma_tokenruOs a) * **rDc|t}|g}|,|||dz n'|||rLt |dt s1||rt |dt 1|t|dz t|S)N) peek_findrur* peek_many peek_bufferrr r consume_manyrWrq)rrN comma_offsetrs rB_parse_comma_list_valuer~Us$..??L'K,66|a7GHHIIII ,88::;;; jR:JKK jR:JKK""3{#3#3a#7888 #K 0 00rDcb|g}d}||t}|Y|dg}|||dz d}t |dz }|dkr||}t |t r|jdr|| |t |dt r |djdsJdt|zd}n |dz}|dk|rn|| |t |dtsJn| }t |}|||rQt |dt s6| |dz}|rt |dt 6| ||t|S)NrxrwFr>zGot: T)ryrur*rzrWrr rrr|strrr{rrq) rrNrr}peeked_elementscomma_was_separatoriremaining_partconsume_elementss rB_parse_uploaders_list_valuergsg 'KL  "(22?CC  # +2/O  " "#4#>#>|a?O#P#P Q Q Q"' O$$q(Aq&&'*e%566z**3//3#**+<+I+I!+L+LMMM)+b/;KLL^*23<22    ~ . . . &jRBR&S&S &!!! A%  &jRBR&S&S &  * *+; < < )rr]s rBrWzDeb822Element.__init__s#rDctr>r=r]s rB iter_partszDeb822Element.iter_parts!!rDc#`K|D]}t||r|VdSr>)rrrQonly_element_or_token_typeparts rBiter_parts_of_typez Deb822Element.iter_parts_of_typesFOO%%  D$ :;;    rDc#K|D]?}|jJt|tr|Ed{V;|V@dSr>)rrrrrrQrs rBrzDeb822Element.iter_tokenss|OO%%  D'333$ .. ++----------   rDNrc#K|D]W}|t||rtd|Vt|tr||Ed{VXdS)Nr6r)rrr/r iter_recursers rBrzDeb822Element.iter_recursesOO%% d dD)1ZF`5a5a14&&&&&$ .. d,,Hb,ccccccccc  d drDc*t|jSr>)rrr]s rBparent_elementzDeb822Element.parent_elements4/000rDc@|tj|nd|_dSr>)rOrPr)rQ new_parents rBrzDeb822Element.parent_elements(;E:Pw{:666VZrDcB|D] }||_ dSr>)rrrs rB_init_parent_of_partsz#Deb822Element._init_parent_of_partss0OO%% ' 'D"&D   ' 'rDcddd|DS)Nrc3$K|] }|jV dSr>rrs rBrz0Deb822Element.convert_to_text..s$::!qv::::::rDrrr]s rBrzDeb822Element.convert_to_texts/ww::t'7'7'9'9::::::rDc*||jur d|_dSdSr>)rr)rQparents rBclear_parent_if_parentz$Deb822Element.clear_parent_if_parents& T( ( (#'D  ) (rD)rcrdrerfrgrWrrrrrhrrirrrr?rDrBrrs;;2I$$$""" 15ddddd11X1[[[''' ;;;(((((rDrc,eZdZdZdZfdZdZxZS)Deb822ErrorElementa|Element representing elements or tokens that are out of place Commonly, it will just be instances of Deb822ErrorToken, but it can be other things. As an example if a parser discovers out of order elements/tokens, it can bundle them in a Deb822ErrorElement to signal that the sequence of elements/tokens are invalid (even if the tokens themselves are valid). _partsc~t||_|dSr>)rrWrr)rQr,rs rBrWzDeb822ErrorElement.__init__s8   ""$$$$$rDc#$K|jEd{VdSr>rr]s rBrzDeb822ErrorElement.iter_partss&;rD)rcrdrerfrgrWrr8r9s@rBrrsXI%%%%% rDrceZdZdZdZfdZedZedZedZ dZ dZ d Z d Z d ZxZS) Deb822ValueLineElementz!Consists of one "line" of a value)_comment_element_continuation_line_token_leading_whitespace_token _value_tokens_trailing_whitespace_token_newline_tokenct||td||_||_||_||_||_||_| dS)Nz)Only continuation lines can have comments) rrWrrrrrrrr)rQcomment_elementcontinuation_line_tokenleading_whitespace_tokenrtrailing_whitespace_token newline_tokenrs rBrWzDeb822ValueLineElement.__init__s   &+B+JHII I /(?% $ &(*C'+ ""$$$$$rDc|jSr>rr]s rBrz&Deb822ValueLineElement.comment_element  $$rDc|jSr>)rr]s rBrz.Deb822ValueLineElement.continuation_line_tokens ,,rDc|jSr>)rr]s rBrz$Deb822ValueLineElement.newline_token ""rDcV|j!t|_||j_dSdSr>)rrrr]s rBadd_newline_if_missingz-Deb822ValueLineElement.add_newline_if_missings2   &">"@"@D 15D  . . . ' &rDc#hK|jr |jV|jEd{V|jr |jVdSdSr>)rrrr]s rB_iter_content_partsz*Deb822ValueLineElement._iter_content_parts se  ) 10 0 0 0%%%%%%%%  * 21 1 1 1 1 1 2 2rDc#K|D]6}t|tr|Ed{V2|V7dSr>)rrrrrs rB_iter_content_tokensz+Deb822ValueLineElement._iter_content_tokens(so,,..  D$ .. ++----------   rDct|jdkr@|js9|js2t |jdt r|jdjSdd|DS)Nrwrrc3$K|] }|jV dSr>rrs rBrzADeb822ValueLineElement.convert_content_to_text..;s$CC!qvCCCCCCrD) rWrrrrr rrrr]s rBconvert_content_to_textz.Deb822ValueLineElement.convert_content_to_text0s t! " "a ' '6 (7 (t1!4kBB (%a(- -wwCCt'@'@'B'BCCCCCCrDc#K|jr |jV|jr |jV|Ed{V|jr |jVdSdSr>)rrrrr]s rBrz!Deb822ValueLineElement.iter_parts=s   (' ' ' '  ( 0/ / / /++---------   &% % % % % % & &rD)rcrdrerfrgrWrhrrrrrrrrr8r9s@rBrrs++RI%%%%%.%%X%--X-##X#666 222 D D D&&&&&&&rDrcDeZdZdZfdZedZdZdZxZ S)Deb822ValueElement_value_entry_elementsc~t||_|dSr>)rrWrr)rQvalue_entry_elementsrs rBrWzDeb822ValueElement.__init__Ks9 %9" ""$$$$$rDc|jS)zRead-only list of value entriesrr]s rB value_lineszDeb822ValueElement.value_linesQs ))rDc#$K|jEd{VdSr>rr]s rBrzDeb822ValueElement.iter_partsWs'----------rDcV|jr!|jddSdS)Nrx)rrr]s rBadd_final_newline_if_missingz/Deb822ValueElement.add_final_newline_if_missing[s:  % D  &r * A A C C C C C D DrD) rcrdrergrWrhrrrr8r9s@rBrrHs}*I%%%%% **X* ...DDDDDDDrDrc8eZdZdZfdZfdZdZdZxZS)rq) _text_cached_text_no_comments_cachedryct||_|t |dt rt |dt st |jjdzt|dkr"|d}|j |_ |j |_ dSd|_ d|_ dS)Nrrxz) MUST start and end on a Deb822ValueTokenrw) rrWryrrr rrrcrWrrr)rQtokensrrs rBrWz!Deb822ParsedValueElement.__init__es ! ""$$$&)%566 dvbz+;<< dT^47bbcc c v;;!  1IE % D ,1JD ) ) ) $D ,0D ) ) )rDcj|j%t|_|jSr>)rrr)rQrs rBrz(Deb822ParsedValueElement.convert_to_textus-  ( 0,1GG,C,C,E,ED ),,rDc|j6dd|D|_|jS)Nrc32K|]}|j |jVdSr>rrrs rBrzLDeb822ParsedValueElement.convert_to_text_without_comments..~sH4I4I89;<<4IAF4I4I4I4I4I4IrD)rrrr]s rB convert_to_text_without_commentsz9Deb822ParsedValueElement.convert_to_text_without_comments{s[  ( 0,.GG4I4I=A=M=M=O=O4I4I4I-I-ID ),,rDc#$K|jEd{VdSr>rr]s rBrz#Deb822ParsedValueElement.iter_partss'##########rD) rcrdrergrWrrrr8r9s@rBrqrqastKI11111 ----- ---$$$$$$$rDrqc4eZdZdZfdZdZdZdZxZS)Deb822CommentElement_comment_tokensct||_|std|dS)Nz5Comment elements must have at least one comment token)rrWrrr)rQcomment_tokensrs rBrWzDeb822CommentElement.__init__sQ - VTUU U ""$$$$$rDc*t|jSr>)rWrr]s rB__len__zDeb822CommentElement.__len__s4'(((rDc|j|Sr>rrQitems rB __getitem__z Deb822CommentElement.__getitem__s#D))rDc#$K|jEd{VdSr>rr]s rBrzDeb822CommentElement.iter_partss'''''''''''rD) rcrdrergrWrrrr8r9s@rBrrsj$I%%%%%)))***(((((((rDrceZdZdZfdZedZedZedZej dZ d dZ ed Z e j d Z d Z xZ S) r<r _field_token_separator_token_value_elementct||_||_||_||_|dSr>)rrWrrrrr)rQr field_tokenrrrs rBrWz"Deb822KeyValuePairElement.__init__sS  /' /+ ""$$$$$rDc|jjSr>)rrr]s rBrz$Deb822KeyValuePairElement.field_names$$rDc|jSr>)rr]s rBrz%Deb822KeyValuePairElement.field_tokens   rDc|jSr>)rr]s rBrz'Deb822KeyValuePairElement.value_elementrrDcV|j|||_||_dSr>)rrrr_s rBrz'Deb822KeyValuePairElement.value_elements1 224888'#'    rDTc0|||SrZ)r@)rQ interpreterr?s rB interpret_asz&Deb822KeyValuePairElement.interpret_ass $$TD\$]]]rDc|jSr>rr]s rBrz)Deb822KeyValuePairElement.comment_elementrrDc|/|djdstd|jr|j||||_||_dS)Nrxrz&Field comments must end with a newline)rrrrrr)rQr\s rBrz)Deb822KeyValuePairElement.comment_elementst  9>**400 K !IJJJ   ?  ! 8 8 > > >  #'E %rDc#`K|jr |jV|jV|jV|jVdSr>rr]s rBrz$Deb822KeyValuePairElement.iter_partssS   (' ' ' '####!!!!!!rDr6)rcrdrergrWrhrrrrirrrr8r9s@rBr<r<sZI % % % % %%%X%!!X!##X#(((/3^^^^%%X% & & &"""""""rDc|dkrdSd|ddvrtd|ds|dz}|dsd|z}|S)Nrz# rrxz-Comment lines must not have embedded newlines#z# )rrrstrip startswithlstrip)cs rBrrsBwwu q"v~~HIII ::d   HHJJ  <<   188::  HrDFc(d}d}t|trE|\}}|r.|dkr&d}t|||d}t |}n0d}t|t r |}|j}nt |}|||fS)NrzECannot resolve key "{key}" with index {index}. The key is not indexedrindex)rtupleKeyErrorrer!rr)rraise_if_indexedr name_tokenrrhs rB _unpack_keyr s EJ$ U  zz]szzcz??@@@ECjj d0 1 1 J/CC++C z !!rDc#K|sd|DEd{VdS|D]5}dd|DV6dS)Nc3>K|]}|VdSr>r )rrAs rBrz0_convert_value_lines_to_lines..s.==AA%%''======rDrc32K|]}|j |jVdSr>rrr!s rBrz0_convert_value_lines_to_lines..s>//Q!"/!&//////rDr)rstrip_commentselements rB_convert_value_lines_to_linesrs /==============" / /G''//'*=*=*?*?///// / / / / / /rDceZdZdS)_ParagraphMapping_BaseN)rcrdrer?rDrBrr"s rDrc^eZdZedZedZdZdZdZdZ dZ dZ d S) AutoResolvingMixincdSrr?r]s rB_auto_resolve_ambiguous_fieldsz1AutoResolvingMixin._auto_resolve_ambiguous_fields+ trDctr>r=r]s rB _paragraphzAutoResolvingMixin._paragraph0 "!rDc|jjSr>)r kvpair_countr]s rBrzAutoResolvingMixin.__len__5s ++rDc6|j|Sr>)rcontains_kvpair_elementrs rB __contains__zAutoResolvingMixin.__contains__9s66t<<)rr iter_keysr]s rBrzAutoResolvingMixin.__iter__=sDO--//000rDc|jr2t|tr|j|df}n|j|}|J|||Sr)rrrrr_interpret_value)rQrrAs rBrzAutoResolvingMixin.__getitem__Asm  . 9:dC3H3H 922D!9==AA22488A}}}$$T1---rDc:|j|dSr>)rremove_kvpair_elementrs rB __delitem__zAutoResolvingMixin.__delitem__Js --d33333rDctr>r=rQrr\s rBr$z#AutoResolvingMixin._interpret_valueNrrDN) rcrdrerhrrrr rrr'r$r?rDrBrr)s X""X",,,===111...444"""""rDrcxeZdZedZedZedZedZdZdZ dZ dS) Deb822ParagraphToStrWrapperMixincdSrr?r]s rB!_auto_map_initial_line_whitespacezBDeb822ParagraphToStrWrapperMixin._auto_map_initial_line_whitespaceYrrDcdSrr?r]s rB_discard_comments_on_readz:Deb822ParagraphToStrWrapperMixin._discard_comments_on_read^rrDcdSrr?r]s rB+_auto_map_final_newline_in_multiline_valueszLDeb822ParagraphToStrWrapperMixin._auto_map_final_newline_in_multiline_valuescrrDcdSrr?r]s rB)_preserve_field_comments_on_field_updateszJDeb822ParagraphToStrWrapperMixin._preserve_field_comments_on_field_updateshrrDc|j}|j}t|dkr9|d}|}|jr|}|S|js|jrMt||j}|jdfdt|dD}n|}|j r|ddkr |dd}|S)Nrwrrc3`K|](\}}r|dkr|dzn|V)dS)rwrN)strip)rrlineauto_map_spaces rBrzIDeb822ParagraphToStrWrapperMixin._convert_value_to_str..s\  ")!T6DXQdjjllT11TX      rDstartrxr) rrrWrr-r6r/rr enumerater1) rQrr value_entries value_entryr@ converteras_textr8s @rB_convert_value_to_strz6Deb822ParagraphToStrWrapperMixin._convert_value_to_strms&4 %1 }   " "(*K++--A5 GGIIH  1 6T5S 65m6:6T88I"CNgg    -6y-J-J-J     GG $3355G  ; # t@S@ScrclGrDc|j}d}|rI|jrBd}|}t|tr|df}|j|d}||j}|jr |d}n#t$rd}YnwxYw|dks|t|kr2|j || ||dS| dd\}} |r8|dddvr,d d | d| f}nd |d| f}|ds|jstd |dz }|j||||dS) NrTuse_getrrxpreserve_original_field_comment field_commentrw) rrrzeValues must end with a newline (or be single line values and use the auto whitespace mapping feature))r3rrrrrrr-rrrWset_field_to_simple_valuer6splitrrr1set_field_from_raw_string) rQrr\ keep_commentscomment key_lookup orig_kvpairidx first_linerests rB __setitem__z,Deb822ParagraphToStrWrapperMixin.__setitem__sF   6T@ 6 !MJ$$$ '"AY /<)r@r)s rBr$z1Deb822ParagraphToStrWrapperMixin._interpret_values))%000rDN) rcrdrerhr-r/r1r3r@rRr$r?rDrBr+r+VsXXXXB. . . `11111rDr+c^eZdZddddZedZedZedZdS) AbstractDeb822ParagraphWrapperFTauto_resolve_ambiguous_fieldsr?c0||_||_||_dSr>)*_AbstractDeb822ParagraphWrapper__paragraph>_AbstractDeb822ParagraphWrapper__auto_resolve_ambiguous_fields9_AbstractDeb822ParagraphWrapper__discard_comments_on_read)rQrrWr?s rBrWz'AbstractDeb822ParagraphWrapper.__init__s"%/L,*B'''rDc|jSr>)rYr]s rBrz)AbstractDeb822ParagraphWrapper._paragraphs rDc|jSr>)r[r]s rBr/z8AbstractDeb822ParagraphWrapper._discard_comments_on_reads ..rDc|jSr>)rZr]s rBrz=AbstractDeb822ParagraphWrapper._auto_resolve_ambiguous_fieldss 33rDN)rcrdrerWrhrr/rr?rDrBrUrUs 05*. C C C C C  X //X/44X444rDrUc,eZdZdddfd ZdZxZS)"Deb822InterpretingParagraphWrapperFTrVc^t|||||_dSNrV)rrW_interpretation)rQrinterpretationrWr?rs rBrWz+Deb822InterpretingParagraphWrapper.__init__s> 7T2J     .rDc6|j|Sr>)rcr@r)s rBr$z3Deb822InterpretingParagraphWrapper._interpret_values#--e444rD)rcrdrerWr$r8r9s@rBr`r`sY 05*. . . . . . . .5555555rDr`cneZdZddddddfd ZedZedZedZxZS)Deb822DictishParagraphWrapperTFr? auto_map_initial_line_whitespacerW(preserve_field_comments_on_field_updates*auto_map_final_newline_in_multiline_valuesczt|||||_||_||_dSrb)rrW@_Deb822DictishParagraphWrapper__auto_map_initial_line_whitespaceH_Deb822DictishParagraphWrapper__preserve_field_comments_on_field_updatesJ_Deb822DictishParagraphWrapper__auto_map_final_newline_in_multiline_values)rQrr?rirWrjrkrs rBrWz&Deb822DictishParagraphWrapper.__init__sR 7T2J    3S/:b7 6 999rDc|jSr>)rmr]s rBr-z?Deb822DictishParagraphWrapper._auto_map_initial_line_whitespace s 66rDc|jSr>)rnr]s rBr3zGDeb822DictishParagraphWrapper._preserve_field_comments_on_field_updatess >>rDc|jSr>)ror]s rBr1zIDeb822DictishParagraphWrapper._auto_map_final_newline_in_multiline_valuess @@rD) rcrdrerWrhr-r3r1r8r9s@rBrgrgs +/26/4:><@7777777&77X7??X?AAXAAAAArDrgcHeZdZedZedZedZedZdddZ ddddddd Z ed Z d Z d Z d ZdZedZdZdZ ddZdZdZ ddZddddZddddZedZedZ ddZdS) Deb822ParagraphElementc:tgtSr>)rr clss rBnew_empty_paragraphz*Deb822ParagraphElement.new_empty_paragraphs7r:<<HHHrDcl|}|D] \}}|||< |Sr>)rxitems)rwmappingrkrAs rB from_dictz Deb822ParagraphElement.from_dict#sA++-- MMOO  DAqIaLLrDc|stdtd|D}t|t|krt||St |S)Nz9A paragraph must consist of at least one field/value pairc3$K|] }|jV dSr>rrkvs rBrz6Deb822ParagraphElement.from_kvpairs..0s$!J!JB"-!J!J!J!J!J!JrD)rr rWr%Deb822DuplicateFieldsParagraphElement)rwkvpair_elements kvpair_orders rB from_kvpairsz#Deb822ParagraphElement.from_kvpairs+su ZXYY Y!!J!J/!J!J!JJJ |  O 4 4 4 4;?LYY Y5_EEErDcdS)z0Tell whether this paragraph has duplicate fieldsFr?r]s rBhas_duplicate_fieldsz+Deb822ParagraphElement.has_duplicate_fields:s urDTrWc&t|||S)a Provide a Dict-like view of the paragraph This method returns a dict-like object representing this paragraph and is useful for accessing fields in a given interpretation. It is possible to use multiple versions of this dict-like view with different interpretations on the same paragraph at the same time (for different fields). >>> example_deb822_paragraph = ''' ... Package: foo ... # Field comment (because it becomes just before a field) ... Architecture: amd64 ... # Inline comment (associated with the next line) ... i386 ... # We also support arm ... arm64 ... armel ... ''' >>> dfile = parse_deb822_file(example_deb822_paragraph.splitlines()) >>> paragraph = next(iter(dfile)) >>> list_view = paragraph.as_interpreted_dict_view(LIST_SPACE_SEPARATED_INTERPRETATION) >>> # With the defaults, you only deal with the semantic values >>> # - no leading or trailing whitespace on the first part of the value >>> list(list_view["Package"]) ['foo'] >>> with list_view["Architecture"] as arch_list: ... orig_arch_list = list(arch_list) ... arch_list.replace('i386', 'kfreebsd-amd64') >>> orig_arch_list ['amd64', 'i386', 'arm64', 'armel'] >>> list(list_view["Architecture"]) ['amd64', 'kfreebsd-amd64', 'arm64', 'armel'] >>> print(paragraph.dump(), end='') Package: foo # Field comment (because it becomes just before a field) Architecture: amd64 # Inline comment (associated with the next line) kfreebsd-amd64 # We also support arm arm64 armel >>> # Format preserved and architecture replaced >>> with list_view["Architecture"] as arch_list: ... # Prettify the result as sorting will cause awkward whitespace ... arch_list.reformat_when_finished() ... arch_list.sort() >>> print(paragraph.dump(), end='') Package: foo # Field comment (because it becomes just before a field) Architecture: amd64 # We also support arm arm64 armel # Inline comment (associated with the next line) kfreebsd-amd64 >>> list(list_view["Architecture"]) ['amd64', 'arm64', 'armel', 'kfreebsd-amd64'] >>> # Format preserved and architecture values sorted :param interpretation: Decides how the field values are interpreted. As an example, use LIST_SPACE_SEPARATED_INTERPRETATION for fields such as Architecture in the debian/control file. :param auto_resolve_ambiguous_fields: This parameter is only relevant for paragraphs that contain the same field multiple times (these are generally invalid). If the caller requests an ambiguous field from an invalid paragraph via a plain field name, the return dict-like object will refuse to resolve the field (not knowing which version to pick). This parameter (if set to True) instead changes the error into assuming the caller wants the *first* variant. r)r`)rQrdrWs rBas_interpreted_dict_viewz/Deb822ParagraphElement.as_interpreted_dict_view@s%T2  *G    rDrhc,t||||||S)aaProvide a Dict[str, str]-like view of this paragraph with non-standard parameters This method returns a dict-like object representing this paragraph that is optionally configured differently from the default view. >>> example_deb822_paragraph = ''' ... Package: foo ... # Field comment (because it becomes just before a field) ... Depends: libfoo, ... # Inline comment (associated with the next line) ... libbar, ... ''' >>> dfile = parse_deb822_file(example_deb822_paragraph.splitlines()) >>> paragraph = next(iter(dfile)) >>> # With the defaults, you only deal with the semantic values >>> # - no leading or trailing whitespace on the first part of the value >>> paragraph["Package"] 'foo' >>> # - no inline comments in multiline values (but whitespace will be present >>> # subsequent lines.) >>> print(paragraph["Depends"]) libfoo, libbar, >>> paragraph['Foo'] = 'bar' >>> paragraph.get('Foo') 'bar' >>> paragraph.get('Unknown-Field') is None True >>> # But you get asymmetric behaviour with set vs. get >>> paragraph['Foo'] = ' bar\n' >>> paragraph['Foo'] 'bar' >>> paragraph['Bar'] = ' bar\n#Comment\n another value\n' >>> # Note that the whitespace on the first line has been normalized. >>> print("Bar: " + paragraph['Bar']) Bar: bar another value >>> # The comment is present (in case you where wondering) >>> print(paragraph.get_kvpair_element('Bar').convert_to_text(), end='') Bar: bar #Comment another value >>> # On the other hand, you can choose to see the values as they are >>> # - We will just reset the paragraph as a "nothing up my sleeve" >>> dfile = parse_deb822_file(example_deb822_paragraph.splitlines()) >>> paragraph = next(iter(dfile)) >>> nonstd_dictview = paragraph.configured_view( ... discard_comments_on_read=False, ... auto_map_initial_line_whitespace=False, ... # For paragraphs with duplicate fields, you can choose to get an error ... # rather than the dict picking the first value available. ... auto_resolve_ambiguous_fields=False, ... auto_map_final_newline_in_multiline_values=False, ... ) >>> # Because we have reset the state, Foo and Bar are no longer there. >>> 'Bar' not in paragraph and 'Foo' not in paragraph True >>> # We can now see the comments (discard_comments_on_read=False) >>> # (The leading whitespace in front of "libfoo" is due to >>> # auto_map_initial_line_whitespace=False) >>> print(nonstd_dictview["Depends"], end='') libfoo, # Inline comment (associated with the next line) libbar, >>> # And all the optional whitespace on the first value line >>> # (auto_map_initial_line_whitespace=False) >>> nonstd_dictview["Package"] == ' foo\n' True >>> # ... which will give you symmetric behaviour with set vs. get >>> nonstd_dictview['Foo'] = ' bar \n' >>> nonstd_dictview['Foo'] ' bar \n' >>> nonstd_dictview['Bar'] = ' bar \n#Comment\n another value\n' >>> nonstd_dictview['Bar'] ' bar \n#Comment\n another value\n' >>> # But then you get no help either. >>> try: ... nonstd_dictview["Baz"] = "foo" ... except ValueError: ... print("Rejected") Rejected >>> # With auto_map_initial_line_whitespace=False, you have to include minimum a newline >>> nonstd_dictview["Baz"] = "foo\n" >>> # The absence of leading whitespace gives you the terse variant at the expensive >>> # readability >>> paragraph.get_kvpair_element('Baz').convert_to_text() 'Baz:foo\n' >>> # But because they are views, changes performed via one view is visible in the other >>> paragraph['Foo'] 'bar' >>> # The views show the values according to their own rules. Therefore, there is an >>> # asymmetric between paragraph['Foo'] and nonstd_dictview['Foo'] >>> # Nevertheless, you can read or write the fields via either - enabling you to use >>> # the view that best suit your use-case for the given field. >>> 'Baz' in paragraph and nonstd_dictview.get('Baz') is not None True >>> # Deletion via the view also works >>> del nonstd_dictview['Baz'] >>> 'Baz' not in paragraph and nonstd_dictview.get('Baz') is None True :param discard_comments_on_read: When getting a field value from the dict, this parameter decides how in-line comments are handled. When setting the value, inline comments are still allowed and will be retained. However, keep in mind that this option makes getter and setter assymetric as a "get" following a "set" with inline comments will omit the comments even if they are there (see the code example). :param auto_map_initial_line_whitespace: Special-case the first value line by trimming unnecessary whitespace leaving only the value. For single-line values, all space including newline is pruned. For multi-line values, the newline is preserved / needed to distinguish the first line from the following lines. When setting a value, this option normalizes the whitespace of the initial line of the value field. When this option is set to True makes the dictionary behave more like the original Deb822 module. :param preserve_field_comments_on_field_updates: Whether to preserve the field comments when mutating the field. :param auto_resolve_ambiguous_fields: This parameter is only relevant for paragraphs that contain the same field multiple times (these are generally invalid). If the caller requests an ambiguous field from an invalid paragraph via a plain field name, the return dict-like object will refuse to resolve the field (not knowing which version to pick). This parameter (if set to True) instead changes the error into assuming the caller wants the *first* variant. :param auto_map_final_newline_in_multiline_values: This parameter controls whether a multiline field with have / need a trailing newline. If True, the trailing newline is hidden on get and automatically added in set (if missing). When this option is set to True makes the dictionary behave more like the original Deb822 module. rh)rg)rQr?rirWrjrks rBconfigured_viewz&Deb822ParagraphElement.configured_views.V- %=-M*G5]7a     rDc|Sr>r?r]s rBrz!Deb822ParagraphElement._paragraph$s  rDct)9Re-order the given field so it is "last" in the paragraphr=rQfields rB order_lastz!Deb822ParagraphElement.order_last)rrDct):Re-order the given field so it is "first" in the paragraphr=rs rB order_firstz"Deb822ParagraphElement.order_first.rrDct)Re-order the given field so appears directly after the reference field in the paragraph The reference field must be present.r=rQrreference_fields rB order_beforez#Deb822ParagraphElement.order_before3rArDct)Re-order the given field so appears directly before the reference field in the paragraph The reference field must be present. r=rs rB order_afterz"Deb822ParagraphElement.order_after:rLrDctr>r=r]s rBrz#Deb822ParagraphElement.kvpair_countBrrDctr>r=r]s rBr"z Deb822ParagraphElement.iter_keysGrrDctr>r=rs rBrz.Deb822ParagraphElement.contains_kvpair_elementKrrDFctr>r=)rQrrCs rBrz)Deb822ParagraphElement.get_kvpair_elementOrArDctr>r=r)s rBset_kvpair_elementz)Deb822ParagraphElement.set_kvpair_elementVrrDctr>r=rQrs rBr&z,Deb822ParagraphElement.remove_kvpair_elementZrrDNct) Re-order all fields :param key: Provide a key function (same semantics as for sorted). Keep in mind that the module preserve the cases for field names - in generally, callers are recommended to use "lower()" to normalize the case. r=rs rB sort_fieldsz"Deb822ParagraphElement.sort_fields^s "!rDrDcd|vrtd|}|r d|zdz}nd}|||||dS)a Sets a field in this paragraph to a simple "word" or "phrase" In many cases, it is better for callers to just use the paragraph as if it was a dictionary. However, this method does enable to you choose the field comment (if any), which can be a reason for using it. This is suitable for "simple" fields like "Package". Example: >>> example_deb822_paragraph = ''' ... Package: foo ... ''' >>> dfile = parse_deb822_file(example_deb822_paragraph.splitlines()) >>> p = next(iter(dfile)) >>> p.set_field_to_simple_value("Package", "mscgen") >>> p.set_field_to_simple_value("Architecture", "linux-any kfreebsd-any", ... field_comment=['Only ported to linux and kfreebsd']) >>> p.set_field_to_simple_value("Priority", "optional") >>> print(p.dump(), end='') Package: mscgen # Only ported to linux and kfreebsd Architecture: linux-any kfreebsd-any Priority: optional >>> # Values are formatted nicely by default, but it does not work with >>> # multi-line values >>> p.set_field_to_simple_value("Foo", "bar\nbin\n") Traceback (most recent call last): ... ValueError: Cannot use set_field_to_simple_value for values with newlines :param item: Name of the field to set. If the paragraph already contains the field, then it will be replaced. If the field exists, then it will preserve its order in the paragraph. Otherwise, it is added to the end of the paragraph. Note this can be a "paragraph key", which enables you to control *which* instance of a field is being replaced (in case of duplicate fields). :param simple_value: The text to use as the value. The value must not contain newlines. Leading and trailing will be stripped but space within the value is preserved. The value cannot contain comments (i.e. if the "#" token appears in the value, then it is considered a value rather than "start of a comment) :param preserve_original_field_comment: See the description for the parameter with the same name in the set_field_from_raw_string method. :param field_comment: See the description for the parameter with the same name in the set_field_from_raw_string method. rz=Cannot use set_field_to_simple_value for values with newlinesrrDN)rr6rJ)rQr simple_valuerErFstripped raw_values rBrHz0Deb822ParagraphElement.set_field_to_simple_valuejsl <  \]] ]  %%''  h-III &&  ,K' '     rDcg}||tdn:|8t|ts!|d|Dd}d}t |\}}}|} ||d} n,#t $r|r||dfd} YnwxYw|d}| r| j}d||f} | d } t| d D]y\} } | d s#td | | d kr6| ddvr,d}t| | | dzt| d kr*| ddrtd|| tt!|}|}|rtd|zt%t!|}t|t&sJ||}|J|r| r| j|_d| _n |||_|||dS)ad Sets a field in this paragraph to a given text value In many cases, it is better for callers to just use the paragraph as if it was a dictionary. However, this method does enable to you choose the field comment (if any) and lets to have a higher degree of control over whitespace (on the first line), which can be a reason for using it. Example usage: >>> example_deb822_paragraph = ''' ... Package: foo ... ''' >>> dfile = parse_deb822_file(example_deb822_paragraph.splitlines()) >>> p = next(iter(dfile)) >>> raw_value = ''' ... Build-Depends: debhelper-compat (= 12), ... some-other-bd, ... # Comment ... another-bd, ... '''.lstrip() # Remove leading newline, but *not* the trailing newline >>> fname, new_value = raw_value.split(':', 1) >>> p.set_field_from_raw_string(fname, new_value) >>> print(p.dump(), end='') Package: foo Build-Depends: debhelper-compat (= 12), some-other-bd, # Comment another-bd, >>> # Format preserved :param item: Name of the field to set. If the paragraph already contains the field, then it will be replaced. Otherwise, it is added to the end of the paragraph. Note this can be a "paragraph key", which enables you to control *which* instance of a field is being replaced (in case of duplicate fields). :param raw_string_value: The text to use as the value. The text must be valid deb822 syntax and is used *exactly* as it is given. Accordingly, multi-line values must include mandatory leading space on continuation lines, newlines after the value, etc. On the flip-side, any optional space or comments will be included. Note that the first line will *never* be read as a comment (if the first line of the value starts with a "#" then it will result in "Field-Name:#..." which is parsed as a value starting with "#" rather than a comment). :param preserve_original_field_comment: If True, then if there is an existing field and that has a comment, then the comment will remain after this operation. This is the default is the `field_comment` parameter is omitted. Note that if the parameter is True and the item is ambiguous, this will raise an AmbiguousDeb822FieldKeyError. When the parameter is omitted, the ambiguity is resolved automatically and if the resolved field has a comment then that will be preserved (assuming field_comment is None). :param field_comment: If not None, add or replace the comment for the field. Each string in the list will become one comment line (inserted directly before the field name). Will appear in the same order as they do in the list. If you want complete control over the formatting of the comments, then ensure that each line start with "#" and end with "\n" before the call. Otherwise, leading/trailing whitespace is normalized and the missing "#"/"\n" character is inserted. NzNThe "preserve_original_field_comment" conflicts with "field_comment" parameterc34K|]}t|VdSr>)rrs rBrzCDeb822ParagraphElement.set_field_from_raw_string..s*"M"M!?1#5#5"M"M"M"M"M"MrDFTrBrr r rwr9rz2Line {i} in new value was missing trailing newline)r)rrGrzLine {i} in new value was invalid. It must either start with " " space (continuation line) or "#" (comment line). The line started with "{line}")rr7rxrz2The last line in a value field cannot be a commentr )rrrr*r rrrrr r;rrerWrrrrrrrr)rQrraw_string_valuerErFrrrrcased_field_nameoriginalraw raw_linesrr7rhrrrr\s rBrJz0Deb822ParagraphElement.set_field_from_raw_stringsT * 6( ">???) &m-ABB %"""M"M}"M"M"MMMM $ .3 +&t,, Aq% N..tT.BBHH+ N N N. .. A.MMHHH  N + 2/3 +  3'2 hh(*:;<<NNDN11  !444 @ @GAt==&& c !U!\!\_`!\!a!abbbAvv$q')9998!ad1g!>!>??? y>>A  )B-":":3"?"? QRR R9%%%([(9(9:: !::<<  RCjPQQ Qk**++ )%LMMMMM,,Z88   * 2 0(0(@%+/(  &$1E ! e,,,,,s'A??&B('B(cdSr>r?rQfds rBdumpzDeb822ParagraphElement.dump< rDcdSr>r?r]s rBrzDeb822ParagraphElement.dumpC  rDc|1dd|DS|D]/}||jd0dS)Nrc3$K|] }|jV dSr>rrs rBrz.Deb822ParagraphElement.dump..M$>>a16>>>>>>rDutf-8rrwriterencoderQrrs rBrzDeb822ParagraphElement.dumpH{ :77>>4+;+;+=+=>>>>> >%%'' 1 1E HHUZ&&w// 0 0 0 0trDr7r>)rcrdre classmethodrxr}rrhrrrrrrrrrr"rrrr&rrHrJr0rr?rDrBrtrts[II[I[ F F[ FX@DN N N N N d269=6:AECG R R R R R hX""" """ """"""""X""""""" $)""""""""""  " " " " CG04 G G G G G ZCG04 G-G-G-G-G-R  X   X rDrtceZdZdZfdZedZdZdZdZ dZ dZ d Z d Z d Z dd ZdZddZdZxZS)rzParagraph implementation optimized for valid deb822 files When there are no duplicated fields, we can use simpler and faster datastructures for common operations. ctd|D|_||_|dS)Nci|] }|j| Sr?rrs rB zDDeb822NoDuplicateFieldsParagraphElement.__init__..`s M M Mr M M MrD)rrW_kvpair_elements _kvpair_orderr)rQrrrs rBrWz0Deb822NoDuplicateFieldsParagraphElement.__init__ZsQ  M M_ M M M) ""$$$$$rDc*t|jSr>)rWrr]s rBrz4Deb822NoDuplicateFieldsParagraphElement.kvpair_countds4()))rDcdt|d\}}}|j|dS)rTrN)r rrrQrunpacked_fieldrrs rBrz2Deb822NoDuplicateFieldsParagraphElement.order_lastis: +54HHH1 %%n55555rDcdt|d\}}}|j|dS)rTrN)r rrrs rBrz3Deb822NoDuplicateFieldsParagraphElement.order_firstos: +54HHH1 &&~66666rDct|d\}}}t|d\}}}|j||dS)rTrN)r rrrQrrrrrunpacked_ref_fields rBrz4Deb822NoDuplicateFieldsParagraphElement.order_beforeusX +54HHH1#.QU#V#V#V Aq ''8JKKKKKrDct|d\}}}t|d\}}}|j||dS)rTrN)r rrrs rBrz3Deb822NoDuplicateFieldsParagraphElement.order_after~sX +54HHH1#.QU#V#V#V Aq &&~7IJJJJJrDc>td|jDS)Nc34K|]}t|VdSr>rrr|s rBrzCDeb822NoDuplicateFieldsParagraphElement.__iter__..(77qCFF777777rD)rrr]s rBrz0Deb822NoDuplicateFieldsParagraphElement.__iter__s"77D$6777777rDc#8Kd|jDEd{VdS)Nc34K|]}t|VdSr>rrs rBrzDDeb822NoDuplicateFieldsParagraphElement.iter_keys..rrDrr]s rBr"z1Deb822NoDuplicateFieldsParagraphElement.iter_keyss577D$6777777777777rDctt|d\}}}|j|=|j|dSNTr)r rrrb)rQrrrs rBr&z=Deb822NoDuplicateFieldsParagraphElement.remove_kvpair_elementsBd;;; Q  !# & !!#&&&&&rDct|tttfsdSt d|}t |d\}}}||jvS)NFr7Tr)rrrrr/r r)rQrrrrs rBrz?Deb822NoDuplicateFieldsParagraphElement.contains_kvpair_elementsV$e-A BCC 5ND))t<<< Qd+++rDFc~t|d\}}}|r|j|S|j|Sr)r rget)rQrrCrrs rBrz:Deb822NoDuplicateFieldsParagraphElement.get_kvpair_elementsI !=== a  3(,,T22 2$T**rDcxt|d\}}}t|tr ||jurt d|j}n!||jkrt d|j}|j|}||j|<|j ||d|_ ||_ dS)NTrzOKey is a Deb822FieldNameToken, but not *the* Deb822FieldNameToken for the valuegCannot insert value under a different field value than field name from its Deb822FieldNameToken implies) r rrrrrrrrrr)rQrr\rroriginal_values rBrz:Deb822NoDuplicateFieldsParagraphElement.set_kvpair_elementsd;;; Q c/ 0 0 #%+++ "2333"CCe&&& "JKKK"C.22377%*c" !!#&&&  %,0N )#rDNct|jD]6}|jtd|}|j|t }tt|j||_dS)rr!Nr2) rrrr/rrr"r sorted)rQrlast_field_name last_kvpairs rBrz3Deb822NoDuplicateFieldsParagraphElement.sort_fieldss} ((:;;  O/Wo0N0NOK  % B B D D D  ;(C't/As(K(K(KLLrDc#ZKfdtdjDEd{VdS)Nc32K|]}j|VdSr>)r)rr!rQs rBrzEDeb822NoDuplicateFieldsParagraphElement.iter_parts..sGJJ)!,JJJJJJrDzIterable[_strI])r/rr]s`rBrz2Deb822NoDuplicateFieldsParagraphElement.iter_partssxJJJJ!"3T5GHHJJJ J J J J J J J J JrDr7r>)rcrdrerfrWrhrrrrrrr"r&rrrrrr8r9s@rBrrSs1 %%%%%**X*666 777 LLLKKK888888''' ,,,$)++++$$$,MMMM$JJJJJJJrDrceZdZfdZedZdZdZdZdZ dZ dZ d Z d Z ed Zd Z ddZ ddZedZdZdZdZddZxZS)rctt|_i|_|||dSr>)rrWrrr_init_kvpair_fieldsr)rQrrs rBrWz.Deb822DuplicateFieldsParagraphElement.__init__s\ '\\     111 ""$$$$$rDcVt|jt|jkSr>)rWrrr]s rBrz:Deb822DuplicateFieldsParagraphElement.has_duplicate_fieldss% 4%&&T-B)C)CCCrDc|jrJ|jrJ|D]X}|j}|j|}||jvr |g|j|<8|j||YdSr>)rrrr)rQkvpairsrrrRs rBrz9Deb822DuplicateFieldsParagraphElement._init_kvpair_fieldss%%%%(((( ? ?BJ%,,R00D!66659F%j11%j188>>>>  ? ?rDct|\}}}|j|}g}||2|||||}|J||n|}||fSr>)r r_resolve_to_single_noder)rQrrrr nodesnodes_being_relocated single_nodes rB_nodes_being_relocatedz > > > > + *~~rDc0||\}}t|dks"t|t|ksJ||\}}|d}||vrtd|j}t |D]-} || || |.t|dkr > > > > + *~~rDcg}|jD]'}|jj|kr||(||j|<dSr>)rrr\rrr)rQrrrRs rBrzGDeb822DuplicateFieldsParagraphElement._regenerate_relative_kvapir_order] s[&1133 # #Dz$ 22 T""",1j)))rDc#$K|jEd{VdSr>rr]s rBrz0Deb822DuplicateFieldsParagraphElement.iter_partse s'%%%%%%%%%%rDc*t|jSr>)rWrr]s rBrz2Deb822DuplicateFieldsParagraphElement.kvpair_counti s4%&&&rDc#8Kd|jDEd{VdS)Nc3$K|] }|jV dSr>rrs rBrzBDeb822DuplicateFieldsParagraphElement.iter_keys..p s$??bBM??????rDrr]s rBr"z/Deb822DuplicateFieldsParagraphElement.iter_keysn s5??D,>????????????rDFc t|ut|dkr`||||}||Sd}t||t|t|dz d} ||S#t$r,|rYdSd}t |||wxYw)NrwzAmbiguous key {key} - the field appears {res_len} times. Use ({key}, index) to denote which instance of the field you want. (Index can be 0..{res_len_1} or e.g. -1 to denote the last field))rres_len res_len_1rz>Field "{key}" was present but the index "{index}" was invalid.r)rW_find_node_via_name_tokenrre IndexErrorr)rQrrrr rCrRrhs rBrz=Deb822DuplicateFieldsParagraphElement._resolve_to_single_noder s =5zzQ)99*eLLD'# T33::#FI%jjHKE UV4>4X4XYYYE =<  = = = ttRC3::#U:;;<< <  =s9B B7'B7ct|\}}}|r|j|}|dSn |j|}||||||}||jSdS)NrB)r rrrr\)rQrrCrrr rrRs rBrz8Deb822DuplicateFieldsParagraphElement.get_kvpair_element s "-T!2!2UJ  /)--c22E}t)#.E++E3zSZ+[[  : trDc4|D]}||jjur|cSdSr>)r\r)r elementsrRs rBrz?Deb822DuplicateFieldsParagraphElement._find_node_via_name_token s6  DTZ333 4trDct|tttfsdSt d|} ||dduS#t $rYdSwxYw)NFr7TrB)rrrrr/rrrs rBrz=Deb822DuplicateFieldsParagraphElement.contains_kvpair_element su$e-A BCC 5ND)) **4*>>dJ J+   44 sA AAct|\}}}|rt||jurc|j|j}d}||||}|t d|J||}|j}n!||jkrt d|j}|j|}||s|,|dkr&d}t| |||j |}||jvr |g|j|<n |j| |dSd} |)d} |d}t|dkr |g|j|<n||}d|j _||_||_ | rFt|dkr5|ddD],} d| j _|j | )dSdSdS) NzKey is a Deb822FieldNameToken, but not *the* Deb822FieldNameToken for the value nor the Deb822FieldNameToken for an existing field in the paragraphrrzCannot replace field ({key}, {index}) as the field does not exist in the first place. Please index-less key or ({key}, 0) if you want to add the field.rFTrw)r rrrrrrrrrerrrWr\rr) rQrr\rr original_nodes original_noderhrR replace_allrs rBrz8Deb822DuplicateFieldsParagraphElement.set_kvpair_element sd!,S!1!1UJ  #!222!%!6!:!:5;K!L!L $ !-$($B$B:~$^$^M ($&deee&111&,,];;"CCe&&& "JKKK"C.22377  ! ! UaZZ0szzcz??@@@%,,U33D$///.2V%c**%c*11$777 F =K!!$D>""a''.2V%c* "%(D%) !#  23~..!33#ABB' 2 2)-&"..q1111  2 233 2 2rDcnt|\}}}|j|}|7|5|D](}d|j_|j|)|j|=dS|@|||}|%d}t|||}nB|J ||}n4#t$r'd}t|||wxYwt|dkr |j|=n| |d|j_|j|dS)Nz>The field "{key}" is present but key used to access it is not.r2z@The field "{key}" is present, but the index "{idx}" was invalid.)rrOrw) r rr\rrrrrrerWrb)rQrrOr  field_listrRrrhs rBr&z;Deb822DuplicateFieldsParagraphElement.remove_kvpair_element sl*3//S**3/  #+" 5 5,0 )"..t4444%c* F  ! :::zRRM$Vszzcz22333 DD??? =!# = = =Xszzcsz;;<<< = z??a  %c**   d # # #$( ! &&t,,,,,s !B**1CNc|t}|fd}t|jD]}|jt |j|}t |_i|_||dS)aRe-order all fields :param key: Provide a key function (same semantics as for sorted). Keep in mind that the module preserve the cases for field names - in generally, callers are recommended to use "lower()" to normalize the case. Nc$|jSr>r)rRkey_impls rB _actual_keyzFDeb822DuplicateFieldsParagraphElement.sort_fields.._actual_key, s8F-.. .rDr2) r"rrrrrrrr)rQrrrsorted_kvpair_listrs @rBrz1Deb822DuplicateFieldsParagraphElement.sort_fields s ;(C / / / / /$D$677  K  % B B D D D #D$6KHHH'\\ "   !344444rDr7r>)rcrdrerWrhrrrrrrrrrrr"rr staticmethodrrrr&rr8r9s@rBrrs%%%%%DDXD ? ? ? , , ,&&&*)))*???.???2222&&&''X'@@@). ====>$)"  \ >2>2>2@!-!-!-F55555555rDrceZdZdZfdZedZedZdZ dZ dZ dZ d Z d Zd Zed Zed Z ddZxZS)Deb822FileElementz!Represents the entire deb822 filec~t||_|dSr>)rrW_token_and_elementsr)rQtoken_and_elementsrs rBrWzDeb822FileElement.__init__= s9 #5  ""$$$$$rDc0|tS)zCreates a new Deb822FileElement with no contents Note that a deb822 file must be non-empty to be considered valid )rrvs rBnew_empty_filez Deb822FileElement.new_empty_fileC ss:<<   rDc`d}|D]}d}|r|jrdS|sdS|duS)aReturns true if the file is valid Invalid elements include error elements (Deb822ErrorElement) but also issues such as paragraphs with duplicate fields or "empty" files (a valid deb822 file contains at least one paragraph). FTN)rr)rQ had_paragraphrs rB is_valid_filezDeb822FileElement.is_valid_fileL sa   I M  > uu  5,,..$66rDcntt|tdS)z:Returns the first Deb822ErrorElement (or None) in the filerN)rrrrr]s rBrz*Deb822FileElement.find_first_error_element` s/D**FX*YYZZ\`aaarDcPt|tSr>)rrrtr]s rBrzDeb822FileElement.__iter__e sD++,BCCDDDrDc#$K|jEd{VdSr>)r#r]s rBrzDeb822FileElement.iter_partsi s'++++++++++rDc<d}d}|dkr?|js||dS|jj}t|j}nLd}|jD]0}|j}t |tr|dz }||dz kr|}n1|||dS|r=|td}|j ||}|j |||dS)aInserts a paragraph into the file at the given "index" of paragraphs Note that if the index is between two paragraphs containing a "free floating" comment (e.g. paragrah/start-of-file, empty line, comment, empty line, paragraph) then it is unspecified which "side" of the comment the new paragraph will appear and this may change between versions of python-debian. >>> original = ''' ... Package: libfoo-dev ... Depends: libfoo1 (= ${binary:Version}), ${shlib:Depends}, ${misc:Depends} ... '''.lstrip() >>> deb822_file = parse_deb822_file(original.splitlines()) >>> para1 = Deb822ParagraphElement.new_empty_paragraph() >>> para1["Source"] = "foo" >>> para1["Build-Depends"] = "debhelper-compat (= 13)" >>> para2 = Deb822ParagraphElement.new_empty_paragraph() >>> para2["Package"] = "libfoo1" >>> para2["Depends"] = "${shlib:Depends}, ${misc:Depends}" >>> deb822_file.insert(0, para1) >>> deb822_file.insert(1, para2) >>> expected = ''' ... Source: foo ... Build-Depends: debhelper-compat (= 13) ... ... Package: libfoo1 ... Depends: ${shlib:Depends}, ${misc:Depends} ... ... Package: libfoo-dev ... Depends: libfoo1 (= ${binary:Version}), ${shlib:Depends}, ${misc:Depends} ... '''.lstrip() >>> deb822_file.dump() == expected True NTrrwr) r#rrboolrr\rrt _set_parentr insert_before) rQrOpara anchor_node needs_newlinerrRentrynl_tokens rBrzDeb822FileElement.insertm sEL  !88+  D!!!2>> deb822_file = Deb822FileElement.new_empty_file() >>> para1 = Deb822ParagraphElement.new_empty_paragraph() >>> para1["Source"] = "foo" >>> para1["Build-Depends"] = "debhelper-compat (= 13)" >>> para2 = Deb822ParagraphElement.new_empty_paragraph() >>> para2["Package"] = "foo" >>> para2["Depends"] = "${shlib:Depends}, ${misc:Depends}" >>> deb822_file.append(para1) >>> deb822_file.append(para2) >>> expected = ''' ... Source: foo ... Build-Depends: debhelper-compat (= 13) ... ... Package: foo ... Depends: ${shlib:Depends}, ${misc:Depends} ... '''.lstrip() >>> deb822_file.dump() == expected True Nz(Paragraph is already a part of this filez/Paragraph is already part of another Deb822Filer)r#rrrrrrr/)rQr tail_elements rBrzDeb822FileElement.append s./4  # /'4// !KLLLNOO O  [ <9N O O [  $ + +D,<,<=RSW=X=X,Y,Y Z Z Z  ''(8(8(C(CDDDDDrDc|j|urtdd}|jD] }|j|urn|t d|j}|j}|j||7|r4t|jtr|j|n4t|jtr|j|d|_dS)Nz%Paragraph is part of a different filezunable to find paragraph) rrr#rr\rYrrrrr)rQrrRrrs rBrbzDeb822FileElement.remove s   #4 / /DEE E,7799  DzY&&' <9:: :* N   ,,T222   DM,?AV!W!W D(44]CCC)/+@AA @(44Y???#'    rDc||_|Sr>)r)rQr@s rBr/zDeb822FileElement._set_parent srDcdSr>r?rs rBrzDeb822FileElement.dump rrDcdSr>r?r]s rBrzDeb822FileElement.dump rrDNc|1dd|DS|D]/}||jd0dS)Nrc3$K|] }|jV dSr>rrs rBrz)Deb822FileElement.dump.. rrDrrrs rBrzDeb822FileElement.dump rrDr>)rcrdrerfrWrr&rhr)rrrrrrbr/r0rr8r9s@rBr!r!: s=++%%%%% !![!77X7&bbb EEE,,,CXCXCXJ#E#E#EJ(((*   X   X rDr!) constructorc6|r tjn tjSr>)rqrr)discard_commentss rB_parsed_value_render_factoryrA sHX 6 # D D % 56rDc tdSr)rr?rDrBrCrC sAZ[^A_A_rDcDt|t p |jdkSr)rrrr^s rB_non_end_of_line_tokenrD1 s#!233 3 Eqv~ErDc #fKt|}d}d}d}|D]}d}t|tr|}d}d}n~t|trd}nft|trQ|}t|tr(d}|}d}t dt|d}|J||V|rt| t}t dt|d}| |j dksJd} d} |rzt|dtr"t d| } |r;t|dtr t d|d} |d d}t||| || |Vd}d}dS) zYParser helper - consumes tokens part of a Deb822ValueEntryElement and turns them into oneNFTrrrrxrrw)rrrrrpeekr/rlist takewhilerDrrrr) token_streambuffered_streamrrrstart_of_value_entry next_tokentokens_in_value eol_tokenleading_whitespacetrailing_whitespaces rB_build_value_linerQ7 s:( 55O:O" E 8+8+$ e9 : : ;&+ ##' EE 8 9 9 ;#' 3 4 4 ;(--//J*&BCC ;'+$"'+//M/3OT/J/J+1+1'/:::  KKK  +"?#<#<=S#T#TUUO4d?D6Q6QRRI$ $(>(>(>(>!% "&  :ob13HII1*./F/>/B/B/D/D+1+1'#:z/"2EG\']']:)-.EWXGY)Z)Z&&5abb&9O()@);)8)<)2 ++ + + +#O&* #q8+8+rDc#Kt|}|D]}d}d}t|trd}nht|trS|}|}t|t}|r& t |}n#t $rtwxYw|r;|}t |d}t |d}||4|r|V|g} || |t| VdSt|tr9t|tr$t|td|||V2|g} | |t |} | r:t| t"r%t |d| | t| V|VdS)NFTr)rrrrrFr StopIterationAssertionErrorrrrrr<r/r*rHrDr) rIrJtoken_or_elementstart_of_fieldrrLr separatorrerror_elements error_tokensnls rB_build_field_with_valuer[ sY( 55O+2#2# &(< = = )!NN (*> ? ? ).O(--//J' 4HIIN ))'+O'<'<$$$)))(() " #)J_d33I $77M M$9#*))))",(")))444(88888)%>?? 7"=2DEE 7/045KZ0X0X090=222222!11 ##O$=$=>T$U$UVVV$))++,*R)EFF,$/// ''+++(666666# " " " "e2#2#s 6BBc#K|D]Y}t|tr>|jdd}t d||VZdS)Nrz\nz4Syntax or Parse error on the line: "{error_as_text}") error_as_text)rrrrrre)sequencerr]s rB_abort_on_error_tokensr_ s e- . . 2!J..tU;;M$FMM"/N1122 2 rDr)accept_files_with_error_tokens#accept_files_with_duplicated_fieldsencodingct|ttfr|d}t ||}|st |}t |}t|}t|}t|}t|}t|}tt|}|st|D]\}}t|trt!}d} |D]I} t%| \} } } t| tsJ| |vr| } n|| J| &d} t)| | ||S)a :param sequence: An iterable over lines of str or bytes (an open file for reading will do). If line endings are provided in the input, then they must be present on every line (except the last) will be preserved as-is. If omitted and the content is at least 2 lines, then parser will assume implicit newlines. :param accept_files_with_error_tokens: If True, files with critical syntax or parse errors will be returned as "successfully" parsed. Usually, working on files with this kind of errors are not desirable as it is hard to make sense of such files (and they might in fact not be a deb822 file at all). When set to False (the default) a ValueError is raised if there is a critical syntax or parse error. Note that duplicated fields in a paragraph is not considered a critical parse error by this parser as the implementation can gracefully cope with these. Use accept_files_with_duplicated_fields to determine if such files should be accepted. :param accept_files_with_duplicated_fields: If True, then files containing paragraphs with duplicated fields will be returned as "successfully" parsed even though they are invalid according to the specification. The paragraphs will prefer the first appearance of the field unless caller explicitly requests otherwise (e.g., via Deb822ParagraphElement.configured_view). If False, then this method will raise a ValueError if any duplicated fields are seen inside any paragraph. :param encoding: The encoding to use (this is here to support Deb822-like APIs, new code should not use this parameter). T)rbNz6Duplicate field "{dup_field}" in paragraph number {no}) dup_fieldno)rrbytesr rr_%_combine_comment_tokens_into_elementsrQ(_combine_vl_elements_into_value_elementsr[%_combine_kvp_elements_into_paragraphs#_combine_error_tokens_into_elementsr!rr;rsetkeysr addrre)r^r`rarbrrrer field_namesrdrrrrrhs rBrr sH(S%L))-&&t,,"(X > > >F )0'// 26 : :F v & &F 5f = =F $V , ,F 26 : :F1 8 8F#Jv$6$677K .M&{33 M MMB )%JKK M!ee  &^^--00E'25'9'9$J1%j#66666![00$. OOJ////(RC$SZZ)Z%K%KLLL rD__main__r7)~collections.abc collections contextlibsysrcrOabcrtypesrrdebian._deb822_repro._utilrrrdebian._deb822_repro.formatterr r r debian._deb822_repro.tokensr r rrrrrrrrrrrrrdebian._deb822_repro.typesrr debian._utilrrrr r!r"typingr#r$r%r&r'r(r)r*r+r,r-r.r/r0r1r2r3r4r5r6r7r8r9r:r;StreamingValueParserrStrToValueParserKVPNode ImportErrorrH version_infoAbstractContextManagerrmrvr;rCr~rkrsrur~rrrrrrqrr<rr rrrr+rUr`rgrtrrr!rjrgrhrrirA#LIST_SPACE_SEPARATED_INTERPRETATION#LIST_COMMA_SEPARATED_INTERPRETATIONLIST_UPLOADERS_INTERPRETATIONrDrQr[r_rrcdoctesttestmodr?rDrBrs  !!!!!!**********XWWWWWWW" '6G 6T(UWY(YZ#SE8E-:K4L+M$MN !<=#""" "~!> "MMMMMWR[MMM`v,6,Ma,P))  _%_%_%_%_%GBFOABab_%_%_%D"""""WQZ"""<1<1<1<1<1q(971b5><1<1<1~!!!H     :;PQSUWQW;XZ\;\]   D--- +++ 111$-1-1-1`>(>(>(>(>(>(>(>(B,W&W&W&W&W&]W&W&W&tDDDDDDDD2$$$$$$$$$$}$$$$$$N(((((=(((0E"E"E"E"E" E"E"E"P    "'""""6 / / /v(_4\1_E     !8'!*c   '"'"'"'"'"%;A%>'"'"'"Zk1k1k1k1k1'9#'>'*k1k1k1\44444%7%:C444:55555)G)J555*#A#A#A#A#A$B3$G$D#A#A#ALttttt],LctttnAJAJAJAJAJ.DAJAJAJH`5`5`5`5`5,B`5`5`5F KKKKK KKK\'?&>?OQc&d&d#(@(@ASAU)W)W%+C+CDZDV,X,X((@(@&3)))%666 '9&89S9U9Q9`9_9_9U ';';#'9&89N9P9Q9I9I9U ';';#!3 23H3N3K3C3C3O !5!5FFF ]+]+]+@7#7#7#t   6;:?& MMMMM` zNNNGOs6A:C11 DD