B
    nôb\t~  ã            
   @   sÎ  d Z ddlmZ ddlZddlmZ ddlmZ ddl	Z	ddl
Z
ddlZddlmZmZ ddlmZmZmZmZmZmZ ddlmZ ddlmZmZmZmZmZmZmZm Z  dd	l!m"Z"m#Z#m$Z$ dd
l%m&Z& ddl'm(Z) ddl*m+Z+m,Z,m-Z- ddl.m/Z/ ddl0m1Z1 ddl2m3Z3m4Z4 ddl5m6Z6 ye#ddƒZ7W n2 e8k
r` Z9 zddl:Z:e:j:Z7W ddZ9[9X Y nX e ;¡ Z<dd„ Z=G dd„ de ƒZ>dd„ Z?G dd„ deƒZ@G dd„ deƒZAdd„ ZBdd „ ZCeDd!krÊeCƒ  dS )"zu
Profiler widget

See the official documentation on python profiling:
https://docs.python.org/3/library/profile.html
é    )Úwith_statementN)Úislice)ÚgetopenfilenameÚgetsavefilename)Ú
QByteArrayÚQProcessÚQProcessEnvironmentÚ
QTextCodecÚQtÚSignal)ÚQColor)ÚQApplicationÚQHBoxLayoutÚQLabelÚQMessageBoxÚQTreeWidgetÚQTreeWidgetItemÚQVBoxLayoutÚQWidget)Úget_conf_pathÚget_translationÚdebug_print)Úto_text_string)Úicon_manager)Úcreate_toolbuttonÚget_item_user_textÚset_item_user_text)Úshell_split)ÚPythonModulesComboBox)Úadd_pathlist_to_PYTHONPATHÚgetcwd_or_home)Ú
TextEditorZprofilerZspyder_profilerc              C   s   ddl m}  | dƒo| dƒS )Nr   )Úis_module_installedÚcProfileÚpstats)Úspyder.utils.programsr"   )r"   © r&   úBlib/python3.7/site-packages/spyder_profiler/widgets/profilergui.pyÚis_profiler_installed7   s    r(   c               @   s¨   e Zd ZdZedƒZdZeeƒZ	d&dd„Z
dd„ Zd	d
„ Zdd„ Zd'dd„Zdd„ Zdd„ Zdd„ Zd(dd„Zdd„ Zd)dd„Zd*dd„Zd d!„ Zd"d#„ Zd+d$d%„ZdS ),ÚProfilerWidgetz
    Profiler widget
    zprofiler.resultsz0.0.1éd   c       
         sú  t  ˆ |¡ ˆ  d¡ d ˆ _d ˆ _d ˆ _d ˆ _d ˆ _tˆ ƒˆ _	t
ˆ t d¡tdƒtdƒ‡ fdd„ddˆ _t
ˆ t d	¡td
ƒtdƒddˆ _ˆ j	j ˆ jj¡ t
ˆ t d¡tdƒˆ jd}tƒ ˆ _t
ˆ t d¡tdƒdtdƒˆ jdˆ _tˆ ƒˆ _t
ˆ t d¡‡ fdd„tdƒdˆ _t
ˆ t d¡‡ fdd„tdƒdˆ _t
ˆ dtdƒt d¡ˆ jtdƒdˆ _t
ˆ dtdƒt d ¡ˆ jtd!ƒdˆ _t
ˆ dtd"ƒt d#¡ˆ j d$ˆ _!t"ƒ }| #ˆ j	¡ | #|¡ | #ˆ j¡ | #ˆ j¡ t"ƒ }| #ˆ j¡ | #ˆ j¡ | $¡  | #ˆ j¡ | $¡  | #ˆ j¡ | #ˆ j¡ | #ˆ j¡ | #ˆ j!¡ t%ƒ }| &|¡ | &|¡ | #ˆ j¡ ˆ  '|¡ d ˆ _(ˆ  )d%¡ ˆ j d%¡ ˆ j! d%¡ t*ƒ söx(ˆ jˆ j	ˆ jˆ jfD ]}| +d¡ qºW d&}d'td(ƒ|td)ƒf }	ˆ j ,|	¡ n d S )*NZProfilerÚrunZProfilezRun profilerc                  s   ˆ   ¡ S )N)Ústartr&   )Úselfr&   r'   Ú<lambda>U   s    z)ProfilerWidget.__init__.<locals>.<lambda>T)ÚiconÚtextÚtipÚ	triggeredÚtext_beside_iconÚstopZStopzStop current profiling)r/   r0   r1   r3   ZfileopenzSelect Python script)r/   r1   r2   ÚlogZOutputzShow program's output)r/   r0   r3   r1   r2   Zcollapsec                s   ˆ j  d¡S )Néÿÿÿÿ)ÚdatatreeÚchange_view)ÚdD)r-   r&   r'   r.   q   s    zCollapse one level up)r/   r2   r1   Úexpandc                s   ˆ j  d¡S )Né   )r7   r8   )r9   )r-   r&   r'   r.   v   s    zExpand one level downz	Save dataZfilesavezSave profiling data)r3   r0   r/   r2   r1   z	Load dataZ
fileimportz"Load profiling data for comparisonzClear comparisonZ
editdelete)r3   r0   r/   r2   Fz.https://docs.python.org/3/library/profile.htmlz%s <a href=%s>%s</a>zPlease installzthe Python profiler modules)-r   Ú__init__ZsetWindowTitleÚoutputÚerror_outputÚ
_last_wdirÚ
_last_argsÚ_last_pythonpathr   Ú	filecombor   Úimar/   Ú_Ústart_buttonÚstop_buttonZvalidÚconnectÚ
setEnabledÚselect_filer   Ú	datelabelÚshow_logÚ
log_buttonÚProfilerDataTreer7   Zcollapse_buttonZexpand_buttonÚ	save_dataZsave_buttonÚcompareZload_buttonÚclearÚclear_buttonr   Z	addWidgetZ
addStretchr   Z	addLayoutZ	setLayoutÚprocessÚset_running_stater(   ÚsetDisabledÚsetText)
r-   ÚparentZmax_entriesZbrowse_buttonZhlayout1Zhlayout2ZlayoutÚwidgetZurlr0   r&   )r-   r'   r<   D   s¨    















zProfilerWidget.__init__c             C   s8   t dƒ}t| |tƒ t dƒd ƒ\}}|r4| j |¡ dS )z	Save datazSave profiler resultzProfiler resultz (*.Result)N)rD   r   r    r7   rN   )r-   ÚtitleÚfilenameÚ
_selfilterr&   r&   r'   rN   ³   s    zProfilerWidget.save_datac             C   sH   t | tdƒtƒ tdƒd ƒ\}}|rD| j |¡ |  ¡  | j d¡ d S )NzSelect script to comparezProfiler resultz (*.Result)T)r   rD   r    r7   rO   Ú	show_datarQ   rH   )r-   rY   rZ   r&   r&   r'   rO   ¼   s    zProfilerWidget.comparec             C   s0   | j  d ¡ | j  d¡ |  ¡  | j d¡ d S )NTF)r7   rO   Úhide_diff_colsr[   rQ   rH   )r-   r&   r&   r'   rP   Å   s    zProfilerWidget.clearNc             C   sŽ   t ƒ s
d S |  ¡  d }|d krB| j |¡ | j | j ¡ d ¡ n| j | j |¡¡ | j ¡  | j ¡ rŠ|d kr|t	 
|¡}|  |||¡ d S )Nr;   )r(   Úkill_if_runningrB   ZaddItemZsetCurrentIndexÚcountZfindTextZselectedZis_validÚospÚdirnamer,   )r-   rY   ÚwdirÚargsÚ
pythonpathÚindexr&   r&   r'   ÚanalyzeË   s    


zProfilerWidget.analyzec             C   sJ   | j  d¡ t| tdƒtƒ tdƒd ƒ\}}| j  d¡ |rF|  |¡ d S )NFzSelect Python scriptzPython scriptsz (*.py ; *.pyw)T)Úredirect_stdioÚemitr   rD   r    re   )r-   rY   rZ   r&   r&   r'   rI   Ü   s    zProfilerWidget.select_filec             C   s$   | j r t| j tdƒddd ¡  d S )NzProfiler outputT)i¼  iô  )rX   ÚreadonlyÚsize)r=   r!   rD   Úexec_)r-   r&   r&   r'   rK   å   s    zProfilerWidget.show_logc             C   s$   | j r t| j tdƒddd ¡  d S )NzProfiler outputT)i¼  iô  )rX   rh   ri   )r>   r!   rD   rj   )r-   r&   r&   r'   Úshow_errorlogê   s    zProfilerWidget.show_errorlogc                s  t ˆ j ¡ ƒ}|d kr.ˆ j}|d kr.t |¡}|d krHˆ j}|d krHg }|d krVˆ j}|ˆ _|ˆ _|ˆ _ˆ j 	t
dƒ¡ tˆ ƒˆ _ˆ j tj¡ ˆ j |¡ ˆ jj ˆ j¡ ˆ jj ‡ fdd„¡ ˆ jj tjf‡ fdd„	¡ ˆ jj ˆ j¡ |d k	rTdd„ ˆ j ¡ D ƒ}t||ƒ tƒ }x*|D ]"}| d¡\}}	}
| ||
¡ q"W ˆ j |¡ dˆ _dˆ _ d	ˆ _!d
ddˆ j"g}t#j$dkrœ| %t &|¡ 't#j(d¡¡ n
| %|¡ |rº| )t*|ƒ¡ t+j,}| -d¡rÐd}ˆ j .||¡ ˆ j /¡ }ˆ  0|¡ |st1 2ˆ t
dƒt
dƒ¡ d S )NzProfiling, please wait...c                  s   ˆ j ddS )NT)Úerror)Úread_outputr&   )r-   r&   r'   r.     s    z&ProfilerWidget.start.<locals>.<lambda>c                s   ˆ   | |¡S )N)Úfinished)ZecZes)r-   r&   r'   r.     s    c             S   s   g | ]}t |ƒ‘qS r&   )r   )Ú.0Z_pthr&   r&   r'   ú
<listcomp>  s   z(ProfilerWidget.start.<locals>.<listcomp>ú=Ú Fz-mr#   z-oÚntú/z
spyder.exez
python.exeÚErrorzProcess failed to start)3r   rB   ÚcurrentTextr?   r_   Úbasenamer@   rA   rJ   rU   rD   r   rR   ZsetProcessChannelModeZSeparateChannelsZsetWorkingDirectoryZreadyReadStandardOutputrG   rm   ZreadyReadStandardErrorrn   Z
ExitStatusrF   ZclickedÚkillZsystemEnvironmentr   r   Ú	partitionÚinsertZsetProcessEnvironmentr=   r>   ÚstoppedÚDATAPATHÚosÚnameÚappendÚnormpathÚreplaceÚsepÚextendr   ÚsysÚ
executableÚendswithr,   ZwaitForStartedrS   r   Úcritical)r-   ra   rb   rc   rY   ÚenvZprocessEnvironmentZenvItemZenvNameZ	separatorZenvValueZp_argsr…   Zrunningr&   )r-   r'   r,   ï   sd    







zProfilerWidget.startc             C   s   | j  ¡  d| _dS )zStop button pressed.TN)rR   rx   r{   )r-   r&   r&   r'   rx   /  s    
zProfilerWidget.killTc             C   s   | j  | ¡ | j |¡ d S )N)rE   rH   rF   )r-   Ústater&   r&   r'   rS   4  s    z ProfilerWidget.set_running_stateFc             C   s’   |r| j  tj¡ n| j  tj¡ tƒ }x0| j  ¡ rX|rH|| j  ¡ 7 }q*|| j  ¡ 7 }q*W t	t
 | ¡ ¡ƒ}|r€|  j|7  _n|  j|7  _d S )N)rR   ZsetReadChannelr   ZStandardErrorZStandardOutputr   ZbytesAvailableZreadAllStandardErrorZreadAllStandardOutputr   Úlocale_codecZ	toUnicodeÚdatar>   r=   )r-   rl   Zqbar0   r&   r&   r'   rm   8  s    zProfilerWidget.read_outputc             C   s0   |   d¡ |  ¡  | j| j | _| jdd d S )NFT)Újustanalyzed)rS   rk   r>   r=   r[   )r-   Z	exit_codeZexit_statusr&   r&   r'   rn   I  s    
zProfilerWidget.finishedc             C   s2   | j d k	r.| j  ¡ tjkr.| j  ¡  | j  ¡  d S )N)rR   r‰   r   ZRunningrx   ZwaitForFinished)r-   r&   r&   r'   r]   Q  s    

zProfilerWidget.kill_if_runningc             C   sÄ   |s
d | _ | j | j d k	o&t| j ƒdk¡ |  ¡  t| j ¡ ƒ}|sHd S | jrl| j	 
tdƒ¡ | j ¡  d S | j	 
tdƒ¡ t ¡  | j | j¡ | j ¡  d}|t dt ¡ ¡ }| j	 
|¡ d S )Nr   zRun stopped by user.zSorting data, please wait...z.<span style='color: #444444'><b>%s </b></span>z%d %b %Y %H:%M)r=   rL   rH   Úlenr]   r   rB   rv   r{   rJ   rU   rD   r7   Úinitialize_viewr   ZprocessEventsÚ	load_datar|   Ú	show_treeÚtimeZstrftimeZ	localtime)r-   rŒ   rY   Z
text_styleZ	date_textr&   r&   r'   r[   W  s(    

zProfilerWidget.show_data)r*   )NNN)NNN)T)F)F)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r|   ZVERSIONr   Úboolrf   r<   rN   rO   rP   re   rI   rK   rk   r,   rx   rS   rm   rn   r]   r[   r&   r&   r&   r'   r)   <   s&   
o		
	
@

r)   c             C   s¶   d}t  || ¡}t|ƒdkr dS d}xŒ|D ]„}t|d ƒ}|d dkrP|d9 }nV|d dkrf|d	9 }n@|d d
kr||d9 }n*|d dkr’|d9 }n|d dkr¦|d9 }||7 }q*W |S )zºParse text and returns a time in seconds
    
    The text is of the format 0h : 0.min:0.0s:0 ms:0us:0 ns. 
    Spaces are not taken into account and any of the specifiers can be ignoredz ([+-]?\d+\.?\d*) ?([munsecinh]+)r   Ng        r;   Únsg•Ö&è.>Úusgíµ ÷Æ°>Zmsgü©ñÒMbP?Úminé<   Úhi  )ÚreÚfindallr   Úfloat)r0   ÚpatternZmatchesr‘   ZresZtmpr&   r&   r'   Ú	gettime_sq  s&    




r    c               @   s   e Zd Zddd„Zdd„ ZdS )ÚTreeWidgetItemNc             C   s   t  | |¡ d S )N)r   r<   )r-   rV   r&   r&   r'   r<   ‹  s    zTreeWidgetItem.__init__c             C   s–   |   ¡  ¡ }y`|dks|dkrRt|  |¡ƒ}t| |¡ƒ}|d k	rR|d k	rR||kS t|  |¡ƒt| |¡ƒkS  tk
r   |  |¡| |¡kS X d S )Nr;   é   )Z
treeWidgetZ
sortColumnr    r0   rž   Ú
ValueError)r-   Z	otherItemÚcolumnZt0Zt1r&   r&   r'   Ú__lt__Ž  s    zTreeWidgetItem.__lt__)N)r’   r“   r”   r<   r¥   r&   r&   r&   r'   r¡   Š  s   
r¡   c               @   sÊ   e Zd ZdZdZd0d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d„ Zdd„ Zdd„ Ze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.d/„ ZdS )1rM   a  
    Convenience tree widget (with built-in model) 
    to store and view profiler data.

    The quantities calculated by the profiler are as follows 
    (from profile.Profile):
    [0] = The number of times this function was called, not counting direct
          or indirect recursion,
    [1] = Number of times this function appears on the stack, minus one
    [2] = Total time spent internal to this function
    [3] = Cumulative time that this function was present on the stack.  In
          non-recursive functions, this is the total execution time from start
          to finish of each invocation of a function, including time spent in
          all subfunctions.
    [4] = A dictionary indicating for each function name, the number of times
          it was called by us.
    z<[=]>Nc          	   C   sØ   t  | |¡ tdƒtdƒtdƒtdƒtdƒtdƒtdƒtdƒg| _t d¡t d¡t d¡t d	¡d
œ| _d | _d | _d | _	d | _
d | _d | _d | _|  t| jƒ¡ |  | j¡ |  ¡  | j | j¡ | j | j¡ d S )NzFunction/Modulez
Total TimeZDiffz
Local TimeZCallsz	File:lineZpythonÚfunctionÚclass)Úmoduler¦   ÚbuiltinÚconstructor)r   r<   rD   Zheader_listrC   r/   Ú	icon_listÚprofdataÚstatsÚ
item_depthÚ	item_listÚitems_to_be_shownÚcurrent_view_depthÚcompare_fileZsetColumnCountr   ZsetHeaderLabelsrŽ   ZitemActivatedrG   Úitem_activatedZitemExpandedÚitem_expanded)r-   rV   r&   r&   r'   r<   ¯  s(    zProfilerDataTree.__init__c             C   s   t |d|| j|f ƒ dS )z@Set tree item user data: filename (string) and line_number (int)z%s%s%dN)r   ÚSEP)r-   ÚitemrY   Úline_numberr&   r&   r'   Úset_item_dataÅ  s    zProfilerDataTree.set_item_datac             C   s    t |ƒ | j¡\}}|t|ƒfS )z0Get tree item user data: (filename, line_number))r   Úsplitrµ   Úint)r-   r¶   rY   Zline_number_strr&   r&   r'   Úget_item_dataÉ  s    zProfilerDataTree.get_item_datac             C   s$   |   ¡  d| _g | _i | _d| _dS )z"Clean the tree and view parametersr   N)rP   r®   r¯   r°   r±   )r-   r&   r&   r'   rŽ   Î  s
    z ProfilerDataTree.initialize_viewc          
   C   sÜ   ddl }y| |¡g}W n ttfk
r0   dS X |d | _| jdk	r®y| | | j¡¡ W nP ttfk
r¬ } z.t | t	dƒt	dƒ¡ t
d |¡ƒ d| _W dd}~X Y nX tdd„ |ƒ | j ¡  || _|d j| _dS )z3Load profiler data saved by profile/cProfile moduler   Nru   z*Error when trying to load profiler resultszError when calling pstats, {}c             S   s   |   ¡ S )N)Úcalc_callees)Úxr&   r&   r'   r.   è  s    z,ProfilerDataTree.load_data.<locals>.<lambda>)r$   ZStatsÚOSErrorÚIOErrorr¬   r²   r   r   r‡   rD   r   ÚformatÚmapr¼   Ústats1r­   )r-   Zprofdatafiler$   Z
stats_indiÚer&   r&   r'   r   Ö  s&    



zProfilerDataTree.load_datac             C   s   |   d¡ || _d S )NF)r\   r²   )r-   rY   r&   r&   r'   rO   í  s    
zProfilerDataTree.comparec             C   s   xdD ]}|   ||¡ qW d S )N)é   é   é   )ZsetColumnHidden)r-   ZhideÚir&   r&   r'   r\   ñ  s    
zProfilerDataTree.hide_diff_colsc             C   s   | j d  |¡ dS )rr   r   N)rÂ   Z
dump_stats)r-   rY   r&   r&   r'   rN   õ  s    zProfilerDataTree.save_datac             C   sD   | j  d¡ x2| j jD ]&}d|dd… kr|d  d¡s|S qW dS )z Find a function without a callerZ
cumulative)ú~r   r   rÄ   z<built-in method exec>N)r¬   Z
sort_statsZfcn_listÚ
startswith)r-   Úfuncr&   r&   r'   Ú	find_rootù  s
    zProfilerDataTree.find_rootc             C   s   | j j| S )z/Find all functions called by (parent) function.)r¬   Zall_callees)r-   rV   r&   r&   r'   Úfind_callees  s    zProfilerDataTree.find_calleesc             C   sj   |   ¡  |  d¡ |  d¡ |  ¡ }|rf|  | |  |¡¡ |  d¡ |  d¡ |  dtj	¡ |  
d¡ dS )z4Populate the tree with profiler data and display it.TFr   r;   N)rŽ   ZsetItemsExpandableZsetSortingEnabledrË   Úpopulate_treerÌ   ZresizeColumnToContentsZ	sortItemsr
   ZAscendingOrderr8   )r-   Zrootkeyr&   r&   r'   r   	  s    



zProfilerDataTree.show_treec       	      C   s†   d}|\}}}|dkrJt  |¡\}}d}|dkr>t  |¡\}}d| d }|rV|dkr`d}d	}n|d
krld}d||f }|||||fS )zAReturns processed information about the function's name and file.r¦   z<module>r¨   z__init__.pyú<ú>rÈ   z
(built-in)r©   r<   rª   z%s : %d)r_   r¹   )	r-   ZfunctionKeyÚ	node_typerY   r·   Úfunction_nameZ
modulePathZ
moduleNameÚfile_and_liner&   r&   r'   Úfunction_info  s    
zProfilerDataTree.function_infoc             C   sH  t | ƒ} t| tƒrt| ƒS d|   k r.dkrDn nd | d ¡} n d|   k rXdkrln nd | d ¡} nØd|   k r€dkr”n nd | d ¡} n°d|   k r¨dkr¸n nd	 | ¡} nŒd|   k rÎd
krn nFt| d
ƒ\}}|dkr
t| dƒ\}}t|ƒ d¡d }d ||¡} n,t| d
ƒ\}}|dkr8|d }d ||¡} | S )z8Get format and units for data coming from profiler task.g•Ö&è.>gíµ ÷Æ°>z
{0:.2f} nsgü©ñÒMbP?z
{0:.2f} usr;   z
{0:.2f} msrš   z{0:.2f} seci  Ú.r6   z{0:.0f}.{1:.2s} minz{0:.0f}h:{1:.0f}min)ÚabsÚ
isinstancerº   r   rÀ   Údivmodr¹   )ZmeasureÚmÚsr›   r&   r&   r'   Úformat_measure)  s,    


zProfilerDataTree.format_measurec             C   sn   d}d}t |ƒdkrX| jdk	rX|d |d  }|rX|dk r>dnd\}}d	 ||  |¡¡}|  |d ¡||ggS )
a•  Return a string formatted delta for the values in x.

        Args:
            x: 2-item list of integers (representing number of calls) or
               2-item list of floats (representing seconds of runtime).

        Returns:
            A list with [formatted x[0], [color, formatted delta]], where
            color reflects whether x[1] is lower, greater, or the same as
            x[0].
        rr   ZblackrÄ   Nr   r;   )Zgreenú-)Zredú+z{}{})r   r²   rÀ   rÚ   )r-   r½   Zdiff_strZcolorÚ
differenceZsignr&   r&   r'   Úcolor_stringI  s    zProfilerDataTree.color_stringc                s,   ‡ fdd„| j D ƒ}t| jtt|Ž ddƒƒS )a    Formats the data.

        self.stats1 contains a list of one or two pstat.Stats() instances, with
        the first being the current run and the second, the saved run, if it
        exists.  Each Stats instance is a dictionary mapping a function to
        5 data points - cumulative calls, number of calls, total time,
        cumulative time, and callers.

        format_output() converts the number of calls, total time, and
        cumulative time to a string format for the child_key parameter.
        c          
      s$   g | ]}|j  ˆ d d d d i g¡‘qS )r   )r­   Úget)ro   r½   )Ú	child_keyr&   r'   rp   k  s    z2ProfilerDataTree.format_output.<locals>.<listcomp>r;   rÅ   )rÂ   rÁ   rÞ   r   Úzip)r-   rà   r‹   r&   )rà   r'   Úformat_output_  s    zProfilerDataTree.format_outputc             C   sv  xn|D ]d}|  j d7  _ |  |¡\}}}}}|  |¡\\}	}
\}}\}}t|ƒ}| j |¡ |  |||¡ | dtdƒ¡ | 	dt
j|¡ | d| j| ¡ | dtdƒ¡ | 	dt
j|¡ | dt
j¡ | 	dt
j|d ¡ | dt|d ƒ¡ | dt
j¡ | dtdƒ¡ | 	dt
j|¡ | dt
j¡ | 	dt
j|d ¡ | dt|d ƒ¡ | dt
j¡ | d	td
ƒ¡ | 	d	t
j|	¡ | d	t
j¡ | 	dt
j|
d ¡ | dt|
d ƒ¡ | dt
j¡ | dtdƒ¡ | 	dt
j|¡ |  |¡r| 	dt
jdtdƒ ¡ | d¡ nD|  |¡}| j dk r@|  ||¡ n |r`| |j¡ || jt|ƒ< |  j d8  _ qW dS )zGRecursive method to create each item (and associated data) in the tree.r;   r   zFunction or module namez*Time in function (including sub-functions)rÄ   r¢   z-Local time in function (not in sub-functions)rÅ   é   z+Total number of calls (including recursion)rÆ   é   z#File:line where function is definedz(%s)Z	recursionTN)r®   rÓ   râ   r¡   r¯   r   r¸   Z
setToolTiprD   ZsetDatar
   ÚDisplayRoleZsetIconr«   ZsetTextAlignmentZ
AlignRightZsetForegroundr   Z	AlignLeftÚis_recursiverT   rÌ   rÍ   ZsetChildIndicatorPolicyZShowIndicatorr°   Úid)r-   Z
parentItemZchildren_listrà   rY   r·   rÑ   rÒ   rÐ   Ztotal_callsZtotal_calls_difZloc_timeZloc_time_difZcum_timeZcum_time_difÚ
child_itemÚcalleesr&   r&   r'   rÍ   n  sP    
zProfilerDataTree.populate_treec             C   s&   |   |¡\}}|  ¡ j ||d¡ d S )Nrr   )r»   rV   Z	edit_gotorg   )r-   r¶   rY   r·   r&   r&   r'   r³   ®  s    zProfilerDataTree.item_activatedc             C   s8   |  ¡ dkr4t|ƒ| jkr4| jt|ƒ }|  ||¡ d S )Nr   )Ú
childCountrç   r°   rÍ   )r-   r¶   ré   r&   r&   r'   r´   ²  s    zProfilerDataTree.item_expandedc             C   sZ   |  ¡ }xL|rT| dtj¡| dtj¡krJ| dtj¡| dtj¡krJdS |  ¡ }q
W dS )z5Returns True is a function is a descendant of itself.r   rä   TF)rV   r‹   r
   rå   )r-   rè   Zancestorr&   r&   r'   ræ   ·  s    zProfilerDataTree.is_recursivec                s   ‡ fdd„t ˆ  ¡ ƒD ƒS )zIterate over top level itemsc                s   g | ]}ˆ   |¡‘qS r&   )ZtopLevelItem)ro   Z_i)r-   r&   r'   rp   Ç  s    z8ProfilerDataTree.get_top_level_items.<locals>.<listcomp>)ÚrangeZtopLevelItemCount)r-   r&   )r-   r'   Úget_top_level_itemsÅ  s    z$ProfilerDataTree.get_top_level_itemsc                sH   g ‰d‡ ‡fdd„	‰ x.|   ¡ D ]"}ˆ |¡ |dkrˆ ||d qW ˆS )z+Return all items with a level <= `maxlevel`r;   c                sJ   |d7 }x<t |  ¡ ƒD ],}|  |¡}ˆ |¡ ||krˆ |||ƒ qW d S )Nr;   )rë   rê   Zchildr   )r¶   ÚmaxlevelÚlevelrd   Zcitem)Úadd_to_itemlistÚitemlistr&   r'   rï   Ì  s    

z3ProfilerDataTree.get_items.<locals>.add_to_itemlistr   )rí   )r;   )rì   r   )r-   rí   Ztlitemr&   )rï   rð   r'   Ú	get_itemsÉ  s    
zProfilerDataTree.get_itemsc             C   sZ   |  j |7  _ | j dk rd| _ |  ¡  | j dkrVx$| j| j d dD ]}| d¡ qDW dS )zBChange the view depth by expand or collapsing all same-level nodesr   r;   )rí   TN)r±   ZcollapseAllrñ   ZsetExpanded)r-   Zchange_in_depthr¶   r&   r&   r'   r8   Ù  s    

zProfilerDataTree.change_view)N)r’   r“   r”   r•   rµ   r<   r¸   r»   rŽ   r   rO   r\   rN   rË   rÌ   r   rÓ   ÚstaticmethodrÚ   rÞ   râ   rÍ   r³   r´   ræ   rì   rñ   r8   r&   r&   r&   r'   rM   ›  s0   

 @rM   c             C   sÂ   | dkrdgS | dk rg S t td| d dƒƒ}| d }| d d d }d}d}x^||kr¬|| r–|| d d }d||< x||k r”d||< ||7 }qzW |d }d| d }qPW dgdd„ |D ƒ S )ze
    Simple test function
    Taken from http://www.huyng.com/posts/python-performance-analysis/
    rÄ   r¢   r;   g      à?r   c             S   s   g | ]}|r|‘qS r&   r&   )ro   r½   r&   r&   r'   rp   þ  s    zprimes.<locals>.<listcomp>)Úlistrë   )ÚnrÙ   ZmrootZhalfrÇ   rØ   Újr&   r&   r'   Úprimesç  s&    

rö   c        	   	   C   s²   ddl } ddl}ddlm} |  t¡}|jdd\}}t |d¡(}| 	d¡ | 	|d ¡ | 	d	¡ W dQ R X |d
d}t
dƒ}| dd¡ | ¡  | |¡ t | ¡ ¡ dS )zRun widget testr   N)Úqapplicationz.py)ÚsuffixÚwz# -*- coding: utf-8 -*-

z

zprimes(100000)rã   )Z	test_timei   iX  )ÚinspectÚtempfileÚspyder.utils.qthelpersr÷   Z	getsourcerö   Zmkstempr}   ÚfdopenÚwriter)   ZresizeZshowre   r„   Úexitrj   )	rú   rû   r÷   Z	primes_scÚfdZscriptÚfZapprW   r&   r&   r'   Útest  s    



r  Ú__main__)Er•   Z
__future__r   r}   Úos.pathÚpathr_   Ú	itertoolsr   r„   r‘   rœ   Zqtpy.compatr   r   Zqtpy.QtCorer   r   r   r	   r
   r   Z
qtpy.QtGuir   Zqtpy.QtWidgetsr   r   r   r   r   r   r   r   Zspyder.config.baser   r   r   Zspyder.py3compatr   Zspyder.utilsr   rC   rü   r   r   r   r%   r   Zspyder.widgets.comboboxesr   Zspyder.utils.miscr   r    Z*spyder.widgets.variableexplorer.texteditorr!   rD   ÚKeyErrorrl   ÚgettextZcodecForLocalerŠ   r(   r)   r    r¡   rM   rö   r  r’   r&   r&   r&   r'   Ú<module>   sL    (  7  N
