U
    祡c(                     @   sT   d Z ddlZddlZddlmZmZ ddlmZ G dd deZ	G dd deZ
dS )	a|  The tracker module allows you to track changes in the memory usage over
time.

Using the SummaryTracker, you can create summaries and compare them
with each other. Stored summaries can be ignored during comparison,
avoiding the observer effect.

The ObjectTracker allows to monitor object creation. You create objects from
one time and compare with objects from an earlier time.

    N)muppysummary)compatc                   @   sH   e Zd ZdZdddZdd Zddd	Zdd
dZdddZdd Z	dS )SummaryTrackerab   Helper class to track changes between two summaries taken.

    Detailed information on single objects will be lost, e.g. object size or
    object id. But often summaries are sufficient to monitor the memory usage
    over the lifetime of an application.

    On initialisation, a first summary is taken. Every time `diff` is called,
    a new summary will be created. Thus, a diff between the new and the last
    summary can be extracted.

    Be aware that filtering out previous summaries is time-intensive. You
    should therefore restrict yourself to the number of summaries you really
    need.

    Tc                 C   s    t t | _i | _|| _dS )aX  Constructor.

        The number of summaries managed by the tracker has a performance
        impact on new summaries, iff you decide to exclude them from further
        summaries. Therefore it is suggested to use them economically.

        Keyword arguments:
        ignore_self -- summaries managed by this object will be ignored.
        N)r   	summarizer   get_objectss0	summariesignore_self)selfr
    r   3/tmp/pip-unpacked-wheel-8ad_c8mj/pympler/tracker.py__init__#   s    
zSummaryTracker.__init__c                    s   | j stt }ng  i  fdd}|| j | j D ]\}}|| t|| q@tt }D ]"}tt	
|dkrpt|| qp D ].}tt	
|t| d krt|| q|S )zReturn a summary.

        See also the notes on ignore_self in the class as well as the
        initializer documentation.

        c                    s<     |  t| kr,t|   d7  < ndt| < d S )N   )appendid)oZall_of_themZref_counterr   r   
store_infoM   s    
z1SummaryTracker.create_summary.<locals>.store_info      )r
   r   r   r   r   r	   itemsZ	_traverselengcZget_referrersZ	_subtractr   )r   resr   kvZ_idr   r   r   r   create_summary1   s"    
zSummaryTracker.create_summaryNc                 C   sp   d}|dkrH|   | _|dkr0t| j| j}nt|| j}| j| _n|dk	r^t||}ntdt|S )a9  Compute diff between to summaries.

        If no summary is provided, the diff from the last to the current
        summary is used. If summary1 is provided the diff from summary1
        to the current summary is used. If summary1 and summary2 are
        provided, the diff between these two is used.

        Nz-You cannot provide summary2 without summary1.)r   s1r   get_diffr   
ValueErrorZ_sweep)r   summary1summary2r   r   r   r   diffi   s    	

zSummaryTracker.diffc                 C   s   t | j||d dS )aE  Compute diff between to summaries and print it.

        If no summary is provided, the diff from the last to the current
        summary is used. If summary1 is provided the diff from summary1
        to the current summary is used. If summary1 and summary2 are
        provided, the diff between these two is used.
        r!   r"   N)r   print_r#   r   r!   r"   r   r   r   
print_diff   s    zSummaryTracker.print_diffc                 C   s   t | j||dS )ae  Compute diff between to summaries and return a list of formatted
        lines.

        If no summary is provided, the diff from the last to the current
        summary is used. If summary1 is provided the diff from summary1
        to the current summary is used. If summary1 and summary2 are
        provided, the diff between these two is used.
        r$   )r   format_r#   r&   r   r   r   format_diff   s    	zSummaryTracker.format_diffc                 C   s   |   | j|< dS )z*Store a current summary in self.summaries.N)r   r	   )r   keyr   r   r   store_summary   s    zSummaryTracker.store_summary)T)NN)NN)NN)
__name__
__module____qualname____doc__r   r   r#   r'   r)   r+   r   r   r   r   r      s   
8



r   c                   @   s@   e Zd ZdZdd ZdddZdddZdd	d
ZdddZdS )ObjectTrackeraq  
    Helper class to track changes in the set of existing objects.

    Each time you invoke a diff with this tracker, the objects which existed
    during the last invocation are compared with the objects which exist during
    the current invocation.

    Please note that in order to do so, strong references to all objects will
    be stored. This means that none of these objects can be garbage collected.
    A use case for the ObjectTracker is the monitoring of a state which should
    be stable, but you see new objects being created nevertheless. With the
    ObjectTracker you can identify these new objects.

    c                 C   s   | j t fd| _dS )zOn initialisation, the current state of objects is stored.

        Note that all objects which exist at this point in time will not be
        released until you destroy this ObjectTracker instance.
        )ignoreN)_get_objectsinspectcurrentframeo0)r   r   r   r   r      s    zObjectTracker.__init__r   c                 C   s   ddd}t  }|t | ||f7 }t| dr<|| jf7 }t| drR|| jf7 }|||}g }|D ],}t|}|D ]}t 	|sv|
| qvqd|| t|}|dk	r|||}~|S )a>  Get all currently existing objects.

        XXX - ToDo: This method is a copy&paste from muppy.get_objects, but
        some modifications are applied. Specifically, it allows to ignore
        objects (which includes the current frame).

        keyword arguments
        ignore -- list of objects to ignore
        r   c                 S   s(   g }| D ]}t ||s|| q|S )N)r   Zobject_in_listr   )Zobjectsr1   r   r   r   r   r   remove_ignore   s
    z1ObjectTracker._get_objects.<locals>.remove_ignorer5   o1N)r   )r   r   r3   r4   hasattrr5   r7   r   Zget_referentsZ
is_trackedr   extendZ_remove_duplicates)r   r1   r6   tmpr   r   refsrefr   r   r   r2      s(    









zObjectTracker._get_objectsc                 C   s2   |  |t f | _t| j| j}| j| _|S )zGet the diff to the last time the  state of objects was measured.

        keyword arguments
        ignore -- list of objects to ignore
        )r2   r3   r4   r7   r   r   r5   )r   r1   r#   r   r   r   r      s    zObjectTracker.get_diffc                 C   s&   |  |t f D ]}t| qdS )zPrint the diff to the last time the state of objects was measured.

        keyword arguments
        ignore -- list of objects to ignore
        N)r)   r3   r4   print)r   r1   liner   r   r   r'      s    zObjectTracker.print_diffc                 C   sx   g }|  |t f }|d tt|d D ]}|| q6|d tt|d D ]}|| qd|S )zFormat the diff to the last time the state of objects was measured.

        keyword arguments
        ignore -- list of objects to ignore
        zAdded objects:+zRemoved objects:-)r   r3   r4   r   r   r(   r   )r   r1   linesr#   r>   r   r   r   r)      s    

zObjectTracker.format_diffN)r   )r   )r   )r   )	r,   r-   r.   r/   r   r2   r   r'   r)   r   r   r   r   r0      s   
-


r0   )r/   r   r3   Zpymplerr   r   Zpympler.utilr   objectr   r0   r   r   r   r   <module>   s    
