o
    ޭh                     @  sB  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m	Z	 d dl
m
Z
mZ d dlmZ d dlmZmZmZm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 m!Z!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z( d dl)m*Z* d dl+m,Z, d dl-m.Z. d dl/m0Z0m1Z1m2Z2m3Z3m4Z4m5Z5m6Z6m7Z7 d dl8m9Z9m:Z: d dl;m<Z< d dl=m>Z> d dl?m@Z@mAZAmBZBmCZCmDZDmEZEmFZF d dlGmHZH d dlImJZJ d dlKmLZL edddZMeN ZOdMd!d"ZPdNd$d%ZQG d&d' d'eZRdOd/d0ZSdPd4d5ZTdQd9d:ZUdRd<d=ZVdSdAdBZWdTdEdFZXG dGdH dHZYG dIdJ dJeZZ[G dKd de[dLZ\dS )U    )annotationsN)	AwaitableCallable	GeneratorIterable)copydeepcopy)partial)Any	TypedDictTypeVarcast)OrderQueryTable)Term)Self)connections)BaseDBAsyncClient)	ConfigurationErrorDoesNotExist
FieldErrorIncompleteInstanceErrorIntegrityErrorObjectDoesNotExistErrorOperationalErrorParamsErrorValidationError)
Expression)Field)IntField)BackwardFKRelationBackwardOneToOneRelationForeignKeyFieldInstanceManyToManyFieldInstanceManyToManyRelationNoneAwaitableOneToOneFieldInstanceReverseRelation)FilterInfoDictget_filters_for_field)Index)Manager)BulkCreateQueryBulkUpdateQueryExistsQueryQQuerySetQuerySetSingleRawSQLQuery)router)Signals)in_transactionMODELModel)boundmeta
Model.Metatogetherstrreturntuple[tuple[str, ...], ...]c                 C  s6   t | |d}|rt|ttfrt|d tr|f}|S )N r   )getattr
isinstancelisttupler=   )r:   r<   	_togetherr@   r@   T/var/www/html/stock_analysis/be/venv/lib/python3.10/site-packages/tortoise/models.pyget_together=   s    rG   tuple[tuple[str, Order], ...]c                 C  s"   t | dd}tdd |D }|S )Norderingr@   c                 s  s    | ]}t |V  qd S N)r1   _resolve_ordering_string).0rI   r@   r@   rF   	<genexpr>J   s    

z+prepare_default_ordering.<locals>.<genexpr>)rA   rD   )r:   ordering_listparsed_orderingr@   r@   rF   prepare_default_orderingG   s
   rP   c                   @  s&   e Zd ZU ded< ded< ded< dS )FkSetterKwargsr=   _keyrelation_fieldto_fieldN)__name__
__module____qualname____annotations__r@   r@   r@   rF   rQ   Q   s   
 rQ   selfvalueModel | NonerR   rS   rT   Nonec                 C  s*   t | ||r
t||nd  t | || d S rJ   )setattrrA   )rY   rZ   rR   rS   rT   r@   r@   rF   
_fk_setterW   s   r^   ftypetype[Model]r   c                 C  sR   zt | |W S  ty(   t | |}|d ur$|jdi ||i  Y S t Y S w Nr@   )rA   AttributeErrorfilterfirstr&   )rY   rR   r_   rS   rT   rZ   r@   r@   rF   
_fk_getterb   s   
re   	frelfield
from_fieldr(   c                 C  s2   t | |d }|d u rt||| |}t| || |S rJ   )rA   r(   r]   rY   rR   r_   rf   rg   valr@   r@   rF   _rfk_gettern   s
   rj   QuerySetSingle[Model | None]c                 C  sB   t | |r
t| |S |jdi |t| |i }t| || |S ra   )hasattrrA   rc   rd   r]   rh   r@   r@   rF   _ro2o_getterx   s
   

rm   field_objectr$   r%   c                 C  s.   t | |d }|d u rt| |}t| || |S rJ   )rA   r%   r]   )rY   rR   rn   ri   r@   r@   rF   _m2m_getter   s
   
ro   clsdict[str, str]c              	   C  s   zt | }W n ttfy   i  Y S w i }t| jD ]+}|tu r#qtd|}|D ]}|d }tj	dd|d tj
d}|d|j||< q+q|S )a  
    Get comments exactly before attributes

    It can be multiline comment. The placeholder "{model}" will be replaced with the name of the
    model class. We require that the comments are in #: (with a colon) format, so you can
    differentiate between private and public comments.

    :param cls: The class we need to extract comments from its source.
    :return: The dictionary of comments by field name
    z3((?:(?!\n|^)[^\w\n]*#:.*?\n)+?)[^\w\n]*(\w+)\s*[:=]   z(^\s*#:\s*|\s*$) r   )flagsz{model})inspect	getsource	TypeErrorOSErrorreversed__mro__objectrefindallsub	MULTILINEreplacerU   )rp   sourcecommentscls_matchesmatch
field_namecommentr@   r@   rF   _get_comments   s    r   c                   @  s   e Zd ZdZd%ddZed&d	d
Zd'ddZed(ddZed)ddZ	d*ddZ
d+ddZd+ddZd+ddZd+d d!Zd+d"d#Zd$S ),MetaInfo)$abstractdb_tableschemaappfields	db_fields
m2m_fields
o2o_fieldsbackward_o2o_fields	fk_fieldsbackward_fk_fieldsfetch_fieldsfields_db_projection_initedfields_db_projection_reversefilters
fields_mapdefault_connection	basequerybasequery_all_fields	basetable_filtersunique_togethermanagerindexespk_attrgenerated_db_fields_modeltable_descriptionpkdb_pk_columndb_native_fieldsdb_default_fieldsdb_complex_fields_default_ordering_ordering_validatedr:   r;   r>   r\   c                 C  s>  t |dd| _t |dt | _t |dd| _t |dd | _t |dd | _t|d| _t|d	| _	t
|| _d| _t | _t | _t | _t | _t | _t | _t | _t | _i | _i | _i | _i | _i | _d| _d | _t | _t | _t d| _!t |d
d| _"d | _#d | _$t |dd| _%d | _&d| _'g | _(g | _)g | _*d S )Nr   Fr   tablers   r   r   r   r   r   r   )+rA   r   r,   r   r   r   r   rG   r   r   rP   r   r   setr   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   )rY   r:   r@   r@   rF   __init__   sH   


zMetaInfo.__init__r=   c                 C  s   | j  d| jj S )N.)r   r   rU   rY   r@   r@   rF   	full_name   s   zMetaInfo.full_namenamerZ   r   c                 C  s   || j v rtd| d| j|_|| j |< ||_|jr$|jp || j|< t|t	r0| j
| nt|tr<| j| nt|trG| j| t|||jpN|d}| j| |   d S )NzField z already present in metar   fieldsource_field)r   r   r   modelmodel_field_namehas_db_fieldr   r   rB   r$   r   addr"   r   r!   r   r*   r   updatefinalise_fields)rY   r   rZ   field_filtersr@   r@   rF   	add_field   s$   




zMetaInfo.add_fieldr   c                 C  s(   | j d u rtd| j dt| j S )Nz!default_connection for the model z cannot be None)r   r   r   r   getr   r@   r@   rF   db  s
   
zMetaInfo.dbrH   c                 C  s@   | j sdd | jD | j }tdd| d| jj | jS )Nc                 S  s   h | ]\}}|qS r@   r@   )rL   f_r@   r@   rF   	<setcomp>   s    z$MetaInfo.ordering.<locals>.<setcomp>zUnknown fields ,z in default ordering for model )r   r   r   r   joinr   rU   )rY   unknown_fieldsr@   r@   rF   rI     s   zMetaInfo.orderingkeyr)   c                 C  s
   | j | S rJ   )r   )rY   r   r@   r@   rF   
get_filter'     
zMetaInfo.get_filterc                 C  s$   |    |   |   |   dS )zD
        Finalise the model after it had been fully loaded.
        N)r   _generate_filters_generate_lazy_fk_m2m_fields_generate_db_fieldsr   r@   r@   rF   finalise_model*  s   zMetaInfo.finalise_modelc                 C  s   t | j | _t | j | _dd | j D | _| j	| j
B | jB | jB | jB | _dd | j D }t|| _d| _| jD ]\}}|dd | jvrTd| _ d S q@d S )	Nc                 S  s   i | ]\}}||qS r@   r@   )rL   r   rZ   r@   r@   rF   
<dictcomp>6  s    
z,MetaInfo.finalise_fields.<locals>.<dictcomp>c                 S  s   g | ]}|j r|jp|jqS r@   )	generatedr   r   )rL   r   r@   r@   rF   
<listcomp>A  s    
z,MetaInfo.finalise_fields.<locals>.<listcomp>T__r   F)r   r   valuesr   r   keysr   itemsr   r   r   r   r   r   r   rD   r   r   r   split)rY   generated_fieldsr   r   r@   r@   rF   r   3  s4   
zMetaInfo.finalise_fieldsc                 C  s  | j D ]?}d| }| j| }tt|j}|jj}t|||d}t| j	|t
ttfd|ji|ttfi |ttfdd i| q| jD ] }d| }| j| }t| j	|t
tt||j|j|jjd qF| jD ]B}d| }tt| j| }tt|j}|jj}t|||d}t| j	|t
ttfd|ji|ttfi |ttfdd i| qj| jD ] }d| }| j| }	t| j	|t
tt||	j|	j|	jjd q| jD ]}d| }tt| j| }
t| j	|t
tt||
d qd S )Nr   )rR   rS   rT   r_   rZ   )rR   r_   rf   rg   )rR   rn   )r   r   r   r=   r   to_field_instancer   dictr]   r   propertyr	   re   related_modelr^   r   rj   rS   r   r'   r   rm   r   r$   ro   )rY   r   rR   fk_field_objectrS   rT   property_kwargsbackward_fk_field_objecto2o_field_objectbackward_o2o_field_objectrn   r@   r@   rF   r   N  s   











z%MetaInfo._generate_lazy_fk_m2m_fieldsc                 C  s   | j   | j  | j  | jD ]A}| j| }| j| }|j| jj	j
v }|jjtju }|r>|s4|jr>| j|||f q|rJ| j |||f q| j|||f qd S rJ   )r   clearr   r   r   r   r   
field_typer   executor_class	DB_NATIVE	__class__to_python_valuer   skip_to_python_if_nativeappend)rY   r   model_fieldr   is_native_field_typedefault_converterr@   r@   rF   r     s   





zMetaInfo._generate_db_fieldsc                 C  sN   | j jj}| j D ]\}}||d d}|rt|}||d< || j|< q
d S )Noperator)filter_func)r   r   get_overridden_filter_funcr   r   r   r   )rY   r   r   filter_infooverridden_operatorr@   r@   rF   r     s   
zMetaInfo._generate_filtersN)r:   r;   r>   r\   r>   r=   )r   r=   rZ   r   r>   r\   )r>   r   )r>   rH   )r   r=   r>   r)   r>   r\   )rU   rV   rW   	__slots__r   r   r   r   r   rI   r   r   r   r   r   r   r@   r@   r@   rF   r      s     
'&

	

	

qr   c                      sd   e Zd ZdZd. fd	d
Zed/ddZed0ddZed1ddZ	ed2d%d&Z
d3d,d-Z  ZS )4	ModelMetar@   r   r=   basestuple[type, ...]attrsdict[str, Any]r>   c              
     s  i }| dtddi }d}i }|D ]}| || q|r#i ||}t|dd}	|dkr7| ||||	\}}| |||	\}
}}}}|
D ]}||d  qE| ||
|||||| |d< }t 	| |||}|j
 D ]}||_qlt| D ]\}}||
v r||
| _|
| jd u r|dd	 |
| _qx|jr|jst|jdd	 |_| D ]
}t|tr||_q||_||j_|  |S )
NMetar@   idr   Fr8   _meta
r   )r   type_search_for_field_attributesrA   _parse_custom_pk_dispatch_fieldspop
build_metasuper__new__r   r   r   r   r   	docstringdescriptionr   __doc__r   ru   cleandocrB   r,   r   r   r   )rp   r   r   r   r   
meta_classr   inherited_attrsbaseis_abstractr   r   r   r   r   slotr:   	new_classr   fnamer   rZ   r   r@   rF   r    sZ   

zModelMeta.__new__r  r   r   r\   c                 C  s   |j dd D ]}| || qt|dd }rA|j D ]\}}|||< q|j D ]\}}t|tr>||vr>| ||< q+dS |j D ]\}}t|t	rW||vrW|||< qFdS )a  
        Searching for class attributes of type fields.Field
        in the given class.

        If an attribute of the class is an instance of fields.Field,
        then it will be added to the fields dict. But only, if the
        key is not already in the dict. So derived classes have a higher
        precedence. Multiple Inheritance is supported from left to right.

        After checking the given class, the function will look into
        the classes according to the MRO (method resolution order).

        The MRO is 'natural' order, in which python traverses methods and
        fields. For more information on the magic behind check out:
        `The Python 2.3 Method Resolution Order
        <https://www.python.org/download/releases/2.3/mro/>`_.
        rr   Nr   )
rz   r   rA   r   r   __dict__rB   r,   r   r   )rp   r  r   parentr:   r   rZ   r@   r@   rF   r     s   
z&ModelMeta._search_for_field_attributesr   tuple[dict, str]c                 C  s   d}|   D ]-\}}t|tr3|jr3|rtd| d|jr/|js/td| d|jj dd}|}q|sY|sYd| vrEdt	dd	i| } t| d trQ| d jsYtd| d
| |fS )NFzCan't create model z< with two primary keys, only single primary key is supportedField 'z' (z) can't be DB-generatedTr   )primary_keyz; without explicit primary key if field 'id' already present)
r   rB   r   r   r   r   allows_generatedr   rU   r    )r   r   r   r  custom_pk_presentr   rZ   r@   r@   rF   r   8  s.   


zModelMeta._parse_custom_pkr   Ptuple[dict[str, Field], dict[str, FilterInfoDict], set[str], set[str], set[str]]c                 C  s   i }i }t  }t  }t  }|  D ]Y\}}	t|	trj|r t|	}	|	 }
||< ||	_t|	tr4|| qt|	tr?|| qt|	t	rJ|| q|	j
pN| }||< |t||
|d |	jrj|td|
|d q|||||fS )Nr   r   )r   r   rB   r   r   r   r'   r   r#   r$   r   r   r*   r   )r   r   r  r   r   r   r   r   r   rZ   r   r   r@   r@   rF   r   U  s>   



zModelMeta._dispatch_fieldsr	  r;   r   dict[str, Field]rq   r   dict[str, FilterInfoDict]r   set[str]r   r   r   c           
      C  s   t | }||_||_||_||_||_||_||_|| }	r:|	|_	|	j
r+|	j
|_nt|	tr7| d|_n||_d|_|sBd|_|S )N_idFT)r   r   r   r   r   r   r   r   r   r   r   r   rB   r'   r   r   )
r	  r   r   r   r   r   r   r   r:   pk_fieldr@   r@   rF   r    s&   

zModelMeta.build_metarp   type[MODEL]r   r
   QuerySetSingle[MODEL]c                 C  
   |  |S rJ   )_getbypkrp   r   r@   r@   rF   __getitem__  r   zModelMeta.__getitem__)r   r=   r   r   r   r   r>   r   )r  r   r   r   r>   r\   )r   r   r   r=   r   r=   r>   r  )r   r   r   r   r>   r  )r	  r;   r   r  r   rq   r   r  r   r  r   r  r   r  r   r=   r>   r   )rp   r  r   r
   r>   r  )rU   rV   rW   r   r  classmethodr   staticmethodr   r   r  r#  __classcell__r@   r@   r  rF   r     s    5#)r   c                      s  e Zd ZU dZedZeji eji ej	i ej
i iZded< dd	d
ZdŇ fddZdddZedddZdddZdddZdddZddd Zdd$d%Zdd&d'Zdd)d*ZeeeZ	 edd-d.Zedd0d1Zefdd4d5Zdd7d8Zedd=d>Z dd?d@Z!ddAdBZ"dddEdFZ#dddGdHZ$		dddKdLZ%		M	dddOdPZ&			M	MdddSdTZ'dddUdVZ(ddWddYdZZ)		ddd\d]Z*eddd`daZ+e		dddedfZ,eddhdiZ-e	MdddkdlZ.e	M	M	m		MdddsdtZ/e		dddvdwZ0e	dddxdyZ1e		ddddZ2e	3	ddddZ3e		M			ddddZ4eddddZ5eddddZ6edddZ7edddZ8edddZ9edddZ:edddZ;eddddZ<eddWdddZ=eddddZ>eddWdddZ?eddWdddZ@eddWdddZAedddZBedddZCedddZDeddddZEdddZFG ddÄ dÃZG  ZHS )r8   z1
    Base class for all Tortoise ORM Models.
    Nz0dict[Signals, dict[type[MODEL], list[Callable]]]
_listenerskwargsr
   r>   r\   c                 K  s   | j }d| _d| _d| _i | _|j| |D ]*}|j| }|j	}t
|r-|| j|< qt|r9t| ||  qt| |t|j	 qd S NF)r   _partial_saved_in_db_custom_generated_pk_await_when_saver   
difference_set_kwargsr   defaultru   iscoroutinefunctioncallabler]   r   )rY   r(  r:   r   rn   field_defaultr@   r@   rF   r     s   

zModel.__init__c                   sN   t | dr| j|d  || jjv s|| jjv r| || t || d S )Nr-  )	rl   r-  r  r   r   r   _validate_relation_typer  __setattr__)rY   r   rZ   r  r@   rF   r5    s
   
zModel.__setattr__r   r  c                 C  s  | j }h | |jB }| D ]q\}}||jv s||jv r;|r+|js+td| dt| || |	|j
| j q||jv rf|j
| }|jrN|jrNd| _|d u r\|js\t| dt| ||| q||jv rotd||jv rxtd||jv rtdq|S )Nz!You should first call .save() on z before referring to itTz+ is non nullable field, but null was passedzKYou can't set backward relations through init, change related model insteadzVYou can't set backward one to one relations through init, change related model insteadzAYou can't set m2m relations through init, use m2m_manager instead)r   r   r   r   r   r   r+  r   r]   r   r   r   r   r   r   r,  null
ValueErrorr   r   r   r   r   )rY   r(  r:   passed_fieldsr   rZ   rn   r@   r@   rF   r/    s>   






zModel._set_kwargsrp   r  r7   c                 K  s  |  | }d|_d|_|jj|jjv|_i |_|j}t }zS|j	D ]\}}}t
||||  || q!|jD ]\}}}||  }d urI||}t
||| || q7|jD ]\}}}t
|||||  || qXW |S  ty   d|_dd |j	D }	d  }
}| D ]H\}}||v s||jvrq|j|  }|	vr|
d u rdd |jD }
||
v r|d ur||}n|d u rdd |jD }||}t
||| qY |S w )NFTc                 S     g | ]^ }}|qS r@   r@   rL   r   r   r@   r@   rF   r         z'Model._init_from_db.<locals>.<listcomp>c                 S  r9  r@   r@   r:  r@   r@   rF   r     r;  c                 S  r9  r@   r@   r:  r@   r@   rF   r     r;  )r  r*  r+  r   r   r   r,  r-  r   r   r]   r   r   r   r   r   KeyErrorr   r   )rp   r(  rY   r:   inited_keysr   r   r   rZ   native_fieldsdefault_fieldscomplex_fieldsr@   r@   rF   _init_from_db  sT   



zModel._init_from_dbr=   c                 C  s   d| j j dS )N<>)r   rU   r   r@   r@   rF   __str__#     zModel.__str__c                 C  s.   | j rd| jj d| j  dS d| jj dS )NrB  z: rC  )r   r   rU   r   r@   r@   rF   __repr__&  s   zModel.__repr__intc                 C  s   | j stdt| j S )Nz)Model instances without id are unhashable)r   rw   hashr   r@   r@   rF   __hash__+  s   
zModel.__hash__Iterable[tuple]c                 c  s$    | j jD ]
}|t| |fV  qd S rJ   )r   r   rA   )rY   r   r@   r@   rF   __iter__0  s   zModel.__iter__otherr{   boolc                 C  s   t |t | u o| j|jkS rJ   )r   r   )rY   rL  r@   r@   rF   __eq__4  s   zModel.__eq__c                 C  s   t | | jjd S rJ   )rA   r   r   r   r@   r@   rF   _get_pk_val7  rE  zModel._get_pk_valrZ   c                 C  s   t | | jj| d S rJ   )r]   r   r   )rY   rZ   r@   r@   rF   _set_pk_val:  s   zModel._set_pk_val	field_keyr[   c                 C  sz   |d u rd S | j j| }t|ttfs td| dt|j |j}t|}||ur;t	d| d|j d|j dd S )Nr  z1' must be a OneToOne or ForeignKey relation, got z%Invalid type for relationship field 'z'. Expected model type 'z', but got 'zH'. Make sure you're using the correct model class for this relationship.)
r   r   rB   r'   r#   r   r   rU   r   r   )rp   rQ  rZ   r   expected_modelreceived_modelr@   r@   rF   r4  C  s(   zModel._validate_relation_typer   c              	     s:   z
| j |dI d H W S  ttfy   t| | jj|w )Nr   )r   r   r7  r   r   r   r"  r@   r@   rF   r!  X  s   zModel._getbypkrY   r   c                 C  sV   t | }|tu r#| jj}|jdu r|jdu rt| jj dd|_n||_d|_|S )a  
        Create a new clone of the object that when you do a ``.save()`` will create a new record.

        :param pk: An optionally required value if the model doesn't generate its own primary key.
            Any value you specify here will always be used.
        :return: A copy of the current object without primary key information.
        :raises ParamsError: If pk is required but not provided.
        FNz= requires explicit primary key. Please use .clone(pk=<value>))	r   EMPTYr   r   r   r0  r   r   r+  )rY   r   objr  r@   r@   rF   clone_  s   	zModel.clonedatac                 C  s   |  | | S )a  
        Updates the current model with the provided dict.
        This can allow mass-updating a model from a dict, also ensuring that datatype conversions happen.

        This will ignore any extra fields, and NOT update the model with them,
        but will raise errors on bad types or updating Many-instance relations.

        :param data: The parameters you want to update in a dict format
        :return: The current model instance

        :raises ConfigurationError: When attempting to update a remote instance
            (e.g. a reverse ForeignKey or ManyToMany relation)
        :raises ValueError: When a passed parameter is not type compatible
        )r/  )rY   rX  r@   r@   rF   update_from_dictv  s   
zModel.update_from_dictsignalr5   listenerr   c                 C  s>   t |std| j|| g }||vr|| dS dS )z
        Register listener to current model class for special Signal.

        :param signal: one of tortoise.signals.Signals
        :param listener: callable listener

        :raises ConfigurationError: When listener is not callable
        z!Signal listener must be callable!N)r2  r   r'  r   
setdefaultr   )rp   rZ  r[  cls_listenersr@   r@   rF   register_listener  s   
zModel.register_listenerc                   sF   t | dr!| j  D ]\}}t| || I dH  qi | _dS dS )z/retrieve value from field's async default valuer-  N)rl   r-  r   r   r]   )rY   kvr@   r@   rF   _set_async_default_field  s   

zModel._set_async_default_fieldc                   sB   j |i jg } fdd|D }tj| I d H  d S )Nc                   s    g | ]}|j g R  qS r@   r  )rL   r[  listener_argsrY   r@   rF   r     s     z-Model._wait_for_listeners.<locals>.<listcomp>)r'  r   r   asynciogather)rY   rZ  rc  r]  	listenersr@   rb  rF   _wait_for_listeners  s   zModel._wait_for_listenersusing_dbBaseDBAsyncClient | Nonec                      |  tj|I d H  d S rJ   )rg  r5   
pre_deleterY   rh  r@   r@   rF   _pre_delete     zModel._pre_deletec                   rj  rJ   )rg  r5   post_deleterl  r@   r@   rF   _post_delete  rn  zModel._post_deleteupdate_fieldsIterable[str] | Nonec                   s   |  tj||I d H  d S rJ   )rg  r5   pre_save)rY   rh  rq  r@   r@   rF   	_pre_save  s   zModel._pre_saveFcreatedc                   s   |  tj|||I d H  d S rJ   )rg  r5   	post_save)rY   rh  ru  rq  r@   r@   rF   
_post_save  s   zModel._post_saveforce_createforce_updatec           
        sl  |   I dH  |p| d}|j| j|d}| jrL|rC|D ]#}t| | jjs0t| jj	 dt| |sAt| jj	 d| dqn	t| jj	 d| 
||I dH  |rb|| I dH  d}nE|r||| |I dH }	|	dkrytd	| j d
}n+| js|r| jdu r|| I dH  d}n|| |I dH  d
}n
|| I dH  d}d| _| |||I dH  dS )a+  
        Creates/Updates the current model object.

        :param update_fields: If provided, it should be a tuple/list of fields by name.

            This is the subset of fields that should be updated.
            If the object needs to be created ``update_fields`` will be ignored.
        :param using_db: Specific DB connection to use instead of default bound
        :param force_create: Forces creation of the record
        :param force_update: Forces updating of the record

        :raises IncompleteInstanceError: If the model is partial and the fields are not available for persistence.
        :raises IntegrityError: If the model can't be created or updated (specifically if force_create or force_update has been set)
        :raises OperationalError: If update_fields include pk field.
        NTr   r   zL is a partial model without primary key fetchd. Partial update not availablez is a partial model, field 'z' is not availablezN is a partial model, can only be saved with the relevant update_field providedr   z,Can't update object that doesn't exist. PK: F)ra  
_choose_dbr   r   r*  rl   r   r   r   rU   rt  execute_insertexecute_updater   r   r+  rw  )
rY   rh  rq  rx  ry  r   executorr   ru  rowsr@   r@   rF   save  sN   



z
Model.savec                   s^   |p|  d}| jstd| |I dH  |j| j|d| I dH  | |I dH  dS )z
        Deletes the current model object.

        :param using_db: Specific DB connection to use instead of default bound

        :raises OperationalError: If object has never been persisted.
        TzCan't delete unpersisted recordNrz  )r{  r+  r   rm  r   r   execute_deleterp  )rY   rh  r   r@   r@   rF   delete  s   zModel.deleterh  argsc                  s8   |p|   }|j| j|dj| gg|R  I dH  dS )a  
        Fetch related fields.

        .. code-block:: python3

            User.fetch_related("emails", "manager")

        :param args: The related fields that should be fetched.
        :param using_db: Specific DB connection to use instead of default bound
        rz  N)r{  r   r   fetch_for_list)rY   rh  r  r   r@   r@   rF   fetch_related
  s   *zModel.fetch_relatedr   c                   sx   | j std|p|  }t| j|}|r|j| }|j| jdI dH }|p,| j	j
D ]}t| |t||d q-dS )a  
        Refresh latest data from db. When this method is called without arguments
        all db fields of the model are updated to the values currently present in the database.

        .. code-block:: python3

            user.refresh_from_db(fields=['name'])

        :param fields: The special fields that to be refreshed.
        :param using_db: Specific DB connection to use instead of default bound.

        :raises OperationalError: If object has never been persisted.
        z Can't refresh unpersisted recordrT  N)r+  r   r{  r1   r   rh  onlyr   r   r   r   r]   rA   )rY   r   rh  r   qsrV  r   r@   r@   rF   refresh_from_db  s   
zModel.refresh_from_db	for_writer   c                 C  s&   |rt | }nt | }|p| jjS )z
        Return the connection that will be used if this query is executed now.

        :param for_write: Whether this query for write.
        :return: BaseDBAsyncClient:
        )r4   db_for_writedb_for_readr   r   )rp   r  r   r@   r@   rF   r{  5  s   
zModel._choose_dbdefaultsdict | Nonetuple[Self, bool]c                   sl   |si }|p|  d}z| jdi || I dH dfW S  ty5   | j||fi |I dH  Y S w )a6  
        Fetches the object if exists (filtering on the provided parameters),
        else creates an instance with any unspecified parameters as default values.

        :param defaults: Default values to be added to a created instance if it can't be fetched.
        :param using_db: Specific DB connection to use instead of default bound
        :param kwargs: Query parameters.
        :raises IntegrityError: If create failed
        :raises TransactionManagementError: If transaction error
        :raises ParamsError: If defaults conflict with kwargs
        TNFr@   )r{  rc   rh  r   r   _create_or_get)rp   r  rh  r(  r   r@   r@   rF   get_or_createC  s   &zModel.get_or_creater   c           
        s  |  |  @ D ]}||  }||  }kr$td|d|d|q	i ||}z3t|jd4 I dH }| jd	d|i|I dH dfW  d  I dH  W S 1 I dH sWw   Y  W dS  ty }	 z$z| jd	i || I dH dfW W  Y d}	~	S  t	y   Y |	w d}	~	ww )
z;Try to create, if fails with IntegrityError then try to getzConflict value with key=z: default_value=z vs query_value=connection_nameNrh  TFr@   )
r   r   r6   r  creater   rc   rh  r   r   )
rp   r   r  r(  r   default_valuequery_valuemerged_defaults
connectionexcr@   r@   rF   r  ]  s&   42zModel._create_or_getQuerySet[Self]c                 C  s    |p|  |}| jj |S rJ   )r{  r   r   get_querysetrh  )rp   rh  r  r   r@   r@   rF   _db_querysetp  s   zModel._db_querysetr@   nowaitskip_lockedoftuple[str, ...]no_keyc                 C  s   | j |ddj||||dS )z
        Make QuerySet select for update.

        Returns a queryset that will lock rows until the end of the transaction,
        generating a SELECT ... FOR UPDATE SQL statement on supported databases.
        Tr  )r  )r  select_for_update)rp   r  r  r  rh  r  r@   r@   rF   r  w  s   zModel.select_for_updatetuple[MODEL, bool]c              	     s   |si }|p|  d}t|jd4 I dH 7}|  |jdi |I dH }|rC||j|dI dH  |dfW  d  I dH  S W d  I dH  n1 I dH sSw   Y  | j||fi |I dH S )a2  
        A convenience method for updating an object with the given kwargs, creating a new one if necessary.

        :param defaults: Default values used to update the object.
        :param using_db: Specific DB connection to use instead of default bound
        :param kwargs: Query parameters.
        Tr  Nr  Fr@   )	r{  r6   r  r  rh  get_or_nonerY  r  r  )rp   r  rh  r(  r   r  instancer@   r@   rF   update_or_create  s    (zModel.update_or_createc                   s<   | di |}d|_ |p| d}|j|ddI dH  |S )a  
        Create a record in the DB and returns the object.

        .. code-block:: python3

            user = await User.create(name="...", email="...")

        Equivalent to:

        .. code-block:: python3

            user = User(name="...", email="...")
            await user.save()

        :param using_db: Specific DB connection to use instead of default bound
        :param kwargs: Model parameters.
        FT)rh  rx  Nr@   )r+  r{  r  )rp   rh  r(  r  r   r@   r@   rF   r    s   zModel.createobjectsIterable[MODEL]Iterable[str]
batch_size
int | NoneBulkUpdateQuery[MODEL]c                 C  s   | j |dd|||S )a
  
        Update the given fields in each of the given objects in the database.
        This method efficiently updates the given fields on the provided model instances, generally with one query.

        .. code-block:: python3

            users = [
                await User.create(name="...", email="..."),
                await User.create(name="...", email="...")
            ]
            users[0].name = 'name1'
            users[1].name = 'name2'

            await User.bulk_update(users, fields=['name'])

        :param objects: List of objects to bulk create
        :param fields: The fields to update
        :param batch_size: How many objects are created in a single query
        :param using_db: Specific DB connection to use instead of default bound
        Tr  )r  bulk_update)rp   r  r   r  rh  r@   r@   rF   r    s   zModel.bulk_updateid_listIterable[str | int]r   dict[str, MODEL]c                   s   |  |||I dH S )aT  
        Return a dictionary mapping each of the given IDs to the object with
        that ID. If `id_list` isn't provided, evaluate the entire QuerySet.

        :param id_list: A list of field values
        :param field_name: Must be a unique field
        :param using_db: Specific DB connection to use instead of default bound
        N)r  in_bulk)rp   r  r   rh  r@   r@   rF   r    s   zModel.in_bulkignore_conflictson_conflictBulkCreateQuery[MODEL]c                 C  s   | j |dd|||||S )a  
        Bulk insert operation:

        .. note::
            The bulk insert operation will do the minimum to ensure that the object
            created in the DB has all the defaults and generated fields set,
            but may be incomplete reference in Python.

            e.g. ``IntField`` primary keys will not be populated.

        This is recommended only for throw away inserts where you want to ensure optimal
        insert performance.

        .. code-block:: python3

            User.bulk_create([
                User(name="...", email="..."),
                User(name="...", email="...")
            ])

        :param on_conflict: On conflict index name
        :param update_fields: Update fields when conflicts
        :param ignore_conflicts: Ignore conflicts when inserting
        :param objects: List of objects to bulk create
        :param batch_size: How many objects are created in a single query
        :param using_db: Specific DB connection to use instead of default bound
        Tr  )r  bulk_create)rp   r  r  r  rq  r  rh  r@   r@   rF   r    s   %
zModel.bulk_createQuerySetSingle[Self | None]c                 C     |  | S )zE
        Generates a QuerySet that returns the first record.
        )r  rd   rp   rh  r@   r@   rF   rd        zModel.firstc                 C  r  )zD
        Generates a QuerySet that returns the last record.
        )r  lastr  r@   r@   rF   r    r  z
Model.lastr0   c                 O     | j j j|i |S )z
        Generates a QuerySet with the filter applied.

        :param args: Q functions containing constraints. Will be AND'ed.
        :param kwargs: Simple filter constraints.
        )r   r   r  rc   rp   r  r(  r@   r@   rF   rc   #     zModel.filter	orderingsc                 G     | j j j| S )z
        Generates a QuerySet with the filter applied that returns the last record.

        :params orderings: Fields to order by.
        )r   r   r  latestrp   r  r@   r@   rF   r  -     zModel.latestc                 G  r  )z
        Generates a QuerySet with the filter applied that returns the first record.

        :params orderings: Fields to order by.
        )r   r   r  earliestr  r@   r@   rF   r  6  r  zModel.earliestc                 O  r  )z
        Generates a QuerySet with the exclude applied.

        :param args: Q functions containing constraints. Will be AND'ed.
        :param kwargs: Simple filter constraints.
        )r   r   r  excluder  r@   r@   rF   r  ?  r  zModel.excludeExpression | Termc                 K  s   | j j jdi |S )z
        Annotates the result set with extra Functions/Aggregations/Expressions.

        :param kwargs: Parameter name and the Function/Aggregation to annotate with.
        Nr@   )r   r   r  annotate)rp   r(  r@   r@   rF   r  I  s   zModel.annotatec                 C  r   )z0
        Returns the complete QuerySet.
        )r  r  r@   r@   rF   allR  s   
z	Model.allQuerySetSingle[Self]c                O     |  |j|i |S )a  
        Fetches a single record for a Model type using the provided filter parameters.

        .. code-block:: python3

            user = await User.get(username="foo")

        :param using_db: The DB connection to use
        :param args: Q functions containing constraints. Will be AND'ed.
        :param kwargs: Simple filter constraints.

        :raises MultipleObjectsReturned: If provided search returned more than one object.
        :raises DoesNotExist: If object can not be found.
        )r  r   rp   rh  r  r(  r@   r@   rF   r   Y  s   z	Model.getsqlr3   c                 C  s   |  ||S )a  
        Executes a RAW SQL and returns the result

        .. code-block:: python3

            result = await User.raw("select * from users where name like '%test%'")

        :param using_db: The specific DB connection to use
        :param sql: The raw sql.
        )r  raw)rp   r  rh  r@   r@   rF   r  m  s   z	Model.rawr/   c                O  s   |  |j|i | S )ao  
        Return True/False whether record exists with the provided filter parameters.

        .. code-block:: python3

            result = await User.exists(username="foo")

        :param using_db: The specific DB connection to use.
        :param args: Q functions containing constraints. Will be AND'ed.
        :param kwargs: Simple filter constraints.
        )r  rc   existsr  r@   r@   rF   r  {  s   zModel.existsc                O  r  )a|  
        Fetches a single record for a Model type using the provided filter parameters or None.

        .. code-block:: python3

            user = await User.get_or_none(username="foo")

        :param using_db: The specific DB connection to use.
        :param args: Q functions containing constraints. Will be AND'ed.
        :param kwargs: Simple filter constraints.
        )r  r  r  r@   r@   rF   r    s   zModel.get_or_noneinstance_listIterable[Model]c                  s4   |p|   }|j| |dj|g|R  I dH  dS )z
        Fetches related models for provided list of Model objects.

        :param instance_list: List of Model objects to fetch relations for.
        :param args: Relation names to fetch.
        :param using_db: DO NOT USE
        rz  N)r{  r   r  )rp   r  rh  r  r   r@   r@   rF   r    s   &zModel.fetch_for_listc                 C  s   |  d |  d dS )z
        Calls various checks to validate the model.

        :raises ConfigurationError: If the model has not been configured correctly.
        r   r   N)_check_together)rp   r@   r@   rF   _check  s   
zModel._checkr<   c              
   C  s   t | j|}t|ttfstd| j d| dtdd |D r.td| j d| d|D ];}t|tr:|j	}|D ].}| jj
|}|sVtd| j d| d| d	t|trjtd| j d| d
| dq<q0dS )z
        Check the value of "unique_together" option.

        :raises ConfigurationError: If the model has not been configured correctly.
        'r   z' must be a list or tuple.c                 s  s"    | ]}t |tttf V  qd S rJ   )rB   rD   rC   r+   )rL   unique_fieldsr@   r@   rF   rM     s     z(Model._check_together.<locals>.<genexpr>zAll 'z#' elements must be lists or tuples.z
' has no 'z' field.z' 'z#' field refers to ManyToMany field.N)rA   r   rB   rD   rC   r   rU   anyr+   r   r   r   r$   )rp   r<   rE   fields_tupler   r   r@   r@   rF   r    s.   

zModel._check_togetherindexIndex | tuple[str, ...]serializableIndex | tuple[str, ...] | dictc                 C  s   t |tr|r| S |S |S rJ   )rB   r+   describe)rp   r  r  r@   r@   rF   _describe_index  s   
zModel._describe_indexTc                   s
   j j j j j j j j j jpdt jpdpd j j	pg  fdd j j
D  j j j j  fdd j j D  fdd j j D  fdd j j D  fdd j j D  fd	d j j D  fd
d j j D dS )a  
        Describes the given list of models or ALL registered models.

        :param serializable:
            ``False`` if you want raw python objects,
            ``True`` for JSON-serializable data. (Defaults to ``True``)

        :return:
            A dictionary containing the model description.

            The base dict has a fixed set of keys that reference a list of fields
            (or a single field in the case of the primary key):

            .. code-block:: python3

                {
                    "name":                 str     # Qualified model name
                    "app":                  str     # 'App' namespace
                    "table":                str     # DB table name
                    "abstract":             bool    # Is the model Abstract?
                    "description":          str     # Description of table (nullable)
                    "docstring":            str     # Model docstring (nullable)
                    "unique_together":      [...]   # List of List containing field names that
                                                    #  are unique together
                    "pk_field":             {...}   # Primary key field
                    "data_fields":          [...]   # Data fields
                    "fk_fields":            [...]   # Foreign Key fields FROM this model
                    "backward_fk_fields":   [...]   # Foreign Key fields TO this model
                    "o2o_fields":           [...]   # OneToOne fields FROM this model
                    "backward_o2o_fields":  [...]   # OneToOne fields TO this model
                    "m2m_fields":           [...]   # Many-to-Many fields
                }

            Each field is specified as defined in :meth:`tortoise.fields.base.Field.describe`
        Nrs   c                   s   g | ]}  |qS r@   )r  )rL   r  rp   r  r@   rF   r     s    z"Model.describe.<locals>.<listcomp>c                   s:   g | ]\}}| j jkr| j j j j v r|qS r@   )r   r   r   r   r  rL   r   r   r  r@   rF   r     s    
c                   &   g | ]\}}| j jv r|qS r@   )r   r   r  r  r  r@   rF   r         
c                   r  r@   )r   r   r  r  r  r@   rF   r     r  c                   r  r@   )r   r   r  r  r  r@   rF   r      r  c                   r  r@   )r   r   r  r  r  r@   rF   r   %  r  c                   r  r@   )r   r   r  r  r  r@   rF   r   *  r  )r   r   r   r   r  r  r   r   r  data_fieldsr   r   r   r   r   )r   r   r   r   r   r   ru   r  r  r   r   r   r   r  r   r  r@   r  rF   r    s8   &







zModel.describeGenerator[Any, None, MODEL]c                   s   d fdd}|   S )Nr>   r7   c                     s    S rJ   r@   r@   r   r@   rF   _self2  s   zModel.__await__.<locals>._self)r>   r7   )	__await__)rY   r  r@   r   rF   r  1  s   
zModel.__await__c                   @  s   e Zd ZdZdS )r;   a:  
        The ``Meta`` class is used to configure metadata for the Model.

        Usage:

        .. code-block:: python3

            class Foo(Model):
                ...

                class Meta:
                    table="custom_table"
                    unique_together=(("field_a", "field_b"), )
        N)rU   rV   rW   r  r@   r@   r@   rF   r   7  s    r   )r(  r
   r>   r\   r   )r(  r   r>   r  )rp   r  r(  r
   r>   r7   r   )r>   rG  )r>   rJ  )rL  r{   r>   rM  )r>   r
   )rZ   r
   r>   r\   )rQ  r=   rZ   r[   r>   r\   )rp   r  r   r
   r>   r7   )rY   r7   r   r
   r>   r7   )rY   r7   rX  r   r>   r7   )rZ  r5   r[  r   r>   r\   )rZ  r5   r>   r\   rJ   )rh  ri  r>   r\   )NN)rh  ri  rq  rr  r>   r\   )NFN)rh  ri  ru  rM  rq  rr  r>   r\   )NNFF)
rh  ri  rq  rr  rx  rM  ry  rM  r>   r\   )r  r
   rh  ri  r>   r\   )r   rr  rh  ri  r>   r\   )F)r  rM  r>   r   )r  r  rh  ri  r(  r
   r>   r  )r   r   r  r   r>   r  r)  )rh  ri  r  rM  r>   r  )FFr@   NF)r  rM  r  rM  r  r  rh  ri  r  rM  r>   r  )
rp   r  r  r  rh  ri  r(  r
   r>   r  )rp   r  rh  ri  r(  r
   r>   r7   )rp   r  r  r  r   r  r  r  rh  ri  r>   r  )r   N)
rp   r  r  r  r   r=   rh  ri  r>   r  )NFNNN)rp   r  r  r  r  r  r  rM  rq  rr  r  rr  rh  ri  r>   r  )rh  ri  r>   r  )r  r0   r(  r
   r>   r  )r  r=   r>   r  )r(  r  r>   r  )rh  ri  r>   r  )r  r0   rh  ri  r(  r
   r>   r  )r  r=   rh  ri  r>   r3   )
rp   r  r  r0   rh  ri  r(  r
   r>   r/   )r  r0   rh  ri  r(  r
   r>   r  )r  r  r  r
   rh  ri  r>   r\   )r<   r=   r>   r\   )r  r  r  rM  r>   r  )T)r  rM  r>   r   )rY   r7   r>   r  )IrU   rV   rW   r  r   r   r5   rs  rv  rk  ro  r'  rX   r   r5  r/  r$  rA  rD  rF  rI  rK  rN  rO  rP  r   r   r4  r!  rU  rW  rY  r^  ra  rg  rm  rp  rt  rw  r  r  r  r  r{  r  r  r  r  r  r  r  r  r  rd   r  rc   r  r  r  r  r  r   r  r  r  r  r  r  r  r  r  r   r&  r@   r@   r  rF   r8     s  
 

%
1









	
B(			 
N)	metaclass)r:   r;   r<   r=   r>   r?   )r:   r;   r>   rH   )rY   r8   rZ   r[   rR   r=   rS   r=   rT   r=   r>   r\   )rY   r8   rR   r=   r_   r`   rS   r=   rT   r=   r>   r   )rY   r8   rR   r=   r_   r`   rf   r=   rg   r=   r>   r(   )rY   r8   rR   r=   r_   r`   rf   r=   rg   r=   r>   rk   )rY   r8   rR   r=   rn   r$   r>   r%   )rp   r`   r>   rq   )]
__future__r   rd  ru   r|   collections.abcr   r   r   r   r   r   	functoolsr	   typingr
   r   r   r   pypika_tortoiser   r   r   pypika_tortoise.termsr   typing_extensionsr   tortoiser   tortoise.backends.base.clientr   tortoise.exceptionsr   r   r   r   r   r   r   r   r   tortoise.expressionsr   tortoise.fields.baser   tortoise.fields.datar    tortoise.fields.relationalr!   r"   r#   r$   r%   r&   r'   r(   tortoise.filtersr)   r*   tortoise.indexesr+   tortoise.managerr,   tortoise.querysetr-   r.   r/   r0   r1   r2   r3   tortoise.routerr4   tortoise.signalsr5   tortoise.transactionsr6   r7   r{   rU  rG   rP   rQ   r^   re   rj   rm   ro   r   r   r   r   r8   r@   r@   r@   rF   <module>   sT    ,(
$	











  2 H