o
    [hx                     @   s   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	 d dl
mZ d dlmZ d dlZd dlZd dlZd dlmZmZ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mZ d dlmZ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+m,Z, d dl-m.Z.m/Z/ e0e1Z2dZ3dd Z4dd Z5dd Z6dZ7e5 Z8e4 Z9da:G dd  d ejZ;d!d" Z<e	d#d$ Z=d%d& Z>e Z?G d'd( d(Z@e@ ZAeAjBZCeDeEd)ZFd*d+ ZGeG ZHeeHd,ZIdZJG d-d. d.ZKd/d0 ZLG d1d2 d2e?ZMG d3d4 d4ejNZOG d5d6 d6eOZPG d7d8 d8eOZQG d9d: d:ZReeRZSG d;d< d<eMZTG d=d> d>eUZVG d?d@ d@eTZWG dAdB dBeXZYG dCdD dDZZG dEdF dFeXZ[dGe\fdHdIZ]dJdK Z^dLe_fdMdNZ`dOdP ZadQdR ZbG dSdT dTee_ZcG dUdV dVejNZdG dWdX dXZee#jfde#jgd e#jhd e#jidYe#jjdYeQe.d ePe/d iZkdddZdGe;fd[d\Zld]d^ Zmd_d` Zndadb Zodcdd Zpdedf Zqdgdh Zrdidj ZsenZteqZueoZvdkdl ZwdGexfdmdnZyG dodp dpZzG dqdr dreMZ{e|edsdtdu Z}e|edvdwdx Z~dS )y    N)defaultdict)contextmanager)Decimal)Path)Column
ForeignKeycreate_engineevent)types)declarative_base)declared_attr)Mutable)mapperrelationship)sessionmakerconfigure_mappers)NoResultFound)sqltypes)HTTPException)__version__)common)settings)expand_choice_tuplesget_models_module)CurrencyRealWorldCurrencyz
db.sqlite3c                   C   s   t jtddS )NFZcheck_same_thread)sqlite3connectDB_FILE r!   r!   u/home/ubuntu/experiments/live_experiments/Pythonexperiments/Otree/venv/lib/python3.10/site-packages/otree/database.pyget_disk_conn+      r#   c                   C   s   t jdddS )Nz:memory:Fr   )r   r   r!   r!   r!   r"   get_mem_conn/   r$   r%   c                 C   s   t | _|  }|d }z
tt| d }W n ty#   i  Y S w i }|D ]}|d|  }tt| d ||< q(|S )Nz2SELECT name FROM sqlite_master WHERE type='table';r   zPRAGMA table_info('%s')   )strZtext_factorycursorexecutefetchalllistzip
IndexError)conncurresultZtable_namesdZ
table_namer!   r!   r"   
get_schema3   s"   r2   TFc                   @   s   e Zd ZU eed< dZdS )OTreeColumn
form_propsN)__name__
__module____qualname__dict__annotations__auto_submit_defaultr!   r!   r!   r"   r3   S   s   
 r3   c                     s0  t t} t t t }t }td d }|t kr,tds,t	
dt d  D ]c| v r fdd|  D }d|}d	| d
 }ddd |D }d d| d| d}|| | }	z|||	 W q. tjy }
 zt	
dt d W Y d }
~
q.d }
~
ww q.t  d S )NzPRAGMA user_versionr   ZOTREE_CORE_DEVz5oTree has been updated. Please delete your database ()c                    s$   g | ]}|  v rd | d qS )"r!   .0c
new_schemaZtblnamer!   r"   
<listcomp>j   s    z%load_in_memory_db.<locals>.<listcomp>, zSELECT z FROM c                 s   s    | ]}d V  qdS )?Nr!   )r>   _r!   r!   r"   	<genexpr>o   s    z$load_in_memory_db.<locals>.<genexpr>zINSERT INTO (z
) VALUES (z0An error occurred. Please delete your database (z).)r2   sqlite_disk_connsqlite_mem_connr(   r)   Zfetchoneversion_for_pragmaosgetenvsysexitr    joinr*   Zexecutemanyr   ZIntegrityErrorcommit)
old_schemaZdisk_curZmem_curZprev_versionZcommon_colsZcommon_cols_joinedZ
select_cmdZquestion_marksZ
insert_cmdrowsexcr!   r@   r"   load_in_memory_dbX   s6   

rT   c                   c   sZ    t rt  zz	d V  t  W n   t   W t r#t  d S d S t r,t  w w N)NEW_IDMAP_EACH_REQUESTdbnew_sessionrP   rollbackcloser!   r!   r!   r"   session_scope}   s   
r[   c                   C   s8   t sd S trd S t dt   tt dad S )NzPRAGMA user_version = T)	IN_MEMORY_dumpedrI   r(   r)   rJ   backuprH   r!   r!   r!   r"   save_sqlite_db   s   
r_   c                   @   st   e Zd ZU dZdZejjed< 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dd Zdd ZdS )	DBWrapperz
    1. this way we can defer definining the ._db attribute
    until all modules are imported
    2. we can add helper methods
    N_dbc                 O   s   | j j|i |S rU   )ra   query)selfargskwargsr!   r!   r"   rb         zDBWrapper.queryc                 C      | j |S rU   )ra   addrc   objr!   r!   r"   rh         zDBWrapper.addc                 C   rg   rU   )ra   add_all)rc   Zobjsr!   r!   r"   rl      rk   zDBWrapper.add_allc                 C   rg   rU   )ra   deleteri   r!   r!   r"   rm      rk   zDBWrapper.delete	Not foundc                 K   sR   z|  |jdi | W S  tjjjy(   | d|j d| }td|w )N: rC   i  r!   )	rb   	filter_byone
sqlalchemyormrS   r   r5   r   )rc   ZModelmsgre   r!   r!   r"   
get_or_404   s   
zDBWrapper.get_or_404c                 C   s    z| j  W S    | j    rU   )ra   rP   rY   rc   r!   r!   r"   rP      s
   
zDBWrapper.commitc                 C   
   | j  S rU   )ra   rY   rv   r!   r!   r"   rY         
zDBWrapper.rollbackc                 C   rw   rU   )ra   rZ   rv   r!   r!   r"   rZ      rx   zDBWrapper.closec                 C   s&   t drttd| _d S t | _d S )NOTREE_EPHEMERALbind)rK   rL   	DBSessionephemeral_connectionra   rv   r!   r!   r"   rX      s   
zDBWrapper.new_sessionc                 C   s   | j   d S rU   )ra   
expire_allrv   r!   r!   r"   r~      r$   zDBWrapper.expire_all)rn   )r5   r6   r7   __doc__ra   rr   rs   Sessionr9   rb   rh   rl   rm   ru   rP   rY   rZ   rX   r~   r!   r!   r!   r"   r`      s   
 
r`   ZOTREE_IN_MEMORYc                  C   s   t rtddd tjjd} n"tddt }i }|dr$dd |d	< t|fd
tjji|} | j	
 dkrFddlm} || ddd  | S )Nz	sqlite://c                   S      t S rU   )rI   r!   r!   r!   r"   <lambda>       zget_engine.<locals>.<lambda>)creator	poolclassDATABASE_URLz
sqlite:///Zsqlitec                   S   r   rU   )rH   r!   r!   r!   r"   r      r   r   r   r   r	   r   c                 S   s
   |  dS )Nzpragma foreign_keys=on)r)   )r?   rE   r!   r!   r"   r      s   
 )r\   r   rr   poolZ
StaticPoolrK   rL   r    
startswithurlZget_backend_namer
   listen)enginer   re   r
   r!   r!   r"   
get_engine   s.   

r   rz   c                   @   s&   e Zd Zdd ZdddZdd ZdS )	VarsDescriptorc                 C   
   || _ d S rU   )attr)rc   r   r!   r!   r"   __init__   rx   zVarsDescriptor.__init__Nc                 C   s   |j | j S rU   varsr   )rc   rj   objtyper!   r!   r"   __get__  rk   zVarsDescriptor.__get__c                 C   s   ||j | j< d S rU   r   )rc   rj   valuer!   r!   r"   __set__     zVarsDescriptor.__set__rU   )r5   r6   r7   r   r   r   r!   r!   r!   r"   r      s    
r   c                  C   s  ddl m}  | D ]}t|}|rt| zt|}W n ty; } zdd l}|	  td W Y d }~nd }~ww t
|}|j|j|jfD ]J}d|_||_
| }|jjD ]5}	t|	tr|	j}
t||
d rot|
}n|	jdr~t|
|	jd }nd }|rd|
 d}t||| qY|  qIqdd	lm}m} |d
f|dffD ]*\}}tt |D ]}t||r| d| d}t| t||t!| q|  qdd l"}t#  t$j%&t' t(rt)*dst+t,- rt+t,. j/dkrt0  t12  d S )Nr   )
OTREE_APPSr&   F_choiceschoicesget__display)Participantr   ZSESSION_FIELDSZPARTICIPANT_FIELDSz cannot contain "z " because that name is reserved.ry   )3Zotree.settingsr   r   Zapp_name_validity_messagerM   rN   r   	Exception	traceback	print_exc	is_noselfPlayerGroupZ
Subsession
_is_frozenget_user_defined_target	__table__columns
isinstancer3   namehasattrmake_get_display_dynamicr4   getmake_get_display_staticsetattrfreeze_setattrZotree.modelsr   r   getattrr   r   Zotree.models_concreter   AnyModelmetadataZ
create_allr   r\   rK   rL   r   r    existsstatst_sizerT   rW   rX   )r   Zapperr_msgmodelsrS   r   r   clstargetfieldr   methodmethod_namer   r   Zsetting_namer   rt   otreer!   r!   r"   init_orm
  sp   


	







r   c                   @   s   e Zd ZdZeejddZdd Zdd Z	e
dd Zed	d
 Zdd ZedddZedddZedd ZedefddZeddddZedddZedd ZdS )r   T)primary_keyc              
   C   s|   | j j}zddd |   D }W n! ty5 } zd}td| dt|  W Y d }~nd }~ww | d| dS )	NrC   c                 s   s"    | ]\}}| d | V  qdS )=Nr!   )r>   kvr!   r!   r"   rF   Y  s    
z$AnyModel.__repr__.<locals>.<genexpr>z???zError during __repr__ of ro   rG   r;   )		__class__r5   rO   _get_repr_attributesitemsr   loggerwarningrepr)rc   cls_nameattrsrS   r!   r!   r"   __repr__V  s   

&zAnyModel.__repr__c                 C   s   t | jdS N)id)r8   r   rv   r!   r!   r"   r   d  rk   zAnyModel._get_repr_attributesc                 C   s   |   d | j  S )NrE   )get_folder_namer5   lowerr   r!   r!   r"   __tablename__g  s   zAnyModel.__tablename__c                 C   s   | j dd S )z
        should be renamed to get_app_name, since we no longer care about
        folders in otree-core. we treat all otree-core models as being in the
        same namespace.
        .r   )r6   splitr   r!   r!   r"   r   k  s   zAnyModel.get_folder_namec                 C   s   t | j| jdS r   )typeobjects_getr   rv   r!   r!   r"   _cloney  rf   zAnyModel._clonereturnc              
   O   s2   z| j |i | W S  ty } z d }~ww rU   )objects_filterrq   r   )r   rd   re   rS   r!   r!   r"   r   |  s   zAnyModel.objects_getc                 O   s   | j |i | S rU   )r   firstr   rd   re   r!   r!   r"   objects_first  s   zAnyModel.objects_firstc                 O   s   t | j| jdi |S Nr!   )dbqfilterrp   r   r!   r!   r"   r     s   zAnyModel.objects_filterc                 O   s   t | j|i | S rU   )boolr   r   r   r!   r!   r"   objects_exists  s   zAnyModel.objects_existsN)order_byc                   sZ    j |i |}|r||}dd  jjD  fddD }fdd|j| D S )Nc                 S      g | ]}|j qS r!   r   r>   fr!   r!   r"   rB         z)AnyModel.values_dicts.<locals>.<listcomp>c                    s   g | ]}t  |qS r!   )r   )r>   r   r   r!   r"   rB     s    c                    s   g | ]	}t t |qS r!   )r8   r,   )r>   row)namesr!   r"   rB     s    )r   r   r   r   with_entities)r   r   rd   re   rb   fieldsr!   )r   r   r"   values_dicts  s   
zAnyModel.values_dictsc                 K   s   | di |}t | |S r   )rW   rh   )r   re   rj   r!   r!   r"   objects_create  s   
zAnyModel.objects_createc                 C   s*   t dd | jjD | _t t| | _d S )Nc                 s   s    | ]}|j V  qd S rU   r   r   r!   r!   r"   rF     s    z*AnyModel.freeze_setattr.<locals>.<genexpr>)	frozensetr   r   _setattr_fieldsdir_setattr_attributesr   r!   r!   r"   r     s   zAnyModel.freeze_setattr)r   r   )r5   r6   r7   __abstract__r   stIntegerr   r   r   r   r   classmethodr   r   r   r   r   r   r   r   r   r   r!   r!   r!   r"   r   Q  s0    


r   c                   @   s(   e Zd Ze Zdd Zdd ZdZdS )BaseCurrencyTypec                 C   s   |d u rd S t t|S rU   )r'   r   rc   r   dialectr!   r!   r"   process_bind_param  s   z#BaseCurrencyType.process_bind_paramc                 C   s   |d u rd S |  t|S rU   )MONEY_CLASSr   r   r!   r!   r"   process_result_value  s   z%BaseCurrencyType.process_result_valueN)	r5   r6   r7   r   Textimplr   r   r   r!   r!   r!   r"   r     s
    r   c                   @      e Zd ZeZdS )CurrencyTypeN)r5   r6   r7   r   r   r!   r!   r!   r"   r         r   c                   @   r   )RealWorldCurrencyTypeN)r5   r6   r7   r   r   r!   r!   r!   r"   r     r   r   c                   @   s$   e Zd Zdd Zdd Zdd ZdS )MRUc                 C   s   t t| _d| _d S )Nr   )r   int_d_countrv   r!   r!   r"   r     s   

zMRU.__init__c                 C   s>   | ds|ds|dv rd S |  jd7  _| j| j|< d S )NrE   _id)r   groupZ
subsessionsessionZparticipantr&   )r   endswithr  r  )rc   itemr!   r!   r"   rh     s   	zMRU.addc                 C   s"   dd t | j dd ddD S )Nc                 S   s   g | ]\}}|qS r!   r!   )r>   r   countr!   r!   r"   rB     s    z#MRU.most_recent.<locals>.<listcomp>c                 S   s   | d S )Nr&   r!   )eler!   r!   r"   r     s    z!MRU.most_recent.<locals>.<lambda>T)keyreverse)sortedr  r   rv   r!   r!   r"   most_recent  s
   zMRU.most_recentN)r5   r6   r7   r   rh   r  r!   r!   r!   r"   r    s    r  c                       s   e Zd ZdZdZejjdd Ze	dZ
ejeee
feee
eeefejee
efejee
fejee
fejee
fiZdhZdef fdd	Zd
Z  ZS )
SSPPGModelTFc                 C   s
   d| _ d S )NT)r   rv   r!   r!   r"   init_on_load  s   
zSSPPGModel.init_on_loadNr   
field_namec                    s  | j rt| dr|| jv rZ| jj| }t|j}|| jv rY| j| }t||sYtt|}|dkr6t	|}n>|dkr?t
|}n5|dkrHt|}n,d||d jt|j}t|n|| jv sd|| jv rend| jj|| j }t|tt|  | t || dS t || dS )	z0note: this is not yet active in creating_sessionr   z<class 'numpy.int32'>z<class 'numpy.float64'>z<class 'numpy.bool_'>z{} should be set to {}, not {}.r   z{} has no field "{}".N)r   r   r   r   r   r   _setattr_datatypesr   r'   r  floatr   formatr5   	TypeErrorr   _setattr_whitelistr   _SETATTR_NO_FIELD_HINTAttributeErrormru_dictrh   super__setattr__)rc   r  r   r   Zfield_type_nameZallowed_types	type_namert   r   r!   r"   r    sB   




	




zSSPPGModel.__setattr__ )r5   r6   r7   r   r   rr   rs   Zreconstructorr  r   NoneTyper   Booleanr   r  r   r   r  r   Floatr   Stringr'   r   r  r  r  r  __classcell__r!   r!   r  r"   r    s"    



4r  c                   @      e Zd ZdS )NullFieldErrorNr5   r6   r7   r!   r!   r!   r"   r&  ;      r&  c                       sd   e Zd ZdZdZ fddZdefddZdd Zd	d
ddZ	e
dd Zdd Zdd Z  ZS )SPGModelTc                    sZ   t t|  | t |}|d u r+t dr+| jj }| d| d}t||S )Nr   r   zu is None. Accessing a null field is generally considered an error. Or, if this is intentional, use field_maybe_none())	r  r   rh   r  __getattribute__r   r5   r   r  )rc   r   resZobject_namert   r  r!   r"   r*  C  s   zSPGModel.__getattribute__r  c                 C   s"   zt | |W S  ty   Y dS w )z
        This isn't needed on ExtraModel because ExtraModel is used in a more unpredictable way,
        e.g. in live pages where the flow is less predictable. Also by more advanced users.
        N)r   r  )rc   r  r!   r!   r"   field_maybe_noneX  s
   zSPGModel.field_maybe_nonec              	   C   s   t | }dd |jjD }g }tt|  D ]8}||v rOz	tt| |}W n ty1   d}Y nw t	|dkr@|d d d }|
||f t	|dkrO nqtt|S )Nc                 S   r   r!   r   r   r!   r!   r"   rB   d  r   z1SPGModel._get_repr_attributes.<locals>.<listcomp>None   z...   )r   r   r   reversedr  r  r   r   r  lenappendr8   )rc   r   Zcolnamesr   r   r   r!   r!   r"   r   b  s"   zSPGModel._get_repr_attributesF)
missing_okc                O   sR   |   }t||d }|d u r|rd S td| dt| || g|R i |S )Nr<   z" not found in )r   r   r   r   )rc   funcnamer3  rd   re   r   funcr!   r!   r"   call_user_definedt  s   zSPGModel.call_user_definedc                 C   s   | j r|  }t|S | S rU   )r   r   r   )r   Zapp_namer!   r!   r"   r   }  s   z SPGModel.get_user_defined_targetc              	   C   s   t | |}|  }t ||d d }|r|| }n
t t| |jd }tt|}z|| W S  tyB   tdt| d| dd w )Nr   r   zCurrent value z" is not a valid choice for field '')	r   r   r   r4   r8   r   KeyErrorr   r   )rc   r   r   r   Zchoices_funcr   Zchoice_dictr!   r!   r"   get_field_display  s    


zSPGModel.get_field_displayc                 C   s
   |  |S )
Deprecated)r9  )rc   r   r!   r!   r"   field_display  s   
zSPGModel.field_display)r5   r6   r7   r   r   r*  r'   r,  r   r6  r   r   r9  r;  r$  r!   r!   r  r"   r)  ?  s    
	
r)  c                   @   r%  )UndefinedUserFunctionNr'  r!   r!   r!   r"   r<    r(  r<  c                   @   s(   e Zd ZdZedd Zedd ZdS )MixinSessionFKzbcan this be combined with SPGModel? maybe there was a specific reason it needed
    to be a mixin.c                 C   s   t tjtdddS )Nzotree_session.idCASCADEZondelete)r   r   r   r   r   r!   r!   r"   
session_id  s   zMixinSessionFK.session_idc                 C   s.   |    d| j }tdtjj|ddddS )NrE   r   zall, delete-orphanT)ZcascadeZpassive_deletes)backref)r   r5   r   rr   rs   rA  )r   Zbackref_namer!   r!   r"   r    s   zMixinSessionFK.sessionN)r5   r6   r7   r   r   r@  r  r!   r!   r!   r"   r=    s    
r=  c                   @   r%  )	VarsErrorNr'  r!   r!   r!   r"   rB    r(  rB  r   c                 C   s   dd |  |D S )Nc                 S   s   g | ]\}|qS r!   r!   )r>   valr!   r!   r"   rB     r   zvalues_flat.<locals>.<listcomp>)r   )rb   r   r!   r!   r"   values_flat  s   rD  c                 C   s$   t | trdt| }t|d S )Nz~Cannot store '{}' object in vars. participant.vars and session.vars cannot contain model instances, like Players, Groups, etc.)r   r   r  r   rB  )rj   rt   r!   r!   r"   inspect_obj  s   

rE  	vars_dictc                 C   sX   |   D ]%}t| t|tr|  D ]}t| qqt|tr)|D ]}t| q"qdS )z
    I don't know how to entirely block pickle from storing model instances,
    (I tried overriding __reduce__ but that interferes with deepcopy())
    so this simple shallow scan should be good enough.
    N)valuesrE  r   r8   r+   )rF  r   Zvvr  r!   r!   r"   scan_for_model_instances  s   



rH  c                    s    fdd}|S )Nc                    s   t | }tt | S rU   )r   r8   r   )rc   r   r   r   r!   r"   get_FIELD_display  s   
z2make_get_display_static.<locals>.get_FIELD_displayr!   )r   r   rJ  r!   rI  r"   r     s   r   c                    s    fdd}|S )Nc                    s4   |   }t| d | }t|  }tt|| S )Nr   )r   r   r8   r   )rc   r   r   r   r   r!   r"   rJ    s   
z3make_get_display_dynamic.<locals>.get_FIELD_displayr!   )r   rJ  r!   r   r"   r     s   r   c                   @   s   e Zd Zedd ZdS )VarsDictc                 C   s,   t |tst |trt|S t||S |S rU   )r   rK  r8   r   coerce)r   r  r   r!   r!   r"   rL    s
   

zVarsDict.coerceN)r5   r6   r7   r   rL  r!   r!   r!   r"   rK    s    rK  c                   @   s"   e Zd ZejZdd Zdd ZdS )_PickleFieldc                 C   s   t tt|dS Nzutf-8)binascii
b2a_base64pickledumpsr8   decoder   r!   r!   r"   r     s   z_PickleField.process_bind_paramc                 C   s   t t|dS rN  )rQ  loadsrO  
a2b_base64encoder   r!   r!   r"   r      s   z!_PickleField.process_result_valueN)r5   r6   r7   r   r   r   r   r   r!   r!   r!   r"   rM    s    rM  c                   @   s*   e Zd ZeeeedZedd Z	dS )	MixinVars)defaultc                 C   s   | j   | j S rU   )_varschangedrv   r!   r!   r"   r     s   
zMixinVars.varsN)
r5   r6   r7   r   rK  Z
as_mutablerM  rY  propertyr   r!   r!   r!   r"   rW    s    rW  r  )initialnullc                K   s\   d|v r	| d}d|v r| d|d< t| ||d}||_tt| tr&| nt|  |_|S )NrX  Zverbose_namelabel)rX  Znullable)popr3   r4   AUTO_SUBMIT_DEFAULTSr   r   r:   )Zcoltyper\  r]  r4   colr!   r!   r"   wrap_column  s   
rb  c                  K      t tjfi | S rU   )rb  r   r!  re   r!   r!   r"   BooleanField'  rf   re  c                  K   s    t tj| dddfi | S )N
max_lengthi'  )length)rb  r   r#  r   rd  r!   r!   r"   StringField+  s
   rh  c                  K   s"   d| v rt dttjfi | S )Nr   z#LongStringField cannot have choices)
ValueErrorrb  r   r   rd  r!   r!   r"   LongStringField2  s   rj  c                  K   rc  rU   )rb  r   r"  rd  r!   r!   r"   
FloatField8  rf   rk  c                  K   rc  rU   )rb  r   r   rd  r!   r!   r"   IntegerField<  rf   rl  c                  K      t tfi | S rU   )rb  r   rd  r!   r!   r"   CurrencyField@  r   rn  c                  K   rm  rU   )rb  r   rd  r!   r!   r"   RealWorldCurrencyFieldD  r   ro  c                 C   s   t d d d d dS )N)Zdropped_tablesZ
new_tablesZdropped_columnsZnew_columns)r8   )rQ   rA   r!   r!   r"   get_changed_columnsN  s   rp  c                   C   s   t ddd tD S )Nr  c                 s   s    | ]	}|d v r|V  qdS )
0123456789Nr!   r=   r!   r!   r"   rF   W  s    z%version_for_pragma.<locals>.<genexpr>)r  rO   r   r!   r!   r!   r"   rJ   T  s   rJ   c                   @   s    e Zd ZdZdd Zdd ZdS )LinkzUA class attribute that generates a mapped attribute
    after mappers are configured.c                 C   r   rU   )
target_cls)rc   rs  r!   r!   r"   r   ^  rx   zLink.__init__c           	      C   sh   | j }|j}t|jd }| d}t||jt|dd}t||| t|||kt	d}t||| d S )Nr   r  r>  r?  )ZprimaryjoinZcollection_class)
rs  r   r+   r   r   r   r   r   r   set)	rc   r   r  rs  Zpk_tableZpk_colZ
fk_colnameZfk_colrelr!   r!   r"   _configa  s   
zLink._configN)r5   r6   r7   r   r   rv  r!   r!   r!   r"   rr  Z  s    rr  c                   @   s8   e Zd ZdZedd Zedd Zdd Zdd	 Zd
S )
ExtraModelTc                 K   s<   |rt dd | D stdt| jdi |dS )Nc                 s   s    | ]}t |tV  qd S rU   )r   r   )r>   r   r!   r!   r"   rF   }  s    z$ExtraModel.filter.<locals>.<genexpr>z^At least one argument to .filter() must be a model instance, e.g. player=player or group=groupr   r!   )anyrG  ri  r+   r   r   )r   re   r!   r!   r"   r   w  s
   zExtraModel.filterc                 K   sL   | j j D ]\}}|jd ur|||jj q| di |}t| |S r   )r   r   r   rX  
setdefaultargrW   rh   )r   re   r  columnrj   r!   r!   r"   create  s   

zExtraModel.createc                 C   s   t |  d S rU   )rW   rm   rv   r!   r!   r"   rm     r$   zExtraModel.deletec                 C   sL   t | }g }|jjD ]}|j}|js!|js!||tt| |f q
t	|S rU   )
r   r   r   r   r   Zforeign_keysr2  r   r   r8   )rc   r   r   ra  r   r!   r!   r"   r     s   zExtraModel._get_repr_attributesN)	r5   r6   r7   r   r   r   r|  rm   r   r!   r!   r!   r"   rw  t  s    

rw  Zinstrument_classc                 C   s   ddg}|j dkr|ddg7 }t|jj}|D ]}|j|v r.t| d|j d}t| q|jj	s?td|j  d	 d S d S )
Norderindexr   ZpayoffZrolez%: You should rename the model field "z+" to something else. This name is reserved.z-"id" cannot be used as a field name on model z because this name is reserved)
r5   r+   r   r   r   r   rM   rN   r   r   )r   r   Zforbidden_listr   r   rt   r!   r!   r"   prevent_forbidden_colnames  s   


r  Zmapper_configuredc                 C   s2   t |j D ]\}}t|tr||| qdS )zFListen for finished mappers and apply DeferredProp
    configurations.N)r+   __dict__r   r   rr  rv  )r   class_r  r   r!   r!   r"   _setup_deferred_properties  s
   
r  )rO  loggingrK   rQ  r   rM   collectionsr   
contextlibr   decimalr   pathlibr   rr   Zsqlalchemy.ormZsqlalchemy.poolr   r   r   r
   r   Zsqlalchemy.ext.declarativer   r   Zsqlalchemy.ext.mutabler   r   r   r   r   Zsqlalchemy.orm.excr   Zsqlalchemy.sqlr   r   Zstarlette.exceptionsr   r   r   r   r   Zotree.commonr   r   Zotree.currencyr   r   	getLoggerr5   r   r    r#   r%   r2   rV   rI   rH   r]   r3   rT   r[   r_   ZDeclarativeBaser`   rW   rb   r   r   rL   r\   r   r   r|   r}   r   r   r   ZTypeDecoratorr   r   r   r  r  r  r  r&  r)  r   r<  r=  rB  r+   rD  rE  r8   rH  r   r   rK  rM  rW  r!  r   r"  r#  r   r`  rb  re  rh  rj  rk  rl  rn  ro  Z	CharFieldZPositiveIntegerFieldZ	TextFieldrp  r  rJ   rr  rw  Zlistens_forr  r  r!   r!   r!   r"   <module>   s    
%
3
GX WZ


/

