o
    PDi2                     @   s  d dl Z d dl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mZmZ d dlmZmZ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#m$Z$ ze
d Z%W n ey   d dl&m'Z' e" j(pej)Z*e'e* Z%Y nw dd Z+dd Z,G dd de-Z.G dd dej/Z0G dd dej/Z1G dd dej2Z3G dd dej/Z4G dd dej/Z5G dd de5Z6dS )     N)uuid4)settings)storages)InvalidStorageError)modelsroutertransaction)BooleanField	CharFieldDateTimeField	FileField
FloatField
ForeignKeyIntegerFieldManyToManyFieldOneToOneFieldSum	TextField)timezone)	mark_safe)SilkyConfig)parse_profileSILKY_STORAGE)import_stringc                 C   s   ||  }|j d |jd  S N  )secondsmicroseconds)
start_timeend_timed r!   D/var/www/Datamplify/venv/lib/python3.10/site-packages/silk/models.py_time_taken(   s   r#   c                 C   s   t | j| jS N)r#   r   r   selfr!   r!   r"   
time_taken-   s   r'   c                       s>   e Zd Z fddZ fddZd
ddZ fdd	Z  ZS )CaseInsensitiveDictionaryc                    s   t  | S r$   )super__getitem__lower)r&   key	__class__r!   r"   r*   2   s   z%CaseInsensitiveDictionary.__getitem__c                    s   t  | | d S r$   )r)   __setitem__r+   )r&   r,   valuer-   r!   r"   r/   5   s   z%CaseInsensitiveDictionary.__setitem__Nc                 K   s8   |  D ]\}}|| |< q|  D ]\}}|| |< qd S r$   )items)r&   otherkwargskvr!   r!   r"   update8   s
   

z CaseInsensitiveDictionary.updatec                    s(   t    | D ]\}}|| |< q	d S r$   )r)   __init__r1   )r&   r    r4   r5   r-   r!   r"   r7   >   s   

z"CaseInsensitiveDictionary.__init__r$   )__name__
__module____qualname__r*   r/   r6   r7   __classcell__r!   r!   r-   r"   r(   1   s
    
r(   c                       sB  e Zd ZededdZedddZedddZedddZ	edddZ
edd	Zeejdd
ZeddddddZedddZedddZedddZedddZedddZedddZedddZeddedZdd Zedd Zedd Z eddZ!edd Z"edd Z#edd Z$e%d#dd Z& fd!d"Z'  Z(S )$Request$   T
max_lengthdefaultprimary_key   )r?   db_index blankr@   
   )r?   )r@   rC   )r?   rC   rF   r@   nullrH   rF   rF   rH   ,  )r?   rF   storagec                 C   s&   |d d  d|t |d d   S )N^   z...]   )len)r&   stringr!   r!   r"   _shorten[   s   &zRequest._shortenc                 C   s   | j pd| jpd S )Nr   )	meta_timemeta_time_spent_queriesr%   r!   r!   r"   total_meta_time^   s   zRequest.total_meta_timec                 c   s    t t| jD ]M\}}|d }|rRd|vrRd|vrRtd}||}| }|d }|d }d| }	d}
|
jd	i t|fi t	 }|d d t
|g V  q|V  qd S )
N{<z"(?P<src>.*\.py)\:(?P<num>[0-9]+).*srcnumzc%dzS<a name={name} href="?pos={n}&file_path={src}&line_num={num}#{name}">{location}</a>r!   )	enumerater   	pyprofilerecompilesearch	groupdictformatdictlocalsr   )r&   ncolumnslocationrmgrouprX   rY   namefmtrepr!   r!   r"   profile_tableb   s   

zRequest.profile_tabler   r@   c                 C   s,   t jj| djtdt dd}|d pdS )zi"
        Calculate the total time spent in milliseconds on SQL queries using Django aggregates.
        )requestr'   output_field
total_timerr           )SQLQueryobjectsfilter	aggregater   r   r&   resultr!   r!   r"   time_spent_on_sql_queriesx   s   z!Request.time_spent_on_sql_queriesc                 C   &   | j rt| j }t|S i }t|S r$   encoded_headersjsonloadsr(   r&   rawr!   r!   r"   headers   s
   zRequest.headersc                 C      | j dd S Nzcontent-typer   getr%   r!   r!   r"   content_type      zRequest.content_typeFc                 C   s   t  j}|d }|t k r|sdS t  j}|dkr"|td| 8 }|dkr/| j   dS z| jdj	ddd| }W n
 t
yH   Y dS w | jj|d	  dS )
z Remove Request/Responses when we are at the SILKY_MAX_RECORDED_REQUESTS limit
        Note that multiple in-flight requests may call this at once causing a
        double collection g      Y@Nr      z-start_timer   T)flat)start_time__lte)r   )SILKY_MAX_RECORDED_REQUESTS_CHECK_PERCENTrandomSILKY_MAX_RECORDED_REQUESTSintru   alldeleteorder_byvalues_list
IndexErrorrv   )clsforcecheck_percenttarget_counttime_cutoffr!   r!   r"   garbage_collect   s0   zRequest.garbage_collectc                    s   | j d u rd| _ | jd u rd| _| jr#| jr#| j| j }| d | _| jr4t| jdkr4| | j| _| j	rEt| j	dkrE| | j	| _	t
 j|i | tjdd d S )NrD   r   rB   F)r   )raw_bodybodyr   r   total_secondsr'   pathrO   rQ   	view_namer)   saver<   r   r&   argsr3   intervalr-   r!   r"   r      s   

zRequest.save)F))r8   r9   r:   r
   r   idr   r   query_paramsr   r   methodr   r   nowr   r   r   r   r'   r}   rR   r   meta_num_queriesrS   r[   r   silk_storage	prof_filerQ   propertyrT   rl   num_sql_queriesrz   r   r   classmethodr   r   r;   r!   r!   r-   r"   r<   D   sF    




	

 r<   c                   @   sz   e Zd ZededdZeeddej	dZ
e ZedddZedddZedddZedd	 Zed
d Zedd ZdS )Responser=   Tr>   response)related_namerC   	on_deleterD   rE   c                 C   r   r   r   r%   r!   r!   r"   r      r   zResponse.content_typec                 C   r{   r$   r|   r   r!   r!   r"   r      s
   zResponse.headersc                 C   s   t | jS r$   )base64	b64decoder   r%   r!   r!   r"   raw_body_decoded   s   zResponse.raw_body_decodedN)r8   r9   r:   r
   r   r   r   r<   r   CASCADErn   r   status_coder   r   r   r}   r   r   r   r   r!   r!   r!   r"   r      s     

r   c                       s   e Zd Z fddZ  ZS )SQLQueryManagerc                    sv   t jttd( t|r|d }n|d}|D ]}|  qt j	|i |W  d   S 1 s4w   Y  dS )zensure that num_sql_queries remains consistent. Bulk create does not call
        the model save() method and hence we must add this logic here toousingr   objsN)
r   atomicr   db_for_writert   rO   r   prepare_saver)   bulk_create)r&   r   r3   r   objr-   r!   r"   r      s   


$zSQLQueryManager.bulk_create)r8   r9   r:   r   r;   r!   r!   r-   r"   r      s    r   c                       s   e Zd Ze ZeddejdZedddZ	e
dddZeddZeeddddejdZe ZedddZe Zed	d
 Zedd Zedd Zedd Zedd Zdd Z fddZ fddZ  Z S )rt   T)rH   rF   r@   rI   rJ   rU   rm   queries)r   rH   rF   rC   r   c                 C   s   d | jdd d d S )N
   )join	tracebacksplitr%   r!   r!   r"   traceback_ln_only  s   zSQLQuery.traceback_ln_onlyc                 C   s   t j| jdddS )NTupper)reindentkeyword_case)sqlparser`   queryr%   r!   r!   r"   formatted_query  s   zSQLQuery.formatted_queryc                 C   s8   t | j}d}|D ]}|ttdd | 7 }q
|S )Nr   c                 S   s   | j tjjdddS )Nz
\.*join\.*T)regex)matchr   tokensKeyword)tr!   r!   r"   <lambda>      z$SQLQuery.num_joins.<locals>.<lambda>)r   parser   summapflatten)r&   parsed_querycount	statementr!   r!   r"   	num_joins
  s
   zSQLQuery.num_joinsc                 C   s@   t | j}g }|d jD ]}|js n||j qd|S )Nr    )r   r   r   r   
is_keywordappendr0   r   )r&   r   keywordsr   r!   r!   r"   first_keywords  s   
zSQLQuery.first_keywordsc              	   C   s   dd | j  D }g }t|D ]A\}}| dks,| dks,| dks,| dkrQz||d  }|dsF| d	}|rF|| W q tyP   Y qw q|S )
z
        A really another rudimentary way to work out tables involved in a
        query.
        TODO: Can probably parse the SQL using sqlparse etc and pull out table
        info that way?
        c                 S   s   g | ]}|  qS r!   )strip).0xr!   r!   r"   
<listcomp>$  r   z,SQLQuery.tables_involved.<locals>.<listcomp>fromr   asr6   r   (,)r   r   rZ   r+   
startswithr   r   r   )r&   
componentstablesidx	component_nextstrippedr!   r!   r"   tables_involved  s&   

zSQLQuery.tables_involvedc                 C   s^   | j r| jr| j | j }| d | _| js+| jr-| j jd7  _| jjdgd d S d S d S )Nr   r   r   )update_fields)r   r   r   r'   pkrn   r   r   )r&   r   r!   r!   r"   r   ;  s   zSQLQuery.prepare_savec                    sR   t jt| d |   t j|i | W d    d S 1 s"w   Y  d S )Nr   )r   r   r   r   r   r)   r   r&   r   r3   r-   r!   r"   r   E  s   "zSQLQuery.savec                    sd   t jt| d | j jd8  _| j  t j|i | W d    d S 1 s+w   Y  d S )Nr   r   )	r   r   r   r   rn   r   r   r)   r   r   r-   r!   r"   r   J  s
   
"zSQLQuery.delete)!r8   r9   r:   r   r   r   r   r   r   r   r   r'   r   
identifierr   r<   r   r   rn   r   analysisr   ru   r   r   r   r   r   r   r   r   r   r;   r!   r!   r-   r"   rt      s4    




	

rt   c                       sp   e Zd ZeddddZeejdZedddZ	e
edddejdZedddZG d	d
 d
Z fddZ  ZS )BaseProfilerK   TrD   r?   rF   r@   rm   rI   )rH   rF   rC   r   rJ   c                   @   s   e Zd ZdZdS )zBaseProfile.MetaTN)r8   r9   r:   abstractr!   r!   r!   r"   Meta[  s    r   c                    s<   | j r| jr| j | j }| d | _t j|i | d S r   )r   r   r   r'   r)   r   r   r-   r!   r"   r   ^  s   zBaseProfile.save)r8   r9   r:   r
   ri   r   r   r   r   r   r   r<   r   r   rn   r   r'   r   r   r;   r!   r!   r-   r"   r   Q  s    r   c                   @   s   e Zd ZeddddZedddZedddZeddddZe	ddZ
eeddd	Ze	ddZed
d Zedd Zedd ZdS )ProfilerK   TrD   r   rI   Frm   profiles)r   rC   c                 C   s
   | j d uS r$   	func_namer%   r!   r!   r"   is_function_profilen     
zProfile.is_function_profilec                 C   s
   | j d u S r$   r   r%   r!   r!   r"   is_context_profiler  r   zProfile.is_context_profilec                 C   s$   | j jtdt dd}|d pdS )zh
        Calculate the total time spent in milliseconds on SQL queries using Django aggregates.
        r'   ro   rq   rr   rs   )r   rw   r   r   rx   r!   r!   r"   rz   v  s   z!Profile.time_spent_on_sql_queriesN)r8   r9   r:   r
   	file_pathr   line_numend_line_numr   r	   exception_raisedr   rt   r   dynamicr   r   r   rz   r!   r!   r!   r"   r   e  s    



r   )7r   r~   r   r\   uuidr   r   django.confr   django.core.files.storager   !django.core.files.storage.handlerr   	django.dbr   r   r   django.db.modelsr	   r
   r   r   r   r   r   r   r   r   r   django.utilsr   django.utils.safestringr   silk.configr   silk.utils.profile_parserr   r   django.utils.module_loadingr   SILKY_STORAGE_CLASSDEFAULT_FILE_STORAGEstorage_classr#   r'   ra   r(   Modelr<   r   Managerr   rt   r   r   r!   r!   r!   r"   <module>   s@    4 ^