o
    Rc                     @   s  d Z 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 Z$dd Z%d@d d!Z&d"d# Z'd$d% Z(d&d' Z)e*d(d)d* Z+d+d, Z,G d-d. d.e-Z.G d/d0 d0e.Z/G d1d2 d2e.Z0e*d(d3d4 Z1G d5d6 d6e0Z2d7d8 Z3d9d: Z4d;d< Z5d=e5_6d>d? Z7dS )Az(Internal implementation for declarative.    )absolute_importN)
attributes)instrumentation   )clsregistry)exc)mapper)InstrumentedAttribute)QueryableAttribute)_is_mapped_class)InspectionAttr)CompositeProperty)SynonymProperty)MapperProperty)Mapper)ColumnProperty)class_mapper   )event)util)
expression)Column)Table)topologicalc                 C   s,   t | r
t | S t| rt| ddS d S )NF)	configure)_DeferredMapperConfighas_clsconfig_for_clsr   r   cls r    :D:\Flask\env\Lib\site-packages\sqlalchemy/orm/decl_base.py_declared_mapping_info%   s
   

r"   c                 C   sX   | t u rd S | jddr!| jD ]}t|}|d ur|  S qd S t| }|r*|jS | S )N__abstract__F)object__dict__get	__bases__"_resolve_for_abstract_or_classical_dive_for_cls_managerclass_)r   supZ
clsmanagerr    r    r!   r(   0   s   
r(   Fc                 C   s   |dksJ t | tsdS || jv rt| |S | jdd D ]"}t|}||jv r@|| u s9|r5|| jv r@n		 |s@t||  S qdS )a  return an attribute of the class that is either present directly
    on the class, e.g. not on a superclass, or is from a superclass but
    this superclass is a non-mapped mixin, that is, not a descendant of
    the declarative base and is also not classically mapped.

    This is used to detect attributes that indicate something about
    a mapped class independently from any mapped classes that it may
    inherit from.

    r#   Nr   )
issubclassr$   r%   getattr__mro__r)   r'   )r   attrnamestrictbaseZ_is_classicial_inheritsr    r    r!   _get_immediate_cls_attrD   s*   



r2   c                 C   s4   t | dsd S | jD ]}t|}|r|  S q
d S )Nr.   )hasattrr.   r   manager_of_class)r   r1   managerr    r    r!   r)   i   s   


r)   c                 C   s   t | ||d i S N)_MapperConfigsetup_mapping)registryr   dict_r    r    r!   _as_declarativey   s   r;   c                 C   s   t | ||| |jS r6   )_ImperativeMapperConfig
__mapper__)r9   r   table	mapper_kwr    r    r!   _mapper   s   r@   zsqlalchemy.orm.decl_apic                 C   s   t jjj}t| |t jfS r6   )r   	preloadedorm_decl_apideclared_attr
isinstanceZclassproperty)objrC   r    r    r!   _is_declarative_props   s   
rF   c                 C   s.   t | rt| ddrtd||f  dS dS )N
_cascadingFz~@declared_attr.cascading is not supported on the %s attribute on class %s.  This attribute invokes for subclasses in any case.T)rF   r-   r   warn)rE   namer   r    r    r!   _check_declared_props_nocascade   s   rJ   c                   @   s4   e Zd ZdZedd Zdd Zdd Zdd	 Zd
S )r7   )r   	classname
propertiesdeclared_attr_reg__weakref__c           	      C   sn   t | }|r|j|u rtd|  |jddrd S t|dddp't|d}|r-t	}nt
}||||||S )Nz4Class %r already has been instrumented declarativelyr#   F_sa_decl_prepare_nocascadeTr0   Z_sa_decl_prepare)r   r4   r*   r   InvalidRequestErrorr%   r&   r2   r3   r   _ClassScanMapperConfig)	r   r9   cls_r:   r>   r?   r5   Z	defer_mapZcfg_clsr    r    r!   r8      s    
z_MapperConfig.setup_mappingc                 C   sz   t |td| _|j| _t  | _i | _|	dds(t
j| jd|| |jd d S t| j}|r3|js;td| j d S )NrS   non_primaryF)finalizer9   Zdeclarative_scanZinit_methodztClass %s has no primary mapper configured.  Configure a primary mapper first before setting up a non primary Mapper.)r   Zassert_arg_typetyper   __name__rK   OrderedDictrL   rM   r&   r   Zregister_classconstructorr   r4   Z	is_mappedr   rQ   )selfr9   rS   r?   r5   r    r    r!   __init__   s(   


z_MapperConfig.__init__c                 C   s   t | j}||| |S r6   )r   r4   r   Zinstall_member)rZ   r/   valuer5   r    r    r!   set_cls_attribute   s   z_MapperConfig.set_cls_attributec                 C   s   |  | d S r6   )maprZ   r?   r    r    r!   _early_mapping      z_MapperConfig._early_mappingN)	rW   
__module____qualname__	__slots__classmethodr8   r[   r]   r`   r    r    r    r!   r7      s    
r7   c                       s6   e Zd ZdZ fddZejfddZdd Z  Z	S )r<   )r:   local_tableinheritsc                    s   t t| ||| i | _| d|| _tj# |dds(t	
| j| j|j | | | | W d    d S 1 s=w   Y  d S )N	__table__rT   F)superr<   r[   r:   r]   rf   	mapperlib_CONFIGURE_MUTEXr&   r   	add_classrK   r   _class_registry_setup_inheritancer`   )rZ   r9   rS   r>   r?   	__class__r    r!   r[      s   

"z _ImperativeMapperConfig.__init__c                 C   s"   t }| d|| j| jfi |S )Nr=   )r   r]   r   rf   rZ   r?   Z
mapper_clsr    r    r!   r^      s
   z_ImperativeMapperConfig.mapc                 C   s   | j }|dd }|d u rFg }|jD ]}t|}|d u rqt|d ur/t|ddds/|| q|rEt|dkrAt	d||f |d }nt
|trN|j}|| _d S )Nrg   rO   TrP   r   &Class %s has multiple mapped bases: %rr   )r   r&   r'   r(   r"   r2   appendlenr   rQ   rD   r   r*   rg   )rZ   r?   r   rg   inherits_searchcr    r    r!   rn      s>   



z*_ImperativeMapperConfig._setup_inheritance)
rW   rb   rc   rd   r[   r   
EMPTY_DICTr^   rn   __classcell__r    r    ro   r!   r<      s
    r<   c                       s   e Zd ZdZ fddZdd Zdd Zdd	 Zd
d Zdd Z	dd Z
dd Zdd ZdddZdd Zdd Zdd ZejfddZ  ZS ) rR   )
r:   rf   persist_selectabledeclared_columnscolumn_copies
table_args	tablenamemapper_argsmapper_args_fnrg   c                    s   |rt |ni | _tt| ||| d | _t | _i | _| 	  | 
  tj* t| j| j|j |   |   | | | | | | W d    d S 1 sUw   Y  d S r6   )dictr:   ri   rR   r[   ry   setrz   r{   _setup_declared_events_scan_attributesrj   rk   r   rl   rK   r   rm   _extract_mappable_attributes_extract_declared_columns_setup_tablern   r`   )rZ   r9   rS   r:   r>   r?   ro   r    r!   r[   ,  s"   

"z_ClassScanMapperConfig.__init__c                    sP   t  jdrttd fdd}t  jdr&ttd fdd}d S d S )	N__declare_last__after_configuredc                          j   d S r6   )r   r   r    rZ   r    r!   r   T     zG_ClassScanMapperConfig._setup_declared_events.<locals>.after_configured__declare_first__before_configuredc                      r   r6   )r   r   r    r   r    r!   r   Z  r   zH_ClassScanMapperConfig._setup_declared_events.<locals>.before_configured)r2   r   r   Zlistens_forr   )rZ   r   r   r    r   r!   r   Q  s   

z-_ClassScanMapperConfig._setup_declared_eventsc                    sp   t dddu rfdd}|S fddtD fddtD t   fdd}|S )	zProduce a function that checks if a class has overridden an
        attribute, taking SQLAlchemy-enabled dataclass fields into account.

        __sa_dataclass_metadata_key__Nc                    s   t  | |uS r6   )r-   )keyrE   r   r    r!   attribute_is_overriddeni  ra   zR_ClassScanMapperConfig._cls_attr_override_checker.<locals>.attribute_is_overriddenc                    $   i | ]} |j v r|j|j   qS r    metadatarI   .0fsa_dataclass_metadata_keyr    r!   
<dictcomp>n      zE_ClassScanMapperConfig._cls_attr_override_checker.<locals>.<dictcomp>c                    r   r    r   r   r   r    r!   r   s  r   c                    s   t |r|j}|  }t |r|j}||u rdS | ur dS |  }t| |}||u r2dS | ur=t|tr=dS ||u rCdS | urIdS dS )NFT)rF   fgetr&   r-   rD   r	   )r   rE   retZ	all_field)absentall_datacls_fieldsr   local_datacls_fieldsr    r!   r   {  s,   
)r2   r   Zdataclass_fieldslocal_dataclass_fieldsr$   )rZ   r   r   r    )r   r   r   r   r   r!   _cls_attr_override_checker^  s   :

(z1_ClassScanMapperConfig._cls_attr_override_checkerc                    s>   t  dddu r fdd}|S t  fdd}|S )zproduce a function to iterate the "attributes" of a class,
        adjusting for SQLAlchemy fields embedded in dataclass fields.

        r   Nc                  3   s(    t   D ]
\} }| |dfV  qd S )NF)varsitems)rI   rE   r   r    r!   local_attributes_for_class  s   zM_ClassScanMapperConfig._cls_attr_resolver.<locals>.local_attributes_for_classc                  3   sl    t  D ]} | jv r| j | jt| jdfV  qt  D ]\}}|vr3||dfV  q%d S )NTF)r   r   r   addrI   _as_dc_declaredattrr   r   )fieldrI   rE   r   field_namesr   r    r!   r     s   
)r2   r   )rZ   r   r   r    r   r!   _cls_attr_resolver  s   z)_ClassScanMapperConfig._cls_attr_resolverc              	      s*  | j  | j}| j}d }d  }}d }| | j }g } jD ]1}	|	 uo/t|	d uo/t|	ddd }
| |	}|
sB|	 urB| ||}ni }|	|	|
||f q|D ]0\}	}
}}|
| | D ] \}}}|dkr|t|| }|s{|
ru|r{ fdd}q_|dkrt|| }|s|
r|r j}q_|dkrt|| }|s|
r|r j}t|tttd fstd	|	 urd}q_|
rt|rtd
|	j||	 f  q_|	 ur\t|trq_t|trtdt|rT|jr||v rtd| f  ||  ||<  ||< }t || n5|r t |d }t|ts|  }nt |}t|tr9|j!r9t|j"ts9|j#}| ||< ||< t|ttfrS|j$d u rS|j%|_$q_| &|	|| q_|r||vsk|| |ur|||rsJ t|r||  }|||< q_qP|r|sd }|| _'|| _(|| _)d S )NrO   TrP   __mapper_args__c                      s
   t  jS r6   )r   r   r    r   r    r!   r     s   
z?_ClassScanMapperConfig._scan_attributes.<locals>.mapper_args_fn__tablename____table_args__z3__table_args__ value must be a tuple, dict, or NonezRegular (i.e. not __special__) attribute '%s.%s' uses @declared_attr, but owning class %s is mapped - not applying to subclass %s.zMapper properties (i.e. deferred,column_property(), relationship(), etc.) must be declared as @declared_attr callables on declarative mixin classes.  For dataclass field() objects, use a lambda:zXAttribute '%s' on class %s cannot be processed due to @declared_attr.cascading; skipping)*r   r:   r{   r   r.   r"   r2   r   _produce_column_copiesrs   updaterJ   r   r   rD   tupler   rV   r   ArgumentErrorrF   r   rH   rW   r   r   rQ   rG   __get__setattrr-   r   r   Z_is_internal_proxyZoriginal_propertyZ
descriptordoc__doc___warn_for_decl_attributesr|   r}   r   )rZ   r:   r{   r   r|   Zinherited_table_argsr}   r   basesr1   Zclass_mappedr   Zlocally_collected_columnsrI   rE   is_dataclassZ
check_declr   r    r   r!   r     s  











  
z'_ClassScanMapperConfig._scan_attributesc                 C   s&   t |tjrtd||f  d S d S )NzAttribute '%s' on class %s appears to be a non-schema 'sqlalchemy.sql.column()' object; this won't be part of the declarative mapping)rD   r   ZColumnClauser   rH   )rZ   r   r   rv   r    r    r!   r     s   z0_ClassScanMapperConfig._warn_for_decl_attributesc                 C   s   | j }| j}i }| j}| D ]@\}}}	t|trN|||rq|jr&td||vrNd|v r8|jp2||d j	v sN|
  ||< }
|j|
_t|||
 |
||< q|S )NzColumns with foreign keys to other columns must be declared as @declared_attr callables on declarative mixin classes.  For dataclass field() objects, use a lambda:.rh   )r   r:   r{   rD   r   Zforeign_keysr   rQ   rI   rv   Z_copy_creation_orderr   )rZ   Zattributes_for_classr   r   r:   Zlocally_collected_attributesr{   rI   rE   r   Zcopy_r    r    r!   r     s.   

z-_ClassScanMapperConfig._produce_column_copiesc                 C   s6  | j }| j}| j}t|ddd}t|D ]}|dv rq|| }t|r4|jr.td| j   t	||}nt
|trN|j|urN|j|krNt|j}t||| t
|trjt|dkrjt
|d ttfrjtd|  qt
|ttfs|d	s|| | ||| |st||| q|d
krtd|||< qd S )NrO   TrP   )rh   r   r   zUse of @declared_attr.cascading only applies to Declarative 'mixin' and 'abstract' classes.  Currently, this flag is ignored on mapped class %sr   r   zIgnoring declarative-like tuple value of attribute '%s': possibly a copy-and-paste error with a comma accidentally placed at the end of the line?__r   zdAttribute name 'metadata' is reserved for the MetaData instance when using a declarative base class.)r   r:   rL   r2   listrF   rG   r   rH   r-   rD   r
   r*   r   r   r   r   rt   r   r   
startswithpopr   r   rQ   )rZ   r   r:   	our_stuffZlate_mappedkr\   r    r    r!   r     sf   




z3_ClassScanMapperConfig._extract_mappable_attributesc              
      s   | j  tj  fddd | j}tt}t  D ]R\}}t	|t
tfrO|jD ]#}t	|trM|jd u rMt|| t	|tsH||j | || q*qt	|trnt|| ||j | || ||jkrn |= q| D ]\}}t|dkrtd| j|dt|f  qsd S )Nc                    s
    |  j S r6   r   r   r   r    r!   <lambda>	  s   
 zB_ClassScanMapperConfig._extract_declared_columns.<locals>.<lambda>r   r   zzOn class %r, Column object %r named directly multiple times, only one will be used: %s. Consider using orm.synonym insteadz, )rL   r   Zsort_dictionaryrz   collectionsdefaultdictr   r   r   rD   r   r   columnsr   r>   _undefer_column_namerI   r   r   rt   rH   rK   joinsorted)rZ   rz   Zname_to_prop_keyr   rv   colrI   keysr    r   r!   r     s@   








z0_ClassScanMapperConfig._extract_declared_columnsNc                 C   sf  | j }| j}| j}| j}| j}t|}t|dd d }| _d|vr|d u rt|dr3t	
|j}nt}|d urdi }	}
|rbt|trH|}
nt|trbt|d tr`|dd |d }	}
n|}	|d	}|rm||
d
< |d}|rxd|
d< | d||| |gt|t|	 R i |
}n|d u r|j}|r|D ]}|j|std|j q|| _d S )Nc                 S   s   | j S r6   r   )rv   r    r    r!   r   7  s    z5_ClassScanMapperConfig._setup_table.<locals>.<lambda>r   rh   __table_cls__r    r   Z__autoload_with__autoload_withZ__autoload__Tautoloadz8Can't add additional column %r when specifying __table__)r   r}   r|   r:   rz   r   r4   r   r3   r   unbound_method_to_callabler   r   rD   r   r   r&   r]   _metadata_for_clsrh   rv   Zcontains_columnr   r   r   rf   )rZ   r>   r   r}   r|   r:   rz   r5   Z	table_clsargsZtable_kwr   r   rv   r    r    r!   r   -  sh   








z#_ClassScanMapperConfig._setup_tablec                 C   s   t | jdr
| jjS |jjS )Nr   )r3   r   r   r9   )rZ   r5   r    r    r!   r   i  s   z(_ClassScanMapperConfig._metadata_for_clsc                 C   s  | j }| j}| j}| j}|dd }|d u rSg }|jD ]!}t|}|d u r&qt|d ur<t|ddds<||vr<|	| q|rRt
|dkrNtd||f |d }nt|tr[|j}|| _|d u rs| jd u rst|dsstd	| | jrt| j}	|	j }
|	j}|d u r|rtd
|D ]=}|j|
jv r|
j|j |u rqtd|||
j|j f |jrtd|
| |d ur||
ur|| qd S d S d S )Nrg   rO   TrP   r   rr   r   Z__no_table__zwClass %r does not have a __table__ or __tablename__ specified and does not inherit from an existing table-mapped class.z?Can't place __table_args__ on an inherited class with no table.z;Column '%s' on class %s conflicts with existing column '%s'zDCan't place primary key columns on an inherited class with no table.)rf   r   r|   rz   r&   r'   r(   r"   r2   rs   rt   r   rQ   rD   r   r*   rg   ry   r   rI   rv   Zprimary_keyappend_columnZ_refresh_for_new_column)rZ   r?   r>   r   r|   rz   rg   ru   rv   inherited_mapperinherited_tableZinherited_persist_selectabler    r    r!   rn   o  s   





	z)_ClassScanMapperConfig._setup_inheritancec                    s  | j }| jr|  }ni }|r|| d|v r#t|}||d  dD ]}||v r8|| }| j||||< q%d|v rW|d }t|trI|j}|| j	urWt
d|d  | j	r_| j	|d< | j	r|ddst| j	  j}d|vrt fdd	|jD  jpd
 |d< }|dd	 | jD  t| D ]"\}}	t|	tjsq| jv r j| }
t|
tr|	g|
j ||< q| }||d< || _d S )NrL   )Zversion_id_colZpolymorphic_onrg   z:mapper inherits argument given for non-inheriting class %sZconcreteFexclude_propertiesc                    s   g | ]
}| j vr|jqS r    )Z_columntopropertyr   r   rv   r   r    r!   
<listcomp>  s    zD_ClassScanMapperConfig._prepare_mapper_arguments.<locals>.<listcomp>r    c                 S   s   g | ]}|j qS r    r   r   r    r    r!   r     s    )rL   r   r   r   r{   r&   rD   r   r*   rg   r   rQ   r"   rf   r   rv   unionr   difference_updaterz   r   r   r   ZColumnElementZ_propsr   r   copyr~   )rZ   r?   rL   r~   r   vZinherits_argr   r   r   pZresult_mapper_argsr    r   r!   _prepare_mapper_arguments  sf   












z0_ClassScanMapperConfig._prepare_mapper_argumentsc                 C   sJ   |  | t| jdrt| jj}nt}| d|| j| jfi | j	S )N__mapper_cls__r=   )
r   r3   r   r   r   r   r   r]   rf   r~   rq   r    r    r!   r^     s   
z_ClassScanMapperConfig.mapr6   )rW   rb   rc   rd   r[   r   r   r   r   r   r   r   r   r   r   rn   r   r   rw   r^   rx   r    r    ro   r!   rR     s"    %G R	!E
)<RKrR   c                 C   s2   t jj}| | }t|rt||js||S |S r6   )r   rA   rB   callablerD   rC   )Zfield_metadatar   Zdecl_apirE   r    r    r!   r     s
   
r   c                       s   e Zd Ze Zdd Zedd Zej	dd Ze
dd Ze
dd	 Ze
d
d Ze
dd Ze
dddZejf fdd	Z  ZS )r   c                 C   s   d S r6   r    r_   r    r    r!   r`   +  s   z$_DeferredMapperConfig._early_mappingc                 C   s   |   S r6   )_clsr   r    r    r!   r   .  s   z_DeferredMapperConfig.clsc                 C   s    t || j| _| | j| j< d S r6   )weakrefref_remove_config_clsr   _configs)rZ   r*   r    r    r!   r   2  s   c                 C   s   | j |d  d S r6   )r   r   )r   r   r    r    r!   r   7  s   z(_DeferredMapperConfig._remove_config_clsc                 C   s   t |tot|| jv S r6   )rD   rV   r   r   r   r   r*   r    r    r!   r   ;  s   z_DeferredMapperConfig.has_clsc                 C   s*   t |dr	|  tj|dt| d)N_sa_raise_deferred_configzOClass %s has a deferred mapping on it.  It is not yet usable as a mapped class.)msg)r3   r   orm_excZUnmappedClassErrorZ_safe_cls_namer   r    r    r!   raise_unmapped_for_cls@  s   
z,_DeferredMapperConfig.raise_unmapped_for_clsc                 C   s   | j t| S r6   )r   r   r   r   r    r    r!   r   K  s   z$_DeferredMapperConfig.config_for_clsTc                    sv   fdddd | j  D D }|s|S tdd |D  g } D ]| fddjD  q"tt||S )Nc                    s&   g | ]\}}|d urt | r|qS r6   )r,   )r   mrS   )base_clsr    r!   r   Q  s    z:_DeferredMapperConfig.classes_for_base.<locals>.<listcomp>c                 S   s   g | ]}||j fqS r    r   r   r   r    r    r!   r   S  s    c                 s   s    | ]}|j |fV  qd S r6   r   r   r    r    r!   	<genexpr>Z  s    z9_DeferredMapperConfig.classes_for_base.<locals>.<genexpr>c                 3   s(    | ]}| v r |   fV  qd S r6   r    )r   r   )all_m_by_clsm_clsr    r!   r   ^  s    
)r   valuesr   extendr'   r   r   sort)r   r   r   classes_for_baseZtuplesr    )r   r   r   r!   r   O  s   

z&_DeferredMapperConfig.classes_for_basec                    s    | j | jd  tt| |S r6   )r   r   r   ri   r   r^   r_   ro   r    r!   r^   e  s   z_DeferredMapperConfig.map)T)rW   rb   rc   r   rX   r   r`   propertyr   setterre   r   r   r   r   r   rw   r^   rx   r    r    ro   r!   r   (  s$    






r   c                 C   s  d| j v rt|tr t|| | jj|dd | j|| dS t|trK|j	D ]}t|trA|j
du rAt|| | jj|dd q(| j|| dS t|trY| j|| dS t|trq|j|krqt|j}| j|| dS t| || | j  dS t| || dS )zadd an attribute to an existing declarative class.

    This runs through the logic to determine MapperProperty,
    adds it to the Mapper, adds a column to the mapped Table, etc.

    r=   T)Zreplace_existingN)r%   rD   r   r   rh   r   r=   Zadd_propertyr   r   r>   r   r
   r   r   rV   __setattr___expire_memoizations)r   r   r\   r   r    r    r!   _add_attributej  s(   







r   c                 C   sj   d| j v r-|| j v r-| jjs-| j | }t|ttttfr tdt	
| | | j  d S t	
| | d S )Nr=   z<Can't un-map individual mapped attributes on a mapped class.)r%   r=   Z_dispose_calledrD   r   r   r   r
   NotImplementedErrorrV   __delattr__r   )r   r   r\   r    r    r!   _del_attribute  s    
r   c                 K   sB   t | }|D ]}t||std||jf t| |||  qdS )a=  A simple constructor that allows initialization from kwargs.

    Sets attributes on the constructed instance using the names and
    values in ``kwargs``.

    Only keys that are present as
    attributes of the instance's class are allowed. These could be,
    for example, any mapped columns or relationships.
    z(%r is an invalid keyword argument for %sN)rV   r3   	TypeErrorrW   r   )rZ   kwargsrS   r   r    r    r!   _declarative_constructor  s   

r   r[   c                 C   s(   |j d u r| |_ |jd u r| |_d S d S r6   )r   rI   )r   columnr    r    r!   r     s
   


r   )F)8r   
__future__r   r   r   Zsqlalchemy.ormr   r    r   r   r   r   rj   r	   r
   r1   r   r   Zdescriptor_propsr   r   Z
interfacesr   r   rL   r   r   r   r   sqlr   Z
sql.schemar   r   r   r"   r(   r2   r)   r;   r@   Zpreload_modulerF   rJ   r$   r7   r<   rR   r   r   r   r   r   rW   r   r    r    r    r!   <module>   sh   
%
@D      
B!