o
    PDi*                     @   s   d dl Z d dlZd dlZd dlZd dlmZ e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d Zdd Zdd ZdS )    N)silk_profilezsilk.profiling.dynamicc                 C   sh   d| v r(|  d}d|dd }|d }t|t t |gd}t||}|S t| t t g d}|S )zY
    Given a module name in form 'path.to.module' return module object for 'module'.
    .Nr   )splitjoin
__import__globalslocalsgetattr)module_namespltimpfrmmodule r   O/var/www/Datamplify/venv/lib/python3.10/site-packages/silk/profiling/dynamic.py_get_module   s   

r   c                 C   sP   d}d}d|v r| d\}}|rt| |}t||}||fS t| |}||fS )z
    Given a module and a function name, return the function.

    func_name can be of the forms:
        - 'foo': return a function
        - 'Class.foo': return a method
    Nr   )r   r
   )r   	func_namecls_nameclsfuncr   r   r   	_get_func   s   


r   c                 C   sf   t | tr	t| } t|dd}|}t| |\}}||}|r+t||dd | dS t| || dS )z
    Programmatically apply a decorator to a function in a given module [+ class]

    @param module: module object or module name in form 'path.to.module'
    @param func: function object or function name in form 'foo' or 'Class.method'
    T)_dynamicr   r   N)
isinstancestrr   r   r   setattrr   )r   r   name	decoratorr   r   wrapped_targetr   r   r   profile_function_or_method.   s   
r   c              	   C   s\   t j}| jd}t|dkr,|d d D ]}zt||}W q ty+   || }Y qw |S )Nr      r   )sysmodules__name__r   lenr
   AttributeError)r   parentr   r   r   r   r   _get_parent_moduleA   s   r'   c              
   C   s   d| }d}t |Z}d}t|D ]J\}}	||krBtd|	}
z|
 d }W n ty2   d}Y nw ||| 7 }||d |	 7 }q||  k rL| krWn n	||d |	 7 }q||	7 }qW d    |S 1 sgw   Y  |S )N(with silk_profile('%s', _dynamic=True):
1from silk.profiling.profiler import silk_profile
 	^(\s+).*$r   z    )open	enumerateresearchgroups
IndexError)end_line	file_pathr   
start_lineinject_codecodefwsilinexr   r   r   _get_context_manager_sourceM   s,   


r<   c                 C   s8   t d| }z	| d }W |S  ty   d}Y |S w )z8
    Return whitespace at the beginning of a string
    r+   r   r*   )r.   r/   r0   r%   )txtmfwsr   r   r   _get_wsc   s   r@   c                 C   sH   t | d }t|d }tdt|D ]}|| |dd||< q|S )Nr   r*   r    )inspectgetsourcelinesr@   ranger$   replace)r   sourcer?   r9   r   r   r   _get_source_lineso   s
   rF   c           	      C   sj   d | }tt }|d d }i }|j}|j}| }|| t	d|  t
||| ||j S )z
    Create new function defined in source but maintain context from func

    @param func: The function whose global + local context we will use
    @param source: Python source code containing def statement
    r*      r   zNew src_str:
 %s)r   rA   getouterframescurrentframe__globals__f_localscopyupdateLoggerdebugexecr#   )	rE   r   src_strframescalling_framecontextr   r	   combinedr   r   r   _new_func_from_sourcew   s   


rV   c              	   C   s   t | }|d7 }|d7 }t|| }t||D ]}z
d||  ||< W q ty3   td| j|f w |||d  ||d |d|   t|| S )a  
    injects a context manager into the given function

    e.g given:

        x = 5
        def foo():
            print x
            print '1'
            print '2'
            print '3'
        inject_context_manager_func(foo, 0, 2, 'cm')

    foo will now have the definition:

        def foo():
            with silk_profile('cm'):
                print x
                print '1'
                print '2'
            print '3'

    closures, globals & locals are honoured

    @param func: object of type<function> or type<instancemethod>
    @param start_line: line at which to inject 'with' statement. line num. is relative to the func, not the module.
    @param end_line: line at which to exit the context
    @param name: name of the profiler
    r    z  z!Function %s does not have line %dr)   r(   )rF   r@   rC   r1   r#   insertrV   )r   r4   r2   r   rE   r8   r9   r   r   r   _inject_context_manager_func   s   
rX   c                 C   s
   t | tS N)r   r   )or   r   r   
is_str_typ   s   
r[   c                 C   sh   t | rt| } d }t |r|}t| |\}}n|j}t||||}|r,t||| d S t| || d S rY   )r[   r   r   r#   rX   r   )r   r   r4   r2   r   r   r   new_funcr   r   r   inject_context_manager_func   s   r]   rY   )rA   loggingr.   r!   silk.profiling.profilerr   	getLoggerrN   r   r   r   r'   r<   r@   rF   rV   rX   r[   r]   r   r   r   r   <module>   s"    

"-