<s> """<STR_LIT>""" <EOL> from __future__ import with_statement <EOL> from spyderlib . qt . QtGui import ( QHBoxLayout , QWidget , QMessageBox , QVBoxLayout , <EOL> QLabel , QTreeWidget , QTreeWidgetItem , <EOL> QApplication , QBrush , QColor , QFont ) <EOL> from spyderlib . qt . QtCore import SIGNAL , QProcess , QByteArray , Qt , QTextCodec <EOL> locale_codec = QTextCodec . codecForLocale ( ) <EOL> from spyderlib . qt . compat import getopenfilename <EOL> import sys <EOL> import os <EOL> import os . path as osp <EOL> import time <EOL> import linecache <EOL> import inspect <EOL> import hashlib <EOL> from spyderlib . utils . qthelpers import create_toolbutton , get_icon <EOL> from spyderlib . utils import programs <EOL> from spyderlib . baseconfig import get_conf_path , get_translation <EOL> from spyderlib . widgets . texteditor import TextEditor <EOL> from spyderlib . widgets . comboboxes import PythonModulesComboBox <EOL> from spyderlib . widgets . externalshell import baseshell <EOL> try : <EOL> from spyderlib . py3compat import to_text_string , getcwd , pickle <EOL> except ImportError : <EOL> to_text_string = unicode <EOL> getcwd = os . getcwdu <EOL> import cPickle as pickle <EOL> _ = get_translation ( "<STR_LIT>" , dirname = "<STR_LIT>" ) <EOL> COL_NO = <NUM_LIT:0> <EOL> COL_HITS = <NUM_LIT:1> <EOL> COL_TIME = <NUM_LIT:2> <EOL> COL_PERHIT = <NUM_LIT:3> <EOL> COL_PERCENT = <NUM_LIT:4> <EOL> COL_LINE = <NUM_LIT:5> <EOL> COL_POS = <NUM_LIT:0> <EOL> CODE_NOT_RUN_COLOR = QBrush ( QColor . fromRgb ( <NUM_LIT> , <NUM_LIT> , <NUM_LIT> , <NUM_LIT:200> ) ) <EOL> WEBSITE_URL = '<STR_LIT>' <EOL> def is_lineprofiler_installed ( ) : <EOL> """<STR_LIT>""" <EOL> return ( programs . is_module_installed ( '<STR_LIT>' ) <EOL> and programs . find_program ( '<STR_LIT>' ) is not None ) <EOL> class LineProfilerWidget ( QWidget ) : <EOL> """<STR_LIT>""" <EOL> DATAPATH = get_conf_path ( '<STR_LIT>' ) <EOL> VERSION = '<STR_LIT>' <EOL> def __init__ ( self , parent ) : <EOL> QWidget . __init__ ( self , parent ) <EOL> self . setWindowTitle ( "<STR_LIT>" ) <EOL> self . output = None <EOL> self . error_output = None <EOL> self . use_colors = True <EOL> self . _last_wdir = None <EOL> self . _last_args = None <EOL> self . _last_pythonpath = None <EOL> self . filecombo = PythonModulesComboBox ( self ) <EOL> self . start_button = create_toolbutton ( <EOL> self , icon = get_icon ( '<STR_LIT>' ) , <EOL> text = _ ( "<STR_LIT>" ) , <EOL> tip = _ ( "<STR_LIT>" ) , <EOL> triggered = self . start , text_beside_icon = True ) <EOL> self . stop_button = create_toolbutton ( <EOL> self , <EOL> icon = get_icon ( '<STR_LIT>' ) , <EOL> text = _ ( "<STR_LIT>" ) , <EOL> tip = _ ( "<STR_LIT>" ) , <EOL> text_beside_icon = True ) <EOL> self . connect ( self . filecombo , SIGNAL ( '<STR_LIT>' ) , <EOL> self . start_button . setEnabled ) <EOL> browse_button = create_toolbutton ( <EOL> self , icon = get_icon ( '<STR_LIT>' ) , <EOL> tip = _ ( '<STR_LIT>' ) , <EOL> triggered = self . select_file ) <EOL> self . datelabel = QLabel ( ) <EOL> self . log_button = create_toolbutton ( <EOL> self , icon = get_icon ( '<STR_LIT>' ) , <EOL> text = _ ( "<STR_LIT>" ) , <EOL> text_beside_icon = True , <EOL> tip = _ ( "<STR_LIT>" ) , <EOL> triggered = self . show_log ) <EOL> self . datatree = LineProfilerDataTree ( self ) <EOL> self . collapse_button = create_toolbutton ( <EOL> self , <EOL> icon = get_icon ( '<STR_LIT>' ) , <EOL> triggered = lambda dD = - <NUM_LIT:1> : self . datatree . collapseAll ( ) , <EOL> tip = _ ( '<STR_LIT>' ) ) <EOL> self . expand_button = create_toolbutton ( <EOL> self , <EOL> icon = get_icon ( '<STR_LIT>' ) , <EOL> triggered = lambda dD = <NUM_LIT:1> : self . datatree . expandAll ( ) , <EOL> tip = _ ( '<STR_LIT>' ) ) <EOL> hlayout1 = QHBoxLayout ( ) <EOL> hlayout1 . addWidget ( self . filecombo ) <EOL> hlayout1 . addWidget ( browse_button ) <EOL> hlayout1 . addWidget ( self . start_button ) <EOL> hlayout1 . addWidget ( self . stop_button ) <EOL> hlayout2 = QHBoxLayout ( ) <EOL> hlayout2 . addWidget ( self . collapse_button ) <EOL> hlayout2 . addWidget ( self . expand_button ) <EOL> hlayout2 . addStretch ( ) <EOL> hlayout2 . addWidget ( self . datelabel ) <EOL> hlayout2 . addStretch ( ) <EOL> hlayout2 . addWidget ( self . log_button ) <EOL> layout = QVBoxLayout ( ) <EOL> layout . addLayout ( hlayout1 ) <EOL> layout . addLayout ( hlayout2 ) <EOL> layout . addWidget ( self . datatree ) <EOL> self . setLayout ( layout ) <EOL> self . process = None <EOL> self . set_running_state ( False ) <EOL> self . start_button . setEnabled ( False ) <EOL> if not is_lineprofiler_installed ( ) : <EOL> for widget in ( self . datatree , self . filecombo , self . log_button , <EOL> self . start_button , self . stop_button , browse_button , <EOL> self . collapse_button , self . expand_button ) : <EOL> widget . setDisabled ( True ) <EOL> text = _ ( <EOL> '<STR_LIT>' <EOL> ) % WEBSITE_URL <EOL> self . datelabel . setText ( text ) <EOL> self . datelabel . setOpenExternalLinks ( True ) <EOL> else : <EOL> pass <EOL> def analyze ( self , filename , wdir = None , args = None , pythonpath = None , <EOL> use_colors = True ) : <EOL> self . use_colors = use_colors <EOL> if not is_lineprofiler_installed ( ) : <EOL> return <EOL> self . kill_if_running ( ) <EOL> index = None <EOL> if index is None : <EOL> self . filecombo . addItem ( filename ) <EOL> self . filecombo . setCurrentIndex ( self . filecombo . count ( ) - <NUM_LIT:1> ) <EOL> else : <EOL> self . filecombo . setCurrentIndex ( self . filecombo . findText ( filename ) ) <EOL> self . filecombo . selected ( ) <EOL> if self . filecombo . is_valid ( ) : <EOL> if wdir is None : <EOL> wdir = osp . dirname ( filename ) <EOL> self . start ( wdir , args , pythonpath ) <EOL> def select_file ( self ) : <EOL> self . emit ( SIGNAL ( '<STR_LIT>' ) , False ) <EOL> filename , _selfilter = getopenfilename ( <EOL> self , _ ( "<STR_LIT>" ) , getcwd ( ) , <EOL> _ ( "<STR_LIT>" ) + "<STR_LIT>" ) <EOL> self . emit ( SIGNAL ( '<STR_LIT>' ) , False ) <EOL> if filename : <EOL> self . analyze ( filename ) <EOL> def show_log ( self ) : <EOL> if self . output : <EOL> TextEditor ( self . output , title = _ ( "<STR_LIT>" ) , <EOL> readonly = True , size = ( <NUM_LIT> , <NUM_LIT> ) ) . exec_ ( ) <EOL> def show_errorlog ( self ) : <EOL> if self . error_output : <EOL> TextEditor ( self . error_output , title = _ ( "<STR_LIT>" ) , <EOL> readonly = True , size = ( <NUM_LIT> , <NUM_LIT> ) ) . exec_ ( ) <EOL> def start ( self , wdir = None , args = None , pythonpath = None ) : <EOL> filename = to_text_string ( self . filecombo . currentText ( ) ) <EOL> if wdir is None : <EOL> wdir = self . _last_wdir <EOL> if wdir is None : <EOL> wdir = osp . basename ( filename ) <EOL> if args is None : <EOL> args = self . _last_args <EOL> if args is None : <EOL> args = [ ] <EOL> if pythonpath is None : <EOL> pythonpath = self . _last_pythonpath <EOL> self . _last_wdir = wdir <EOL> self . _last_args = args <EOL> self . _last_pythonpath = pythonpath <EOL> self . datelabel . setText ( _ ( '<STR_LIT>' ) ) <EOL> self . process = QProcess ( self ) <EOL> self . process . setProcessChannelMode ( QProcess . SeparateChannels ) <EOL> self . process . setWorkingDirectory ( wdir ) <EOL> self . connect ( self . process , SIGNAL ( "<STR_LIT>" ) , <EOL> self . read_output ) <EOL> self . connect ( self . process , SIGNAL ( "<STR_LIT>" ) , <EOL> lambda : self . read_output ( error = True ) ) <EOL> self . connect ( self . process , <EOL> SIGNAL ( "<STR_LIT>" ) , <EOL> self . finished ) <EOL> self . connect ( self . stop_button , SIGNAL ( "<STR_LIT>" ) , self . process . kill ) <EOL> if pythonpath is not None : <EOL> env = [ to_text_string ( _pth ) <EOL> for _pth in self . process . systemEnvironment ( ) ] <EOL> baseshell . add_pathlist_to_PYTHONPATH ( env , pythonpath ) <EOL> self . process . setEnvironment ( env ) <EOL> self . output = '<STR_LIT>' <EOL> self . error_output = '<STR_LIT>' <EOL> if os . name == '<STR_LIT>' : <EOL> filename = osp . normpath ( filename ) . replace ( os . sep , '<STR_LIT:/>' ) <EOL> p_args = [ '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT:">' + self . DATAPATH + '<STR_LIT:">' , <EOL> '<STR_LIT:">' + filename + '<STR_LIT:">' ] <EOL> if args : <EOL> p_args . extend ( programs . shell_split ( args ) ) <EOL> executable = programs . find_program ( '<STR_LIT>' ) <EOL> executable += '<STR_LIT:U+0020>' + '<STR_LIT:U+0020>' . join ( p_args ) <EOL> executable = executable . replace ( os . sep , '<STR_LIT:/>' ) <EOL> self . process . start ( executable ) <EOL> else : <EOL> p_args = [ '<STR_LIT>' , '<STR_LIT>' , self . DATAPATH , filename ] <EOL> if args : <EOL> p_args . extend ( programs . shell_split ( args ) ) <EOL> executable = '<STR_LIT>' <EOL> self . process . start ( executable , p_args ) <EOL> running = self . process . waitForStarted ( ) <EOL> self . set_running_state ( running ) <EOL> if not running : <EOL> QMessageBox . critical ( self , _ ( "<STR_LIT>" ) , <EOL> _ ( "<STR_LIT>" ) ) <EOL> def set_running_state ( self , state = True ) : <EOL> self . start_button . setEnabled ( not state ) <EOL> self . stop_button . setEnabled ( state ) <EOL> def read_output ( self , error = False ) : <EOL> if error : <EOL> self . process . setReadChannel ( QProcess . StandardError ) <EOL> else : <EOL> self . process . setReadChannel ( QProcess . StandardOutput ) <EOL> qba = QByteArray ( ) <EOL> while self . process . bytesAvailable ( ) : <EOL> if error : <EOL> qba += self . process . readAllStandardError ( ) <EOL> else : <EOL> qba += self . process . readAllStandardOutput ( ) <EOL> text = to_text_string ( locale_codec . toUnicode ( qba . data ( ) ) ) <EOL> if error : <EOL> self . error_output += text <EOL> else : <EOL> self . output += text <EOL> def finished ( self ) : <EOL> self . set_running_state ( False ) <EOL> self . show_errorlog ( ) <EOL> self . output = self . error_output + self . output <EOL> self . show_data ( justanalyzed = True ) <EOL> def kill_if_running ( self ) : <EOL> if self . process is not None : <EOL> if self . process . state ( ) == QProcess . Running : <EOL> self . process . kill ( ) <EOL> self . process . waitForFinished ( ) <EOL> def show_data ( self , justanalyzed = False ) : <EOL> if not justanalyzed : <EOL> self . output = None <EOL> self . log_button . setEnabled ( <EOL> self . output is not None and len ( self . output ) > <NUM_LIT:0> ) <EOL> self . kill_if_running ( ) <EOL> filename = to_text_string ( self . filecombo . currentText ( ) ) <EOL> if not filename : <EOL> return <EOL> self . datatree . load_data ( self . DATAPATH ) <EOL> self . datelabel . setText ( _ ( '<STR_LIT>' ) ) <EOL> QApplication . processEvents ( ) <EOL> self . datatree . show_tree ( ) <EOL> text_style = "<STR_LIT>" <EOL> date_text = text_style % time . strftime ( "<STR_LIT>" , <EOL> time . localtime ( ) ) <EOL> self . datelabel . setText ( date_text ) <EOL> class LineProfilerDataTree ( QTreeWidget ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , parent = None ) : <EOL> QTreeWidget . __init__ ( self , parent ) <EOL> self . header_list = [ <EOL> _ ( '<STR_LIT>' ) , _ ( '<STR_LIT>' ) , _ ( '<STR_LIT>' ) , _ ( '<STR_LIT>' ) , <EOL> _ ( '<STR_LIT>' ) , _ ( '<STR_LIT>' ) ] <EOL> self . stats = None <EOL> self . max_time = <NUM_LIT:0> <EOL> self . header ( ) . setDefaultAlignment ( Qt . AlignCenter ) <EOL> self . setColumnCount ( len ( self . header_list ) ) <EOL> self . setHeaderLabels ( self . header_list ) <EOL> self . clear ( ) <EOL> self . connect ( self , SIGNAL ( '<STR_LIT>' ) , <EOL> self . item_activated ) <EOL> def show_tree ( self ) : <EOL> """<STR_LIT>""" <EOL> self . clear ( ) <EOL> self . setItemsExpandable ( True ) <EOL> self . setSortingEnabled ( False ) <EOL> self . populate_tree ( ) <EOL> self . expandAll ( ) <EOL> for col in range ( self . columnCount ( ) - <NUM_LIT:1> ) : <EOL> self . resizeColumnToContents ( col ) <EOL> self . collapseAll ( ) <EOL> self . setSortingEnabled ( True ) <EOL> self . sortItems ( COL_POS , Qt . AscendingOrder ) <EOL> def load_data ( self , profdatafile ) : <EOL> """<STR_LIT>""" <EOL> with open ( profdatafile , '<STR_LIT:rb>' ) as fid : <EOL> lstats = pickle . load ( fid ) <EOL> self . stats = dict ( ) <EOL> linecache . checkcache ( ) <EOL> for func_info , stats in lstats . timings . items ( ) : <EOL> filename , start_line_no = func_info [ : <NUM_LIT:2> ] <EOL> start_line_no -= <NUM_LIT:1> <EOL> all_lines = linecache . getlines ( filename ) <EOL> block_lines = inspect . getblock ( all_lines [ start_line_no : ] ) <EOL> func_stats = [ ] <EOL> func_total_time = <NUM_LIT:0.0> <EOL> next_stat_line = <NUM_LIT:0> <EOL> for line_no , code_line in enumerate ( block_lines ) : <EOL> line_no += start_line_no + <NUM_LIT:1> <EOL> code_line = code_line . rstrip ( '<STR_LIT:\n>' ) <EOL> if ( next_stat_line >= len ( stats ) <EOL> or line_no != stats [ next_stat_line ] [ <NUM_LIT:0> ] ) : <EOL> hits , line_total_time , time_per_hit = None , None , None <EOL> else : <EOL> hits , line_total_time = stats [ next_stat_line ] [ <NUM_LIT:1> : ] <EOL> line_total_time *= lstats . unit <EOL> time_per_hit = line_total_time / hits <EOL> func_total_time += line_total_time <EOL> next_stat_line += <NUM_LIT:1> <EOL> func_stats . append ( <EOL> [ line_no , code_line , line_total_time , time_per_hit , <EOL> hits ] ) <EOL> for line in func_stats : <EOL> line_total_time = line [ <NUM_LIT:2> ] <EOL> if line_total_time is None : <EOL> line . append ( None ) <EOL> else : <EOL> line . append ( line_total_time / func_total_time ) <EOL> self . stats [ func_info ] = [ func_stats , func_total_time ] <EOL> def fill_item ( self , item , filename , line_no , code , time , percent , perhit , <EOL> hits ) : <EOL> item . setData ( COL_POS , Qt . UserRole , ( osp . normpath ( filename ) , line_no ) ) <EOL> item . setData ( COL_NO , Qt . DisplayRole , line_no ) <EOL> item . setData ( COL_LINE , Qt . DisplayRole , code ) <EOL> if percent is None : <EOL> percent = '<STR_LIT>' <EOL> else : <EOL> percent = '<STR_LIT>' % ( <NUM_LIT:100> * percent ) <EOL> item . setData ( COL_PERCENT , Qt . DisplayRole , percent ) <EOL> item . setTextAlignment ( COL_PERCENT , Qt . AlignCenter ) <EOL> if time is None : <EOL> time = '<STR_LIT>' <EOL> else : <EOL> time = '<STR_LIT>' % ( time * <NUM_LIT> ) <EOL> item . setData ( COL_TIME , Qt . DisplayRole , time ) <EOL> item . setTextAlignment ( COL_TIME , Qt . AlignCenter ) <EOL> if perhit is None : <EOL> perhit = '<STR_LIT>' <EOL> else : <EOL> perhit = '<STR_LIT>' % ( perhit * <NUM_LIT> ) <EOL> item . setData ( COL_PERHIT , Qt . DisplayRole , perhit ) <EOL> item . setTextAlignment ( COL_PERHIT , Qt . AlignCenter ) <EOL> if hits is None : <EOL> hits = '<STR_LIT>' <EOL> else : <EOL> hits = '<STR_LIT>' % hits <EOL> item . setData ( COL_HITS , Qt . DisplayRole , hits ) <EOL> item . setTextAlignment ( COL_HITS , Qt . AlignCenter ) <EOL> def populate_tree ( self ) : <EOL> """<STR_LIT>""" <EOL> if not self . stats : <EOL> warn_item = QTreeWidgetItem ( self ) <EOL> warn_item . setData ( <EOL> <NUM_LIT:0> , Qt . DisplayRole , <EOL> _ ( '<STR_LIT>' <EOL> '<STR_LIT>' ) <EOL> . format ( url = WEBSITE_URL ) ) <EOL> warn_item . setFirstColumnSpanned ( True ) <EOL> warn_item . setTextAlignment ( <NUM_LIT:0> , Qt . AlignCenter ) <EOL> font = warn_item . font ( <NUM_LIT:0> ) <EOL> font . setStyle ( QFont . StyleItalic ) <EOL> warn_item . setFont ( <NUM_LIT:0> , font ) <EOL> return <EOL> try : <EOL> monospace_font = self . window ( ) . editor . get_plugin_font ( ) <EOL> except AttributeError : <EOL> monospace_font = QFont ( "<STR_LIT>" ) <EOL> monospace_font . setPointSize ( <NUM_LIT:10> ) <EOL> for func_info , func_data in self . stats . items ( ) : <EOL> filename , start_line_no , func_name = func_info <EOL> func_stats , func_total_time = func_data <EOL> func_item = QTreeWidgetItem ( self ) <EOL> func_item . setData ( <EOL> <NUM_LIT:0> , Qt . DisplayRole , <EOL> _ ( '<STR_LIT>' <EOL> '<STR_LIT>' ) . format ( <EOL> filename = filename , <EOL> line_no = start_line_no , <EOL> func_name = func_name , <EOL> time_ms = func_total_time * <NUM_LIT> ) ) <EOL> func_item . setFirstColumnSpanned ( True ) <EOL> func_item . setData ( COL_POS , Qt . UserRole , <EOL> ( osp . normpath ( filename ) , start_line_no ) ) <EOL> func_item . setData ( COL_TIME , Qt . DisplayRole , func_total_time * <NUM_LIT> ) <EOL> func_item . setData ( COL_PERCENT , Qt . DisplayRole , <EOL> func_total_time * <NUM_LIT> ) <EOL> if self . parent ( ) . use_colors : <EOL> md5 = hashlib . md5 ( ( filename + func_name ) . encode ( "<STR_LIT:utf8>" ) ) . hexdigest ( ) <EOL> hue = ( int ( md5 [ : <NUM_LIT:2> ] , <NUM_LIT:16> ) - <NUM_LIT> ) % <NUM_LIT> <EOL> func_color = QColor . fromHsv ( hue , <NUM_LIT:200> , <NUM_LIT:255> ) <EOL> else : <EOL> func_color = QColor . fromRgb ( <NUM_LIT:255> , <NUM_LIT:0> , <NUM_LIT:0> ) <EOL> for line_info in func_stats : <EOL> line_item = QTreeWidgetItem ( func_item ) <EOL> ( line_no , code_line , line_total_time , time_per_hit , <EOL> hits , percent ) = line_info <EOL> self . fill_item ( <EOL> line_item , filename , line_no , code_line , <EOL> line_total_time , percent , time_per_hit , hits ) <EOL> if line_total_time is not None : <EOL> alpha = percent <EOL> color = QColor ( func_color ) <EOL> color . setAlphaF ( alpha ) <EOL> color = QBrush ( color ) <EOL> for col in range ( self . columnCount ( ) ) : <EOL> line_item . setBackground ( col , color ) <EOL> else : <EOL> for col in range ( self . columnCount ( ) ) : <EOL> line_item . setForeground ( col , CODE_NOT_RUN_COLOR ) <EOL> line_item . setFont ( COL_LINE , monospace_font ) <EOL> def item_activated ( self , item ) : <EOL> filename , line_no = item . data ( COL_POS , Qt . UserRole ) <EOL> self . parent ( ) . emit ( SIGNAL ( "<STR_LIT>" ) , <EOL> filename , line_no , '<STR_LIT>' ) <EOL> def test ( ) : <EOL> """<STR_LIT>""" <EOL> from spyderlib . utils . qthelpers import qapplication <EOL> app = qapplication ( ) <EOL> widget = LineProfilerWidget ( None ) <EOL> widget . resize ( <NUM_LIT> , <NUM_LIT> ) <EOL> widget . show ( ) <EOL> widget . analyze ( osp . normpath ( osp . join ( osp . dirname ( __file__ ) , os . pardir , <EOL> '<STR_LIT>' ) ) , <EOL> use_colors = True ) <EOL> sys . exit ( app . exec_ ( ) ) <EOL> if __name__ == '<STR_LIT:__main__>' : <EOL> test ( ) </s>
