o
    voiz                     @  s  U d dl mZ d dlZd dlZd dlmZ d dlmZ d dlmZ d dlmZ d dlm	Z	 d dlm
Z
 d d	lmZ d d
lmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d dlmZ ddlmZ ddlmZ ddlmZ ddlm Z  ddlm!Z! dd l!m"Z" erLd d!lm#Z# d d"lm$Z$ d d#l%m&Z& d d$l%m'Z' d d%l(m)Z) d d&l*m+Z+ d d'l*m,Z, d d(l*m-Z- d d)l*m.Z. d d*l/m0Z0 d d+l1m2Z2 d d,l1m3Z3 d d-l4m5Z5 d d.l6m7Z7 d d/l6m8Z8 d d0l6m9Z9 d d1l6m:Z: d d2l;m<Z< d d3l=m>Z> dd4lm?Z? dd5l@mAZA dd6lBmCZC dd7lBmDZD e+e-B e,B e.B ZEeFeGZHG d8d9 d9eIZJi ZKd:eLd;< G d<d= d=eJd>ZMG d?d@ d@eZNdJdHdIZOdS )K    )annotationsN)Any)Callable)Dict)Iterable)List)Mapping)
NamedTuple)Optional)Sequence)Set)Tuple)Type)TYPE_CHECKING)Union)cast)Column)MetaData)PrimaryKeyConstraintschema)String)Table)text   )_autogen)base)_constraint_sig)ComparisonResult   )util)sqla_compat)Literal)TextIO)
Connection)Dialect)CursorResult)ReflectedForeignKeyConstraint)ReflectedIndex)ReflectedPrimaryKeyConstraint)ReflectedUniqueConstraint)	Inspector)ClauseElement)
Executable)quoted_name)
Constraint)ForeignKeyConstraint)Index)UniqueConstraint)TableClause)
TypeEngine)_ServerDefaultType)AutogenContext)ApplyBatchImpl)BatchOperationsImplc                   @  s   e Zd Zd
ddZd	S )ImplMeta	classnamestrbasesTuple[Type[DefaultImpl]]dict_Dict[str, Any]c                 C  s(   t | |||}d|v r| t|d < |S )N__dialect__)type__init___impls)clsr:   r<   r>   newtype rF   D/home/ubuntu/.local/lib/python3.10/site-packages/alembic/ddl/impl.pyrB   L   s   zImplMeta.__init__N)r:   r;   r<   r=   r>   r?   )__name__
__module____qualname__rB   rF   rF   rF   rG   r9   K   s    r9   zDict[str, Type[DefaultImpl]]rC   c                   @  sx  e Zd ZU dZdZdZdZddhfZded< d	Z	d
ed< dZ
ded< dddZedd d!Zdd$d%Zdd-d.Zdd1d2Zdd6d7Zedd8d9Zd:d:e fddDdEZ	:dddHdIZd:dd:d:d:d:dd:d:d:d:d:dJdd\d]Zd:d:d:d:d^ddedfZd:d:dgddidjZddldmZddodpZ	:dddtduZddvdwZddxdyZdd|d}Z dd~dZ!dddZ"dddZ#dddZ$	ddddZ%dddZ&dddZ'dddZ(dddZ)dd Z*dddZ+dd Z,	dd ddZ-dddZ.dddZ/dd Z0dddZ1dddZ2dddZ3dddƄZ4ddȄ Z5ddd̄Z6ddd҄Z7dddԄZ8dddׄZ9ddd܄Z:ddބ Z;d	ddZ<d:S (
  DefaultImpla  Provide the entrypoint for major migration operations,
    including database-specific behavioral variances.

    While individual SQL/DDL constructs already provide
    for database-specific implementations, variances here
    allow for entirely different sequences of operations
    to take place for a particular migration, such as
    SQL Server's special 'IDENTITY INSERT' step for
    bulk inserts.

    defaultF;NUMERICDECIMALzTuple[Set[str], ...]type_synonymsrF   zSequence[str]type_arg_extract)orderon_nullzTuple[str, ...]identity_attrs_ignoredialectr%   
connectionOptional[Connection]as_sqlbooltransactional_ddlOptional[bool]output_bufferOptional[TextIO]context_optsr?   returnNonec                 C  s^   || _ || _|| _|dd| _|| _i | _|| _|d ur || _| jr+| js-t	
dd S d S )Nliteral_bindsFz3Can't use literal_binds setting without as_sql mode)rU   rV   rX   getra   r\   memor^   rZ   r    CommandError)selfrU   rV   rX   rZ   r\   r^   rF   rF   rG   rB   t   s    	zDefaultImpl.__init__Type[DefaultImpl]c                 C  s
   t |j S N)rC   name)rD   rU   rF   rF   rG   get_by_dialect   s   
zDefaultImpl.get_by_dialectr   r;   c                 C  s,   | j d usJ | j |d  | j   d S )Nz

)r\   writeflush)re   r   rF   rF   rG   static_output   s   zDefaultImpl.static_outputversion_tableversion_table_schemaOptional[str]version_table_pkkwr   r   c                K  s@   t |t tdtddd|d}|r|td| dd |S )a  Generate a :class:`.Table` object which will be used as the
        structure for the Alembic version table.

        Third party dialects may override this hook to provide an alternate
        structure for this :class:`.Table`; requirements are only that it
        be named based on the ``version_table`` parameter and contains
        at least a single string-holding column named ``version_num``.

        .. versionadded:: 1.14

        version_num    F)nullabler   _pkcrh   )r   r   r   r   append_constraintr   )re   rm   rn   rp   rq   vtrF   rF   rG   version_table_impl   s   
zDefaultImpl.version_table_implbatch_opr8   c                 C     dS )zReturn True if the given :class:`.BatchOperationsImpl`
        would need the table to be recreated and copied in order to
        proceed.

        Normally, only returns True on SQLite when operations other
        than add_column are present.

        FrF   )re   rz   rF   rF   rG   requires_recreate_in_batch   s   z&DefaultImpl.requires_recreate_in_batch
batch_implr7   tablec                 C  r{   )zperform any operations needed on a table before a new
        one is created to replace it in batch mode.

        the PG dialect uses this to drop constraints on the table
        before the new one uses those same names.

        NrF   )re   r}   r~   rF   rF   rG   prep_table_for_batch       z DefaultImpl.prep_table_for_batchc                 C     | j S rg   )rV   re   rF   rF   rG   bind   s   zDefaultImpl.bindN	constructUnion[Executable, str]execution_optionsOptional[Mapping[str, Any]]multiparams%Optional[Sequence[Mapping[str, Any]]]paramsMapping[str, Any]Optional[CursorResult]c                 C  s   t |tr	t|}| jrO|d us|rtd| jr't |tjs'tddid}ni }t	r2t |t
s2J |jd	d| ji|}| t|dd | j  d S | j}|d usXJ |rb|jd	i |}|rl|d urltd|rt|||S |||S )
Nz&SQL parameters not allowed with as_sqlra   T)compile_kwargsrU   	z    z2Can't send params and multiparams at the same timerF   )
isinstancer;   r   rX   	TypeErrorra   r   
DDLElementdictr   r,   compilerU   rl   replacestripcommand_terminatorrV   r   execute)re   r   r   r   r   
compile_kwcompiledconnrF   rF   rG   _exec   s<   
zDefaultImpl._execsqlOptional[dict[str, Any]]c                 C  s   |  || d S rg   )r   )re   r   r   rF   rF   rG   r     s   zDefaultImpl.execute)rt   server_defaultrh   type_r   autoincrementcommentexisting_commentexisting_typeexisting_server_defaultexisting_nullableexisting_autoincrement
table_namecolumn_namert   r   3Optional[Union[_ServerDefaultType, Literal[False]]]rh   r   Optional[TypeEngine]r   r   r   $Optional[Union[str, Literal[False]]]r   r   r   r   r   c                K  s,  |d us|d urt jddd |d ur#| tj||||||||
d |durWi }t||r3tj}nt||rAtj	}| |d< ntj
}| ||||f|||||
d| |d urk| tj||||||||
d |	dur| tj|||	|||||
d |d ur| tj|||||||d d S d S )NzBautoincrement and existing_autoincrement only make sense for MySQL   )
stacklevel)r   r   r   r   r   Fimpl)r   r   r   r   )r    warnr   r   ColumnNullabler!   _server_default_is_computedComputedColumnDefault_server_default_is_identityIdentityColumnDefaultColumnDefault
ColumnTypeColumnComment
ColumnName)re   r   r   rt   r   rh   r   r   r   r   r   r   r   r   r   rq   cls_rF   rF   rG   alter_column	  s   
	zDefaultImpl.alter_columnr   if_not_existsinline_referencesinline_primary_keycolumnColumn[Any]!Optional[Union[str, quoted_name]]r   r   r   c             
   C  s    |  tj||||||d d S )Nr   )r   r   	AddColumn)re   r   r   r   r   r   r   rF   rF   rG   
add_column~  s   
zDefaultImpl.add_columnr   	if_existsr   c                K  s   |  tj||||d d S )Nr   )r   r   
DropColumn)re   r   r   r   r   rq   rF   rF   rG   drop_column  s
   	zDefaultImpl.drop_columnconstc                 K  sF   |j d u s
| | r!tjr|dd | tj|fi | d S d S )Nisolate_from_tableT)_create_ruler!   sqla_2_1
setdefaultr   r   AddConstraintre   r   rq   rF   rF   rG   add_constraint  s
   zDefaultImpl.add_constraintr/   c                 K     |  tj|fi | d S rg   )r   r   DropConstraintr   rF   rF   rG   drop_constraint     zDefaultImpl.drop_constraintold_table_namenew_table_nameUnion[str, quoted_name]c                 C  s   |  tj|||d d S )Nr   )r   r   RenameTable)re   r   r   r   rF   rF   rG   rename_table  s   zDefaultImpl.rename_tablec                 K  s   |j j|| jd| d | tj|fi | |j j|| jd| d |jD ]
}| t| q%| j	j
o8| j	j }|j}|rE|rE| | |jD ]}|j}|rV|rV| | qHd S NF)
checkfirst_ddl_runner)dispatchbefore_createrV   r   r   CreateTableafter_createindexesCreateIndexrU   supports_commentsinline_commentsr   create_table_commentcolumnscreate_column_comment)re   r~   rq   indexwith_commentr   r   rF   rF   rG   create_table  s(   





zDefaultImpl.create_tablec                 K  sH   |j j|| jd| d | tj|fi | |j j|| jd| d d S r   )r   before_droprV   r   r   	DropTable
after_drop)re   r~   rq   rF   rF   rG   
drop_table  s   


zDefaultImpl.drop_tabler   r1   c                 K  r   rg   )r   r   r   re   r   rq   rF   rF   rG   create_index  r   zDefaultImpl.create_indexc                 C     |  t| d S rg   )r   r   SetTableCommentre   r~   rF   rF   rG   r        z DefaultImpl.create_table_commentc                 C  r   rg   )r   r   DropTableCommentr   rF   rF   rG   drop_table_comment  r   zDefaultImpl.drop_table_commentc                 C  r   rg   )r   r   SetColumnComment)re   r   rF   rF   rG   r     r   z!DefaultImpl.create_column_commentc                 K  r   rg   )r   r   	DropIndexr   rF   rF   rG   
drop_index  r   zDefaultImpl.drop_indexTUnion[TableClause, Table]rows
List[dict]multiinsertc              	     s   t |ts	td|rt |d tstd| jr8|D ]}|    jdi  fdd|	 D  qd S |r]|rI| j   |d d S |D ]}|    jdi | qKd S d S )NzList expectedr   zList of dictionaries expectedc                   s:   i | ]\}}|t |tjstj|| j| jd n|qS ))r   )r   r!   _literal_bindparamcrA   ).0kvr~   rF   rG   
<dictcomp>  s    
z+DefaultImpl.bulk_insert.<locals>.<dictcomp>)r   rF   )
r   listr   r   rX   r   insertinlinevaluesitems)re   r~   r   r   rowrF   r  rG   bulk_insert  s0   


 zDefaultImpl.bulk_insertr   Paramsc                 C  s   | j j|j }td|}g }d }|D ]}td|r!|}q|| qt	|d |dd  g i }|r\td|D ]}d|v rS|
d\}	}
|
 |j|	 < q<|j|  q<|S )Nz[\w\-_]+|\(.+?\)z^\(.*\)$r   r   z[^(),]+=)rU   type_compilerprocessrA   lowerrefindallmatchappendr  splitr   kwargsargs)re   r   
definitiontokensterm_tokens
paren_termtokenr   termkeyvalrF   rF   rG   _tokenize_column_type  s    z!DefaultImpl._tokenize_column_typeinspector_paramsmetadata_paramsc                 C  s|   |j |j krdS dd | jD }d|j g|j }d|j g|j }|D ]}||h|s8|j |j h|r; dS q&dS )NTc                 S  s   g | ]	}d d |D qS )c                 S  s   h | ]}|  qS rF   )r  )r   trF   rF   rG   	<setcomp>9      z=DefaultImpl._column_types_match.<locals>.<listcomp>.<setcomp>rF   )r   batchrF   rF   rG   
<listcomp>9  s    z3DefaultImpl._column_types_match.<locals>.<listcomp> F)token0rP   joinr  issubset)re   r   r!  synonymsinspector_all_termsmetadata_all_termsr%  rF   rF   rG   _column_types_match3  s&   zDefaultImpl._column_types_matchinspected_paramsmeta_paramsc                 C  s   t |jt |jkr|j|jkrdS t |jt |jkr$|j|jkr$dS d|j }d|j }| jD ]}t||}t||}|rV|rV|d|dkrV dS q7dS )a  We want to compare column parameters. However, we only want
        to compare parameters that are set. If they both have `collation`,
        we want to make sure they are the same. However, if only one
        specifies it, dont flag it for being less specific
        Fr'  r   T)	lenr  r  r)  r  rQ   r  searchgroup)re   r/  r0  inspmetaregmimmrF   rF   rG   _column_args_matchI  s   

zDefaultImpl._column_args_matchinspector_columnmetadata_columnc                 C  s8   |  |}|  |}| ||sdS | ||sdS dS )zReturns True if there ARE differences between the types of the two
        columns. Takes impl.type_synonyms into account between retrospected
        and metadata types
        TF)r  r.  r9  )re   r:  r;  r   r!  rF   rF   rG   compare_typej  s   

zDefaultImpl.compare_typec                 C  s   ||kS rg   rF   )re   r:  r;  rendered_metadata_defaultrendered_inspector_defaultrF   rF   rG   compare_server_defaultz  s   z"DefaultImpl.compare_server_defaultconn_uniquesSet[UniqueConstraint]conn_indexes
Set[Index]metadata_unique_constraintsmetadata_indexesc                 C     d S rg   rF   )re   r@  rB  rD  rE  rF   rF   rG   correct_for_autogen_constraints  s   z+DefaultImpl.correct_for_autogen_constraintsc                 C  s(   |j j|jurt|d ||d< d S d S )Nexpr)rA   _type_affinityr   )re   existingexisting_transfernew_typerF   rF   rG   cast_for_batch_migrate  s
   z"DefaultImpl.cast_for_batch_migraterH  r,   is_server_defaultc                 K  s   ddd}t |j| j|dS )zdRender a SQL expression that is typically a server default,
        index expression, etc.

        TF)ra   include_table)rU   r   )r;   r   rU   )re   rH  rN  rq   r   rF   rF   rG   render_ddl_sql_expr  s   
zDefaultImpl.render_ddl_sql_expr	inspectorr+   r   c                 C  r   rg   )autogen_column_reflect)re   rQ  rF   rF   rG   _compat_autogen_column_reflect  s   z*DefaultImpl._compat_autogen_column_reflectconn_fksSet[ForeignKeyConstraint]metadata_fksc                 C  rF  rg   rF   )re   rT  rV  rF   rF   rG   correct_for_autogen_foreignkeys  s   z+DefaultImpl.correct_for_autogen_foreignkeysc                 C  r{   )zA hook that is attached to the 'column_reflect' event for when
        a Table is reflected from the database during the autogenerate
        process.

        Dialects can elect to modify the information gathered here.

        NrF   )re   rQ  r~   column_inforF   rF   rG   rR    r   z"DefaultImpl.autogen_column_reflectc                 C  r{   )zA hook called when :meth:`.EnvironmentContext.run_migrations`
        is called.

        Implementations can set up per-migration-run state here.

        NrF   r   rF   rF   rG   start_migrations  r   zDefaultImpl.start_migrationsc                 C     |  d| j  dS )zEmit the string ``BEGIN``, or the backend-specific
        equivalent, on the current connection context.

        This is used in offline mode and typically
        via :meth:`.EnvironmentContext.begin_transaction`.

        BEGINNrl   r   r   rF   rF   rG   
emit_begin     zDefaultImpl.emit_beginc                 C  rZ  )zEmit the string ``COMMIT``, or the backend-specific
        equivalent, on the current connection context.

        This is used in offline mode and typically
        via :meth:`.EnvironmentContext.begin_transaction`.

        COMMITNr\  r   rF   rF   rG   emit_commit  r^  zDefaultImpl.emit_committype_objr4   autogen_contextr6   Union[str, Literal[False]]c                 C  r{   NFrF   )re   ra  rb  rF   rF   rG   render_type  s   zDefaultImpl.render_typec                 C  sv   t ||t dhd\}}t|dd }t|dd }t|t|kr&|d || j ||t|p9t|t|kfS )Nalways)skip)_compare_identity_optionsr   IdentitygetattrrY   adddifference_updaterT   )re   metadata_identityinspector_identitydiffignoredmeta_alwaysinspector_alwaysrF   rF   rG   _compare_identity_default  s   

z%DefaultImpl._compare_identity_defaultmetadata_indexreflected_indexc                 C  s0   t |j}t |j}||krd| d| S d S )Nzunique=z to unique=)rY   unique)re   rt  ru  conn_uniquemeta_uniquerF   rF   rG   _compare_index_unique  s
   

z!DefaultImpl._compare_index_unique
constraint_autogen._Copts_constraint_sig[_autogen._C]c                 K     t jd| |fi |S )NTr   from_constraintre   rz  r|  rF   rF   rG   _create_metadata_constraint_sig     z+DefaultImpl._create_metadata_constraint_sigc                 K  r~  rd  r  r  rF   rF   rG    _create_reflected_constraint_sig  r  z,DefaultImpl._create_reflected_constraint_sigr   c                 C  s   g }|  ||}|r|| | |}| |}t|s J t|s'J ||fD ]}|jr7td|j	 q+|j
|j
krK|d|j
 d|j
  |rRt|S t S )zCompare two indexes by comparing the signature generated by
        ``create_index_sig``.

        This method returns a ``ComparisonResult``.
        zGenerating approximate signature for index %s. The dialect implementation should either skip expression indexes or provide a custom implementation.expression  to )ry  r  r  r  r   is_index_sighas_expressionslogwarningr   column_namesr   	DifferentEqual)re   rt  ru  msg
unique_msgm_sigr_sigsigrF   rF   rG   compare_indexes  s0   




zDefaultImpl.compare_indexesmetadata_constraintr2   reflected_constraintc                 C  sF   |  |}| |}|j}|j}||krtd| d| S t S )a  Compare two unique constraints by comparing the two signatures.

        The arguments are two tuples that contain the unique constraint and
        the signatures generated by ``create_unique_constraint_sig``.

        This method returns a ``ComparisonResult``.
        r  r  )r  r  unnamedr   r  r  )re   r  r  metadata_tupreflected_tupmeta_sigconn_sigrF   rF   rG   compare_unique_constraint/  s   z%DefaultImpl.compare_unique_constraintc              
   C  sh   dd |D }t |D ]&}|j|v rqt|}|r1td|jd| jdtj d || qd S )Nc                 S  s   i | ]}|j |qS rF   rv   )r   r   rF   rF   rG   r  L  r$  z8DefaultImpl._skip_functional_indexes.<locals>.<dictcomp>z@autogenerate skipping metadata-specified expression-based index z
; dialect z under SQLAlchemy z6 can't reflect these indexes so they can't be compared)	r  rh   r!   is_expression_indexr    r   r@   sqlalchemy_versiondiscard)re   rE  rB  conn_indexes_by_nameidxiexrF   rF   rG   _skip_functional_indexesK  s$   


z$DefaultImpl._skip_functional_indexesreflected_object_ReflectedConstraintkindc                 C  s   | di S )Ndialect_options)rb   )re   r  r  rF   rF   rG    adjust_reflected_dialect_options\  s   z,DefaultImpl.adjust_reflected_dialect_options)rU   r%   rV   rW   rX   rY   rZ   r[   r\   r]   r^   r?   r_   r`   )rU   r%   r_   rf   )r   r;   r_   r`   )
rm   r;   rn   ro   rp   rY   rq   r   r_   r   )rz   r8   r_   rY   )r}   r7   r~   r   r_   r`   )r_   rW   )
r   r   r   r   r   r   r   r   r_   r   rg   )r   r   r   r   r_   r`   ) r   r;   r   r;   rt   r[   r   r   rh   ro   r   r   r   ro   r   r[   r   r   r   ro   r   r   r   r   r   r[   r   r[   rq   r   r_   r`   )r   r;   r   r   r   r   r   r[   r   r[   r   r[   r_   r`   )
r   r;   r   r   r   ro   r   r[   r_   r`   )r   r   rq   r   r_   r`   )r   r/   rq   r   r_   r`   )r   r;   r   r   r   r   r_   r`   )r~   r   rq   r   r_   r`   )r   r1   rq   r   r_   r`   )r~   r   r_   r`   )r   r   r_   r`   )T)r~   r   r   r   r   rY   r_   r`   )r   r   r_   r  )r   r  r!  r  r_   rY   )r/  r  r0  r  r_   rY   )r:  r   r;  r   r_   rY   )
r@  rA  rB  rC  rD  rA  rE  rC  r_   r`   )F)rH  r,   rN  rY   rq   r   r_   r;   )rQ  r+   r_   r   )rT  rU  rV  rU  r_   r`   )r_   r`   )ra  r4   rb  r6   r_   rc  )rt  r1   ru  r1   r_   ro   )rz  r{  r|  r   r_   r}  )rt  r1   ru  r1   r_   r   )r  r2   r  r2   r_   r   )r  r  r  r;   r_   r?   )=rH   rI   rJ   __doc__r@   rZ   r   rP   __annotations__rQ   rT   rB   classmethodri   rl   ry   r|   r   propertyr   r    immutabledictr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r
  r  r.  r9  r<  r?  rG  rM  rP  rS  rW  rR  rY  r]  r`  re  rs  ry  r  r  r  r  r  r  rF   rF   rF   rG   rK   [   s   
 



"
0z





	




&
(

!
			


+rK   )	metaclassc                   @  s.   e Zd ZU ded< ded< ded< ded< dS )	r  r;   r(  z	List[str]r  r  zDict[str, str]r  N)rH   rI   rJ   r  rF   rF   rF   rG   r  b  s
   
 r  metadata_io-Union[schema.Identity, schema.Sequence, None]inspector_io
default_io'Union[schema.Identity, schema.Sequence]rg  Set[str]c                   s   t | }t |}t  t d
 fdd}|||t |t|| t jrFt|d	s2J |t| d	i t|d	i |jt|d	i   fS )N	meta_dictr   	insp_dictdefault_dictattrsIterable[str]c                   s\   t |D ]$}| |}||}||kr+||}||kr&| q | qd S rg   )set
differencerb   rk  )r  r  r  r  attr
meta_value
insp_valuedefault_valuero  ignored_attrrg  rF   rG   check_dictsx  s   



z._compare_identity_options.<locals>.check_dictsdialect_kwargs)r  r   r  r   r  r   r  r  )r!   _get_identity_options_dictr  unionidentity_has_dialect_kwargshasattrrj  r  )r  r  r  rg  meta_dinsp_dr  rF   r  rG   rh  i  s(   
	



rh  )r  r  r  r  r  r  rg  r  )P
__future__r   loggingr  typingr   r   r   r   r   r   r	   r
   r   r   r   r   r   r   
sqlalchemyr   r   r   r   r   r   r   r    r   r   r   r   r    r!   r"   r#   sqlalchemy.enginer$   r%   sqlalchemy.engine.cursorr&   sqlalchemy.engine.interfacesr'   r(   r)   r*   sqlalchemy.engine.reflectionr+   sqlalchemy.sqlr,   r-   sqlalchemy.sql.elementsr.   sqlalchemy.sql.schemar/   r0   r1   r2   sqlalchemy.sql.selectabler3   sqlalchemy.sql.type_apir4   r5   autogenerate.apir6   operations.batchr7   r8   r  	getLoggerrH   r  rA   r9   rC   r  rK   r  rh  rF   rF   rF   rG   <module>   s   
      