U
    祡c*                     @   s  d 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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 zddlZW n  ek
r   ddlmZ Y nX G dd dejZe Zdd Z dd Z!ej"#ej"$e%Z&ej"'e&dZ(ej)*e( e+de,ddd Z-e+de,ddd Z.e+de,ddd  Z/e+d!e,d"d#d" Z0e+d$d%d& Z1e+d'e,d(d)d* Z2e+d+e,d,d-d. Z3e+d/d0d1 Z4d2d3 Z5e+d4e,d5d6d5 Z6e+d7e,d8d9d: Z7d;d< Z8e+d=d>d? Z9e+d@dAdB Z:G dCdD dDej;Z<dNdHdIZ=G dJdK dKeZ>dLdM Z?dS )Oak  
This module provides a web-based memory profiling interface. The Pympler web
frontend exposes process information, tracker statistics, and garbage graphs.
The web frontend uses `Bottle <http://bottlepy.org>`_, a lightweight Python
web framework. Bottle is packaged with Pympler.

The web server can be invoked almost as easily as setting a breakpoint using
*pdb*::

    from pympler.web import start_profiler
    start_profiler()

Calling ``start_profiler`` suspends the current thread and executes the Pympler
web server, exposing profiling data and various facilities of the Pympler
library via a graphic interface.
    N)getouterframes)dumps)rmtree)mkdtemp)Thread)WeakValueDictionary)make_server)asizeof)GarbageGraph)get_current_threadsProcessMemoryInfo)	safe_repr)bottlec                   @   s    e Zd ZdZdd Zdd ZdS )ServerStatez
    Represents the state of a running server. Needs to be thread local so
    multiple servers can be started in different threads without interfering
    with each other.

    Cache internal structures (garbage graphs, tracker statistics).
    c                 C   s&   d | _ d | _d | _t | _t | _d S N)serverstatsgarbage_graphsr   id2refdictid2objself r   //tmp/pip-unpacked-wheel-8ad_c8mj/pympler/web.py__init__4   s
    zServerState.__init__c                 C   s
   d | _ d S r   r   r   r   r   r   clear_cache;   s    zServerState.clear_cacheN)__name__
__module____qualname____doc__r   r   r   r   r   r   r   ,   s   r   c                 C   s>   t | }z| tj|< W n tk
r4   | tj|< Y nX t|S )a*  
    Get string reference to object. Stores a weak reference in a dictionary
    using the object's id as the key. If the object cannot be weakly
    referenced (e.g. dictionaries, frame objects), store a strong references
    in a classic dictionary.

    Returns the object's id as a string.
    )idr   r   	TypeErrorr   str)objoidr   r   r   get_refB   s    	r'   c                 C   s   t | }tj|ptj| S )z!Get object from string reference.)intr   r   getr   )refr&   r   r   r   get_objS   s    r+   Z	templates/indexc                  C   s   t  } t| dS )zGet overview.)Zprocessinfo)r   r   )pmir   r   r   root_   s    r/   z/processprocessc                  C   s   t  } t }t| |dS )zGet process overview.)infothreads)r   r   r   )r.   r2   r   r   r   r0   g   s    /trackertrackerc                  C   sZ  t j} | rL| jrL|   g }| jD ]>}g }| jD ] }||j|i dd q4|||f q&dd | jD }|d|f | jd jj	rdd | jD }|d|f dd | jD }|d	|f d
d | jD }|d|f dd | jD }|d|f ndd | jD }|d|f dd |D }t
| jt|dS t
g dS dS )zGet tracker overview.sumr   c                 S   s   g | ]
}|j qS r   )overhead.0sr   r   r   
<listcomp>~   s     z!tracker_index.<locals>.<listcomp>zProfiling overheadc                 S   s    g | ]}|j j|j |j qS r   )system_totaldata_segmenttracked_totalr6   r7   r   r   r   r:      s   zData segmentc                 S   s   g | ]}|j jqS r   )r;   Zcode_segmentr7   r   r   r   r:      s     zCode segmentc                 S   s   g | ]}|j jqS r   )r;   Zstack_segmentr7   r   r   r   r:      s     zStack segmentc                 S   s   g | ]}|j jqS r   )r;   Zshared_segmentr7   r   r   r   r:      s     zShared memoryc                 S   s   g | ]}|j |j |j qS r   )totalr=   r6   r7   r   r   r   r:      s   ZOtherc                 S   s$   g | ]\}}t |tt|d qS ))labeldata)r   list	enumerate)r8   r?   r@   r   r   r   r:      s   )	snapshots
timeseries)rC   N)r   r   rC   annotateZtracked_classesappendclassesr)   r;   r<   r   r   )r   rD   clsZseriesZsnapshotr   r   r   tracker_indexp   s>    

rI   z/tracker/class/<clsname>tracker_classc                 C   s(   t j}|std |  t|| dS )zGet class instance details.r3   )r   clsname)r   r   r   redirectrE   r   )rK   r   r   r   r   rJ      s
    
z/refreshc                   C   s   t   td dS )zClear all cached information.r,   N)r   r   r   rL   r   r   r   r   refresh   s    rM   z/traceback/<threadid>Z
stacktracec                 C   sR   t | } t }| |krB||  }t|d}|  dd |D }ng }t|| dS )N   c                 S   s(   g | ] }t |d  jf|dd  qS )r      N)r'   f_locals)r8   fr   r   r   r:      s     z!get_traceback.<locals>.<listcomp>)stackthreadid)r(   sys_current_framesr   reverser   )rS   framesframerR   r   r   r   get_traceback   s    
rY   z/objects/<oid>	referentsc                 C   s|   i }t | }t|tkr$t|}nt|}dd |D }|D ]0\}}t|t|jt|ddt|f||< q@t|dS )Nc                 S   s   g | ]}t t||fqS r   )reprtype)r8   xr   r   r   r:      s     z%get_obj_referents.<locals>.<listcomp>0   )Zclip)rZ   )	r+   r\   r   r	   Z
named_refsZ_getreferentsr'   r   r   )r&   rZ   r%   Znamed_objectsrefsnameor   r   r   get_obj_referents   s    

 
rb   z/static/<filename>c                 C   s   t j| tdS )zGet static files (CSS-files).r/   )r   static_filestatic_files)filenamer   r   r   rd      s    rd   c                   C   s   t jdkrt  t _t jS )zN
    Retrieve garbage graph objects from cache, compute if cache is cold.
    N)r   r   r
   Zsplit_and_sortr   r   r   r   _compute_garbage_graphs   s    
rg   z/garbagegarbage_indexc                  C   s   t  } t| dS )zGet garbage overview.)Zgraphs)rg   r   r   r   r   r   rh      s    z/garbage/<index:int>garbagec                 C   s8   t  t|  }|  |j}|jdd d t|| dS )zGet reference cycle details.c                 S   s   | j  S r   )size)r]   r   r   r   <lambda>       zgarbage_cycle.<locals>.<lambda>)key)objectsr-   )rg   r(   reduce_to_cyclesmetadatasortr   )r-   graphrn   r   r   r   garbage_cycle   s
    rs   c                 C   sf   z
| j }W nP tk
rZ   z"| jtjtj|dd |}W n tk
rT   d}Y nX Y nX || _ |S )zRetrieve or render a graph.Zpng)formatN)	rendered_fileAttributeErrorrenderospathjoinr   tmpdirOSError)rr   rf   renderedr   r   r   
_get_graph   s    
r~   z/garbage/graph/<index:int>c                 C   sd   t  t|  }tjjdd}|r*| }|s2dS d| |f }t||}|r\tj|t	j
dS dS dS )z,Get graph representation of reference cycle.reduce Nzgarbage%so%s.pngrc   )rg   r(   r   requestGETr)   ro   r~   rd   r   r{   )r-   rr   Zreduce_graphrf   ru   r   r   r   garbage_graph   s    
r   z/helpc                   C   s   t d dS )z!Redirect to online documentation.z)https://pympler.readthedocs.io/en/latest/N)r   rL   r   r   r   r   show_documentation	  s    r   c                   @   s   e Zd ZdZdd ZdS )PymplerServerzSimple WSGI server.c                 C   s    t | j| j|| _| j  d S r   )r   hostportr   serve_forever)r   handlerr   r   r   run  s    zPymplerServer.runN)r   r   r    r!   r   r   r   r   r   r     s   r   	localhost  Fc                 K   sh   |r|s|j t_ n|t_ z>tddt_tf | |d|t_t| tjtjd W 5 ttj X dS )a  
    Start the web server to show profiling data. The function suspends the
    Python application (the current thread) until the web server is stopped.

    The only way to stop the server is to signal the running thread, e.g. press
    Ctrl+C in the console. If this isn't feasible for your application use
    `start_in_background` instead.

    During the execution of the web server, profiling data is (lazily) cached
    to improve performance. For example, garbage graphs are rendered when the
    garbage profiling data is requested and are simply retransmitted upon later
    requests.

    The web server can display profiling data from previously taken snapshots
    when `tracker` or `stats` is specified. The former is useful for profiling
    a running application, the latter for off-line analysis. Requires existing
    snapshots taken with
    :py:meth:`~pympler.classtracker.ClassTracker.create_snapshot` or
    :py:meth:`~pympler.classtracker.ClassTracker.start_periodic_snapshots`.

    :param host: the host where the server shall run, default is localhost
    :param port: server listens on the specified port, default is 8090 to allow
        coexistance with common web applications
    :param tracker: `ClassTracker` instance, browse profiling data (on-line
        analysis)
    :param stats: `Stats` instance, analyze `ClassTracker` profiling dumps
        (useful for off-line analysis)
    pympler)prefix)r   r   )r   N)	r   r   r   r{   r   r   r   debugr   )r   r   r4   r   r   kwargsr   r   r   start_profiler  s    

r   c                       s*   e Zd ZdZd fdd	Zdd Z  ZS )	ProfilerThreadz,Encapsulates a thread to run the web server.NPympler web frontendc                    s&   t t| j|||d || _d| _d S )N)grouptargetr`   T)superr   r   r   daemon)r   r   r   r`   r   	__class__r   r   r   C  s    zProfilerThread.__init__c                 C   s   t f | j d S r   )r   r   r   r   r   r   r   K  s    zProfilerThread.run)NNr   )r   r   r    r!   r   r   __classcell__r   r   r   r   r   A  s   r   c                  K   s   t f | }|  |S )a	  
    Start the web server in the background. A new thread is created which
    serves the profiling interface without suspending the current application.

    For the documentation of the parameters see `start_profiler`.

    Returns the created thread object.
    )r   start)r   threadr   r   r   start_in_backgroundO  s    	
r   )r   r   NNF)@r!   rT   rx   	threadinginspectr   jsonr   shutilr   tempfiler   r   weakrefr   Zwsgiref.simple_serverr   r   r	   Zpympler.garbagegraphr
   Zpympler.processr   r   Zpympler.util.stringutilsr   r   ImportErrorZpympler.utillocalr   r   r'   r+   ry   dirnameabspath__file__Zpympler_pathrz   re   ZTEMPLATE_PATHrF   Zrouteviewr/   r0   rI   rJ   rM   rY   rb   rd   rg   rh   rs   r~   r   r   ZServerAdapterr   r   r   r   r   r   r   r   <module>   s   %	

		

  
+