
    hw`                     :   d Z ddlZddlZddlm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mZ 	 dd	lmZ 	 ddlmZ d Zg dZej6                  dd dk(  rd;dZee_        	 ddlmZ  eg dg        eg dg        eg dg        G d de       Z! G d de       Z" G d de       Z# G d de$      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+ejX                        Z- G d) d*e+ej\                        Z/ G d+ d,e+ej`                        Z1 G d- d.e$      Z2 G d/ d0e$      Z3d1ddg di fd2Z4d<d3Z5d4 Z6 G d5 d6e$      Z7 G d7 d8e7      Z8 G d9 d:e7      Z9y# e$ r
 dd
lmZ Y ?w xY w# e$ r
 ddlmZ Y Gw xY w# e$ r Y w xY w)=z0
State tracking functionality for django models
    N)wraps)models)Field)DeferredAttribute)class_prepared)pre_transitionpost_transition)partialmethod)curry)appsc                 N    t        j                  |       }|j                  |      S N)django_appsget_app_config	get_model)	app_label
model_nameapps      C/home/dcms/DCMS/lib/python3.12/site-packages/django_fsm/__init__.pyr   r      s!    ((3}}Z((    )r   )TransitionNotAllowedConcurrentTransitionFSMFieldMixinFSMFieldFSMIntegerFieldFSMKeyFieldConcurrentTransitionMixin
transitioncan_proceedhas_transition_perm	GET_STATERETURN_VALUE   )r#      c                     g }t        |       D ]-  }	 t        | |      }|r	 ||      s|j                  ||f       / |j	                          |S # t        $ r Y Mw xY w)zReturn all members of an object as (name, value) pairs sorted by name.
        Optionally, only return members that satisfy a given predicate.)dirgetattrAttributeErrorappendsort)object	predicateresultskeyvalues        r   __getmembersr0   4   sm     v; 	-C, 	% 0U|,	- 	 " s   A	AA)add_introspection_rulesz^django_fsm\.FSMFieldz^django_fsm\.FSMIntegerFieldz^django_fsm\.FSMKeyFieldc                   "     e Zd ZdZ fdZ xZS )r   z'Raised when a transition is not allowedc                     |j                  dd       | _        |j                  dd       | _        t        t        |   |i | y )Nr+   method)popr+   r4   superr   __init__selfargskwargs	__class__s      r   r7   zTransitionNotAllowed.__init__R   s<    jj40jj40"D2DCFCr   __name__
__module____qualname____doc__r7   __classcell__r<   s   @r   r   r   O   s    1D Dr   r   c                       e Zd ZdZy)InvalidResultStatez'Raised when we got invalid result stateNr>   r?   r@   rA    r   r   rE   rE   X   s    1r   rE   c                       e Zd ZdZy)r   z
    Raised when the transition cannot be executed because the
    object has become stale (state has been changed since it
    was fetched from the database).
    NrF   rG   r   r   r   r   \   s    r   r   c                   4    e Zd Zd Zed        Zd Zd Zd Zy)
Transitionc                 f    || _         || _        || _        || _        || _        || _        || _        y r   r4   sourcetargeton_error
conditions
permissioncustomr9   r4   rM   rN   rO   rP   rQ   rR   s           r   r7   zTransition.__init__e   s3     $$r   c                 .    | j                   j                  S r   )r4   r>   r9   s    r   namezTransition.namen   s    {{###r   c                     | j                   syt        | j                         rt        | j                  ||            S |j                  | j                   |      ry|j                  | j                         ryy)NTF)rQ   callableboolhas_perm)r9   instanceusers      r   rZ   zTransition.has_permr   sY    doo&$788]]4??H5]]4??+r   c                 ,    t        | j                        S r   )hashrV   rU   s    r   __hash__zTransition.__hash__~   s    DIIr   c                     t        |t              r|| j                  k(  S t        |t              r|j                  | j                  k(  S yNF)
isinstancestrrV   rJ   )r9   others     r   __eq__zTransition.__eq__   s;    eS!DII%%eZ(::**r   N)	r>   r?   r@   r7   propertyrV   rZ   r_   re   rG   r   r   rJ   rJ   d   s*     $ $
r   rJ   c              #     K   |j                  |       }|j                  | j                     }|j                         D ]I  \  }}|j                  }|j                  |      s$|j                  | |      s7|j                  |       K yw)zZ
    List of transitions available in current model state
    with all conditions met
    N)	get_statetransitionsr<   items_django_fsmhas_transitionconditions_metget_transition)r[   field
curr_stateri   rV   r   metas          r   get_available_FIELD_transitionsrr      s     
 *J##H$6$67K'--/ 2j%%z*t/B/B8Z/X%%j112s   AB
!B
4B
c                 8    |j                  | j                        S )zB
    List of all transitions available in current model state
    )get_all_transitionsr<   )r[   ro   s     r   get_all_FIELD_transitionsru      s     $$X%7%788r   c              #   \   K   t        | |      D ]  }|j                  | |      s|  yw)zu
    List of transitions available in current model state
    with all conditions met and user have rights on it
    N)rr   rZ   )r[   r\   ro   r   s       r   $get_available_user_FIELD_transitionsrw      s4     
 6hF 
x.s   ",,c                   J    e Zd ZdZd Zd Zdg di fdZd Zd Zd Z	d	 Z
d
 Zy)FSMMetaz5
    Models methods transitions meta information
    c                      || _         i | _        y r   )ro   ri   )r9   ro   r4   s      r   r7   zFSMMeta.__init__   s    
r   c                     | j                   j                  |d       }|| j                   j                  dd       }|| j                   j                  dd       }|S )N*+)ri   get)r9   rM   r   s      r   rn   zFSMMeta.get_transition   s\    %%))&$7
))--c48J))--c48Jr   Nc           	          || j                   v rt        dj                  |            t        |||||||      | j                   |<   y )Nz"Duplicate transition for {0} staterL   )ri   AssertionErrorformatrJ   rS   s           r   add_transitionzFSMMeta.add_transition   sQ    T%%% !E!L!LV!TUU#-!!$
 r   c                     || j                   v ryd| j                   v ryd| j                   v r| j                   d   j                  |k7  ryy)z_
        Lookup if any transition exists from current model state using current method
        Tr|   r}   F)ri   rN   )r9   states     r   rl   zFSMMeta.has_transition   sR     D$$$$"""$"""t'7'7'<'C'Cu'Lr   c                     | j                  |      }|y|j                  yt        t        fd|j                              S )z7
        Check if all conditions have been met
        FTc                      |       S r   rG   )	conditionr[   s    r   <lambda>z(FSMMeta.conditions_met.<locals>.<lambda>   s    Yx-@ r   )rn   rP   allmap)r9   r[   r   r   s    `  r   rm   zFSMMeta.conditions_met   sF     ((/
""*s@*BWBWXYYr   c                 N    | j                  |      }|sy|j                  ||      S ra   )rn   rZ   )r9   r[   r   r\   r   s        r   r    zFSMMeta.has_transition_perm   s+    ((/
&&x66r   c                 t    | j                  |      }|t        dj                  |            |j                  S NzNo transition from {0})rn   r   r   rN   r9   current_stater   s      r   
next_statezFSMMeta.next_state   s;    ((7
&'?'F'F}'UVV   r   c                 t    | j                  |      }|t        dj                  |            |j                  S r   )rn   r   r   rO   r   s      r   exception_statezFSMMeta.exception_state   s;    ((7
&'?'F'F}'UVV"""r   )r>   r?   r@   rA   r7   rn   r   rl   rm   r    r   r   rG   r   r   ry   ry      s>     ?Cr^bkm 
Z7!#r   ry   c                        e Zd Zd ZddZd Zy)FSMFieldDescriptorc                     || _         y r   ro   )r9   ro   s     r   r7   zFSMFieldDescriptor.__init__   s	    
r   Nc                 @    || S | j                   j                  |      S r   )ro   rh   )r9   r[   types      r   __get__zFSMFieldDescriptor.__get__  s"    Kzz##H--r   c                 @   | j                   j                  rP| j                   j                  |j                  v r.t	        dj                  | j                   j                              | j                   j                  ||       | j                   j                  ||       y )Nz&Direct {0} modification is not allowed)ro   	protectedrV   __dict__r(   r   	set_proxy	set_state)r9   r[   r/   s      r   __set__zFSMFieldDescriptor.__set__  sr    ::DJJOOx7H7H$H !I!P!PQUQ[Q[Q`Q`!abb 	

Xu-

Xu-r   r   )r>   r?   r@   r7   r   r   rG   r   r   r   r      s    .
.r   r   c                   Z     e Zd ZeZ fdZ fdZd Zd Zd Z	d Z
d Z fdZd	 Z xZS )
r   c                 H   |j                  dd      | _        i | _        i | _        |j                  dd       }|j	                  dd       }||t        d      |4g }|D ](  \  }}}|j                  ||f       || j                  |<   * ||d<   t        t        | &  |i | y )Nr   Fstate_choiceschoicesz)Use one of choices or state_choices value)
r5   r   ri   state_proxyr~   
ValueErrorr)   r6   r   r7   )	r9   r:   r;   r   r   r   titleproxy_cls_refr<   s	           r   r7   zFSMFieldMixin.__init__  s    K7

?D9**Y-$)<HII$G/< 8+umu~.*7  '8 !(F9mT+T<V<r   c                 t    t         t        |          \  }}}}| j                  r| j                  |d<   ||||fS )Nr   )r6   r   deconstructr   )r9   rV   pathr:   r;   r<   s        r   r   zFSMFieldMixin.deconstruct%  s?    #(#I#K dD&>>"&..F;T4''r   c                    t         j                  d d dk\  rt        |       j                  |      S t         j                  d d dk\  r$t        | j                        j                  |      S t         j                  d d dk\  r&t        | j                  d       j                  |      S |j
                  | j                     S )N   )r   r   r   )r#      r   )r   
   r   model)djangoVERSIONr   r   rV   r   r9   r[   s     r   rh   zFSMFieldMixin.get_state+  s     >>"1*$T*228<<^^BQ9,$TYY/77AA^^BQ:-$TYYd;CCHMM $$TYY//r   c                 6    ||j                   | j                  <   y r   )r   rV   r9   r[   r   s      r   r   zFSMFieldMixin.set_stateA  s    ',$))$r   c                    || j                   v rT| j                   |   }	 |j                  d      \  }}t        ||      }|t        dj                  |            ||_        yy# t        $ r |j                  j                  }|}Y Tw xY w)z
        Change class
        .NzNo model found {0})r   splitr   _metar   r   r   r<   )r9   r[   r   r   r   r   r   s          r   r   zFSMFieldMixin.set_proxyD  s     D$$$**51K)(3(9(9#(>%	: i4E} !5!<!<[!IJJ!&H %
  )$NN44	(
)s   A$ $!BBc           	      T   |j                   }|j                  }| j                  |      }|j                  |      st	        dj                  ||      ||      |j                  ||      st	        dj                  |      ||      |j                  |      }|j                  |||j                  ||||d}	t        j                  d	i |	 	  ||g|i |}
|Ot        |d      r|j                  |t        |
||      }||	d<   | j                  ||       | j                  ||       t!        j                  d	i |	 |
S # t"        $ r\}|j%                  |      }|rC| j                  ||       | j                  ||       ||	d<   ||	d<   t!        j                  d	i |	  d }~ww xY w)
Nz0Can't switch from state '{0}' using method '{1}')r+   r4   z8Transition conditions have not been met for method '{0}')senderr[   rV   ro   rM   rN   method_argsmethod_kwargsrh   )r:   r;   rN   	exceptionrG   )rk   r>   rh   rl   r   r   rm   r   r<   ro   r   sendhasattrr   r   r   r	   	Exceptionr   )r9   r[   r4   r:   r;   rq   method_namer   r   signal_kwargsresultexcr   s                r   change_statezFSMFieldMixin.change_stateX  s   !!oox0""=1&BII-Yde 
 ""8];&JQQR]^gox~  __]3
 (( ZZ# #	
 	,m,	2H6t6v6F%:{3!+!5!5h
FY]fl!5!mJ.8M(+x4x4   1=1  	"22=AOx9x9*9h'-0k*$$5}5	s   AE 	F'AF""F'c              #      K   | j                   |   }|j                         D ]4  \  }}|j                  }|j                   j                         D ]  }|  6 yw)zT
        Returns [(source, target, name, method)] for all field transitions
        N)ri   rj   rk   values)r9   instance_clsri   rV   r   rq   s         r   rt   z!FSMFieldMixin.get_all_transitions  sd      &&|4 + 1 1 3 	!D*))D"..557 !
  !	!s   AAc                    || _         t        t        |   ||fi | t	        || j
                  | j                  |              t	        |dj                  | j
                        t        t        |              t	        |dj                  | j
                        t        t        |              t	        |dj                  | j
                        t        t        |              t        j                  | j                         y )Nzget_all_{0}_transitionsr   zget_available_{0}_transitionsz"get_available_user_{0}_transitions)base_clsr6   r   contribute_to_classsetattrrV   descriptor_classr   r
   ru   rr   rw   r   connect_collect_transitions)r9   clsrV   r;   r<   s       r   r   z!FSMFieldMixin.contribute_to_class  s    mT6sDKFKTYY 5 5d ;<.55dii@-PiquBvw077		BMRqy}D~	
 	077		B>dK	
 	t889r   c                      |d   }t        | j                        sy  fd}i }t        j                  ||      }|D ]  \  }} |j                  _        |||<    | j                  |<   y )Nr   c                    t        j                  |       xs t        j                  |       xr t        | d      xr | j                  j
                  j                  fv xs t        | j                  j
                  t              xr\ | j                  j
                  j                  j                  k(  xr- | j                  j
                  j                  j                  k(  S )Nrk   )
inspectismethod
isfunctionr   rk   ro   rV   rb   r   creation_counter)attrr9   s    r   is_field_transition_methodzFFSMFieldMixin._collect_transitions.<locals>.is_field_transition_method  s    !!$'C7+=+=d+C 	D-0	 $$**tTYY.?? "4#3#3#9#95A ] ,,2277499D] ,,22CCtG\G\\r   )r,   )
issubclassr   r   
getmembersrk   ro   ri   )	r9   r:   r;   r   r   sender_transitionsri   r   r4   s	   `        r   r   z"FSMFieldMixin._collect_transitions  s}    !&$--0	  ((;UV#. 	5K'+F$.4{+	5 $6 r   )r>   r?   r@   r   r   r7   r   rh   r   r   r   rt   r   r   rB   rC   s   @r   r   r     s7    )=&(0,-'(3j
!:"6r   r   c                   "     e Zd ZdZ fdZ xZS )r   z=
    State Machine support for Django model as CharField
    c                 P    |j                  dd       t        t        |   |i | y )N
max_length2   )
setdefaultr6   r   r7   r8   s      r   r7   zFSMField.__init__  s'    ,+h&77r   r=   rC   s   @r   r   r     s    8 8r   r   c                       e Zd ZdZy)r   zJ
    Same as FSMField, but stores the state value in an IntegerField.
    NrF   rG   r   r   r   r     s     	r   r   c                       e Zd ZdZd Zd Zy)r   z0
    State Machine support for Django model
    c                 4    |j                   | j                     S r   )r   attnamer   s     r   rh   zFSMKeyField.get_state  s      ..r   c                 T    | j                  |      |j                  | j                  <   y r   )	to_pythonr   r   r   s      r   r   zFSMKeyField.set_state  s    *...*?$,,'r   N)r>   r?   r@   rA   rh   r   rG   r   r   r   r     s    /@r   r   c                   (     e Zd ZdZd Z fdZ xZS )FSMModelMixinzP
    Mixin that allows refresh_from_db for models with fsm protected fields
    c                     d }t        || j                  j                        }|D ch c]  }|j                   c}S c c}w )Nc                 >    t        | t              xr | j                  S r   )rb   r   r   )fs    r   is_fsm_and_protectedzEFSMModelMixin._get_protected_fsm_fields.<locals>.is_fsm_and_protected  s    a/?AKK?r   )filterr   concrete_fieldsr   )r9   r   protected_fieldsr   s       r   _get_protected_fsm_fieldsz'FSMModelMixin._get_protected_fsm_fields  s8    	@!"6

8R8RS#34a		444s   >c                 @   |j                  dd       }|sl| j                         }| j                         }|j                  |      }| j                  j
                  D cg c]  }|j                  |vr|j                   }}||d<   t        t        | &  |i | y c c}w )Nfields)
r5   get_deferred_fieldsr   unionr   r   r   r6   r   refresh_from_db)	r9   r:   r;   r   deferred_fieldsr   skipped_fieldsr   r<   s	           r   r   zFSMModelMixin.refresh_from_db  s    Hd+ "668O#==?,223CDN)-)C)C :A.8 ii :F : "xmT2DCFC	:s   !B)r>   r?   r@   rA   r   r   rB   rC   s   @r   r   r     s    5D Dr   r   c                   V     e Zd ZdZ fdZed        Z fdZd Z fdZ	 fdZ
 xZS )r   aH  
    Protects a Model from undesirable effects caused by concurrently executed transitions,
    e.g. running the same transition multiple times at the same time, or running different
    transitions with the same SOURCE state at the same time.

    This behavior is achieved using an idea based on optimistic locking. No additional
    version field is required though; only the state field(s) is/are used for the tracking.
    This scheme is not that strict as true *optimistic locking* mechanism, it is however
    more lightweight - leveraging the specifics of FSM models.

    Instance of a model based on this Mixin will be prevented from saving into DB if any
    of its state fields (instances of FSMFieldMixin) has been changed since the object
    was fetched from the database. *ConcurrentTransition* exception will be raised in such
    cases.

    For guaranteed protection against such race conditions, make sure:
    * Your transitions do not have any side effects except for changes in the database,
    * You always run the save() method on the object within django.db.transaction.atomic()
    block.

    Following these recommendations, you can rely on ConcurrentTransitionMixin to cause
    a rollback of all the changes that have been executed in an inconsistent (out of sync)
    state, thus practically negating their effect.
    c                 L    t        t        | 
  |i | | j                          y r   )r6   r   r7   _update_initial_stater8   s      r   r7   z"ConcurrentTransitionMixin.__init__  s$    '7HH""$r   c                 D    t        d | j                  j                        S )Nc                 "    t        | t              S r   )rb   r   r   s    r   r   z8ConcurrentTransitionMixin.state_fields.<locals>.<lambda>  s    Jum$D r   )r   r   r   rU   s    r   state_fieldsz&ConcurrentTransitionMixin.state_fields  s    DdjjFWFWXXr   c                 0    t        fd j                        }t         fd|D              }t        t            j                   di ||||||      }	|	s:j                  |      j                  |      j                         rt        d      |	S )Nc                 6    | j                   j                   k(  S r   r   )ro   base_qss    r   r   z6ConcurrentTransitionMixin._do_update.<locals>.<lambda>&  s    )E r   c              3   h   K   | ])  }|j                   j                  |j                      f + y wr   )r   *_ConcurrentTransitionMixin__initial_states.0ro   r9   s     r   	<genexpr>z7ConcurrentTransitionMixin._do_update.<locals>.<genexpr>)  s*     iV[U]]D,A,A%--,PQis   /2)r  usingpk_valr   update_fieldsforced_update)pkzOCannot save object! The state has been changed since fetched from the database!rG   )	r   r   dictr6   r   
_do_updater  existsr   )r9   r  r  r  r   r	  r
  	filter_onstate_filterupdatedr<   s   ``        r   r  z$ConcurrentTransitionMixin._do_update!  s    
 EtGXGXY	 i_hii14C"GNN2\2'' D 
 7>>V>4::5AHHJ&'xyyr   c                 L     t         fd j                  D               _        y )Nc              3   X   K   | ]!  }|j                   |j                        f # y wr   )r   value_from_objectr  s     r   r  zBConcurrentTransitionMixin._update_initial_state.<locals>.<genexpr>@  s&     $sX]emmU5L5LT5R%S$ss   '*)r  r   r  rU   s   `r   r   z/ConcurrentTransitionMixin._update_initial_state?  s     $$saearar$s sr   c                 L    t        t        | 
  |i | | j                          y r   )r6   r   r   r   r8   s      r   r   z)ConcurrentTransitionMixin.refresh_from_dbB  s$    '>OO""$r   c                 L    t        t        | 
  |i | | j                          y r   )r6   r   saver   r8   s      r   r  zConcurrentTransitionMixin.saveF  s$    '3TDVD""$r   )r>   r?   r@   rA   r7   rf   r   r  r   r   r  rB   rC   s   @r   r   r     s=    2% Y Y<t%% %r   r   r|   c                 *      fd}|S )z
    Method decorator to mark allowed transitions.

    Set target to None if current state needs to be validated and
    has not changed after the function call.
    c           
      b    dt         dd       c}sd}t               t         d       t        
t        t
        t        f      r)
D ]#  } j                  j                   |	       % n! j                  j                   
	       t                fd       }|s|S  S )NTrk   F)ro   r4   c                 F     j                   j                  | g|i |S r   )ro   r   )r[   r:   r;   fsm_metafuncs      r   _change_statez;transition.<locals>.inner_transition.<locals>._change_state`  s&    .8>>..xOOOOr   )
r'   ry   r   rb   listtuplesetrk   r   r   )r  wrapper_installedr   r  r  rP   rR   ro   rO   rQ   rM   rN   s   `   @r   inner_transitionz$transition.<locals>.inner_transitionS  s    &*GD-,N#8 %U48HD-2ftUC01 o  //eVXz[egmno ++D&&(JXbdjk	t	P 
	P !  r   rG   )ro   rM   rN   rO   rP   rQ   rR   r"  s   ``````` r   r   r   K  s     , r   c                 H   t        | d      s/t        | dt        | d            }t        d|j                  z        | j                  }t        | dt        | d            }|j
                  j                  |      }|j                  |      xr | xs |j                  ||      S )z
    Returns True if model in state allows to call bound_method

    Set ``check_conditions`` argument to ``False`` to skip checking
    conditions.
    rk   im_func__func__%s method is not transitionim_self__self__)	r   r'   	TypeErrorr>   rk   ro   rh   rl   rm   )bound_methodcheck_conditionsr$  rq   r'  r   s         r   r   r   l  s     </,	7<3TU58H8HHII##DlIw|Z/PQGJJ((1M}-w7G3G3v4K^K^_fhuKvwr   c                 h   t        | d      s/t        | dt        | d            }t        d|j                  z        | j                  }t        | dt        | d            }|j
                  j                  |      }|j                  |      xr' |j                  ||      xr |j                  |||      S )z_
    Returns True if model in state allows to call bound_method and user have rights on it
    rk   r$  r%  r&  r'  r(  )
r   r'   r)  r>   rk   ro   rh   rl   rm   r    )r*  r\   r$  rq   r'  r   s         r   r    r    ~  s     </,	7<3TU58H8HHII##DlIw|Z/PQGJJ((1M 	M* 	C7	C$$WmTBr   c                       e Zd Zg i fdZy)Statec                     t         r   )NotImplementedErrorr9   r   r   r   r:   r;   s         r   rh   zState.get_state  s    !!r   N)r>   r?   r@   rh   rG   r   r   r.  r.    s    8:2 "r   r.  c                       e Zd Zd Zg i fdZy)r"   c                 &    |r|| _         y d | _         y r   )allowed_states)r9   r4  s     r   r7   zRETURN_VALUE.__init__  s    0>nDr   c                     | j                   3|| j                   vr%t        dj                  || j                               |S Nz&{} is not in list of allowed states
{})r4  rE   r   r1  s         r   rh   zRETURN_VALUE.get_state  sB    *T000()R)Y)YZ`bfbubu)vwwr   Nr>   r?   r@   r7   rh   rG   r   r   r"   r"     s    I 9;2 r   r"   c                        e Zd ZddZg i fdZy)r!   Nc                      || _         || _        y r   )r  r4  )r9   r  statess      r   r7   zGET_STATE.__init__  s    	$r   c                      | j                   |g|i |}| j                  3|| j                  vr%t        dj                  || j                              |S r6  )r  r4  rE   r   )r9   r   r   r   r:   r;   result_states          r   rh   zGET_STATE.get_state  s]     tyy888*4#6#66()R)Y)YZfhlh{h{)|}}r   r   r7  rG   r   r   r!   r!     s    % 9;2 r   r!   r   )T):rA   r   sys	functoolsr   r   	django.dbr   django.db.modelsr   django.db.models.query_utilsr   django.db.models.signalsr   django_fsm.signalsr   r	   r
   ImportErrordjango.utils.functionalr   django.appsr   r   r   django.db.models.loading__all__version_infor0   r   south.modelsinspectorr1   r   r   rE   r   r+   rJ   rr   ru   rw   ry   r   r   	CharFieldr   IntegerFieldr   
ForeignKeyr   r   r   r   r   r    r.  r"   r!   rG   r   r   <module>rN     s    
    " : 3 >?'
	3/) BQ6! &G?= B!9 :;B!@ ABB!< =>D9 D2 29 # #L29Q#f Q#h. .$u6F u6p8}f.. 8	mV%8%8 		@-!2!2 	@DF D4I% I%X !X\eg Bx$&"F "
5 
 
_  ?>>?  3223R  		s4   E- 	E? (F -E<;E<?FFFF