ó
    áÅŸg+@  ã                  óú  • S r SSKJr  SSKrSSKrSSKrSSKrSSKrSSKJ	r	  SSKJ
r
  SSKJr  SSKJr  SSKJr  SS	KJr  SS
KJr  SSKJr  SSKJr  \R*                  " \5      r\" \R2                  \R4                  /5      r\" \R2                  \R4                  \R6                  \R8                  /5      r\\\\\\4   4      r\\\    \\    \4   r! " S S5      r"SS jr#SS jr$SS jr%SS jr&SS jr'SS jr(g)zFModule containing our file processor that tokenizes a file for checks.é    )ÚannotationsN)ÚAny)Ú	Generator)ÚList)ÚTuple)Údefaults)Úutils)ÚFSTRING_END)ÚFSTRING_MIDDLE)ÚLoadedPluginc                  óp  • \ rS rSrSrSr S       SS jjr\R                  S S j5       r	S!S jr
    S"S jrS#S	 jrS#S
 jrS#S jrS$S jrS%S jrS#S jrS&S jrS'S jrS(S jr      S)S jrS*S jrS+S jr\R                  S,S j5       rS-S jrS.S jrS/S jrS/S jrS/S jrS0S jrS#S jrSr g)1ÚFileProcessoré   aá  Processes a file and holds state.

This processes a file by generating tokens, logical and physical lines,
and AST trees. This also provides a way of passing state about the file
to checks expecting that state. Any public attribute on this object can
be requested by a plugin. The known public attributes are:

- :attr:`blank_before`
- :attr:`blank_lines`
- :attr:`checker_state`
- :attr:`indent_char`
- :attr:`indent_level`
- :attr:`line_number`
- :attr:`logical_line`
- :attr:`max_line_length`
- :attr:`max_doc_length`
- :attr:`multiline`
- :attr:`noqa`
- :attr:`previous_indent_level`
- :attr:`previous_logical`
- :attr:`previous_unindented_logical_line`
- :attr:`tokens`
- :attr:`file_tokens`
- :attr:`total_lines`
- :attr:`verbose`
FNc                ó$  • X l         Xl        Ub  UOU R                  5       U l        U R	                  5         SU l        SU l        0 U l        0 U l        UR                  U l	        SU l
        SU l        UR                  U l        SU l        SU l        UR                  U l        UR                   U l        SU l        SU l        SU l        SU l        / U l        [-        U R                  5      U l        UR0                  U l        SS0U l        SU l        g)zMInitialize our file processor.

:param filename: Name of the file to process
Nr   Ú Fúlogical lineséÿÿÿÿ)ÚoptionsÚfilenameÚ
read_linesÚlinesÚstrip_utf_bomÚblank_beforeÚblank_linesÚ_checker_statesÚchecker_stateÚhang_closingÚindent_charÚindent_levelÚindent_sizeÚline_numberÚlogical_lineÚmax_line_lengthÚmax_doc_lengthÚ	multilineÚprevious_indent_levelÚprevious_logicalÚ previous_unindented_logical_lineÚtokensÚlenÚtotal_linesÚverboseÚ
statisticsÚ_fstring_start)Úselfr   r   r   s       ÚQ/var/www/blue/EV-Temp_rev04/venv/lib/python3.13/site-packages/flake8/processor.pyÚ__init__ÚFileProcessor.__init__>   sþ   € ð ŒØ ŒØ#Ñ/‘U°T·_±_Ó5FˆŒ
Ø×ÑÔð ˆÔàˆÔà:<ˆÔà-/ˆÔà#×0Ñ0ˆÔà'+ˆÔàˆÔà"×.Ñ.ˆÔàˆÔàˆÔà&×6Ñ6ˆÔà%×4Ñ4ˆÔàˆŒà%&ˆÔ"à "ˆÔà02ˆÔ-à02ˆŒä˜tŸz™z›?ˆÔà—‘ˆŒà*¨AÐ.ˆŒØ ˆÕó    c                ót   ^• [        U R                  5      m[        [        R                  " U4S j5      5      $ )z-Return the complete set of tokens for a file.c                 ó   >• [        T 5      $ ©N)Únext)Ú	line_iters   €r0   Ú<lambda>Ú+FileProcessor.file_tokens.<locals>.<lambda>|   s	   ø€ ´T¸)´_r3   )Úiterr   ÚlistÚtokenizeÚgenerate_tokens)r/   r8   s    @r0   Úfile_tokensÚFileProcessor.file_tokensx   s*   ø€ ô ˜Ÿ™Ó$ˆ	Ü”H×,Ò,Ô-DÓEÓFÐFr3   c                ó   • Xl         g)z#Signal the beginning of an fstring.N)r.   )r/   Úlinenos     r0   Úfstring_startÚFileProcessor.fstring_start~   s   € à$Õr3   c              #  ó8  #   • UR                   [        :X  a  U R                  nOUR                  S   nSU l        X l        [        X!R                  S   5       H6  nU R                  U R
                  S-
     v •  U =R
                  S-  sl        M8     SU l        g7f)z0Iterate through the lines of a multiline string.r   Té   FN)	Útyper
   r.   Ústartr%   r!   ÚrangeÚendr   )r/   ÚtokenrH   Ú_s       r0   Úmultiline_stringÚFileProcessor.multiline_string‚   s…   é € ð �:‰:œÓ$Ø×'Ñ'‰Eà—K‘K ‘NˆEàˆŒØ Ôô �uŸi™i¨™lÖ+ˆAØ—*‘*˜T×-Ñ-°Ñ1Ñ2Ò2Ø×Ò Ñ!×ñ ,ð ˆ�ùs   ‚BBc                ó   • SU l         g)z)Reset the blank_before attribute to zero.r   N)r   ©r/   s    r0   Úreset_blank_beforeÚ FileProcessor.reset_blank_before”   s
   € àˆÕr3   c                ó   • U R                   S	 g)z-Delete the first token in the list of tokens.r   N)r)   rP   s    r0   Údelete_first_tokenÚ FileProcessor.delete_first_token˜   s   € à�K‰K˜‰Nr3   c                ó.   • U =R                   S-  sl         g)z&Note that we visited a new blank line.rF   N)r   rP   s    r0   Úvisited_new_blank_lineÚ$FileProcessor.visited_new_blank_lineœ   s   € à×Ò˜AÑÖr3   c                óº   • US   S   u  p#U R                   US-
     n[        USU 5      U l        U R                  U R                  :  a  U R                  U l        gg)z:Update the indent level based on the logical line mapping.r   rF   N)r   Úexpand_indentr   r   r   )r/   ÚmappingÚ	start_rowÚ	start_colÚ
start_lines        r0   Úupdate_stateÚFileProcessor.update_state    s_   € à!(¨¡¨A¡ÑˆØ—Z‘Z 	¨A¡Ñ.ˆ
Ü)¨*°Z°iÐ*@ÓAˆÔØ×Ñ˜t×/Ñ/Ó/Ø $× 0Ñ 0ˆDÕð 0r3   c                ó|   • SUR                   ;   a,  U R                  R                  UR                  0 5      U l        gg)z2Update the checker_state attribute for the plugin.r   N)Ú
parametersr   Ú
setdefaultÚ
entry_namer   )r/   Úplugins     r0   Úupdate_checker_state_forÚ&FileProcessor.update_checker_state_for¨   s9   € à˜f×/Ñ/Ó/Ø!%×!5Ñ!5×!@Ñ!@Ø×!Ñ! 2ó"ˆDÕð 0r3   c                óÊ   • U R                   (       aD  U R                  U l        U R                   U l        U R                  (       d  U R                   U l        SU l        / U l        g)z_Record the previous logical line.

This also resets the tokens list and the blank_lines count.
r   N)r"   r   r&   r'   r(   r   r)   rP   s    r0   Únext_logical_lineÚFileProcessor.next_logical_line¯   sO   € ð
 ××Ø)-×):Ñ):ˆDÔ&Ø$(×$5Ñ$5ˆDÔ!Ø×$×$Ø8<×8IÑ8I�Ô5ØˆÔØˆ�r3   c                ó°  • / n/ n/ nSnS=pVU R                    GH7  u  pxpšnU[        ;   a  M  U(       d  SU	4/nU[        R                  :X  a  UR	                  U5        MG  U[        R
                  :X  a  [        U5      nOKU[        :X  aA  UR                  S5      UR                  S5      -   nS[        U5      U-   -  nU
S   U
S   U-   4n
U(       aI  U	u  pÞX]:w  a4  US-
  nUS-
  nU R                  U   U   nUS:X  d  US;  a  US	;  a  S
U 3nOXn:w  a  X¶U U-   nUR	                  U5        U[        U5      -  nUR	                  XJ45        U
u  pVGM:     X!U4$ )z4Build the mapping, comments, and logical line lists.r   NÚ{Ú}ÚxrF   Ú,z{[(ú}])Ú )r)   ÚSKIP_TOKENSr=   ÚCOMMENTÚappendÚSTRINGÚmutate_stringr   Úcountr*   r   )r/   ÚlogicalÚcommentsr[   ÚlengthÚprevious_rowÚprevious_columnÚ
token_typeÚtextrH   rJ   ÚlineÚbrace_offsetr\   Ústart_columnÚ	row_indexÚcolumn_indexÚprevious_texts                     r0   Úbuild_logical_line_tokensÚ'FileProcessor.build_logical_line_tokens¼   s~  € àˆØˆØ#%ˆØˆØ)-Ð-ˆØ26·+µ+Ñ.ˆJ˜e¨$Øœ[Ó(ÙÞØ˜u˜:˜,�ØœX×-Ñ-Ó-Ø—‘ Ô%ÙØœXŸ_™_Ó,Ü$ TÓ*‘Øœ~Ó-ð
  $Ÿz™z¨#›°·±¸C³Ñ@�Øœc $›i¨,Ñ6Ñ7�Ø˜1‘v˜s 1™v¨Ñ4Ð5�ÞØ,1Ñ)�ØÓ,Ø ,¨qÑ 0�IØ#2°QÑ#6�LØ$(§J¡J¨yÑ$9¸,Ñ$G�MØ$¨Ó+Ø%¨UÓ2°tÀ5Ó7Hà!" 4 &˜z˜øØ$Ó4Ø°Ð=ÀÑD�DØ�N‰N˜4Ô Ø”c˜$“iÑˆFØ�N‰N˜F˜=Ô)Ø.1Ñ+ˆ\š?ñC 3>ðD  'Ð)Ð)r3   c                ó`   • [         R                  " SR                  U R                  5      5      $ )z5Build an abstract syntax tree from the list of lines.r   )ÚastÚparseÚjoinr   rP   s    r0   Ú	build_astÚFileProcessor.build_astç   s   € ä�yŠy˜Ÿ™ §¡Ó,Ó-Ð-r3   c                óÀ   • U R                  5       u  pnSR                  U5      nSR                  U5      U l        U R                  S==   S-  ss'   X@R                  U4$ )z2Build a logical line from the current tokens list.r   r   rF   )r…   rŠ   r"   r-   )r/   ry   rx   Úmapping_listÚjoined_commentss        r0   Úbuild_logical_lineÚ FileProcessor.build_logical_lineë   sY   € à*.×*HÑ*HÓ*JÑ'ˆ˜<ØŸ'™' (Ó+ˆØŸG™G GÓ,ˆÔØ�‰˜Ó(¨AÑ-Ó(Ø× 1Ñ 1°<Ð?Ð?r3   c                óÄ   • 0 nUR                  5        H  u  pEXB;   a  M   [        X5      X4'   M     U$ ! [         a"    U(       a  e [        R	                  SU5         MK  f = f)z8Generate the keyword arguments for a list of parameters.zPPlugin requested optional parameter "%s" but this is not an available parameter.)ÚitemsÚgetattrÚAttributeErrorÚLOGÚwarning)r/   rb   Ú	argumentsÚretÚparamÚrequireds         r0   Úkeyword_arguments_forÚ#FileProcessor.keyword_arguments_foró   sk   € ð ˆØ)×/Ñ/Ö1‰OˆEØÓ!Ùð
Ü$ TÓ1�“
ñ	  2ð ˆ
øô "ó ÞØä—K‘KðBà÷ð	ús    3³(AÁAc              #  óÈ   #   • [         R                  " U R                  5       H:  nUS   S   U R                  :”  a    gU R                  R                  U5        Uv •  M<     g7f)z'Tokenize the file and yield the tokens.é   r   N)r=   r>   Ú	next_liner+   r)   rt   )r/   rK   s     r0   r>   ÚFileProcessor.generate_tokens
  sN   é € ä×-Ò-¨d¯n©nÖ=ˆEØ�Q‰x˜‰{˜T×-Ñ-Ó-ÙØ�K‰K×Ñ˜uÔ%ØŒKò	 >ùs   ‚A A"c                óŠ   • [        XS-   5      nSR                  U R                  US-
  U 5      n[        R	                  X45      $ )NrF   r   )rI   rŠ   r   ÚdictÚfromkeys)r/   Úmin_lineÚmax_lineÚ
line_rangeÚjoineds        r0   Ú_noqa_line_rangeÚFileProcessor._noqa_line_range  s<   € Ü˜8°¡\Ó2ˆ
Ø—‘˜Ÿ™ H¨q¡L°8Ð<Ó=ˆÜ�}‰}˜ZÓ0Ð0r3   c                ó  •  U R                   n0 n[        U R                  5      S-   nSnU H­  u  pVu  pvu  n  nU[        R                  :X  d  U[        R
                  :X  a  M7  [        X75      n[        XH5      nU[        R                  [        R                  4;   d  Ms  UR                  U R                  X45      5        [        U R                  5      S-   nSnM¯     U$ ! [        R                  [        4 a    0 s $ f = f)z<Map from line number to the line we'll search for `noqa` in.rŸ   r   )r?   r*   r   r=   Ú	ENDMARKERÚDEDENTÚminÚmaxÚNLÚNEWLINEÚupdater©   Ú
TokenErrorÚSyntaxError)	r/   r?   r™   r¥   r¦   ÚtprL   Ús_lineÚe_lines	            r0   Ú_noqa_line_mappingÚ FileProcessor._noqa_line_mapping  sé   € ð	Ø×*Ñ*ˆKð ˆCä˜4Ÿ:™:“¨Ñ*ˆHØˆHÛ6AÑ2�‘{˜¡K V¨Q°Øœ×+Ñ+Ó+¨r´X·_±_Ó/DÙä˜xÓ0�Ü˜xÓ0�àœ(Ÿ+™+¤x×'7Ñ'7Ð8Õ8Ø—J‘J˜t×4Ñ4°XÓHÔIä" 4§:¡:›°Ñ2�HØ!’Hñ 7Bð ˆJøô- ×#Ñ#¤[Ð1ó 	ð ŠIð	ús   ‚C ÃC>Ã=C>c                ó8   • U R                   R                  U5      $ )z7Retrieve the line which will be used to determine noqa.)r¸   Úget)r/   r!   s     r0   Únoqa_line_forÚFileProcessor.noqa_line_for4  s   € ð
 ×&Ñ&×*Ñ*¨;Ó7Ð7r3   c                óô   • U R                   U R                  :¼  a  gU R                  U R                      nU =R                   S-  sl         U R                  c!  USS [        R
                  ;   a
  US   U l        U$ )z Get the next line from the list.r   rF   Nr   )r!   r+   r   r   r   Ú
WHITESPACE)r/   r   s     r0   r    ÚFileProcessor.next_line;  sn   € à×Ñ˜t×/Ñ/Ó/ØØ�z‰z˜$×*Ñ*Ñ+ˆØ×Ò˜AÑÕØ×ÑÑ#¨¨R¨a¨´H×4GÑ4GÓ(GØ# A™wˆDÔØˆr3   c                ó²   • U R                   S:X  a6  U R                  R                  =(       d    SU l         U R                  5       nU$ U R	                  5       nU$ )z%Read the lines for this file checker.Ú-Ústdin)r   r   Ústdin_display_nameÚread_lines_from_stdinÚread_lines_from_filename)r/   r   s     r0   r   ÚFileProcessor.read_linesE  sN   € à�=‰=˜CÓØ ŸL™L×;Ñ;×F¸wˆDŒMØ×.Ñ.Ó0ˆEð ˆð ×1Ñ1Ó3ˆEØˆr3   c                óF  •  [         R                  " U R                  5       nUR                  5       sSSS5        $ ! , (       d  f       g= f! [        [
        4 aC    [        U R                  SS9 nUR                  5       sSSS5        s $ ! , (       d  f        g= ff = f)zRead the lines for a file.Nzlatin-1)Úencoding)r=   Úopenr   Ú	readlinesr´   ÚUnicodeError)r/   Úfds     r0   rÆ   Ú&FileProcessor.read_lines_from_filenameN  sk   € ð	&Ü—’˜tŸ}™}Ô-°Ø—|‘|“~÷ .×-×-ûäœ\Ð*ó 	&ô �d—m‘m¨iÒ8¸BØ—|‘|“~÷ 9×8×8Ò8úð	&úsC   ‚ A ¢<²	A ¼
A
ÁA Á
A Á$B Á1BÂ
B Â
B	ÂB ÂB c                ó,   • [         R                  " 5       $ )z Read the lines from standard in.)r	   Ústdin_get_linesrP   s    r0   rÅ   Ú#FileProcessor.read_lines_from_stdinY  s   € ä×$Ò$Ó&Ð&r3   c                óì   • U R                   R                  (       d"  [        S U R                   5       5      (       a  g[        S U R                   5       5      (       a  [        R                  S5        gg)zŽCheck if ``flake8: noqa`` is in the file to be ignored.

:returns:
    True if a line matches :attr:`defaults.NOQA_FILE`,
    otherwise False
c              3  ó^   #   • U H$  n[         R                  R                  U5      v •  M&     g 7fr6   )r   Ú	NOQA_FILEÚmatch©Ú.0r   s     r0   Ú	<genexpr>Ú3FileProcessor.should_ignore_file.<locals>.<genexpr>d  s'   é € ð 1
Ù7A¨tŒH×Ñ×$Ñ$ T×*Ð*²zùó   ‚+-Tc              3  ó^   #   • U H$  n[         R                  R                  U5      v •  M&     g 7fr6   )r   rÔ   ÚsearchrÖ   s     r0   rØ   rÙ   h  s$   é € ÐH¹Z°T”×#Ñ#×*Ñ*¨4×0Ð0ºZùrÚ   z[Detected `flake8: noqa` on line with code. To ignore an error on a line use `noqa` instead.F)r   Údisable_noqaÚanyr   r–   r—   rP   s    r0   Úshould_ignore_fileÚ FileProcessor.should_ignore_file]  sa   € ð �|‰|×(×(¬Sñ 1
Ø7;·z²zó1
÷ .
ñ .
ð ÜÑH¸T¿ZºZÓH×HÑHÜ�K‰Kð6ôð àr3   c                ó   • U R                   (       d  gU R                   S   SS S:X  a   U R                   S   SS U R                   S'   gU R                   S   SS S:X  a   U R                   S   SS U R                   S'   gg)z-Strip the UTF bom from the lines of the file.Nr   rF   u   ï»¿é   u   Ã¯Â»Â¿)r   rP   s    r0   r   ÚFileProcessor.strip_utf_bomq  sy   € à�z�zàð �:‰:�a‰=˜˜!Ð Ó(Ø ŸJ™J q™M¨!¨"Ð-ˆD�J‰J�qŠMØ�Z‰Z˜‰]˜2˜AÐ .Ó0Ø ŸJ™J q™M¨!¨"Ð-ˆD�J‰J�qŠMð 1r3   )r   r.   r   r   r   r   r   r   r   r    r!   r   r"   r$   r#   r%   r   r&   r'   r(   r-   r)   r+   r,   r6   )r   Ústrr   zargparse.Namespacer   zlist[str] | NoneÚreturnÚNone)rå   zlist[tokenize.TokenInfo])rB   Úintrå   ræ   )rK   útokenize.TokenInforå   zGenerator[str, None, None])rå   ræ   )r[   Ú_LogicalMappingrå   ræ   )re   r   rå   ræ   )rå   Ú_Logical)rå   zast.AST)rå   z tuple[str, str, _LogicalMapping])rb   zdict[str, bool]r˜   údict[str, Any]rå   rë   )rå   z)Generator[tokenize.TokenInfo, None, None])r¥   rç   r¦   rç   rå   údict[int, str])rå   rì   )r!   rç   rå   z
str | None)rå   rä   )rå   z	list[str])rå   Úbool)!Ú__name__Ú
__module__Ú__qualname__Ú__firstlineno__Ú__doc__Únoqar1   Ú	functoolsÚcached_propertyr?   rC   rM   rQ   rT   rW   r_   rf   ri   r…   r‹   r�   rœ   r>   r©   r¸   r¼   r    r   rÆ   rÅ   rß   r   Ú__static_attributes__© r3   r0   r   r      s  † ñð8 €Dð #'ð	8!àð8!ð $ð8!ð  ð	8!ð
 
õ8!ðt ×ÑóGó ðGô
%ðØ'ðà	#ôô$ôôô1ôôô)*ôV.ô@ðà#ðð "ðð 
ô	ô.ô1ð
 ×Ñóó ðô88ôôô	&ô'ô÷(
.r3   r   c                óf   • U S   [         ;   =(       d    U S   U S   S   S R                  5       S:H  $ )z+Check if the token is an end-of-line token.r   é   râ   rF   Nz\
)r±   Úlstrip©rK   s    r0   Úis_eol_tokenrü   ~  s7   € à�‰8”wÑ×L %¨¡(¨5°©8°A©;¨=Ð"9×"@Ñ"@Ó"BÀfÑ"LÐLr3   c                óœ   • U R                   [        :H  =(       d3    U R                   [        R                  :H  =(       a    SU R                  ;   $ )z$Check if this is a multiline string.Ú
)rG   r
   r=   ru   Ústringrû   s    r0   Úis_multiline_stringr   ƒ  s6   € à�:‰:œÑ$÷ Ø�
‰
”h—o‘oÑ%×>¨$°%·,±,Ñ*>ðr3   c                ó   • U S   [         ;   $ )z0Check if the token type is a newline token type.r   )r±   rû   s    r0   Útoken_is_newliner  Š  s   € à�‰8”wÑÐr3   c                ó2   • US;   a  U S-   $ US;   a  U S-
  $ U $ )z Count the number of parentheses.z([{rF   rp   r÷   )Úcurrent_parentheses_countÚ
token_texts     r0   Úcount_parenthesesr  �  s.   € à�UÓØ(¨1Ñ,Ð,Ø	�uÓ	Ø(¨1Ñ,Ð,Ø$Ð$r3   c                ó6   • [        U R                  S5      5      $ )zËReturn the amount of indentation.

Tabs are expanded to the next multiple of 8.

>>> expand_indent('    ')
4
>>> expand_indent('\t')
8
>>> expand_indent('       \t')
8
>>> expand_indent('        \t')
16
é   )r*   Ú
expandtabs)r   s    r0   rZ   rZ   ˜  s   € ô ˆt�‰˜qÓ!Ó"Ð"r3   c                ó–   • U R                  U S   5      S-   n[        U 5      S-
  nU SS S;   a
  US-  nUS-  nU SU SX!-
  -  -   XS -   $ )z¬Replace contents with 'xxx' to prevent syntax matching.

>>> mutate_string('"abc"')
'"xxx"'
>>> mutate_string("'''abc'''")
"'''xxx'''"
>>> mutate_string("r'abc'")
"r'xxx'"
r   rF   éýÿÿÿN)z"""z'''rŸ   rn   )Úindexr*   )r~   rH   rJ   s      r0   rv   rv   ¬  si   € ð �J‰J�t˜B‘xÓ  1Ñ$€EÜ
ˆd‹)�a‰-€CàˆBˆC€y�NÓ"Ø�‰
ˆØˆq‰ˆØ��ˆ<˜# ¡Ñ-Ñ-°°T°
Ñ:Ð:r3   )rK   rè   rå   rí   )r  rç   r  rä   rå   rç   )r   rä   rå   rç   )r~   rä   rå   rä   ))rò   Ú
__future__r   Úargparserˆ   rô   Úloggingr=   Útypingr   r   r   r   Úflake8r   r	   Úflake8._compatr
   r   Úflake8.plugins.finderr   Ú	getLoggerrî   r–   Ú	frozensetr°   r±   ÚINDENTr­   rr   rç   ré   rä   rê   r   rü   r   r  r  rZ   rv   r÷   r3   r0   Ú<module>r     sé   ðÙ LÝ "ã Û 
Û Û Û Ý Ý Ý Ý å Ý Ý &Ý )Ý .à×Ò˜Ó!€Ù
�X—[‘[ (×"2Ñ"2Ð3Ó
4€áØ‡[�[�(×"Ñ" H§O¡O°X·_±_ÐEó€ð �u˜S %¨¨S¨¡/Ð1Ñ2Ñ3€Ø��c‘˜D ™I Ð6Ñ7€÷\.ñ \.ô~
Mô
ôô
%ô#õ(;r3   