
    dafsk                         d Z dZddlZddlZddlZddlZddlZddlZddlZddl	m
Z
 ddlmZmZmZ ddlmZ ddlmZmZ dd	lmZ dd
Z G d de      Zd Zd Zd Zd Zd Z G d de      Z G d de      Z  G d de      Z! G d de       Z"y)zRefactoring framework.

Used as a main program, this can refactor any number of files and/or
recursively descend down directories.  Imported as a module, this
provides infrastructure to write your own refactoring tool.
z#Guido van Rossum <guido@python.org>    N)chain   )drivertokenizetoken)	find_root)pytreepygram)btm_matcherc                     t        | g g dg      }g }t        j                  |j                        D ]0  \  }}}|j	                  d      s|r|dd }|j                  |       2 |S )zEReturn a sorted list of all available fix names in the given package.*fix_   N)
__import__pkgutiliter_modules__path__
startswithappend)	fixer_pkgremove_prefixpkg	fix_namesfindernameispkgs          +/root/Python-3.12.4/Lib/lib2to3/refactor.pyget_all_fix_namesr      sn    
YB
.CI&33CLLA #e??6"ABxT"	#
     c                       e Zd Zy)
_EveryNodeN__name__
__module____qualname__ r   r   r!   r!   +       r   r!   c                    t        | t        j                  t        j                  f      r| j                  t
        | j                  hS t        | t        j                        r'| j                  rt        | j                        S t
        t        | t        j                        r>t               }| j                  D ]#  }|D ]  }|j                  t        |              % |S t        d| z        )zf Accepts a pytree Pattern Node and returns a set
        of the pattern types which will match first. z$Oh no! I don't understand pattern %s)
isinstancer	   NodePatternLeafPatterntyper!   NegatedPatterncontent_get_head_typesWildcardPatternsetupdate	Exception)patrpxs       r   r/   r/   /   s     #**F,>,>?@ 88z#v,,-;;"3;;//#v--.E 	-A -+,-	- 
:SA
BBr   c                 X   t        j                  t              }g }| D ]|  }|j                  r2	 t	        |j                        }|D ]  }||   j                  |        A|j                  ||j                     j                  |       l|j                  |       ~ t        t        j                  j                  j                         t        j                  j                        D ]  }||   j                  |        t        |      S # t        $ r |j                  |       Y 
w xY w)z^ Accepts a list of fixers and returns a dictionary
        of head node type --> fixer list.  )collectionsdefaultdictlistpatternr/   r   r!   _accept_typer   r
   python_grammarsymbol2numbervaluestokensextenddict)
fixer_list
head_nodeseveryfixerheads	node_types         r   _get_headnode_dictrJ   K   s    ((.JE $==8'6 "' 8Iy)0078 !!-5--.55e<U#$ 600>>EEG!00779 ,	9$$U+, 
  $U#$s   DD)(D)c                 L    t        | d      D cg c]
  }| dz   |z    c}S c c}w )zN
    Return the fully qualified names for fixers in the package pkg_name.
    F.)r   )pkg_namefix_names     r   get_fixers_from_packagerO   d   s8    
 .h>@ sNX% @ @ @s   !c                     | S Nr&   )objs    r   	_identityrS   k   s    Jr   c                 |   d}t        j                  t        j                  |       j                        fd}t        t        j                  t         j                  t        j                  h      }t               }	 	  |       \  }}||v r|t        j                  k(  r|rnd}n|t        j                  k(  r|dk(  r |       \  }}|t        j                  k7  s|dk7  rn |       \  }}|t        j                  k7  s|dk7  rn |       \  }}|t        j                  k(  r|dk(  r
 |       \  }}|t        j                  k(  rT|j                  |        |       \  }}|t        j                  k7  s|dk7  rn  |       \  }}|t        j                  k(  rRnnt        |      S # t        $ r Y t        |      S w xY w)	NFc                  .    t              } | d   | d   fS )Nr   r   )next)tokgens    r   advancez(_detect_future_features.<locals>.advancer   s    3i1vs1v~r   Tfrom
__future__import(,)r   generate_tokensioStringIOreadline	frozensetr   NEWLINENLCOMMENTr1   STRINGNAMEOPaddStopIteration)sourcehave_docstringrY   ignorefeaturestpvaluerX   s          @r   _detect_future_featuresrr   o   s   N

"
"2;;v#6#?#?
@C x{{EMMBCFuH	IBV|u||#!!%uzz!evo#I	E#u'<#I	E#u'8#I	E>esl '	IBEJJ&LL' '	IBUXX~# '	IB EJJ& 3 8 X  Xs   >DF% F% %	F;:F;c                       e Zd ZdZy)
FixerErrorzA fixer could not be loaded.N)r#   r$   r%   __doc__r&   r   r   rt   rt      s    &r   rt   c                       e Zd ZddddZdZdZddZd Zd Zd	 Z	d
 Z
d ZddZddZd ZddZd Zd dZd Zd Z	 	 d!dZd"dZdZdZd Zd Zd Zd Zd Zd Zy)#RefactoringToolF)print_functionexec_functionwrite_unchanged_filesFixr   Nc                    || _         |xs g | _        | j                  j                         | _        || j                  j                  |       t        j                  j                         | _        | j                  d   r| j                  j                  d= n&| j                  d   r| j                  j                  d= | j                  j                  d      | _        g | _        t        j                  d      | _        g | _        d| _        t%        j&                  | j                  t(        j*                  | j                  	      | _        | j-                         \  | _        | _        g | _        t5        j6                         | _        g | _        g | _        t?        | j0                  | j.                        D ]~  }|j@                  r| j8                  jC                  |       +|| j.                  v r| j:                  jE                  |       U|| j0                  v sd| j<                  jE                  |        tG        | j:                        | _$        tG        | j<                        | _%        y)
zInitializer.

        Args:
            fixer_names: a list of fixers to import
            options: a dict with configuration.
            explicit: a list of fixers to run even if they are explicit.
        Nrx   printry   execrz   rw   F)convertlogger)&fixersexplicit_default_optionscopyoptionsr2   r
   r>   grammarkeywordsgetrz   errorslogging	getLoggerr   	fixer_logwroter   Driverr	   r   
get_fixers	pre_order
post_orderfilesbmBottomMatcherBMbmi_pre_orderbmi_post_orderr   BM_compatible	add_fixerr   rJ   bmi_pre_order_headsbmi_post_order_heads)selffixer_namesr   r   rG   s        r   __init__zRefactoringTool.__init__   s    " B,,113LL(,,113<<()%%g.\\/*%%f-
 &*\\%5%56M%N"''(9:
mmDLL,2NN+/;;8 +///*;' 
""$ 4??DNN; 	2E""!!%( $..(""))%0$//)##**51	2 $6d6H6H#I $6t7J7J$K!r   c           	         g }g }| j                   D ]w  }t        |i i dg      }|j                  dd      d   }|j                  | j                        r|t        | j                        d }|j                  d      }| j                  dj                  |D cg c]  }|j                          c}      z   }	 t        ||      }	 |	| j                  | j                        }
|
j                  r0| j                  d	ur"|| j                  vr| j!                  d
|       | j#                  d|       |
j$                  dk(  r|j'                  |
       @|
j$                  dk(  r|j'                  |
       bt        d|
j$                  z         t)        j*                  d      }|j-                  |       |j-                  |       ||fS c c}w # t        $ r t        d|d|      dw xY w)a  Inspects the options to load the requested patterns and handlers.

        Returns:
          (pre_order, post_order), where pre_order is the list of fixers that
          want a pre-order AST traversal, and post_order is the list that want
          post-order traversal.
        r   rL   r   N_ zCan't find TzSkipping optional fixer: %szAdding transformation: %sprepostzIllegal fixer order: %r	run_orderkey)r   r   rsplitr   FILE_PREFIXlensplitCLASS_PREFIXjointitlegetattrAttributeErrorrt   r   r   r   log_message	log_debugorderr   operator
attrgettersort)r   pre_order_fixerspost_order_fixersfix_mod_pathmodrN   partsr6   
class_name	fix_classrG   key_funcs               r   r   zRefactoringTool.get_fixers   s     KK 	JL\2rC59C#**3226H""4#3#34#C(8(8$9$:;NN3'E**RWW5OAaggi5O-PPJX#C4	 dllDNN;E~~$--t"; 5  !>INN6A{{e# ''.&!((/ !:U[[!HII/	J2 &&{3(+8, "344- 6P " X x!LMSWWXs   G	8GG*c                       )zCalled when an error occurs.r&   )r   msgargskwdss       r   	log_errorzRefactoringTool.log_error  s    r   c                 H    |r||z  }| j                   j                  |       y)zHook to log a message.N)r   infor   r   r   s      r   r   zRefactoringTool.log_message  s     *Cr   c                 H    |r||z  }| j                   j                  |       y rQ   )r   debugr   s      r   r   zRefactoringTool.log_debug  s     *C#r   c                      y)zTCalled with the old version, new version, and filename of a
        refactored file.Nr&   )r   old_textnew_textfilenameequals        r   print_outputzRefactoringTool.print_output  s     	r   c                     |D ]H  }t         j                  j                  |      r| j                  |||       6| j	                  |||       J y)z)Refactor a list of files and directories.N)ospathisdirrefactor_dirrefactor_file)r   itemswritedoctests_onlydir_or_files        r   refactorzRefactoringTool.refactor  sI     ! 	FKww}}[)!!+umD"";}E		Fr   c                    t         j                  dz   }t        j                  |      D ]  \  }}}| j                  d|       |j	                          |j	                          |D ]m  }|j                  d      rt         j                  j                  |      d   |k(  s;t         j                  j                  ||      }	| j                  |	||       o |D 
cg c]  }
|
j                  d      r|
 c}
|dd  yc c}
w )zDescends down a directory and refactor every Python file found.

        Python files are assumed to have a .py extension.

        Files and subdirectories starting with '.' are skipped.
        pyzDescending into %srL   r   N)
r   extsepwalkr   r   r   r   splitextr   r   )r   dir_namer   r   py_extdirpathdirnames	filenamesr   fullnamedns              r   r   zRefactoringTool.refactor_dir   s     T!,.GGH,= 
	L(GXyNN/9MMONN! G,GG$$T*1-7!ww||GT:H&&xF	G )1K"c8J2KHQK
	L Ls   C</C<c                    	 t        |d      }	 t        j                  |j
                        d   }|j                          t        j                   |d|d      5 }|j                         |fcddd       S # t        $ r}| j                  d||       Y d}~yd}~ww xY w# |j                          w xY w# 1 sw Y   yxY w)	zG
        Do our best to decode a Python source file correctly.
        rbzCan't open %s: %sNNNr   r5   r   encodingnewline)	openOSErrorr   r   detect_encodingrb   closer`   read)r   r   ferrr   s        r   _read_python_sourcez#RefactoringTool._read_python_source4  s    	Xt$A	//

;A>HGGIWWXsXrB 	&a668X%	& 	&  	NN.#>	 GGI	& 	&s.   A6 "B B46	B?BBB14B=c                    | j                  |      \  }}|y|dz  }|r^| j                  d|       | j                  ||      }| j                  s||k7  r| j	                  |||||       y| j                  d|       y| j                  ||      }| j                  s|r.|j                  r"| j	                  t        |      dd |||       y| j                  d|       y)zRefactors a file.N
zRefactoring doctests in %szNo doctest changes in %sr   )r   r   zNo changes in %s)r   r   refactor_docstringrz   processed_filerefactor_stringwas_changedstr)r   r   r   r   inputr   outputtrees           r   r   zRefactoringTool.refactor_fileD  s    228<x=NN7B,,UH=F))Vu_##FHeUHM98D''x8D))dt7G7G##CIcrNH*/( $ D 18<r   c                    t        |      }d|v rt        j                  | j                  _        	 | j                  j                  |      }	 | j                  | j                  _        ||_
        | j                  d|       | j                  ||       |S # t        $ rM}| j                  d||j                  j                  |       Y d}~| j                  | j                  _        yd}~ww xY w# | j                  | j                  _        w xY w)aF  Refactor a given input string.

        Args:
            data: a string holding the code to be refactored.
            name: a human-readable name for use in error/log messages.

        Returns:
            An AST corresponding to the refactored input stream; None if
            there were errors during the parse.
        rx   zCan't parse %s: %s: %sNzRefactoring %s)rr   r
   !python_grammar_no_print_statementr   r   parse_stringr3   r   	__class__r#   future_featuresr   refactor_tree)r   datar   ro   r   r   s         r   r   zRefactoringTool.refactor_string[  s     +40x'"("J"JDKK	/;;++D1D #',,DKK''.4&  	NN3!7!7>"&,,DKK	
 #',,DKKs)   B 	C*(C%C- %C**C- -D
c                    t         j                  j                         }|rZ| j                  d       | j	                  |d      }| j
                  s||k7  r| j                  |d|       y | j                  d       y | j                  |d      }| j
                  s|r)|j                  r| j                  t        |      d|       y | j                  d       y )NzRefactoring doctests in stdinz<stdin>zNo doctest changes in stdinzNo changes in stdin)
sysstdinr   r   r   rz   r   r   r   r   )r   r   r   r   r   s        r   refactor_stdinzRefactoringTool.refactor_stdinv  s    		 NN:;,,UI>F))Vu_##FIu=<=''y9D))dt7G7G##CIy%@45r   c                    t        | j                  | j                        D ]  }|j                  ||        | j	                  | j
                  |j                                | j	                  | j                  |j                                | j                  j                  |j                               }t        |j                               r| j                  j                  D ]  }||v s	||   s||   j                  t        j                  j                   d       |j"                  r-||   j                  t        j                  j$                         t'        ||         D ]  }|||   v r||   j)                  |       	 t+        |       |j.                  r||j.                  v rF|j1                  |      }|sZ|j3                  ||      }|o|j5                  |       |j                         D ]0  }|j.                  sg |_        |j.                  j7                  |       2 | j                  j                  |j                               }|D ]"  }	|	|vrg ||	<   ||	   j9                  ||	          $   t        |j                               rt        | j                  | j                        D ]  }|j;                  ||        |j<                  S # t,        $ r Y w xY w)a  Refactors a parse tree (modifying the tree in place).

        For compatible patterns the bottom matcher module is
        used. Otherwise the tree is traversed node-to-node for
        matches.

        Args:
            tree: a pytree.Node instance representing the root of the tree
                  to be refactored.
            name: a human-readable name for this tree.

        Returns:
            True if the tree was modified, False otherwise.
        T)r   reverser   )r   r   r   
start_treetraverse_byr   r   r   runleavesanyr@   r   r   r	   Basedepthkeep_line_order
get_linenor;   remover   
ValueErrorfixers_appliedmatch	transformreplacer   rB   finish_treer   )
r   r   r   rG   	match_setnoderesultsnewnew_matchesfxrs
             r   r  zRefactoringTool.refactor_tree  s     4>>4??; 	)ET4(	) 	114>>3CD22DOO4EF GGKK.	)""$% .LI%)E*:e$))fkk.?.?)N,, "%(--&++2H2H-I $Yu%5 6 $L9U#33%e,33D9%%dO  ..5D<O<O3O$"'++d"3""'//$"@C" $S 1,/NN,< !FD ,0+>+>>@(;$($7$7$>$>u$E!F /3ggkk#**,.G+6 !LC+.)+;79	#$-cN$9$9+c:J$K	!LA$L.L )""$%b 4>>4??; 	*EdD)	*E  * % %%s   	K  	K-,K-c                     |sy|D ]R  }||j                      D ]>  }|j                  |      }|s|j                  ||      }|,|j                  |       |}@ T y)a  Traverse an AST, applying a set of fixers to each node.

        This is a helper method for refactor_tree().

        Args:
            fixers: a list of fixer instances.
            traversal: a generator that yields AST nodes.

        Returns:
            None
        N)r,   r  r  r  )r   r   	traversalr  rG   r  r  s          r   r  zRefactoringTool.traverse_by  sh      	#D		* #++d+//$8CS)"#	#r   c                 2   | j                   j                  |       || j                  |      d   }|y||k(  }| j                  ||||       |r| j	                  d|       | j
                  sy|r| j                  ||||       y| j	                  d|       y)zR
        Called when a file has been refactored and there may be changes.
        Nr   zNo changes to %szNot writing changes to %s)r   r   r   r   r   rz   
write_file)r   r   r   r   r   r   r   s          r   r   zRefactoringTool.processed_file  s    
 	

(#//9!<HH$(Hh>NN-x8--OOHh(CNN6Ar   c                 `   	 t        j                  |d|d      }|5  	 |j	                  |       ddd       | j                  d|       d| _        y# t        $ r}| j                  d||       Y d}~yd}~ww xY w# t        $ r}| j                  d||       Y d}~ld}~ww xY w# 1 sw Y   uxY w)	zWrites a string to a file.

        It first shows a unified diff between the old text and the new text, and
        then rewrites the file; the latter is only done if the write option is
        set.
        wr   r   zCan't create %s: %sNzCan't write %s: %szWrote changes to %sT)r`   r   r   r   r   r   r   )r   r   r   r   r   fpr   s          r   r$  zRefactoringTool.write_file  s    	32FB
  	DD"	D
 	,h7
  	NN0(C@	  D3XsCCD	D 	DsE   A B$A;	A8A33A8;	B!BB$B!!B$$B-z>>> z... c           	         g }d}d}d}d}|j                  d      D ]  }|dz  }|j                         j                  | j                        rK|#|j	                  | j                  ||||             |}|g}|j                  | j                        }	|d|	 }}|S|j                  || j                  z         s#||| j                  j                         z   dz   k(  r|j                  |       |#|j	                  | j                  ||||             d}d}|j                  |        |#|j	                  | j                  ||||             dj                  |      S )a  Refactors a docstring, looking for doctests.

        This returns a modified version of the input string.  It looks
        for doctests, which start with a ">>>" prompt, and may be
        continued with "..." prompts, as long as the "..." is indented
        the same as the ">>>".

        (Unfortunately we can't use the doctest module's parser,
        since, like most parsers, it is not geared towards preserving
        the original source.)
        Nr   Tkeependsr   r   r   )
splitlineslstripr   PS1rB   refactor_doctestfindPS2rstripr   r   )
r   r   r   resultblockblock_linenoindentlinenolineis
             r   r   z"RefactoringTool.refactor_docstring  sl    $$d$3 	$DaKF{{}''1$MM$"7"7|8>#J K%IIdhh'bq$??6DHH#456DHHOO$55<<T"$MM$"7"7|8>#J Kd#)	$* MM$//|06B Cwwvr   c                    	 | j                  |||      }| j                  ||      rt        |      j                  d      }|d|dz
   ||dz
  d }}	|	dg|dz
  z  k(  sJ |	       |d   j                  d      s|dxx   dz  cc<   || j                  z   |j!                  d	      z   g}|r#||D cg c]  }|| j"                  z   |z    c}z  }|S # t        $ r}| j                  j                  t        j
                        r(|D ]#  }| j                  d|j                  d             % | j                  d|||j                  j                  |       |cY d}~S d}~ww xY wc c}w )
zRefactors one doctest.

        A doctest is given as a block of lines, the first of which starts
        with ">>>" (possibly indented), while the remaining lines start
        with "..." (identically indented).

        z
Source: %sr   z+Can't parse docstring in %s line %s: %s: %sNTr)  r   r   r   )parse_blockr3   r   isEnabledForr   DEBUGr   r1  r   r  r#   r  r   r+  endswithr-  popr0  )
r   r3  r6  r5  r   r   r   r7  r  clippeds
             r   r.  z RefactoringTool.refactor_doctestD  sd   	##E66:D dH-d)&&&5Cyq>3vaxy>SGtfq11:7:1r7##D)B4dhh&34EsCt&488+d2CC#  	{{''6! DDNN<T1BCDNNH#VS]]-C-CSJL	  Ds$   C /E!	EA;EEEc                 X   | j                   rd}nd}| j                  s| j                  d|       n4| j                  d|       | j                  D ]  }| j                  |        | j                  r3| j                  d       | j                  D ]  }| j                  |        | j                  r{t        | j                        dk(  r| j                  d       n%| j                  dt        | j                               | j                  D ]  \  }}} | j                  |g|i |  y y )	Nwerez
need to bezNo files %s modified.zFiles that %s modified:z$Warnings/messages while refactoring:r   zThere was 1 error:zThere were %d errors:)r   r   r   r   r   r   )r   rA  filemessager   r   r   s          r   	summarizezRefactoringTool.summarizea  s   ::DDzz4d;6=

 '  &'>>CD>> *  )*;;4;;1$  !56  !8#dkk:JK#';; 5T4   4t4t45 r   c                 |    | j                   j                  | j                  |||            }t               |_        |S )zParses a block into a tree.

        This is necessary to get correct line number / offset information
        in the parser diagnostics and embedded into the parse tree.
        )r   parse_tokens	wrap_toksrc   r  )r   r3  r6  r5  r   s        r   r:  zRefactoringTool.parse_blockx  s4     {{''uff(MN({r   c              #      K   t        j                  | j                  ||      j                        }|D ]+  \  }}\  }}\  }	}
}||dz
  z  }|	|dz
  z  }	||||f|	|
f|f - yw)z;Wraps a tokenize stream to systematically modify start/end.r   N)r   r_   	gen_lines__next__)r   r3  r6  r5  rA   r,   rq   line0col0line1col1	line_texts               r   rG  zRefactoringTool.wrap_toks  s     ))$..*G*P*PQDJ 	G@D%%yVaZEVaZE t}udmYFF	Gs   A!A#c              #     K   || j                   z   }|| j                  z   }|}|D ]R  }|j                  |      r|t        |      d  n,||j	                         dz   k(  rd nt        d|d|      |}T 	 d w)zGenerates lines as expected by tokenize from a list of lines.

        This strips the first len(indent + self.PS1) characters off each line.
        Nr   zline=z	, prefix=r   )r-  r0  r   r   r1  AssertionError)r   r3  r5  prefix1prefix2prefixr7  s          r   rI  zRefactoringTool.gen_lines  s     
 488#488# 	Dv&3v;<((4//
$T6%JKKF	 H s   A>B r   )FF)F)NFNrQ   )r#   r$   r%   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r   r$  r-  r0  r   r.  rD  r:  rG  rI  r&   r   r   rw   rw      s    +0).279 LK3Ln&5P

FL(& =.66 M ^#. GL $B** C
C)V:5.Gr   rw   c                       e Zd Zy)MultiprocessingUnsupportedNr"   r&   r   r   rV  rV    r'   r   rV  c                   B     e Zd Z fdZ	 	 d fd	Z fdZ fdZ xZS )MultiprocessRefactoringToolc                 H    t        t        | 
  |i | d | _        d | _        y rQ   )superrX  r   queueoutput_lockr   r   kwargsr  s      r   r   z$MultiprocessRefactoringTool.__init__  s'    )494J6J
r   c                    |dk(  rt         t        |   |||      S 	 dd l}| j                  t        d      |j                         | _        |j                         | _
        t        |      D cg c]  }|j                  | j                          }}	 |D ]  }|j                           t         t        |   |||       | j                  j                          t        |      D ]  }| j                  j!                  d         |D ]#  }|j#                         s|j                          % d | _        y # t        $ r t
        w xY wc c}w # | j                  j                          t        |      D ]  }| j                  j!                  d         |D ]#  }|j#                         s|j                          % d | _        w xY w)Nr   r   z already doing multiple processes)target)rZ  rX  r   multiprocessingImportErrorrV  r[  RuntimeErrorJoinableQueueLockr\  rangeProcess_childstartr   putis_alive)
r   r   r   r   num_processesra  r8  	processesr6   r  s
            r   r   z$MultiprocessRefactoringTool.refactor  s   A4dDum- -	-" ::!ABB$224
*//1#M24 %,,DKK,@ 4	 4	 	-t=eU>KM JJOO=) %

t$% ::<FFH DJ)  	-,,	-4 JJOO=) %

t$% ::<FFH DJs$   D6 /#E	,E 6EAG*Gc                    | j                   j                         }|Q|\  }}	 t        t        |   |i | | j                   j                          | j                   j                         }|Py y # | j                   j                          w xY wrQ   )r[  r   rZ  rX  r   	task_done)r   taskr   r^  r  s       r   rh  z"MultiprocessRefactoringTool._child  s    zz~~LD&'14F%#% 

$$&::>>#D  

$$&s   A0 0Bc                 ~    | j                   | j                   j                  ||f       y t        t        |   |i |S rQ   )r[  rj  rZ  rX  r   r]  s      r   r   z)MultiprocessRefactoringTool.refactor_file  sA    ::!JJNND&>*4dI!! !r   )FFr   )r#   r$   r%   r   r   rh  r   __classcell__)r  s   @r   rX  rX    s$     
 :? :	$! !r   rX  )T)#ru   
__author__r`   r   r   r  r   r   r9   	itertoolsr   pgen2r   r   r   
fixer_utilr   r   r	   r
   r   r   r   r3   r!   r/   rJ   rO   rS   rr   rt   objectrw   rV  rX  r&   r   r   <module>rx     s    3
 
 	  
     + * !  		 	C82@%P' 'Ff FR	 	4!/ 4!r   