U
    祡cq                     @   s  d 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ZddlZddlZddlmZ ddlmZmZmZ ddlmZ e	rddlmZmZmZ d	d
dgZeedddZdeeeddddZeedddddZ ee edddZ!G dd	 d	e"Z#G dd
 d
e#Z$G dd de#Z%dS )zL
Provide saving, loading and presenting gathered `ClassTracker` statistics.
    )	AnyDictIOIterableListOptionalTupleTYPE_CHECKINGUnionN)deepcopy)truncpppp_timestamp)Asized   )TrackedObjectClassTrackerSnapshotStatsConsoleStats	HtmlStats)refreturnc                 C   s   | j dd S )N:r   )namesplit)r    r   >/tmp/pip-unpacked-wheel-8ad_c8mj/pympler/classtracker_stats.py_ref2key   s    r   )baseotherlevelr   c                 C   s   |  j |j 7  _ |  j|j7  _|dkr2t| | _t| j| _i }| jD ]}||t|< qH|jD ]H}t|}||krt|| ||d d q`| jt| || jd _q`dS )zD
    Merge **Asized** instances `base` and `other` into `base`.
    r   r   r!   N)	sizeZflatr   r   listrefs_merge_asizedappendr   )r   r    r!   r&   r   keyr   r   r   r'      s    


r'   r   )trefmergedobjr   c                 C   s2   d}|j D ]\}}|| kr
|}q
|r.t|| dS )z
    Merge the snapshot size information of multiple tracked objects.  The
    tracked object `obj` is scanned for size information at time `tref`.
    The sizes are merged into **Asized** instance `merged`.
    N)	snapshotsr'   )r*   r+   r,   r$   	timestamptsizer   r   r   _merge_objects3   s    r0   )tracer   c                 C   sZ   g }| D ]F\}}}}}|r:|D ]}| d|  d  q| d|||f  qd|S )z
    Convert the (stripped) stack-trace to a nice readable format. The stack
    trace `trace` is a list of frame records as returned by
    **inspect.stack** but without the frame objects.
    Returns a string.
        
z  %s:%4d in %s
 )r(   stripjoin)r1   linesfnamelinenofuncsrc_liner   r   r   _format_traceA   s    r>   c                   @   s   e Zd ZdZddee ee dddZeeee	 f dddd	Z
deeee	 f eddddZddddZed dddZd dddZddddZdeeeeef f dddZeee dddZdS ) r   zd
    Presents the memory statistics gathered by a `ClassTracker` based on user
    preferences.
    NzOptional[ClassTracker])trackerfilenamestreamc                 C   sZ   |r|| _ ntj| _ || _i | _g | _|rB|j| _|j| _|j| _g | _|rV| | dS )ap  
        Initialize the data log structures either from a `ClassTracker`
        instance (argument `tracker`) or a previously dumped file (argument
        `filename`).

        :param tracker: ClassTracker instance
        :param filename: filename of previously dumped statistics
        :param stream: where to print statistics, defaults to ``sys.stdout``
        N)	rA   sysstdoutr?   indexr-   historysorted
load_stats)selfr?   r@   rA   r   r   r   __init__W   s    zStats.__init__)fdumpr   c                 C   s6   t |trt|d}t|| _t|| _g | _dS )z
        Load the data from a dump file.
        The argument `fdump` can be either a filename or an open file object
        that requires read access.
        rbN)
isinstancestropenpickleloadrD   r-   rF   )rH   rJ   r   r   r   rG   r   s
    

zStats.load_statsT)rJ   closer   c                 C   s\   | j r| j   t|tr$t|d}tj| j|tjd tj| j	|tjd |rX|
  dS )a  
        Dump the logged data to a file.
        The argument `file` can be either a filename or an open file object
        that requires write access. `close` controls if the file is closed
        before leaving this method (the default behaviour).
        wb)protocolN)r?   stop_periodic_snapshotsrL   rM   rN   rO   dumprD   HIGHEST_PROTOCOLr-   rQ   )rH   rJ   rQ   r   r   r   
dump_stats~   s    


zStats.dump_statsr   c                 C   s   | j s|d}d}| jD ]}|j|kr|j}qt| j D ]B}| j| D ] }||_| |_	|
||_qF| j | j|  q8dS )z
        Prepare the data to be sorted.
        If not yet sorted, import all tracked objects from the tracked index.
        Extend the tracking information by implicit information to make
        sorting easier (DSU pattern).
        Nr   )rF   r-   tracked_totalr.   r%   rD   keys	classnameget_max_sizer$   get_size_at_timer/   extend)rH   Ztmaxmaxsizesnapshotr)   tobjr   r   r   
_init_sort   s    


zStats._init_sort)argsr   c                    s\   d}t |t  std s&| dttdf d fdd}|   | jj|d | S )	a-  
        Sort the tracked objects according to the supplied criteria. The
        argument is a string identifying the basis of a sort (example: 'size'
        or 'classname'). When more than one key is provided, then additional
        keys are used as secondary criteria when there is equality in all keys
        selected before them. For example, ``sort_stats('name', 'size')`` will
        sort all the entries according to their class name, and resolve all
        ties (identical class names) by sorting by size.  The criteria are
        fields in the tracked object instances. Results are stored in the
        ``self.sorted`` list which is used by ``Stats.print_stats()`` and other
        methods. The fields available for sorting are:

            'classname'
                the name with which the class was registered
            'name'
                the classname
            'birth'
                creation timestamp
            'death'
                destruction timestamp
            'size'
                the maximum measured size of the object
            'tsize'
                the measured size during the largest snapshot
            'repr'
                string representation of the object

        Note that sorts on size are in descending order (placing most memory
        consuming items first), whereas name, repr, and creation time searches
        are in ascending order (alphabetical).

        The function returns self to allow calling functions on the result::

            stats.sort_stats('size').reverse_order().print_stats()
        )r[   r/   birthdeathr   reprr$   zInvalid sort criteriar   .)r,   r   c                    s>   g } D ],}t | |d}|dkr*t| }|| qt|S )Nr4   )r/   r$   )getattrintr(   tuple)r,   rZ   attr	attributerc   r   r   args_to_tuple   s    
z'Stats.sort_stats.<locals>.args_to_tupler)   )set
issuperset
ValueErrorr   rM   rb   rF   sort)rH   rc   Zcriteriarm   r   rl   r   
sort_stats   s    %	zStats.sort_statsc                 C   s   |    | j  | S )zP
        Reverse the order of the tracked instance index `self.sorted`.
        )rb   rF   reverserH   r   r   r   reverse_order   s    
zStats.reverse_orderc                 C   s   | j D ]}| | qdS )zD
        Annotate all snapshots with class-based summaries.
        N)r-   annotate_snapshot)rH   r`   r   r   r   annotate   s    
zStats.annotater   )r`   r   c           	   	   C   s  |j dk	r|j S i |_ t| j D ]}d}d}tdd}| j| D ]L}t|j|| |||j7 }|j|jk rD|j	dks|j	|jkrD|d7 }qDz|d |j
 }W n tk
r   d}Y nX z|| }W n tk
r   d}Y nX t||||d|j |< ||j | d< q$|j S )z@
        Store additional statistical data in snapshot.
        Nr   r         Y@)sumavgpctactiver+   )classesr%   rD   rZ   r   r0   r.   r]   rd   re   totalZeroDivisionErrordict)	rH   r`   r[   r   r}   r+   ra   r|   r{   r   r   r   rw      s>    





zStats.annotate_snapshotc                 C   s   t t| j S )z?Return a list of all tracked classes occurring in any snapshot.)rF   r%   rD   rZ   ru   r   r   r   tracked_classes  s    zStats.tracked_classes)NNN)T)__name__
__module____qualname____doc__r   rM   r   rI   r
   bytesrG   boolrW   rb   rs   rv   rx   r   r   rw   propertyr   r   r   r   r   r   r   Q   s*      <'c                	   @   sf   e Zd ZdZdee eeeeedddd	Z	d
ddddZ
dee eddddZddddZdS )r   zK
    Presentation layer for `Stats` to be used in text-based consoles.
    r2   r   r   皙?N)r&   r   prefixr!   minsizeminpctr   c           	   	   C   s   t |}|jdd d |  |D ]x}|j|kr$|jd | |kr$| jdt|t|j dt	|jt
|jd | |f  | j|j||d |d d	 q$d
S )9
        Print individual referents recursively.
        c                 S   s   | j S Nr$   xr   r   r   <lambda>)      z*ConsoleStats._print_refs.<locals>.<lambda>rn   ry   z%-50s %-14s %3d%% [%d]
2   z  r   )r   r!   N)r%   rr   rt   r$   rA   writer   rM   r   r   rh   _print_refsr&   )	rH   r&   r   r   r!   r   r   lrefsr   r   r   r   r   "  s    zConsoleStats._print_refsr   )ra   r   c                 C   s   |j r0| jdt|jdddt|jdf  n,| jdt|jddd|jt|jdf  |jrt| jt|j |j	D ]6\}}| jdt
|t|jf  | |j|j qz|j dk	r| jd	t
|j f  dS )
zc
        Print the gathered information of object `tobj` in human-readable
        format.
        z%-32s ( free )   %-35s
    T)left#   z%-32s 0x%08x %-35s
z  %-30s %s
Nz  %-30s finalize
)re   rA   r   r   r   rf   idr1   r>   r-   r   r   r$   r   r&   )rH   ra   r.   r$   r   r   r   print_object6  s,     


 
zConsoleStats.print_object      ?)clsnamelimitr   c                    s   | j r| j   | js|   | j} r: fdd|D }|dk rZtdtt| j| }|dt| }|D ]}| | qndS )a  
        Write tracked objects to stdout.  The output can be filtered and
        pruned.  Only objects are printed whose classname contain the substring
        supplied by the `clsname` argument.  The output can be pruned by
        passing a `limit` value.

        :param clsname: Only print objects whose classname contain the given
            substring.
        :param limit: If `limit` is a float smaller than one, only the supplied
            percentage of the total tracked data is printed. If `limit` is
            bigger than one, this number of tracked objects are printed.
            Tracked objects are first filtered, and then pruned (if specified).
        c                    s   g | ]} |j kr|qS r   )r[   ).0tor   r   r   
<listcomp>i  s   
z,ConsoleStats.print_stats.<locals>.<listcomp>r   r   N)r?   rT   rF   rs   maxrh   lenr   )rH   r   r   Z_sortedra   r   r   r   print_statsQ  s    

zConsoleStats.print_statsrX   c                 C   s   | j }| j}|d | jD ]|}| |}|dt|jddt|jddf  |D ]B}|| }|dt|d|d t|d	 t|d
 |d f  qTq|d dS )z<
        Print per-class summary for each snapshot.
        zP---- SUMMARY ------------------------------------------------------------------
z%-35s %11s %12s %12s %5s
r   r}   Zaverager|   z  %-33s %11d %12s %12s %4d%%
!   rz   r{   zP-------------------------------------------------------------------------------
N)	r   rA   r   r-   rw   r   descr   asizeof_total)rH   	classlistfobjr`   r~   r[   infor   r   r   print_summaryv  s,    





zConsoleStats.print_summary)r2   r   r   r   )Nr   )r   r   r   r   r   r   rh   rM   floatr   r   r   r   r   r   r   r   r   r     s"         
   
%c                	   @   s   e Zd ZdZdZdZdZdZdZdZ	dZ
d	Zd.eee eeeeddddZdZdZeeddddZdZdZdZd/eee edddZd0eeddddZd1eeed d!d"Zd2eed#d$d%Zd3d&eed'd(d)Zd4eedd+d,d-ZdS )5r   zH
    Output the `ClassTracker` statistics as HTML pages and graphs.
    aL  <style type="text/css">
        table { width:100%; border:1px solid #000; border-spacing:0px; }
        td, th { border:0px; }
        div { width:200px; padding:10px; background-color:#FFEECC; }
        #nb { border:0px; }
        #tl { margin-top:5mm; margin-bottom:5mm; }
        #p1 { padding-left: 5px; }
        #p2 { padding-left: 50px; }
        #p3 { padding-left: 100px; }
        #p4 { padding-left: 150px; }
        #p5 { padding-left: 200px; }
        #p6 { padding-left: 210px; }
        #p7 { padding-left: 220px; }
        #hl { background-color:#FFFFCC; }
        #r1 { background-color:#BBBBBB; }
        #r2 { background-color:#CCCCCC; }
        #r3 { background-color:#DDDDDD; }
        #r4 { background-color:#EEEEEE; }
        #r5,#r6,#r7 { background-color:#FFFFFF; }
        #num { text-align:right; }
    </style>
    z<div color="#FFCCCC">Could not generate %s chart!
    Install <a href="http://matplotlib.sourceforge.net/">Matplotlib</a>
    to generate charts.</div>
z<img src="%s">
z-<html><head><title>%s</title>%s</head><body>
z<table border="1">
	</table>
z</body></html>
z<tr id="r%(level)d">
        <td id="p%(level)d">%(name)s</td>
        <td id="num">%(size)s</td>
        <td id="num">%(pct)3.1f%%</td></tr>r   r   r   N)r   r&   r   r!   r   r   r   c           
      C   s   t |}|jdd d |  |dkr2|d |D ]t}|j|kr6|jd | |kr6t|tt|jdt	|j|jd | d}	|| j
|	  | j||j||d d	 q6|dkr|d
 dS )r   c                 S   s   | j S r   r   r   r   r   r   r     r   z'HtmlStats._print_refs.<locals>.<lambda>rn   r   z<table>
ry      )r!   r   r$   r|   r"   r   N)r%   rr   rt   r   r$   r   r   rM   r   r   refrowr   r&   )
rH   r   r&   r   r!   r   r   r   r   datar   r   r   r     s     
zHtmlStats._print_refsz<p>%(cnt)d instances of %(cls)s were registered. The
        average size is %(avg)s, the minimal size is %(min)s, the maximum size
        is %(max)s.</p>
zV<h3>Snapshot: %(name)s, %(total)s occupied by instances
        of class %(cls)s</h3>
)r8   r[   r   c                 C   sn  t |d}|| j|| jf  |d|  dd | j| D }d}|D ]}||7 }qJt| j| |d}t|t| |d< tt||d< tt||d	< || j	|  || j
|  |d
 | jD ]h}|jr||jkr|j| d }	|| j|j|t|	jd  |	jr.| ||	j|	j q|d q|d | j| D ]}
|d |dd|
j|
jf   |
jr|dd|
j   |dt|
jt|
jf  |
jrdt|
j }|d|  |
jD ]j\}}|dt|  |js|dt|j  n0|dt|j  | ||j|j |d q|d qN|| j |  dS )z
        Print detailed statistics and instances for the class `classname`. All
        data will be written to the file `fname`.
        w<h1>%s</h1>
c                 S   s   g | ]}|  qS r   )r\   )r   ra   r   r   r   r     s     z1HtmlStats.print_class_details.<locals>.<listcomp>r   )cntclsr{   r   minz*<h2>Coalesced Referents per Snapshot</h2>
r+   )r   r   r   z'<p>No per-referent sizes recorded.</p>
z<h2>Instances</h2>
z*<table id="tl" width="100%" rules="rows">
z+<tr><td id="hl" width="140px">Instance</td>z#<td id="hl">%s at 0x%08x</td></tr>
z<tr><td>Representation</td>z<td>%s&nbsp;</td></tr>
z+<tr><td>Lifetime</td><td>%s - %s</td></tr>
z<pre>%s</pre>z+<tr><td>Instantiation</td><td>%s</td></tr>
z<tr><td>%s</td>z<td>%s</td></tr>
z<td>%s</td></tr>
r   N)rN   r   headerstylerD   r   r   r   r   class_summarychartsr-   r~   class_snapshotr   r$   r&   r   r   r   rf   r   rd   re   r1   r>   footerrQ   )rH   r8   r[   r   sizesr   sr   r`   r+   ra   r1   r.   r$   r   r   r   print_class_details  sn    







zHtmlStats.print_class_detailsz<tr>
        <th id="hl">Class</th>
        <th id="hl" align="right">Instance #</th>
        <th id="hl" align="right">Total</th>
        <th id="hl" align="right">Average size</th>
        <th id="hl" align="right">Share</th></tr>
z<tr>
        <td>%(cls)s</td>
        <td align="right">%(active)d</td>
        <td align="right">%(sum)s</td>
        <td align="right">%(avg)s</td>
        <td align="right">%(pct)3.2f%%</td></tr>
a4  <p>Total virtual memory assigned to the program
        at that time was %(sys)s, which includes %(overhead)s profiling
        overhead. The ClassTracker tracked %(tracked)s in total. The measurable
        objects including code objects but excluding overhead have a total size
        of %(asizeof)s.</p>
)filepathbasepathr   c                 C   sR   |dkr| j }|s|S ||r0|t|d }|rN|d tjkrN|dd }|S )z}
        Convert the filepath path to a relative path against basepath. By
        default basepath is self.basedir.
        Nr   r   )basedir
startswithr   ossep)rH   r   r   r   r   r   relative_path0  s    
zHtmlStats.relative_pathr4   )r@   titler   c           
      C   s  t |d}|| j|| jf  |d|  |d || jd  |d |d t| j }|  | j	D ]F}|d |d |d	|j
pd
t|jf  i }t|jj|d< t|j|d< t|j|d< tt|dd|d< || j|  |jr|| j |D ]l}|jr|j|  }| | j| }	d|	|f |d< t|d |d< t|d |d< || j|  q|d |d |jr|| j|  |d qx|d || j |  dS )z(
        Output the title page.
        r   r   z'<h2>Memory distribution over time</h2>
r-   z<h2>Snapshots statistics</h2>
z<table id="nb">
z	<tr><td>
z<table id="tl" rules="rows">
z<h3>%s snapshot at %s</h3>
ZUntitledrB   ZtrackedZasizeofZoverheadr   z<a href="%s">%s</a>r   rz   r{   z</table>z
</td><td>
r   r   N)rN   r   r   r   r   r%   rD   rZ   rr   r-   r   r   r.   r   Zsystem_totalZvszrY   r   rg   snapshot_summarysnapshot_cls_headerr~   copyr   linkssnapshot_clsr   rQ   )
rH   r@   r   r   r   r`   r   r[   r   pathr   r   r   create_title_page@  sP    








zHtmlStats.create_title_page)r[   r@   r   c                 C   s"  z$ddl m}m}m}m}m}m} W n" tk
rF   tj	|d   Y S X g }	| j
| D ]*}
|	|
jdg |
jrV|	|
jdg qV|	  tdt|	D ]$}|	| d  |	|d  d 7  < qdd |	D }dd |	D }|  |d	 |d
 |d|  |||d || | jtj| S )z
        Create chart that depicts the lifetime of the instance registered with
        `classname`. The output is written to `filename`.
        r   )figurer   xlabelylabelplotsavefigz	 lifetimer   r#   c                 S   s   g | ]\}}|qS r   r   r   tcr   r   r   r     s     z3HtmlStats.create_lifetime_chart.<locals>.<listcomp>c                 S   s   g | ]\}}|qS r   r   r   r   r   r   r     s     zExecution time [s]z
Instance #z%s instanceso)pylabr   r   r   r   r   r   ImportErrorr   nopylab_msgrD   r(   rd   re   rr   ranger   	chart_tagr   r   basename)rH   r[   r@   r   r   r   r   r   r   r   ra   ir   yr   r   r   create_lifetime_chartu  s*    $"zHtmlStats.create_lifetime_chart)r@   r   c                    s  z8ddl m}m}m}m}m}m}m}m}	 ddl	m
}
 W n tk
rV   | jd  Y S X | j}dd | jD }dgt| j }g }g }|D ]  fdd| jD }|rt|d	kr fd
d| jD }dd t||D }|
|||\}}|||fd if |  |}q|  |d |d |d dd | jD }|||ddd dd | jD }|||ddd |D ]\}}||| qt|dd |	| | j| | S )zw
        Create chart that depicts the memory allocation over time apportioned
        to the tracked classes.
        r   )r   r   r   r   r   filllegendr   Nzmemory allocationc                 S   s   g | ]
}|j qS r   )r.   r   r`   r   r   r   r     s     z3HtmlStats.create_snapshot_chart.<locals>.<listcomp>g        c                    s$   g | ]}|j d k	r|j   d qS )Nr|   )r~   r   cnr   r   r     s    
      @c                    s,   g | ]$}|j d k	rt|j   d d qS )Nrz      )r~   r   r   fpr   r   r   r     s   
c                 S   s   g | ]\}}|| qS r   r   )r   ZsxZsyr   r   r   r     s     labelzSnapshot MemoryzExecution Time [s]zVirtual Memory [MiB]c                 S   s   g | ]}t |jd  qS r   )r   r   r   r   r   r   r     s   zr--ZTotal)r   c                 S   s   g | ]}t |jd  qS r   )r   rY   r   r   r   r   r     s   zb--zTracked total   )loc)r   r   r   r   r   r   r   r   r   Zmatplotlib.mlabmlabr   r   r   r-   r   r   zipZpoly_betweenr(   r   r   )rH   r@   r   r   r   r   r   r   r   r   r   r   timesr   Zpoly_labelsZpolysr|   szZxpZypr   rc   kwdsr   r   r   create_snapshot_chart  sL    (


zHtmlStats.create_snapshot_chartr   )r`   r@   r   c                 C   s  z,ddl m}m}m}m}m} ddl m} W n tk
rJ   | jd  Y S X |j	r\|j
dkr`dS g }	g }
t|j
 D ],\}}|d dkrv|	| |
|d	  qv|
d|j||
  |	dd
 |d|j  |dd |ddddg ||
|	d ||dd | j| | S )z
        Create a pie chart that depicts the distribution of the allocated
        memory for a given `snapshot`. The chart is saved to `filename`.
        r   )r   r   pieaxesr   )rz   Z	pie_chartNr4   r|   r   rz   ZOtherz!Snapshot (%s) Memory Distribution)   r   )Zfigsizer   g?)labelsr   )Zdpi)r   r   r   r   r   r   rz   r   r   rY   r~   r%   itemsr(   insertr   r   r   r   )rH   r`   r@   r   r   r   r   r   Z	pylab_sumr   Zsizelistkvr   r   r   create_pie_chart  s*    

zHtmlStats.create_pie_chartClassTracker Statistics)r8   r   r   c                 C   sp  t jt j|| _t j|d d | _t j| jsFt | j t j| j| _i | _	| 
  i | _t j| jd}| || jd< t| jttt| jD ].\}}t j| jd| }| ||| j|< qt| j D ]2}t j| j|ddd }| ||| j|< qt| j D ]8}t j| j|ddd	 }|| j	|< | || q$| j||d
 dS )zl
        Create HTML page `fname` and additional files in a directory derived
        from `fname`.
        r   _filesztimespace.pngr-   zfp%d.png.r<   z-lt.pngz.html)r   N)r   r   dirnameabspathr   splitextZfilesdirisdirmkdirr   rx   r   r6   r   r   r-   r%   r   r   r   rD   rZ   replacer   r   r   )rH   r8   r   fnr   idxr   r   r   r   create_html  s*    "
zHtmlStats.create_html)r   r   r   )N)r4   )r4   )r4   )r4   )r   ) r   r   r   r   r   r   r   r   ZtableheaderZtablefooterr   r   r   r   r   rh   r   r   r   r   rM   r   r   r   r   r   r   r   r   r   r   r  r   r   r   r   r     sD          @
52 )r   )&r   typingr   r   r   r   r   r   r   r	   r
   r   rO   rB   r   r   Zpympler.util.stringutilsr   r   r   Zpympler.asizeofr   Zclasstrackerr   r   r   __all__rM   r   rh   r'   r   r0   r>   objectr   r   r   r   r   r   r   <module>   s$   ,
 Mx