U
    祡c;                     @   sf  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 G dd de	Z
G dd	 d	e	ZG d
d deZG dd deZG dd deZzPejdk rddlmZ nddlmZ G dd dejZG dd dejejZW n ek
r   dZY nX dd ZG dd deZg ZdZedD ]ZegZ e!e  q"dd Z"dd  Z#d!d" Z$e%d#krbe$  dS )$a>  Tree-like exploration of object referrers.

This module provides a base implementation for tree-like referrers browsing.
The two non-interactive classes ConsoleBrowser and FileBrowser output a tree
to the console or a file. One graphical user interface for referrers browsing
is provided as well. Further types can be subclassed.

All types share a similar initialisation. That is, you provide a root object
and may specify further settings such as the initial depth of the tree or an
output function.
Afterwards you can print the tree which will be arranged based on your previous
settings.

The interactive browser is based on a TreeWidget implemented in IDLE. It is
available only if you have Tcl/Tk installed. If you try to instantiate the
interactive browser without having Tkinter installed, an ImportError will be
raised.

    N)muppy)summary)tkinterc                   @   s"   e Zd ZdZdddZdd ZdS )_Nodea  A node as it is used in the tree structure.

    Each node contains the object it represents and a list of children.
    Children can be other nodes or arbitrary other objects. Any object
    in a tree which is not of the type _Node is considered a leaf.

    Nc                 C   s   || _ g | _|| _dS )a!  You have to define the object this node represents. Also you can
        define an output function which will be used to represent this node.
        If no function is defined, the default str representation is used.

        keyword arguments
        str_func -- output function

        N)ochildrenstr_func)selfr   r    r
   6/tmp/pip-unpacked-wheel-8ad_c8mj/pympler/refbrowser.py__init__&   s    	z_Node.__init__c                 C   s$   | j dk	r|  | jS t| jS dS )z,Override str(self.o) if str_func is defined.N)r   r   strr	   r
   r
   r   __str__3   s    
z_Node.__str__)N)__name__
__module____qualname____doc__r   r   r
   r
   r
   r   r      s   
r   c                   @   s4   e Zd ZdZdejddfddZdd Zd	d
 ZdS )
RefBrowserzBase class to other RefBrowser implementations.

    This base class provides means to extract a tree from a given root object
    and holds information on already known objects (to avoid repetition
    if requested).

       TNc                 C   s>   || _ || _|| _|| _|| _g | _t | _| j| j dS )a  You have to provide the root object used in the refbrowser.

        keyword arguments
        maxdepth -- maximum depth of the initial tree
        str_func -- function used when calling str(node)
        repeat -- should nodes appear repeatedly in the tree, or should be
                  referred to existing nodes
        stream -- output stream (used in derived classes)

        N)	rootmaxdepthr   repeatstreamignoresetalready_includedappend)r	   
rootobjectr   r   r   r   r
   r
   r   r   D   s    zRefBrowser.__init__c                 C   s    | j t  | | j| jS )z+Get a tree of referrers of the root object.)r   r   inspectcurrentframe	_get_treer   r   r   r
   r
   r   get_tree\   s    zRefBrowser.get_treec                 C   s   t |}t|| j}| jt| |dkr2|S | jt	
  | j| |D ]}t|trztdd t |D rzqRt|}| js|| jkr| |}|jd||f  qRt|tsR|| jkrR|j| ||d  qR|S )a`  Workhorse of the get_tree implementation.

        This is a recursive method which is why we have a wrapper method.
        root is the current root object of the tree which should be returned.
        Note that root is not of the type _Node.
        maxdepth defines how much further down the from the root the tree
        should be build.

        r   c                 s   s   | ]}t |ttfV  qd S N)
isinstancer   r   ).0refr
   r
   r   	<genexpr>u   s   z'RefBrowser._get_tree.<locals>.<genexpr>z%s (already included, id %s)   )gcZget_referrersr   r   r   addidr   r   r   r    r$   dictanyr   r   r!   )r	   r   r   Zobjectsresr   Z_idsr
   r
   r   r!   a   s.    



zRefBrowser._get_tree)	r   r   r   r   r   _reprr   r"   r!   r
   r
   r
   r   r   ;   s    
r   c                   @   s2   e Zd ZdZdZdZdZdZdddZd	d
 Z	dS )StreamBrowserzRefBrowser implementation which prints the tree to the console.

    If you don't like the looks, you can change it a little bit.
    The class attributes 'hline', 'vline', 'cross', and 'space' can be
    modified to your needs.

    -|+ Nc                 C   s"   |dkr|   }| |dd dS )z Print referrers tree to console.

        keyword arguments
        tree -- if not None, the passed tree will be printed. Otherwise it is
        based on the rootobject.

        N )r"   _print)r	   treer
   r
   r   
print_tree   s    zStreamBrowser.print_treec                 C   s  | | j| | j }d}t|tr0t|j}|t|7 }|| jtt| 7 }|| j	ksnt|trn|dkr| j
|d  dS || j7 }|| j7 }t|jdkr|| j7 }|| j7 }|| j7 }|| j7 }|dkr| |jd || td|D ]}|dd | j | j }||d kr4|dd d| j  }| |j| || ||d krt|ddkrn dS | j
|dd  d  qdS )a  Compute and print a new line of the tree.

        This is a recursive function.

        arguments
        tree -- tree to print
        prefix -- prefix to the current line to print
        carryon -- prefix which is used to carry on the vertical lines

        r   
Nr(      r5   )countcrossvliner$   r   lenr   r   spacer   r   writehliner7   rangestriprstrip)r	   r8   prefixZcarryonlevelZlen_childrenbr
   r
   r   r7      s:    








zStreamBrowser._print)N)
r   r   r   r   rC   r?   r>   rA   r9   r7   r
   r
   r
   r   r1      s   
r1   c                       s    e Zd ZdZ fddZ  ZS )ConsoleBrowserz/RefBrowser that prints to the console (stdout).c                    s$   t t| j|| | js tj| _d S r#   )superrJ   r   r   sysstdout)r	   argskwargs	__class__r
   r   r      s    zConsoleBrowser.__init__)r   r   r   r   r   __classcell__r
   r
   rP   r   rJ      s   rJ   c                       s"   e Zd ZdZd fdd	Z  ZS )FileBrowserz:RefBrowser implementation which prints the tree to a file.Nc                    s@   | j }t|d| _ ztt| j|d W 5 | j   || _ X dS )z Print referrers tree to file (in text format).

        keyword arguments
        tree -- if not None, the passed tree will be printed.

        wr8   N)r   opencloserK   rS   r9   )r	   filenamer8   Z
old_streamrP   r
   r   r9      s    
zFileBrowser.print_tree)N)r   r   r   r   r9   rR   r
   r
   rP   r   rS      s   rS   )r      r<   )
TreeWidgetrU   c                   @   s(   e Zd ZdZdd Zdd Zdd ZdS )		_TreeNodezTreeNode used by the InteractiveBrowser.

        Not to be confused with _Node. This one is used in the GUI
        context.

        c                 C   s8   | j j| j jjd| j _| j   |   |   dS )z(Reload all referrers for this _TreeNode.r(   N)itemreftreer!   noder   _clear_childrenexpandupdater   r
   r
   r   reload_referrers  s    
z_TreeNode.reload_referrersc                 C   s   t | jjj dS )z8Print object which this _TreeNode represents to console.N)printr\   r^   r   r   r
   r
   r   print_object  s    z_TreeNode.print_objectc                    s   t j|  tj| jdd  jd| jd  jd| jd  	   jd| j
d  	   jdd  fd	d
}| jd| ddd}ddd}ddd}dS )z|Override drawtext from _TreeWidget.TreeNode.

            This seems to be a good place to add the popup menu.

            r   )Ztearoffzreload referrers)labelcommandrc   r`   zClose Popup Menu)re   c                    s     | j| j d S r#   )postZx_rootZy_root)eventmenur
   r   do_popup  s    z$_TreeNode.drawtext.<locals>.do_popupz
<Button-3>Nc                 S   s   d S r#   r
   r	   rh   r
   r
   r   edit%  s    z _TreeNode.drawtext.<locals>.editc                 S   s   d S r#   r
   rl   r
   r
   r   edit_finish(  s    z'_TreeNode.drawtext.<locals>.edit_finishc                 S   s   d S r#   r
   rl   r
   r
   r   edit_cancel+  s    z'_TreeNode.drawtext.<locals>.edit_cancel)N)N)N)_TreeWidgetTreeNodedrawtextr   ZMenucanvasZadd_commandrb   rd   Zadd_separatorr`   re   bind)r	   rk   rm   rn   ro   r
   ri   r   rr     s    

z_TreeNode.drawtextN)r   r   r   r   rb   rd   rr   r
   r
   r
   r   r[      s   r[   c                   @   s@   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d Zdd Z	dS )_ReferrerTreeItemz&Tree item wrapper around _Node object.c                 C   s0   t j|  tj| | || _|| _|| _dS )zYou need to provide the parent window, the node this TreeItem
            represents, as well as the tree (_Node) which the node
            belongs to.

            N)rp   TreeItemr   r   Labelr^   parentwindowr]   )r	   rx   r^   r]   r
   r
   r   r   1  s
    z_ReferrerTreeItem.__init__c                 C   s2   g }| j jD ]}t|ts|| q|| j _dS )zClear children list from any TreeNode instances.

            Normally these objects are not required for memory profiling, as
            they are part of the profiler.

            N)r^   r   r$   r[   r   )r	   Znew_childrenchildr
   r
   r   r_   =  s
    
z!_ReferrerTreeItem._clear_childrenc                 C   s
   t | jS r#   )r   r^   r   r
   r
   r   GetTextJ  s    z_ReferrerTreeItem.GetTextc                 C   s   |   sdS dS )z_Different icon when object cannot be expanded, i.e. has no
            referrers.

            pythonN)IsExpandabler   r
   r
   r   GetIconNameM  s    z_ReferrerTreeItem.GetIconNamec                 C   s6   t | jtsdS t| jjdkr$dS t| jjS dS )zqAn object is expandable when it is a node which has children and
            is a container object.

            Fr   TN)r$   r^   r   r@   r   r   _is_containerobjectr   r   r
   r
   r   r|   U  s
    z_ReferrerTreeItem.IsExpandablec                 C   sr   g }| j j}t|dkrJt| j jrJ| j| j jd| _ |   | j j}|D ]}t	| j
|| j}|| qN|S )zThis method is the point where further referrers are computed.

            Thus, the computation is done on-demand and only when needed.

            r   r(   )r^   r   r@   r   r~   r   r]   r!   r_   ru   rx   r   )r	   Zsublistr   ry   r\   r
   r
   r   
GetSubListb  s    z_ReferrerTreeItem.GetSubListN)
r   r   r   r   r   r_   rz   r}   r|   r   r
   r
   r
   r   ru   .  s   ru   c                 C   s   t | dt|   S )z,Default str function for InteractiveBrowser.z(id=%s))r   r0   r+   r   r
   r
   r   gui_default_str_function{  s    r   c                   @   s*   e Zd ZdZdedfddZd
ddZd	S )InteractiveBrowsera!  Interactive referrers browser.

    The interactive browser is based on a TreeWidget implemented in IDLE. It is
    available only if you have Tcl/Tk installed. If you try to instantiate the
    interactive browser without having Tkinter installed, an ImportError will
    be raised.

    r   Tc                 C   s&   t dkrtdt| |||| dS )aG  You have to provide the root object used in the refbrowser.

        keyword arguments
        maxdepth -- maximum depth of the initial tree
        str_func -- function used when calling str(node)
        repeat -- should nodes appear repeatedly in the tree, or should be
                  referred to existing nodes

        Nz4InteractiveBrowser requires Tkinter to be installed.)r   ImportErrorr   r   )r	   r   r   r   r   r
   r
   r   r     s
    zInteractiveBrowser.__init__Fc                 C   s`   t  }tj|dddd}|jjddd t||  | }t|j	d|}|
  |r\|  dS )zCreate interactive browser window.

        keyword arguments
        standalone -- Set to true, if the browser is not attached to other
        windows

        Zwhiter   r(   )bgZhighlightthicknessZ	takefocusZboth)r`   fillN)r   ZTkrp   ZScrolledCanvasframepackru   r"   r[   rs   r`   Zmainloop)r	   
standaloneZwindowZscr\   r^   r
   r
   r   main  s     zInteractiveBrowser.mainN)F)r   r   r   r   r   r   r   r
   r
   r
   r   r     s    
r   r   r   c                 C   s   t t| S r#   )r   typer   r
   r
   r   foo  s    r   c                  C   s   t ttd} |   d S )Nr   )rJ   r   r   r9   )cbr
   r
   r   print_sample  s    r   c                  C   s   t ttd} | d d S )Nr   z
sample.txt)rS   r   r   r9   )Zfbr
   r
   r   write_sample  s    r   __main__)&r   r)   r   rL   Zpymplerr   r   Zpympler.util.compatr   objectr   r   r1   rJ   rS   version_infoZidlelibrZ   rp   r8   rq   r[   rv   rw   ru   r   r   r   Z	superlistr   rD   itmpr   r   r   r   r   r
   r
   r
   r   <module>   s>   HM	
4I
-
