def run(self): self.ipython_shell = None from __main__ import __dict__ as glbs while True: if self.ipython_shell is None and '__ipythonshell__' in glbs: self.ipython_shell = glbs['__ipythonshell__'].IP glbs = self.ipython_shell.user_ns try: command = read_packet(self.request) result = eval(command, glbs, self.locals) self.locals["_"] = result output = pickle.dumps(result, pickle.HIGHEST_PROTOCOL) write_packet(self.request, output) except StandardError: out = StringIO.StringIO() traceback.print_exc(file=out) if DEBUG: from spyderlib.config import get_conf_path import time errors = open(get_conf_path('monitor_errors.txt'), 'a') print >>errors, "*"*5, time.ctime(time.time()), "*"*49 print >>errors, "command:", command print >>errors, "error:" traceback.print_exc(file=errors) print >>errors, " " data = out.getvalue() write_packet(self.request, data)
def save_session(filename): """Save Spyder session""" local_fname = get_conf_path(osp.basename(filename)) filename = osp.abspath(filename) old_cwd = os.getcwdu() os.chdir(get_conf_path()) error_message = None try: tar = tarfile.open(local_fname, "w") for fname in SAVED_CONFIG_FILES: if osp.isfile(fname): tar.add(fname) tar.close() shutil.move(local_fname, filename) except Exception, error: error_message = unicode(error)
def reset_session(): """Remove all config files""" print >>STDERR, "*** Reset Spyder settings to defaults ***" for fname in SAVED_CONFIG_FILES: cfg_fname = get_conf_path(fname) if osp.isfile(cfg_fname): os.remove(cfg_fname) print >>STDERR, "removing:", cfg_fname
def __init__(self, parent=None, namespace=None, commands=None, message="", font=None, debug=False, exitfunc=None, profile=False): PythonShellWidget.__init__(self, parent, get_conf_path('.history_ic.py'), debug, profile) if font is not None: self.set_font(font) # Capture all interactive input/output self.initial_stdout = sys.stdout self.initial_stderr = sys.stderr self.initial_stdin = sys.stdin self.stdout = IOHandler('<spyder_stdout>', 'w', write_func=self.write, flush_func=lambda: self.flush(error=False)) self.stderr = IOHandler('<spyder_stderr>', 'w', write_func=self.write_error, flush_func=lambda: self.flush(error=True)) self.stdin = IOHandler('<spyder_stdin>', 'r', read_func=self.wait_input) self.redirect_stds() # KeyboardInterrupt support self.interrupted = False self.connect(self, SIGNAL("keyboard_interrupt()"), self.keyboard_interrupt) # Code completion / calltips getcfg = lambda option: CONF.get('shell', option) case_sensitive = getcfg('autocompletion/case-sensitivity') show_single = getcfg('autocompletion/select-single') from_document = getcfg('autocompletion/from-document') self.setup_code_completion(case_sensitive, show_single, from_document) # keyboard events management self.busy = False self.eventqueue = [] # Execution Status self.more = False # Init interpreter self.exitfunc = exitfunc self.commands = commands self.message = message self.interpreter = None self.start_interpreter(namespace) # Clear status bar self.emit(SIGNAL("status(QString)"), QString())
def __init__(self, parent=None, wdir=None, history_filename=None, show_icontext=True): QWidget.__init__(self, parent) self.run_button = None self.kill_button = None self.options_button = None self.icontext_action = None if wdir is None: wdir = osp.dirname(osp.abspath(self.fname)) self.wdir = wdir if osp.isdir(wdir) else None self.arguments = "" self.shell = self.SHELL_CLASS(parent, get_conf_path(history_filename)) self.connect(self.shell, SIGNAL("execute(QString)"), self.send_to_process) self.connect(self.shell, SIGNAL("keyboard_interrupt()"), self.keyboard_interrupt) # Redirecting some SIGNALs: self.connect(self.shell, SIGNAL('redirect_stdio(bool)'), lambda state: self.emit(SIGNAL('redirect_stdio(bool)'), state)) self.state_label = QLabel() self.time_label = QLabel() hlayout = QHBoxLayout() hlayout.addWidget(self.state_label) hlayout.addStretch(0) hlayout.addWidget(self.time_label) hlayout.addStretch(0) for button in self.get_toolbar_buttons(): hlayout.addWidget(button) vlayout = QVBoxLayout() vlayout.addLayout(hlayout) vlayout.addWidget(self.get_shell_widget()) self.setLayout(vlayout) self.resize(640, 480) if parent is None: self.setWindowIcon(self.get_icon()) self.setWindowTitle(translate('ExternalShellBase', "Console")) self.t0 = None self.timer = QTimer(self) self.process = None self.is_closing = False
def load_session(filename): """Load Spyder session""" filename = osp.abspath(filename) old_cwd = os.getcwdu() os.chdir(osp.dirname(filename)) error_message = None renamed = False try: tar = tarfile.open(filename, "r") extracted_files = tar.getnames() # Rename original config files for fname in extracted_files: orig_name = get_conf_path(fname) bak_name = get_conf_path(fname+'.bak') if osp.isfile(bak_name): os.remove(bak_name) if osp.isfile(orig_name): os.rename(orig_name, bak_name) renamed = True tar.extractall() for fname in extracted_files: shutil.move(fname, get_conf_path(fname)) except Exception, error: error_message = unicode(error) if renamed: # Restore original config files for fname in extracted_files: orig_name = get_conf_path(fname) bak_name = get_conf_path(fname+'.bak') if osp.isfile(orig_name): os.remove(orig_name) if osp.isfile(bak_name): os.rename(bak_name, orig_name)
def __init__(self, parent=None, wdir=None, history_filename=None): QWidget.__init__(self, parent) if wdir is None: wdir = osp.dirname(osp.abspath(self.fname)) self.wdir = wdir if osp.isdir(wdir) else None self.arguments = "" self.shell = self.SHELL_CLASS(parent, get_conf_path(history_filename)) self.connect(self.shell, SIGNAL("execute(QString)"), self.send_to_process) self.connect(self.shell, SIGNAL("keyboard_interrupt()"), self.keyboard_interrupt) # Redirecting some SIGNALs: self.connect(self.shell, SIGNAL('redirect_stdio(bool)'), lambda state: self.emit(SIGNAL('redirect_stdio(bool)'), state)) self.state_label = QLabel() self.time_label = QLabel() hlayout = QHBoxLayout() hlayout.addWidget(self.state_label) hlayout.addStretch(0) hlayout.addWidget(self.time_label) hlayout.addStretch(0) for button in self.get_toolbar_buttons(): hlayout.addWidget(button) vlayout = QVBoxLayout() vlayout.addLayout(hlayout) vlayout.addWidget(self.get_shell_widget()) self.setLayout(vlayout) self.resize(640, 480) if parent is None: self.setWindowIcon(self.get_icon()) self.setWindowTitle(self.tr("Console")) self.t0 = None self.timer = QTimer(self) self.process = None self.is_closing = False
def __init__(self, parent=None, namespace=None, commands=[], message="", max_line_count=300, font=None, debug=False, exitfunc=None, profile=False, multithreaded=True): PythonShellWidget.__init__(self, parent, get_conf_path('.history_internal.py'), debug, profile) self.multithreaded = multithreaded self.setMaximumBlockCount(max_line_count) if font is not None: self.set_font(font) # KeyboardInterrupt support self.interrupted = False # used only for not-multithreaded mode self.connect(self, SIGNAL("keyboard_interrupt()"), self.keyboard_interrupt) # Code completion / calltips getcfg = lambda option: CONF.get('shell', option) case_sensitive = getcfg('codecompletion/case-sensitivity') show_single = getcfg('codecompletion/select-single') from_document = getcfg('codecompletion/from-document') self.setup_code_completion(case_sensitive, show_single, from_document) # keyboard events management self.eventqueue = [] # Init interpreter self.exitfunc = exitfunc self.commands = commands self.message = message self.interpreter = None self.start_interpreter(namespace) # Clear status bar self.emit(SIGNAL("status(QString)"), QString())
def __init__(self, parent, history_filename, debug=False, profile=False): """ parent : specifies the parent widget """ ConsoleBaseWidget.__init__(self, parent) # Prompt position: tuple (line, index) self.current_prompt_pos = None self.new_input_line = True # History self.histidx = None self.hist_wholeline = False assert isinstance(history_filename, (str, unicode)) self.history_filename = history_filename self.history = self.load_history() # Session self.historylog_filename = CONF.get('main', 'historylog_filename', get_conf_path('history.log')) # Context menu self.menu = None self.setup_context_menu() # Debug mode self.debug = debug # Simple profiling test self.profile = profile # write/flush self.__buffer = [] self.__timestamp = 0.0 # Give focus to widget self.setFocus()
class DocViewer(ReadOnlyEditor): """ Docstrings viewer widget """ ID = 'docviewer' LOG_PATH = get_conf_path('.docviewer') def __init__(self, parent): ReadOnlyEditor.__init__(self, parent) self.shell = None # locked = disable link with Console self.locked = False self._last_text = None # Object name layout_edit = QHBoxLayout() layout_edit.addWidget(QLabel(self.tr("Object"))) self.combo = DocComboBox(self) layout_edit.addWidget(self.combo) self.combo.setMaxCount(CONF.get(self.ID, 'max_history_entries')) dvhistory = self.load_dvhistory() self.combo.addItems(dvhistory) # Doc/source checkbox self.help_or_doc = QCheckBox(self.tr("Show source")) self.connect(self.help_or_doc, SIGNAL("stateChanged(int)"), self.toggle_help) layout_edit.addWidget(self.help_or_doc) self.docstring = None self.autosource = False self.toggle_help(Qt.Unchecked) # Lock checkbox self.locked_button = create_toolbutton(self, triggered=self.toggle_locked) layout_edit.addWidget(self.locked_button) self._update_lock_icon() # Main layout layout = QVBoxLayout() layout.addLayout(layout_edit) layout.addWidget(self.editor) layout.addWidget(self.find_widget) self.setLayout(layout) def get_widget_title(self): """Return widget title""" return self.tr('Doc') def get_focus_widget(self): """ Return the widget to give focus to when this plugin's dockwidget is raised on top-level """ self.combo.lineEdit().selectAll() return self.combo def load_dvhistory(self, obj=None): """Load history from a text file in user home directory""" if osp.isfile(self.LOG_PATH): dvhistory = [ line.replace('\n', '') for line in file(self.LOG_PATH, 'r').readlines() ] else: dvhistory = [] return dvhistory def save_dvhistory(self): """Save history to a text file in user home directory""" file(self.LOG_PATH, 'w').write("\n".join( \ [ unicode( self.combo.itemText(index) ) for index in range(self.combo.count()) ] )) def toggle_help(self, state): """Toggle between docstring and help()""" self.docstring = (state == Qt.Unchecked) self.refresh(force=True) def toggle_locked(self): """ Toggle locked state locked = disable link with Console """ self.locked = not self.locked self._update_lock_icon() def _update_lock_icon(self): """Update locked state icon""" icon = get_icon("lock.png" if self.locked else "lock_open.png") self.locked_button.setIcon(icon) tip = self.tr("Unlock") if self.locked else self.tr("Lock") self.locked_button.setToolTip(tip) def set_shell(self, shell): """Bind to shell""" self.shell = shell def refresh(self, text=None, force=False): """Refresh widget""" if (self.locked and not force): return if text is None: text = self.combo.currentText() else: index = self.combo.findText(text) while index != -1: self.combo.removeItem(index) index = self.combo.findText(text) self.combo.insertItem(0, text) self.combo.setCurrentIndex(0) self.set_help(text) self.save_dvhistory() if hasattr(self.main, 'tabifiedDockWidgets'): # 'QMainWindow.tabifiedDockWidgets' was introduced in PyQt 4.5 if self.dockwidget and self.dockwidget.isVisible() \ and not self.ismaximized and text != self._last_text: dockwidgets = self.main.tabifiedDockWidgets(self.dockwidget) if self.main.console.dockwidget not in dockwidgets and \ (hasattr(self.main, 'extconsole') and \ self.main.extconsole.dockwidget not in dockwidgets): self.dockwidget.raise_() self._last_text = text def set_help(self, obj_text): """Show help""" if self.shell is None: return if isinstance(self.shell, ExtPyQsciShell): if not self.shell.externalshell.is_running(): # Binded external shell was stopped: # binding DocViewer to interactive console instead self.shell = self.main.console.shell obj_text = unicode(obj_text) doc_text = self.shell.get_doc(obj_text) try: source_text = self.shell.get_source(obj_text) except (TypeError, IOError): source_text = None if self.docstring: hlp_text = doc_text if hlp_text is None: hlp_text = source_text if hlp_text is None: hlp_text = self.tr("No documentation available.") else: hlp_text = source_text if hlp_text is None: hlp_text = doc_text if hlp_text is None: hlp_text = self.tr("No source code available.") self.editor.set_text(hlp_text) self.editor.set_cursor_position('sof')
class Workspace(DictEditorTableView, PluginMixin): """ Workspace widget (namespace explorer) """ ID = 'workspace' TEMPFILE_PATH = get_conf_path('.temp.spydata') def __init__(self, parent): self.interpreter = None self.namespace = None self.filename = None truncate = CONF.get(self.ID, 'truncate') inplace = CONF.get(self.ID, 'inplace') minmax = CONF.get(self.ID, 'minmax') collvalue = CONF.get(self.ID, 'collvalue') DictEditorTableView.__init__(self, parent, None, names=True, truncate=truncate, inplace=inplace, minmax=minmax, collvalue=collvalue) PluginMixin.__init__(self, parent) self.setup_io() self.load_temp_namespace() self.setFont(get_font(self.ID)) def setup_io(self): """Setup I/O functions and filters""" iofuncs = ( ('.spydata', translate('Workspace', "Spyder data files"), load_dictionary, save_dictionary), ('.npy', translate('Workspace', "NumPy arrays"), load_array, None), ('.mat', translate('Workspace', "Matlab files"), load_matlab, save_matlab), ('.csv', translate('Workspace', "CSV text files"), 'import_wizard', None), ('.txt', translate('Workspace', "Text files"), 'import_wizard', None), ('.jpg', translate('Workspace', "JPEG images"), load_image, None), ('.png', translate('Workspace', "PNG images"), load_image, None), ('.gif', translate('Workspace', "GIF images"), load_image, None), ('.tif', translate('Workspace', "TIFF images"), load_image, None), ('.dcm', translate('Workspace', "DICOM images"), load_dicom, None), ) load_funcs = {} save_funcs = {} load_filters = [] save_filters = [] load_ext = [] for ext, name, loadfunc, savefunc in iofuncs: filter_str = unicode(name + " (*%s)" % ext) if loadfunc is not None: load_filters.append(filter_str) load_funcs[ext] = loadfunc load_ext.append(ext) if savefunc is not None: save_filters.append(filter_str) save_funcs[ext] = savefunc load_filters.insert(0, unicode(self.tr("Supported files")+" (*"+\ " *".join(load_ext)+")")) self.load_filters = "\n".join(load_filters) self.save_filters = "\n".join(save_filters) self.load_funcs = load_funcs self.save_funcs = save_funcs def get_widget_title(self): """Return widget title""" return self.tr('Workspace') def get_focus_widget(self): """ Return the widget to give focus to when this plugin's dockwidget is raised on top-level """ return self def set_interpreter(self, interpreter): """Bind to interpreter""" self.interpreter = interpreter self.refresh() def get_namespace(self, itermax=ITERMAX): """Return filtered namespace""" return wsfilter(self.namespace, itermax=itermax) def __clear_namespace(self): """Clear namespace""" keys = self.get_namespace().keys() for key in keys: self.namespace.pop(key) self.refresh() def clear(self): """Ask to clear workspace""" answer = QMessageBox.question( self, self.tr("Clear workspace"), self.tr("Do you want to clear all data from workspace?"), QMessageBox.Yes | QMessageBox.No) if answer == QMessageBox.Yes: self.__clear_namespace() def refresh(self): """Refresh widget""" if CONF.get(self.ID, 'autorefresh'): self.refresh_editor() def refresh_editor(self): """Refresh DictEditor""" if self.interpreter is not None: self.namespace = self.interpreter.namespace self.set_filter(wsfilter) self.set_data(self.namespace) self.adjust_columns() def set_actions(self): """Setup actions""" import_action = create_action(self, self.tr("Import data..."), None, 'ws_open.png', self.tr("Import data to workspace"), triggered=self.import_data) save_as_action = create_action(self, self.tr("Save workspace as..."), None, 'ws_save_as.png', self.tr("Save workspace as..."), triggered=self.save_as) exclude_private_action = create_action( self, self.tr("Exclude private references"), tip=self.tr("Exclude references which name starts" " with an underscore"), toggled=self.toggle_exclude_private) exclude_private_action.setChecked(CONF.get(self.ID, 'exclude_private')) exclude_upper_action = create_action( self, self.tr("Exclude capitalized references"), tip=self.tr("Exclude references which name starts with an " "upper-case character"), toggled=self.toggle_exclude_upper) exclude_upper_action.setChecked(CONF.get(self.ID, 'exclude_upper')) exclude_unsupported_action = create_action( self, self.tr("Exclude unsupported data types"), tip=self.tr("Exclude references to unsupported data types" " (i.e. which won't be handled/saved correctly)"), toggled=self.toggle_exclude_unsupported) exclude_unsupported_action.setChecked( CONF.get(self.ID, 'exclude_unsupported')) refresh_action = create_action(self, self.tr("Refresh workspace"), None, 'ws_refresh.png', self.tr("Refresh workspace"), triggered=self.refresh_editor) autorefresh_action = create_action(self, self.tr("Auto refresh"), toggled=self.toggle_autorefresh) autorefresh_action.setChecked(CONF.get(self.ID, 'autorefresh')) autosave_action = create_action( self, self.tr("Auto save"), toggled=self.toggle_autosave, tip=self.tr("Automatically save workspace in a temporary file" " when quitting")) autosave_action.setChecked(CONF.get(self.ID, 'autosave')) clear_action = create_action( self, self.tr("Clear workspace"), icon=get_icon('clear.png'), tip=self.tr("Clear all data from workspace"), triggered=self.clear) font_action1 = create_action(self, self.tr("Header Font..."), None, 'font.png', self.tr("Set font style"), triggered=self.change_font1) font_action2 = create_action(self, self.tr("Value Font..."), None, 'font.png', self.tr("Set font style"), triggered=self.change_font2) option_menu = QMenu(self.tr("Workspace settings"), self) option_menu.setIcon(get_icon('tooloptions.png')) add_actions( option_menu, (autosave_action, None, self.truncate_action, self.inplace_action, None, exclude_private_action, exclude_upper_action, exclude_unsupported_action, font_action1, font_action2)) menu_actions = (import_action, save_as_action, refresh_action, autorefresh_action, clear_action, option_menu) toolbar_actions = (refresh_action, import_action, save_as_action) return (menu_actions, toolbar_actions) def change_font1(self): """Change font""" self.__change_font('dicteditor_header') def change_font2(self): """Change font""" self.__change_font('dicteditor') def __change_font(self, section): font, valid = QFontDialog.getFont(get_font(section), self, self.tr("Select a new font")) if valid: set_font(font, section) def toggle_autorefresh(self, checked): """Toggle autorefresh mode""" CONF.set(self.ID, 'autorefresh', checked) self.refresh() def toggle_autosave(self, checked): """Toggle autosave mode""" CONF.set(self.ID, 'autosave', checked) def closing(self, cancelable=False): """Perform actions before parent main window is closed""" if CONF.get(self.ID, 'autosave'): # Saving workspace self.__save(self.TEMPFILE_PATH) else: workspace = self.get_namespace(itermax=-1) if workspace is None: return True refnb = len(workspace) if refnb > 1: srefnb = str(refnb) s_or_not = 's' it_or_them = self.tr('them') else: srefnb = self.tr('one') s_or_not = '' it_or_them = self.tr('it') if refnb > 0: buttons = QMessageBox.Yes | QMessageBox.No if cancelable: buttons = buttons | QMessageBox.Cancel answer = QMessageBox.question(self, self.get_widget_title(), self.tr("Workspace is currently keeping reference " "to %1 object%2.\n\nDo you want to save %3?") \ .arg(srefnb).arg(s_or_not).arg(it_or_them), buttons) if answer == QMessageBox.Yes: # Saving workspace self.__save(self.TEMPFILE_PATH) elif answer == QMessageBox.Cancel: return False elif osp.isfile(self.TEMPFILE_PATH): # Removing last saved workspace os.remove(self.TEMPFILE_PATH) return True def load_temp_namespace(self): """Attempt to load last session namespace""" self.filename = self.TEMPFILE_PATH if osp.isfile(self.filename): self.import_data(self.filename) else: self.namespace = None self.refresh() def import_data(self, filename=None): """ Import data from workspace or other data type (not implemented yet) """ title = self.tr("Import data") if filename is None: self.emit(SIGNAL('redirect_stdio(bool)'), False) basedir = osp.dirname(self.filename) filename = QFileDialog.getOpenFileName(self, title, basedir, self.load_filters) self.emit(SIGNAL('redirect_stdio(bool)'), True) if filename: filename = unicode(filename) else: return self.filename = unicode(filename) ext = osp.splitext(self.filename)[1] if ext not in self.load_funcs: buttons = QMessageBox.Yes | QMessageBox.Cancel answer = QMessageBox.question(self, title, self.tr("<b>Unsupported file type '%1'</b><br><br>" "Would you like to import it as a text file?") \ .arg(ext), buttons) if answer == QMessageBox.Cancel: return else: load_func = 'import_wizard' else: load_func = self.load_funcs[ext] if isinstance(load_func, basestring): # 'import_wizard' (self.setup_io) # Import data with import wizard error_message = None try: from spyderlib.utils import encoding text, _encoding = encoding.read(self.filename) self.import_from_string(text) except Exception, error: error_message = str(error) else:
except Exception, error: error_message = unicode(error) if renamed: # Restore original config files for fname in extracted_files: orig_name = get_conf_path(fname) bak_name = get_conf_path(fname+'.bak') if osp.isfile(orig_name): os.remove(orig_name) if osp.isfile(bak_name): os.rename(bak_name, orig_name) finally: # Removing backup config files for fname in extracted_files: bak_name = get_conf_path(fname+'.bak') if osp.isfile(bak_name): os.remove(bak_name) os.chdir(old_cwd) return error_message from PyQt4.QtGui import QFileDialog from PyQt4.QtCore import QObject class IOFunctions(QObject): def __init__(self): QObject.__init__(self) self.load_filters = None self.save_filters = None
class PylintWidget(QWidget): """ Pylint widget """ DATAPATH = get_conf_path('.pylint.results') VERSION = '1.0.2' def __init__(self, parent, max_entries=100): QWidget.__init__(self, parent) self.output = None self.error_output = None self.max_entries = max_entries self.data = [self.VERSION] if osp.isfile(self.DATAPATH): try: data = cPickle.load(file(self.DATAPATH)) if data[0] == self.VERSION: self.data = data except EOFError: pass self.filecombo = PythonModulesComboBox(self) if self.data: self.remove_obsolete_items() self.filecombo.addItems(self.get_filenames()) self.start_button = create_toolbutton(self, get_icon('run.png'), translate('Pylint', "Analyze"), tip=translate( 'Pylint', "Run analysis"), triggered=self.start) self.stop_button = create_toolbutton(self, get_icon('terminate.png'), translate('Pylint', "Stop"), tip=translate( 'Pylint', "Stop current analysis")) self.connect(self.filecombo, SIGNAL('valid(bool)'), self.start_button.setEnabled) self.connect(self.filecombo, SIGNAL('valid(bool)'), self.show_data) browse_button = create_toolbutton(self, get_icon('fileopen.png'), tip=translate( 'Pylint', 'Select Python script'), triggered=self.select_file) self.ratelabel = QLabel() self.datelabel = QLabel() self.log_button = create_toolbutton(self, get_icon('log.png'), translate('Pylint', "Output"), tip=translate( 'Pylint', "Complete Pylint output"), triggered=self.show_log) self.treewidget = ResultsTree(self) hlayout1 = QHBoxLayout() hlayout1.addWidget(self.filecombo) hlayout1.addWidget(browse_button) hlayout1.addWidget(self.start_button) hlayout1.addWidget(self.stop_button) hlayout2 = QHBoxLayout() hlayout2.addWidget(self.ratelabel) hlayout2.addStretch() hlayout2.addWidget(self.datelabel) hlayout2.addStretch() hlayout2.addWidget(self.log_button) layout = QVBoxLayout() layout.addLayout(hlayout1) layout.addLayout(hlayout2) layout.addWidget(self.treewidget) self.setLayout(layout) self.process = None self.set_running_state(False) if not is_pylint_installed(): for widget in (self.treewidget, self.filecombo, self.start_button, self.stop_button): widget.setDisabled(True) text = translate('Pylint', 'Please install <b>pylint</b>:') url = 'http://www.logilab.fr' text += ' <a href=%s>%s</a>' % (url, url) self.ratelabel.setText(text) else: self.show_data() def analyze(self, filename): if not is_pylint_installed(): return filename = unicode(filename) # filename is a QString instance self.kill_if_running() index, _data = self.get_data(filename) if index is None: self.filecombo.addItem(filename) self.filecombo.setCurrentIndex(self.filecombo.count() - 1) else: self.filecombo.setCurrentIndex(index) self.filecombo.selected() if self.filecombo.is_valid(): self.start() def select_file(self): self.emit(SIGNAL('redirect_stdio(bool)'), False) filename = QFileDialog.getOpenFileName( self, translate('Pylint', "Select Python script"), os.getcwdu(), translate('Pylint', "Python scripts") + " (*.py ; *.pyw)") self.emit(SIGNAL('redirect_stdio(bool)'), False) if filename: self.analyze(filename) def remove_obsolete_items(self): """Removing obsolete items""" self.data = [self.VERSION] + \ [(filename, data) for filename, data in self.data[1:] if is_module_or_package(filename)] def get_filenames(self): return [filename for filename, _data in self.data[1:]] def get_data(self, filename): filename = osp.abspath(filename) for index, (fname, data) in enumerate(self.data[1:]): if fname == filename: return index, data else: return None, None def set_data(self, filename, data): filename = osp.abspath(filename) index, _data = self.get_data(filename) if index is not None: self.data.pop(index) self.data.append((filename, data)) self.save() def set_max_entries(self, max_entries): self.max_entries = max_entries self.save() def save(self): while len(self.data) > self.max_entries + 1: self.data.pop(1) cPickle.dump(self.data, file(self.DATAPATH, 'w')) def show_log(self): if self.output: TextEditor(self.output, title=translate('Pylint', "Pylint output"), readonly=True, size=(700, 500)).exec_() def start(self): filename = unicode(self.filecombo.currentText()) self.process = QProcess(self) self.process.setProcessChannelMode(QProcess.SeparateChannels) self.process.setWorkingDirectory(osp.dirname(filename)) self.connect(self.process, SIGNAL("readyReadStandardOutput()"), self.read_output) self.connect(self.process, SIGNAL("readyReadStandardError()"), lambda: self.read_output(error=True)) self.connect(self.process, SIGNAL("finished(int,QProcess::ExitStatus)"), self.finished) self.connect(self.stop_button, SIGNAL("clicked()"), self.process.kill) self.output = '' self.error_output = '' p_args = [osp.basename(filename)] self.process.start(PYLINT_PATH, p_args) running = self.process.waitForStarted() self.set_running_state(running) if not running: QMessageBox.critical( self, translate('Pylint', "Error"), translate('Pylint', "Process failed to start")) def set_running_state(self, state=True): self.start_button.setEnabled(not state) self.stop_button.setEnabled(state) def read_output(self, error=False): if error: self.process.setReadChannel(QProcess.StandardError) else: self.process.setReadChannel(QProcess.StandardOutput) bytes = QByteArray() while self.process.bytesAvailable(): if error: bytes += self.process.readAllStandardError() else: bytes += self.process.readAllStandardOutput() text = unicode(QString.fromLocal8Bit(bytes.data())) if error: self.error_output += text else: self.output += text def finished(self): self.set_running_state(False) if not self.output: return # Convention, Refactor, Warning, Error results = {'C:': [], 'R:': [], 'W:': [], 'E:': []} txt_module = '************* Module ' module = '' # Should not be needed - just in case something goes wrong for line in self.output.splitlines(): if line.startswith(txt_module): # New module module = line[len(txt_module):] continue for prefix in results: if line.startswith(prefix): break else: continue i1 = line.find(':') if i1 == -1: continue i2 = line.find(':', i1 + 1) if i2 == -1: continue line_nb = line[i1 + 1:i2].strip() if not line_nb: continue line_nb = int(line_nb) message = line[i2 + 1:] item = (module, line_nb, message) results[line[:i1 + 1]].append(item) # Rate rate = None txt_rate = 'Your code has been rated at ' i_rate = self.output.find(txt_rate) if i_rate > 0: i_rate_end = self.output.find('/10', i_rate) if i_rate_end > 0: rate = self.output[i_rate + len(txt_rate):i_rate_end] # Previous run previous = '' if rate is not None: txt_prun = 'previous run: ' i_prun = self.output.find(txt_prun, i_rate_end) if i_prun > 0: i_prun_end = self.output.find('/10', i_prun) previous = self.output[i_prun + len(txt_prun):i_prun_end] filename = unicode(self.filecombo.currentText()) self.set_data(filename, (time.localtime(), rate, previous, results)) self.output = self.error_output + self.output self.show_data(justanalyzed=True) def kill_if_running(self): if self.process is not None: if self.process.state() == QProcess.Running: self.process.kill() self.process.waitForFinished() def show_data(self, justanalyzed=False): if not justanalyzed: self.output = None self.log_button.setEnabled(self.output is not None \ and len(self.output) > 0) self.kill_if_running() filename = unicode(self.filecombo.currentText()) if not filename: return _index, data = self.get_data(filename) if data is None: text = translate('Pylint', 'Source code has not been rated yet.') self.treewidget.clear() date_text = '' else: datetime, rate, previous_rate, results = data if rate is None: text = translate( 'Pylint', 'Analysis did not succeed ' '(see output for more details).') self.treewidget.clear() date_text = '' else: text_style = "<span style=\'color: #444444\'><b>%s </b></span>" rate_style = "<span style=\'color: %s\'><b>%s</b></span>" prevrate_style = "<span style=\'color: #666666\'>%s</span>" color = "#FF0000" if float(rate) > 5.: color = "#22AA22" elif float(rate) > 3.: color = "#EE5500" text = translate('Pylint', 'Global evaluation:') text = (text_style % text) + (rate_style % (color, ('%s/10' % rate))) if previous_rate: text_prun = translate('Pylint', 'previous run:') text_prun = ' (%s %s/10)' % (text_prun, previous_rate) text += prevrate_style % text_prun self.treewidget.set_results(filename, results) date_text = text_style % time.strftime("%d %b %Y %H:%M", datetime) self.ratelabel.setText(text) self.datelabel.setText(date_text)
class WorkingDirectory(QToolBar, PluginMixin): """ Working directory changer widget """ ID = 'workingdir' # allowed_areas = Qt.TopDockWidgetArea | Qt.BottomDockWidgetArea # location = Qt.TopDockWidgetArea LOG_PATH = get_conf_path('.workingdir') def __init__(self, parent, workdir=None): QToolBar.__init__(self, parent) PluginMixin.__init__(self, parent) self.setWindowTitle(self.get_widget_title()) # Toolbar title self.setObjectName( self.get_widget_title()) # Used to save Window state self.addWidget(QLabel(self.tr("Working directory:") + " ")) # Previous dir action self.history = [] self.histindex = None self.previous_action = create_action(self, "previous", None, get_icon('previous.png'), self.tr('Back'), triggered=self.previous_directory) self.addAction(self.previous_action) # Next dir action self.history = [] self.histindex = None self.next_action = create_action(self, "next", None, get_icon('next.png'), self.tr('Next'), triggered=self.next_directory) self.addAction(self.next_action) # Enable/disable previous/next actions self.connect(self, SIGNAL("set_previous_enabled(bool)"), self.previous_action.setEnabled) self.connect(self, SIGNAL("set_next_enabled(bool)"), self.next_action.setEnabled) # Path combo box adjust = CONF.get('shell', 'working_dir_adjusttocontents', False) self.pathedit = PathComboBox(self, adjust_to_contents=adjust) self.pathedit.setToolTip(self.tr("Working directory")) self.connect(self.pathedit, SIGNAL("open_dir(QString)"), self.pathedit_activated) self.pathedit.setMaxCount(CONF.get('shell', 'working_dir_history')) wdhistory = self.load_wdhistory(workdir) if workdir is None: if wdhistory: workdir = wdhistory[0] else: workdir = "." self.chdir(workdir) self.pathedit.addItems(wdhistory) self.refresh() self.addWidget(self.pathedit) # Browse action browse_action = create_action(self, "browse", None, get_std_icon('DirOpenIcon'), self.tr('Browse a working directory'), triggered=self.select_directory) self.addAction(browse_action) # Parent dir action parent_action = create_action(self, "parent", None, get_icon('up.png'), self.tr('Change to parent directory'), triggered=self.parent_directory) self.addAction(parent_action) def get_widget_title(self): """Return widget title""" return self.tr('Working directory') def set_actions(self): """Setup actions""" return (None, None) def closing(self, cancelable=False): """Perform actions before parent main window is closed""" return True def load_wdhistory(self, workdir=None): """Load history from a text file in user home directory""" if osp.isfile(self.LOG_PATH): wdhistory, _ = encoding.readlines(self.LOG_PATH) wdhistory = [name for name in wdhistory if os.path.isdir(name)] else: if workdir is None: workdir = os.getcwdu() wdhistory = [workdir] return wdhistory def save_wdhistory(self): """Save history to a text file in user home directory""" text = [ unicode( self.pathedit.itemText(index) ) \ for index in range(self.pathedit.count()) ] encoding.writelines(text, self.LOG_PATH) def refresh(self): """Refresh widget""" curdir = os.getcwdu() index = self.pathedit.findText(curdir) while index != -1: self.pathedit.removeItem(index) index = self.pathedit.findText(curdir) self.pathedit.insertItem(0, curdir) self.pathedit.setCurrentIndex(0) self.save_wdhistory() self.emit(SIGNAL("set_previous_enabled(bool)"), self.histindex is not None and self.histindex > 0) self.emit(SIGNAL("set_next_enabled(bool)"), self.histindex is not None and \ self.histindex < len(self.history)-1) def select_directory(self): """Select directory""" self.emit(SIGNAL('redirect_stdio(bool)'), False) directory = QFileDialog.getExistingDirectory( self.main, self.tr("Select directory"), os.getcwdu()) if not directory.isEmpty(): self.chdir(directory) self.emit(SIGNAL('redirect_stdio(bool)'), True) def previous_directory(self): """Back to previous directory""" self.histindex -= 1 self.chdir(browsing_history=True) def next_directory(self): """Return to next directory""" self.histindex += 1 self.chdir(browsing_history=True) def parent_directory(self): """Change working directory to parent directory""" self.chdir(os.path.join(os.getcwdu(), os.path.pardir)) def chdir(self, directory=None, browsing_history=False): """Set directory as working directory""" # Working directory history management if browsing_history: directory = self.history[self.histindex] else: if self.histindex is None: self.history = [] else: self.history = self.history[:self.histindex + 1] self.history.append(osp.abspath((unicode(directory)))) self.histindex = len(self.history) - 1 # Changing working directory os.chdir(unicode(directory)) self.refresh() if not isinstance(self.sender(), Explorer): # Explorer is not the sender: let's refresh it self.emit(SIGNAL("refresh_explorer()")) self.emit(SIGNAL("refresh_findinfiles()")) def pathedit_activated(self, directory): """Path combo box activated""" if self.main is not None: # Give focus to interactive shell self.main.console.shell.setFocus() self.chdir(directory)
except Exception, error: error_message = unicode(error) if renamed: # Restore original config files for fname in extracted_files: orig_name = get_conf_path(fname) bak_name = get_conf_path(fname+'.bak') if osp.isfile(orig_name): os.remove(orig_name) if osp.isfile(bak_name): os.rename(bak_name, orig_name) finally: # Removing backup config files for fname in extracted_files: bak_name = get_conf_path(fname+'.bak') if osp.isfile(bak_name): os.remove(bak_name) os.chdir(old_cwd) return error_message if __name__ == "__main__": import datetime testdict = {'d': 1, 'a': np.random.rand(10, 10), 'b': [1, 2]} testdate = datetime.date(1945, 5, 8) example = {'str': 'kjkj kj k j j kj k jkj', 'unicode': u'éù', 'list': [1, 3, [4, 5, 6], 'kjkj', None], 'tuple': ([1, testdate, testdict], 'kjkj', None),
def reset_session(): """Remove all config files""" for fname in SAVED_CONFIG_FILES: cfg_fname = get_conf_path(fname) if osp.isfile(cfg_fname): os.remove(cfg_fname)