def start(self, wdir=None, args=None, pythonpath=None): filename = to_text_string(self.filecombo.currentText()) if wdir is None: wdir = self._last_wdir if wdir is None: wdir = osp.basename(filename) if args is None: args = self._last_args if args is None: args = [] if pythonpath is None: pythonpath = self._last_pythonpath self._last_wdir = wdir self._last_args = args self._last_pythonpath = pythonpath self.datelabel.setText(_('Profiling, please wait...')) self.process = QProcess(self) self.process.setProcessChannelMode(QProcess.SeparateChannels) self.process.setWorkingDirectory(wdir) 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) if pythonpath is not None: env = [to_text_string(_pth) for _pth in self.process.systemEnvironment()] baseshell.add_pathlist_to_PYTHONPATH(env, pythonpath) self.process.setEnvironment(env) self.output = '' self.error_output = '' p_args = ['-m', 'cProfile', '-o', self.DATAPATH] if os.name == 'nt': # On Windows, one has to replace backslashes by slashes to avoid # confusion with escape characters (otherwise, for example, '\t' # will be interpreted as a tabulation): p_args.append(osp.normpath(filename).replace(os.sep, '/')) else: p_args.append(filename) if args: p_args.extend(shell_split(args)) executable = sys.executable if executable.endswith("spyder.exe"): # py2exe distribution executable = "python.exe" self.process.start(executable, p_args) running = self.process.waitForStarted() self.set_running_state(running) if not running: QMessageBox.critical(self, _("Error"), _("Process failed to start"))
def rename_file(self, fname): """Rename file""" path, valid = QInputDialog.getText(self, _("Rename"), _("New name:"), QLineEdit.Normal, osp.basename(fname)) if valid: path = osp.join(osp.dirname(fname), to_text_string(path)) if path == fname: return if osp.exists(path): if ( QMessageBox.warning( self, _("Rename"), _("Do you really want to rename <b>%s</b> and " "overwrite the existing file <b>%s</b>?") % (osp.basename(fname), osp.basename(path)), QMessageBox.Yes | QMessageBox.No, ) == QMessageBox.No ): return try: misc.rename_file(fname, path) self.parent_widget.renamed.emit(fname, path) return path except EnvironmentError as error: QMessageBox.critical( self, _("Rename"), _("<b>Unable to rename file <i>%s</i></b>" "<br><br>Error message:<br>%s") % (osp.basename(fname), to_text_string(error)), )
def update_browse_tabs_menu(self): """Update browse tabs menu""" self.browse_tabs_menu.clear() names = [] dirnames = [] for index in range(self.count()): if self.menu_use_tooltips: text = to_text_string(self.tabToolTip(index)) else: text = to_text_string(self.tabText(index)) names.append(text) if osp.isfile(text): # Testing if tab names are filenames dirnames.append(osp.dirname(text)) offset = None # If tab names are all filenames, removing common path: if len(names) == len(dirnames): common = get_common_path(dirnames) if common is None: offset = None else: offset = len(common)+1 if offset <= 3: # Common path is not a path but a drive letter... offset = None for index, text in enumerate(names): tab_action = create_action(self, text[offset:], icon=self.tabIcon(index), toggled=lambda state, index=index: self.setCurrentIndex(index), tip=self.tabToolTip(index)) tab_action.setChecked(index == self.currentIndex()) self.browse_tabs_menu.addAction(tab_action)
def value_to_display(value, truncate=False, trunc_len=80, minmax=False): """Convert value for display purpose""" if minmax and isinstance(value, (ndarray, MaskedArray)): if value.size == 0: return repr(value) try: return 'Min: %r\nMax: %r' % (value.min(), value.max()) except TypeError: pass except ValueError: # Happens when one of the array cell contains a sequence pass if isinstance(value, Image): return '%s Mode: %s' % (address(value), value.mode) if isinstance(value, DataFrame): cols = value.columns cols = [to_text_string(c) for c in cols] return 'Column names: ' + ', '.join(list(cols)) if is_binary_string(value): try: value = to_text_string(value, 'utf8') except: pass if not is_text_string(value): if isinstance(value, (list, tuple, dict, set)): value = CollectionsRepr.repr(value) else: value = repr(value) if truncate and len(value) > trunc_len: value = value[:trunc_len].rstrip() + ' ...' return value
def setup(self): iofuncs = self.get_internal_funcs() + self.get_3rd_party_funcs() load_extensions = {} save_extensions = {} load_funcs = {} save_funcs = {} load_filters = [] save_filters = [] load_ext = [] for ext, name, loadfunc, savefunc in iofuncs: filter_str = to_text_string(name + " (*%s)" % ext) if loadfunc is not None: load_filters.append(filter_str) load_extensions[filter_str] = ext load_funcs[ext] = loadfunc load_ext.append(ext) if savefunc is not None: save_extensions[filter_str] = ext save_filters.append(filter_str) save_funcs[ext] = savefunc load_filters.insert(0, to_text_string(_("Supported files") + " (*" + " *".join(load_ext) + ")")) load_filters.append(to_text_string(_("All files (*.*)"))) self.load_filters = "\n".join(load_filters) self.save_filters = "\n".join(save_filters) self.load_funcs = load_funcs self.save_funcs = save_funcs self.load_extensions = load_extensions self.save_extensions = save_extensions
def _find_parenthesis(self, position, forward=True): """ If 'forward' is True (resp. False), proceed forwards (resp. backwards) through the line that contains 'position' until an unmatched closing (resp. opening) parenthesis is found. Returns a tuple containing the position of this parenthesis (or -1 if it is not found) and the number commas (at depth 0) found along the way. """ commas = depth = 0 document = self._text_edit.document() char = to_text_string(document.characterAt(position)) # Search until a match is found or a non-printable character is # encountered. while category(char) != 'Cc' and position > 0: if char == ',' and depth == 0: commas += 1 elif char == ')': if forward and depth == 0: break depth += 1 elif char == '(': if not forward and depth == 0: break depth -= 1 position += 1 if forward else -1 char = to_text_string(document.characterAt(position)) else: position = -1 return position, commas
def register_plugin(self): """Register plugin in Spyder's main window""" self.main.add_dockwidget(self) self.edit.connect(self.main.editor.load) self.removed.connect(self.main.editor.removed) self.renamed.connect(self.main.editor.renamed) self.main.editor.open_dir.connect(self.chdir) self.create_module.connect(self.main.editor.new) self.run.connect( lambda fname: self.main.open_external_console(to_text_string(fname), osp.dirname(to_text_string(fname)), '', False, False, True, '', False)) # Signal "set_explorer_cwd(QString)" will refresh only the # contents of path passed by the signal in explorer: self.main.workingdirectory.set_explorer_cwd.connect( lambda directory: self.refresh_plugin(new_path=directory, force_current=True)) self.open_dir.connect( lambda dirname: self.main.workingdirectory.chdir(dirname, refresh_explorer=False)) self.sig_open_file.connect(self.main.open_file) self.sig_new_file.connect(lambda t: self.main.editor.new(text=t))
def run(self): html_text = self.html_text_no_doc doc = self.doc if doc is not None: if type(doc) is dict and 'docstring' in doc.keys(): try: context = generate_context(name=doc['name'], argspec=doc['argspec'], note=doc['note'], math=self.math_option, img_path=self.img_path) html_text = sphinxify(doc['docstring'], context) if doc['docstring'] == '': html_text += '<div class="hr"></div>' html_text += self.html_text_no_doc except Exception as error: self.error_msg.emit(to_text_string(error)) return elif self.context is not None: try: html_text = sphinxify(doc, self.context) except Exception as error: self.error_msg.emit(to_text_string(error)) return self.html_ready.emit(html_text)
def replace_find(self): """Replace and find""" if self.editor is not None: replace_text = to_text_string(self.replace_text.currentText()) search_text = to_text_string(self.search_text.currentText()) pattern = search_text if self.re_button.isChecked() else None case = self.case_button.isChecked() first = True cursor = None while True: if first: # First found seltxt = to_text_string(self.editor.get_selected_text()) cmptxt1 = search_text if case else search_text.lower() cmptxt2 = seltxt if case else seltxt.lower() if self.editor.has_selected_text() and cmptxt1 == cmptxt2: # Text was already found, do nothing pass else: if not self.find(changed=False, forward=True, rehighlight=False): break first = False wrapped = False position = self.editor.get_position("cursor") position0 = position cursor = self.editor.textCursor() cursor.beginEditBlock() else: position1 = self.editor.get_position("cursor") if is_position_inf(position1, position0 + len(replace_text) - len(search_text) + 1): # Identify wrapping even when the replace string # includes part of the search string wrapped = True if wrapped: if position1 == position or is_position_sup(position1, position): # Avoid infinite loop: replace string includes # part of the search string break if position1 == position0: # Avoid infinite loop: single found occurence break position0 = position1 if pattern is None: cursor.removeSelectedText() cursor.insertText(replace_text) else: seltxt = to_text_string(cursor.selectedText()) cursor.removeSelectedText() cursor.insertText(re.sub(pattern, replace_text, seltxt)) if self.find_next(): found_cursor = self.editor.textCursor() cursor.setPosition(found_cursor.selectionStart(), QTextCursor.MoveAnchor) cursor.setPosition(found_cursor.selectionEnd(), QTextCursor.KeepAnchor) else: break if not self.all_check.isChecked(): break self.all_check.setCheckState(Qt.Unchecked) if cursor is not None: cursor.endEditBlock()
def find_multiline_pattern(self, regexp, cursor, findflag): """Reimplement QTextDocument's find method Add support for *multiline* regular expressions""" pattern = to_text_string(regexp.pattern()) text = to_text_string(self.toPlainText()) try: regobj = re.compile(pattern) except sre_constants.error: return if findflag & QTextDocument.FindBackward: # Find backward offset = min([cursor.selectionEnd(), cursor.selectionStart()]) text = text[:offset] matches = [_m for _m in regobj.finditer(text, 0, offset)] if matches: match = matches[-1] else: return else: # Find forward offset = max([cursor.selectionEnd(), cursor.selectionStart()]) match = regobj.search(text, offset) if match: pos1, pos2 = match.span() fcursor = self.textCursor() fcursor.setPosition(pos1) fcursor.setPosition(pos2, QTextCursor.KeepAnchor) return fcursor
def create_new_folder(self, current_path, title, subtitle, is_package): """Create new folder""" if current_path is None: current_path = "" if osp.isfile(current_path): current_path = osp.dirname(current_path) name, valid = QInputDialog.getText(self, title, subtitle, QLineEdit.Normal, "") if valid: dirname = osp.join(current_path, to_text_string(name)) try: os.mkdir(dirname) except EnvironmentError as error: QMessageBox.critical( self, title, _("<b>Unable " "to create folder <i>%s</i></b>" "<br><br>Error message:<br>%s") % (dirname, to_text_string(error)), ) finally: if is_package: fname = osp.join(dirname, "__init__.py") try: with open(fname, "wb") as f: f.write(to_binary_string("#")) return dirname except EnvironmentError as error: QMessageBox.critical( self, title, _("<b>Unable " "to create file <i>%s</i></b>" "<br><br>Error message:<br>%s") % (fname, to_text_string(error)), )
def run_script_in_current_client(self, filename, wdir, args, debug): """Run script in current client, if any""" norm = lambda text: remove_backslashes(to_text_string(text)) client = self.get_current_client() if client is not None: # Internal kernels, use runfile if client.kernel_widget_id is not None: line = "%s('%s'" % ('debugfile' if debug else 'runfile', norm(filename)) if args: line += ", args='%s'" % norm(args) if wdir: line += ", wdir='%s'" % norm(wdir) line += ")" else: # External kernels, use %run line = "%run " if debug: line += "-d " line += "\"%s\"" % to_text_string(filename) if args: line += " %s" % norm(args) self.execute_python_code(line) self.visibility_changed(True) self.raise_() else: #XXX: not sure it can really happen QMessageBox.warning(self, _('Warning'), _("No IPython console is currently available to run <b>%s</b>." "<br><br>Please open a new one and try again." ) % osp.basename(filename), QMessageBox.Ok)
def chdir(self, directory=None, browsing_history=False): """Set directory as working directory""" if directory is not None: directory = osp.abspath(to_text_string(directory)) if browsing_history: directory = self.history[self.histindex] elif directory in self.history: self.histindex = self.history.index(directory) else: if self.histindex is None: self.history = [] else: self.history = self.history[: self.histindex + 1] if len(self.history) == 0 or (self.history and self.history[-1] != directory): self.history.append(directory) self.histindex = len(self.history) - 1 directory = to_text_string(directory) if PY2: PermissionError = OSError try: os.chdir(directory) self.parent_widget.open_dir.emit(directory) self.refresh(new_path=directory, force_current=True) except PermissionError: QMessageBox.critical( self.parent_widget, "Error", _("You don't have the right permissions to " "open this directory") )
def _qfiledialog_wrapper(attr, parent=None, caption='', basedir='', filters='', selectedfilter='', options=None): if options is None: options = QFileDialog.Options(0) try: # PyQt <v4.6 (API #1) from spyderlib.qt.QtCore import QString except ImportError: # PySide or PyQt >=v4.6 QString = None # analysis:ignore tuple_returned = True try: # PyQt >=v4.6 func = getattr(QFileDialog, attr+'AndFilter') except AttributeError: # PySide or PyQt <v4.6 func = getattr(QFileDialog, attr) if QString is not None: selectedfilter = QString() tuple_returned = False # Calling QFileDialog static method if sys.platform == "win32": # On Windows platforms: redirect standard outputs _temp1, _temp2 = sys.stdout, sys.stderr sys.stdout, sys.stderr = None, None try: result = func(parent, caption, basedir, filters, selectedfilter, options) except TypeError: # The selectedfilter option (`initialFilter` in Qt) has only been # introduced in Jan. 2010 for PyQt v4.7, that's why we handle here # the TypeError exception which will be raised with PyQt v4.6 # (see Issue 960 for more details) result = func(parent, caption, basedir, filters, options) finally: if sys.platform == "win32": # On Windows platforms: restore standard outputs sys.stdout, sys.stderr = _temp1, _temp2 # Processing output if tuple_returned: # PySide or PyQt >=v4.6 output, selectedfilter = result else: # PyQt <v4.6 (API #1) output = result if QString is not None: # PyQt API #1: conversions needed from QString/QStringList selectedfilter = to_text_string(selectedfilter) if isinstance(output, QString): # Single filename output = to_text_string(output) else: # List of filenames output = [to_text_string(fname) for fname in output] # Always returns the tuple (output, selectedfilter) return output, selectedfilter
def is_cell_separator(self, cursor=None, block=None): """Return True if cursor (or text block) is on a block separator""" assert cursor is not None or block is not None if cursor is not None: cursor0 = QTextCursor(cursor) cursor0.select(QTextCursor.BlockUnderCursor) text = to_text_string(cursor0.selectedText()) else: text = to_text_string(block.text()) return text.lstrip().startswith(CELL_SEPARATORS)
def get(self): self.runconf.args_enabled = self.clo_cb.isChecked() self.runconf.args = to_text_string(self.clo_edit.text()) self.runconf.wdir_enabled = self.wd_cb.isChecked() self.runconf.wdir = to_text_string(self.wd_edit.text()) self.runconf.current = self.current_radio.isChecked() self.runconf.systerm = self.systerm_radio.isChecked() self.runconf.interact = self.interact_cb.isChecked() self.runconf.show_kill_warning = self.show_kill_warning_cb.isChecked() self.runconf.python_args_enabled = self.pclo_cb.isChecked() self.runconf.python_args = to_text_string(self.pclo_edit.text()) return self.runconf.get()
def show(self, dialog): """Generic method to show a non-modal dialog and keep reference to the Qt C++ object""" for dlg in list(self.dialogs.values()): if to_text_string(dlg.windowTitle()) == to_text_string(dialog.windowTitle()): dlg.show() dlg.raise_() break else: dialog.show() self.dialogs[id(dialog)] = dialog dialog.accepted.connect(lambda eid=id(dialog): self.dialog_finished(eid)) dialog.rejected.connect(lambda eid=id(dialog): self.dialog_finished(eid))
def append_to_history(self, filename, command): """ Append an entry to history filename Slot for append_to_history signal emitted by shell instance """ if not is_text_string(filename): # filename is a QString filename = to_text_string(filename.toUtf8(), 'utf-8') command = to_text_string(command) index = self.filenames.index(filename) self.editors[index].append(command) if self.get_option('go_to_eof'): self.editors[index].set_cursor_position('eof') self.tabwidget.setCurrentIndex(index)
def process(self): """Process the data from clipboard""" var_name = self.name_edt.text() try: self.var_name = str(var_name) except UnicodeEncodeError: self.var_name = to_text_string(var_name) if self.text_widget.get_as_data(): self.clip_data = self._get_table_data() elif self.text_widget.get_as_code(): self.clip_data = try_to_eval(to_text_string(self._get_plain_text())) else: self.clip_data = to_text_string(self._get_plain_text()) self.accept()
def replace(self, text, pattern=None): """Replace selected text by *text* If *pattern* is not None, replacing selected text using regular expression text substitution""" cursor = self.textCursor() cursor.beginEditBlock() if pattern is not None: seltxt = to_text_string(cursor.selectedText()) cursor.removeSelectedText() if pattern is not None: text = re.sub(to_text_string(pattern), to_text_string(text), to_text_string(seltxt)) cursor.insertText(text) cursor.endEditBlock()
def listdir(path, include=".", exclude=r"\.pyc$|^\.", show_all=False, folders_only=False): """List files and directories""" namelist = [] dirlist = [to_text_string(osp.pardir)] for item in os.listdir(to_text_string(path)): if re.search(exclude, item) and not show_all: continue if osp.isdir(osp.join(path, item)): dirlist.append(item) elif folders_only: continue elif re.search(include, item) or show_all: namelist.append(item) return sorted(dirlist, key=str_lower) + sorted(namelist, key=str_lower)
def option_changed(self, option, value): """Option has changed""" setattr(self, to_text_string(option), value) if not self.is_internal_shell: settings = self.get_view_settings() communicate(self._get_sock(), 'set_remote_view_settings()', settings=[settings])
def delete_file(self, fname, multiple, yes_to_all): """Delete file""" if multiple: buttons = QMessageBox.Yes | QMessageBox.YesAll | QMessageBox.No | QMessageBox.Cancel else: buttons = QMessageBox.Yes | QMessageBox.No if yes_to_all is None: answer = QMessageBox.warning( self, _("Delete"), _("Do you really want " "to delete <b>%s</b>?") % osp.basename(fname), buttons ) if answer == QMessageBox.No: return yes_to_all elif answer == QMessageBox.Cancel: return False elif answer == QMessageBox.YesAll: yes_to_all = True try: if osp.isfile(fname): misc.remove_file(fname) self.parent_widget.removed.emit(fname) else: self.remove_tree(fname) self.parent_widget.removed_tree.emit(fname) return yes_to_all except EnvironmentError as error: action_str = _("delete") QMessageBox.critical( self, _("Project Explorer"), _("<b>Unable to %s <i>%s</i></b>" "<br><br>Error message:<br>%s") % (action_str, fname, to_text_string(error)), ) return False
def start(self): filename = to_text_string(self.filecombo.currentText()) self.process = QProcess(self) self.process.setProcessChannelMode(QProcess.SeparateChannels) self.process.setWorkingDirectory(osp.dirname(filename)) self.process.readyReadStandardOutput.connect(self.read_output) self.process.readyReadStandardError.connect( lambda: self.read_output(error=True)) self.process.finished.connect(lambda ec, es=QProcess.ExitStatus: self.finished(ec, es)) self.stop_button.clicked.connect(self.process.kill) self.output = '' self.error_output = '' plver = PYLINT_VER if plver is not None: if plver.split('.')[0] == '0': p_args = ['-i', 'yes'] else: # Option '-i' (alias for '--include-ids') was removed in pylint # 1.0 p_args = ["--msg-template='{msg_id}:{line:3d},"\ "{column}: {obj}: {msg}"] p_args += [osp.basename(filename)] else: 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, _("Error"), _("Process failed to start"))
def move(self, fnames=None): """Move files/directories""" if fnames is None: fnames = self.get_selected_filenames() orig = fixpath(osp.dirname(fnames[0])) while True: self.parent_widget.redirect_stdio.emit(False) folder = getexistingdirectory(self, _("Select directory"), orig) self.parent_widget.redirect_stdio.emit(True) if folder: folder = fixpath(folder) if folder != orig: break else: return for fname in fnames: basename = osp.basename(fname) try: misc.move_file(fname, osp.join(folder, basename)) except EnvironmentError as error: QMessageBox.critical( self, _("Error"), _("<b>Unable to move <i>%s</i></b>" "<br><br>Error message:<br>%s") % (basename, to_text_string(error)), )
def get_arguments(self): arguments, valid = QInputDialog.getText( self, _("Arguments"), _("Command line arguments:"), QLineEdit.Normal, self.arguments ) if valid: self.arguments = to_text_string(arguments) return valid
def get_current_word(self): """Return current word, i.e. word at cursor position""" cursor = self.textCursor() if cursor.hasSelection(): # Removes the selection and moves the cursor to the left side # of the selection: this is required to be able to properly # select the whole word under cursor (otherwise, the same word is # not selected when the cursor is at the right side of it): cursor.setPosition(min([cursor.selectionStart(), cursor.selectionEnd()])) else: # Checks if the first character to the right is a white space # and if not, moves the cursor one word to the left (otherwise, # if the character to the left do not match the "word regexp" # (see below), the word to the left of the cursor won't be # selected), but only if the first character to the left is not a # white space too. def is_space(move): curs = self.textCursor() curs.movePosition(move, QTextCursor.KeepAnchor) return not to_text_string(curs.selectedText()).strip() if is_space(QTextCursor.NextCharacter): if is_space(QTextCursor.PreviousCharacter): return cursor.movePosition(QTextCursor.WordLeft) cursor.select(QTextCursor.WordUnderCursor) text = to_text_string(cursor.selectedText()) match = re.findall(r'([a-zA-Z\_]+[0-9a-zA-Z\_]*)', text) if match: return match[0]
def set_object_text(self, text, force_refresh=False, ignore_unknown=False): """Set object analyzed by Help""" if (self.locked and not force_refresh): return self.switch_to_console_source() add_to_combo = True if text is None: text = to_text_string(self.combo.currentText()) add_to_combo = False found = self.show_help(text, ignore_unknown=ignore_unknown) if ignore_unknown and not found: return if add_to_combo: self.combo.add_text(text) if found: self.save_history() if self.dockwidget is not None: self.dockwidget.blockSignals(True) self.__eventually_raise_help(text, force=force_refresh) if self.dockwidget is not None: self.dockwidget.blockSignals(False)
def send_to_process(self, text): if not self.is_running(): return if not is_text_string(text): text = to_text_string(text) if self.mpl_backend == 'Qt4Agg' and os.name == 'nt' and \ self.introspection_socket is not None: communicate(self.introspection_socket, "toggle_inputhook_flag(True)") # # Socket-based alternative (see input hook in sitecustomize.py): # while self.local_server.hasPendingConnections(): # self.local_server.nextPendingConnection().write('go!') if any([text == cmd for cmd in ['%ls', '%pwd', '%scientific']]) or \ any([text.startswith(cmd) for cmd in ['%cd ', '%clear ']]): text = 'evalsc(r"%s")\n' % text if not text.endswith('\n'): text += '\n' self.process.write(to_binary_string(text, 'utf8')) self.process.waitForBytesWritten(-1) # Eventually write prompt faster (when hitting Enter continuously) # -- necessary/working on Windows only: if os.name == 'nt': self.write_error()
def data(self, index, role=Qt.DisplayRole): """Cell content""" if not index.isValid(): return to_qvariant() value = self.get_value(index) if is_binary_string(value): try: value = to_text_string(value, 'utf8') except: pass if role == Qt.DisplayRole: if value is np.ma.masked: return '' else: return to_qvariant(self._format % value) elif role == Qt.TextAlignmentRole: return to_qvariant(int(Qt.AlignCenter|Qt.AlignVCenter)) elif role == Qt.BackgroundColorRole and self.bgcolor_enabled \ and value is not np.ma.masked: hue = self.hue0+\ self.dhue*(self.vmax-self.color_func(value)) \ /(self.vmax-self.vmin) hue = float(np.abs(hue)) color = QColor.fromHsvF(hue, self.sat, self.val, self.alp) return to_qvariant(color) elif role == Qt.FontRole: return to_qvariant(get_font('arrayeditor')) return to_qvariant()
def save_session(filename): """Save Spyder session""" local_fname = get_conf_path(osp.basename(filename)) filename = osp.abspath(filename) old_cwd = getcwd() 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 as error: error_message = to_text_string(error) os.chdir(old_cwd) return error_message
def _is_pid_running_on_windows(pid): """Check if a process is running on windows systems based on the pid.""" pid = str(pid) # Hide flashing command prompt startupinfo = subprocess.STARTUPINFO() startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW process = subprocess.Popen(r'tasklist /fi "PID eq {0}"'.format(pid), stdout=subprocess.PIPE, stderr=subprocess.STDOUT, startupinfo=startupinfo) stdoutdata, stderrdata = process.communicate() stdoutdata = to_text_string(stdoutdata) process.kill() check = pid in stdoutdata return check
def setData(self, index, value, role=Qt.EditRole): """Cell content change""" if not index.isValid() or self.readonly: return False i = index.row() j = index.column() value = from_qvariant(value, str) if self._data.dtype.name == "bool": try: val = bool(float(value)) except ValueError: val = value.lower() == "true" elif self._data.dtype.name.startswith("string"): val = str(value) elif self._data.dtype.name.startswith("unicode"): val = to_text_string(value) else: if value.lower().startswith('e') or value.lower().endswith('e'): return False try: val = complex(value) if not val.imag: val = val.real except ValueError as e: QMessageBox.critical(self.dialog, "Error", "Value error: %s" % str(e)) return False try: self.test_array[0] = val # will raise an Exception eventually except OverflowError as e: print(type(e.message)) QMessageBox.critical(self.dialog, "Error", "Overflow error: %s" % e.message) return False # Add change to self.changes self.changes[(i, j)] = val self.emit(SIGNAL("dataChanged(QModelIndex,QModelIndex)"), index, index) if val > self.vmax: self.vmax = val if val < self.vmin: self.vmin = val return True
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 = to_text_string(self.filecombo.currentText()) if not filename: return self.datatree.load_data(self.DATAPATH) self.datelabel.setText(_('Sorting data, please wait...')) QApplication.processEvents() self.datatree.show_tree() text_style = "<span style=\'color: #444444\'><b>%s </b></span>" date_text = text_style % time.strftime("%d %b %Y %H:%M", time.localtime()) self.datelabel.setText(date_text)
def create_new_file(self, current_path, title, filters, create_func): """Create new file Returns True if successful""" if current_path is None: current_path = '' if osp.isfile(current_path): current_path = osp.dirname(current_path) self.parent_widget.emit(SIGNAL('redirect_stdio(bool)'), False) fname, _selfilter = getsavefilename(self, title, current_path, filters) self.parent_widget.emit(SIGNAL('redirect_stdio(bool)'), True) if fname: try: create_func(fname) return fname except EnvironmentError as error: QMessageBox.critical(self, _("New file"), _("<b>Unable to create file <i>%s</i>" "</b><br><br>Error message:<br>%s" ) % (fname, to_text_string(error)))
def _write(self, fp): """ Private write method for Python 2 The one from configparser fails for non-ascii Windows accounts """ if self._defaults: fp.write("[%s]\n" % DEFAULTSECT) for (key, value) in self._defaults.items(): fp.write("%s = %s\n" % (key, str(value).replace('\n', '\n\t'))) fp.write("\n") for section in self._sections: fp.write("[%s]\n" % section) for (key, value) in self._sections[section].items(): if key == "__name__": continue if (value is not None) or (self._optcre == self.OPTCRE): value = to_text_string(value) key = " = ".join((key, value.replace('\n', '\n\t'))) fp.write("%s\n" % (key)) fp.write("\n")
def register_plugin(self): """Register plugin in Spyder's main window""" self.connect(self, SIGNAL("edit_goto(QString,int,QString)"), self.main.editor.load) self.connect(self, SIGNAL('redirect_stdio(bool)'), self.main.redirect_internalshell_stdio) self.connect(self, SIGNAL('clear_all_breakpoints()'), self.main.editor.clear_all_breakpoints) self.connect(self, SIGNAL('clear_breakpoint(QString,int)'), self.main.editor.clear_breakpoint) self.connect(self, SIGNAL('set_or_edit_conditional_breakpoint()'), self.main.editor.set_or_edit_conditional_breakpoint) self.connect(self.main.editor, SIGNAL("breakpoints_saved()"), self.set_data) self.main.add_dockwidget(self) list_action = create_action(self, _("List breakpoints"), triggered=self.show) list_action.setEnabled(True) # A fancy way to insert the action into the Breakpoints menu under # the assumption that Breakpoints is the first QMenu in the list. for item in self.main.debug_menu_actions: try: menu_title = item.title() except AttributeError: pass else: # Depending on Qt API version, could get a QString or # unicode from title() if not is_text_string(menu_title): # string is a QString menu_title = to_text_string(menu_title.toUtf8) item.addAction(list_action) # If we've reached this point it means we've located the # first QMenu in the run_menu. Since there might be other # QMenu entries in run_menu, we'll break so that the # breakpoint action is only inserted once into the run_menu. break self.main.editor.pythonfile_dependent_actions += [list_action]
def load_dictionary(filename): """Load dictionary from .spydata file""" filename = osp.abspath(filename) old_cwd = getcwd() os.chdir(osp.dirname(filename)) data = None error_message = None try: tar = tarfile.open(filename, "r") tar.extractall() pickle_filename = osp.splitext(filename)[0] + '.pickle' try: # Old format (Spyder 2.0-2.1 for Python 2) with open(pickle_filename, 'U') as fdesc: data = pickle.loads(fdesc.read()) except (pickle.PickleError, TypeError, UnicodeDecodeError): # New format (Spyder >=2.2 for Python 2 and Python 3) with open(pickle_filename, 'rb') as fdesc: data = pickle.loads(fdesc.read()) saved_arrays = {} if load_array is not None: # Loading numpy arrays saved with np.save try: saved_arrays = data.pop('__saved_arrays__') for (name, index), fname in list(saved_arrays.items()): arr = np.load(osp.join(osp.dirname(filename), fname)) if index is None: data[name] = arr elif isinstance(data[name], dict): data[name][index] = arr else: data[name].insert(index, arr) except KeyError: pass for fname in [pickle_filename ] + [fn for fn in list(saved_arrays.values())]: os.remove(fname) except (EOFError, ValueError) as error: error_message = to_text_string(error) os.chdir(old_cwd) return data, error_message
def show(self): """Overrides Qt Method""" QWidget.show(self) self.visibility_changed.emit(True) if self.editor is not None: text = self.editor.get_selected_text() # If no text is highlighted for search, use whatever word is under the cursor if not text: cursor = self.editor.textCursor() cursor.select(QTextCursor.WordUnderCursor) text = to_text_string(cursor.selectedText()) # Now that text value is sorted out, use it for the search if text: self.search_text.setEditText(text) self.search_text.lineEdit().selectAll() self.refresh() else: self.search_text.lineEdit().selectAll() self.search_text.setFocus()
def add_to_history(self, command): """Add command to history""" command = to_text_string(command) if command in ['', '\n'] or command.startswith('Traceback'): return if command.endswith('\n'): command = command[:-1] self.histidx = None if len(self.history) > 0 and self.history[-1] == command: return self.history.append(command) text = os.linesep + command # When the first entry will be written in history file, # the separator will be append first: if self.history_filename not in HISTORY_FILENAMES: HISTORY_FILENAMES.append(self.history_filename) text = self.SEPARATOR + text encoding.write(text, self.history_filename, mode='ab') self.emit(SIGNAL('append_to_history(QString,QString)'), self.history_filename, text)
def getexistingdirectory(parent=None, caption='', basedir='', options=QFileDialog.ShowDirsOnly): """Wrapper around QtGui.QFileDialog.getExistingDirectory static method Compatible with PyQt >=v4.4 (API #1 and #2) and PySide >=v1.0""" # Calling QFileDialog static method if sys.platform == "win32": # On Windows platforms: redirect standard outputs _temp1, _temp2 = sys.stdout, sys.stderr sys.stdout, sys.stderr = None, None try: result = QFileDialog.getExistingDirectory(parent, caption, basedir, options) finally: if sys.platform == "win32": # On Windows platforms: restore standard outputs sys.stdout, sys.stderr = _temp1, _temp2 if not is_text_string(result): # PyQt API #1 result = to_text_string(result) return result
def value_to_display(value, truncate=False, trunc_len=80, minmax=False): """Convert value for display purpose""" if minmax and isinstance(value, (ndarray, MaskedArray)): if value.size == 0: return repr(value) try: return 'Min: %r\nMax: %r' % (value.min(), value.max()) except TypeError: pass except ValueError: # Happens when one of the array cell contains a sequence pass if isinstance(value, Image): return '%s Mode: %s' % (address(value), value.mode) if isinstance(value, DataFrame): cols = value.columns if PY2 and len(cols) > 0: # Get rid of possible BOM utf-8 data present at the # beginning of a file, which gets attached to the first # column header when headers are present in the first # row. # Fixes Issue 2514 try: ini_col = to_text_string(cols[0], encoding='utf-8-sig') except: ini_col = to_text_string(cols[0]) cols = [ini_col] + [to_text_string(c) for c in cols[1:]] else: cols = [to_text_string(c) for c in cols] return 'Column names: ' + ', '.join(list(cols)) if isinstance(value, NavigableString): # Fixes Issue 2448 return to_text_string(value) if is_binary_string(value): try: value = to_text_string(value, 'utf8') except: pass if not is_text_string(value): if isinstance(value, (list, tuple, dict, set)): value = CollectionsRepr.repr(value) else: value = repr(value) if truncate and len(value) > trunc_len: value = value[:trunc_len].rstrip() + ' ...' return value
def send_to_process(self, text): if not self.is_running(): return if not is_text_string(text): text = to_text_string(text) if self.mpl_backend == 0 and os.name == 'nt' and \ self.introspection_socket is not None: communicate(self.introspection_socket, "toggle_inputhook_flag(True)") # # Socket-based alternative (see input hook in sitecustomize.py): # while self.local_server.hasPendingConnections(): # self.local_server.nextPendingConnection().write('go!') if any([text == cmd for cmd in ['%ls', '%pwd', '%scientific']]) or \ any([text.startswith(cmd) for cmd in ['%cd ', '%clear ']]): text = 'evalsc(r"%s")\n' % text if not text.endswith('\n'): text += '\n' self.process.write(to_binary_string(text, 'utf8')) self.process.waitForBytesWritten(-1) # Eventually write prompt faster (when hitting Enter continuously) # -- necessary/working on Windows only: if os.name == 'nt': self.write_error()
def send_to_process(self, text): if not self.is_running(): return if not is_text_string(text): text = to_text_string(text) if self.install_qt_inputhook and self.introspection_socket is not None: communicate(self.introspection_socket, "toggle_inputhook_flag(True)") # # Socket-based alternative (see input hook in sitecustomize.py): # while self.local_server.hasPendingConnections(): # self.local_server.nextPendingConnection().write('go!') if text.startswith(('%', '!')): text = 'evalsc(r"%s")\n' % text if not text.endswith('\n'): text += '\n' self.process.write(LOCALE_CODEC.fromUnicode(text)) self.process.waitForBytesWritten(-1) # Eventually write prompt faster (when hitting Enter continuously) # -- necessary/working on Windows only: if os.name == 'nt': self.write_error()
def start(self): filename = to_text_string(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 = '' plver = PYLINT_VER if plver is not None: if plver.split('.')[0] == '0': p_args = ['-i', 'yes'] else: # Option '-i' (alias for '--include-ids') was removed in pylint # 1.0 p_args = ["--msg-template='{msg_id}:{line:3d},"\ "{column}: {obj}: {msg}"] p_args += [osp.basename(filename)] else: 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, _("Error"), _("Process failed to start"))
def cursor_position_changed(self): """Brace matching""" if self.bracepos is not None: self.__highlight(self.bracepos, cancel=True) self.bracepos = None cursor = self.textCursor() if cursor.position() == 0: return cursor.movePosition(QTextCursor.PreviousCharacter, QTextCursor.KeepAnchor) text = to_text_string(cursor.selectedText()) pos1 = cursor.position() if text in (')', ']', '}'): pos2 = self.find_brace_match(pos1, text, forward=False) elif text in ('(', '[', '{'): pos2 = self.find_brace_match(pos1, text, forward=True) else: return if pos2 is not None: self.bracepos = (pos1, pos2) self.__highlight(self.bracepos, color=self.matched_p_color) else: self.bracepos = (pos1, ) self.__highlight(self.bracepos, color=self.unmatched_p_color)
def register_plugin(self): """Register plugin in Spyder's main window""" self.connect(self, SIGNAL("edit_goto(QString,int,QString)"), self.main.editor.load) self.connect(self, SIGNAL('redirect_stdio(bool)'), self.main.redirect_internalshell_stdio) self.main.add_dockwidget(self) s2p_act = create_action(self, _("Import SED-ML as Python"), triggered=self.run_s2p) s2p_act.setEnabled(True) #self.register_shortcut(s2p_act, context="SED-ML to Python", # name="Import SED-ML file", default="Alt-I") for item in self.main.file_menu_actions: try: menu_title = item.title() except AttributeError: pass else: if not is_text_string(menu_title): # string is a QString menu_title = to_text_string(menu_title.toUtf8) if item.title() == str("Import"): item.addAction(s2p_act)
def is_valid(self, qstr=None): """Return True if string is valid""" if not self.help.source_is_console(): return True if qstr is None: qstr = self.currentText() if not re.search('^[a-zA-Z0-9_\.]*$', str(qstr), 0): return False objtxt = to_text_string(qstr) if self.help.get_option('automatic_import'): shell = self.help.internal_shell if shell is not None: return shell.is_defined(objtxt, force_import=True) shell = self.help.get_shell() if shell is not None: try: return shell.is_defined(objtxt) except socket.error: shell = self.help.get_shell() try: return shell.is_defined(objtxt) except socket.error: # Well... too bad! pass
def move(self, fnames=None): """Move files/directories""" if fnames is None: fnames = self.get_selected_filenames() orig = fixpath(osp.dirname(fnames[0])) while True: self.parent_widget.emit(SIGNAL('redirect_stdio(bool)'), False) folder = getexistingdirectory(self, _("Select directory"), orig) self.parent_widget.emit(SIGNAL('redirect_stdio(bool)'), True) if folder: folder = fixpath(folder) if folder != orig: break else: return for fname in fnames: basename = osp.basename(fname) try: misc.move_file(fname, osp.join(folder, basename)) except EnvironmentError as error: QMessageBox.critical(self, _("Error"), _("<b>Unable to move <i>%s</i></b>" "<br><br>Error message:<br>%s" ) % (basename, to_text_string(error)))
def execute_python_code(self, lines): client = self.get_current_client() if client is not None: client.shellwidget.execute(to_text_string(lines)) self.activateWindow() client.get_control().setFocus()
def create_process(self): self.shell.clear() self.process = QProcess(self) if self.merge_output_channels: self.process.setProcessChannelMode(QProcess.MergedChannels) else: self.process.setProcessChannelMode(QProcess.SeparateChannels) self.shell.wait_for_ready_read.connect( lambda: self.process.waitForReadyRead(250)) # Working directory if self.wdir is not None: self.process.setWorkingDirectory(self.wdir) #-------------------------Python specific------------------------------ # Python arguments p_args = ['-u'] if DEBUG >= 3: p_args += ['-v'] p_args += get_python_args(self.fname, self.python_args, self.interact_action.isChecked(), self.debug_action.isChecked(), self.arguments) env = [ to_text_string(_path) for _path in self.process.systemEnvironment() ] if self.pythonstartup: env.append('PYTHONSTARTUP=%s' % self.pythonstartup) #-------------------------Python specific------------------------------- # Post mortem debugging if self.post_mortem_action.isChecked(): env.append('SPYDER_EXCEPTHOOK=True') # Set standard input/output encoding for Python consoles # (IPython handles it on its own) # See http://stackoverflow.com/q/26312400/438386, specifically # the comments of Martijn Pieters if not self.is_ipykernel: env.append('PYTHONIOENCODING=UTF-8') # Monitor if self.monitor_enabled: env.append('SPYDER_SHELL_ID=%s' % id(self)) env.append('SPYDER_AR_TIMEOUT=%d' % self.autorefresh_timeout) env.append('SPYDER_AR_STATE=%r' % self.autorefresh_state) from spyderlib.widgets.externalshell import introspection introspection_server = introspection.start_introspection_server() introspection_server.register(self) notification_server = introspection.start_notification_server() self.notification_thread = notification_server.register(self) self.notification_thread.sig_pdb.connect( lambda fname, lineno: self.sig_pdb.emit(fname, lineno)) self.notification_thread.new_ipython_kernel.connect( lambda args: self.create_ipython_client.emit(args)) self.notification_thread.open_file.connect( lambda fname, lineno: self.open_file.emit(fname, lineno)) if self.namespacebrowser is not None: self.configure_namespacebrowser() env.append('SPYDER_I_PORT=%d' % introspection_server.port) env.append('SPYDER_N_PORT=%d' % notification_server.port) # External modules options env.append('ETS_TOOLKIT=%s' % self.ets_backend) if self.mpl_backend: env.append('MATPLOTLIB_BACKEND=%s' % self.mpl_backend) if self.qt_api: env.append('QT_API=%s' % self.qt_api) env.append('COLORIZE_SYS_STDERR=%s' % self.colorize_sys_stderr) # # Socket-based alternative (see input hook in sitecustomize.py): # if self.install_qt_inputhook: # from PyQt4.QtNetwork import QLocalServer # self.local_server = QLocalServer() # self.local_server.listen(str(id(self))) if self.pyqt_api: env.append('PYQT_API=%d' % self.pyqt_api) env.append('IGNORE_SIP_SETAPI_ERRORS=%s' % self.ignore_sip_setapi_errors) # User Module Deleter if self.is_interpreter: env.append('UMR_ENABLED=%r' % self.umr_enabled) env.append('UMR_NAMELIST=%s' % ','.join(self.umr_namelist)) env.append('UMR_VERBOSE=%r' % self.umr_verbose) env.append('MATPLOTLIB_ION=True') else: if self.interact: env.append('MATPLOTLIB_ION=True') else: env.append('MATPLOTLIB_ION=False') # IPython kernel env.append('IPYTHON_KERNEL=%r' % self.is_ipykernel) # Add sitecustomize path to path list pathlist = [] scpath = osp.dirname(osp.abspath(__file__)) pathlist.append(scpath) # Adding Spyder path pathlist += self.path # Adding path list to PYTHONPATH environment variable add_pathlist_to_PYTHONPATH(env, pathlist) #-------------------------Python specific------------------------------ self.process.readyReadStandardOutput.connect(self.write_output) self.process.readyReadStandardError.connect(self.write_error) self.process.finished.connect( lambda ec, es=QProcess.ExitStatus: self.finished(ec, es)) self.sig_finished.connect(self.dialog_manager.close_all) self.terminate_button.clicked.connect(self.process.terminate) self.kill_button.clicked.connect(self.process.kill) #-------------------------Python specific------------------------------ # Fixes for our Mac app: # 1. PYTHONPATH and PYTHONHOME are set while bootstrapping the app, # but their values are messing sys.path for external interpreters # (e.g. EPD) so we need to remove them from the environment. # 2. Set PYTHONPATH again but without grabbing entries defined in the # environment (Fixes Issue 1321) # 3. Remove PYTHONOPTIMIZE from env so that we can have assert # statements working with our interpreters (See Issue 1281) if running_in_mac_app(): env.append('SPYDER_INTERPRETER=%s' % self.pythonexecutable) if MAC_APP_NAME not in self.pythonexecutable: env = [p for p in env if not (p.startswith('PYTHONPATH') or \ p.startswith('PYTHONHOME'))] # 1. add_pathlist_to_PYTHONPATH(env, pathlist, drop_env=True) # 2. env = [p for p in env if not p.startswith('PYTHONOPTIMIZE')] # 3. processEnvironment = QProcessEnvironment() for envItem in env: envName, separator, envValue = envItem.partition('=') processEnvironment.insert(envName, envValue) self.process.setProcessEnvironment(processEnvironment) self.process.start(self.pythonexecutable, p_args) #-------------------------Python specific------------------------------ running = self.process.waitForStarted(3000) self.set_running_state(running) if not running: if self.is_ipykernel: self.ipython_kernel_start_error.emit( _("The kernel failed to start!! That's all we know... " "Please close this console and open a new one.")) else: QMessageBox.critical(self, _("Error"), _("A Python console failed to start!")) else: self.shell.setFocus() self.started.emit() return self.process
def translate_dumb(x): if not is_unicode(x): return to_text_string(x, "utf-8") return x
def filter_text(self): """Get the normalized (lowecase) content of the filter text.""" return to_text_string(self.edit.text()).lower()
def setup_and_check(self, data, title=''): """ Setup DataFrameEditor: return False if data is not supported, True otherwise """ self.layout = QGridLayout() self.setLayout(self.layout) self.setWindowIcon(get_icon('arredit.png')) if title: title = to_text_string(title) # in case title is not a string else: title = _("%s editor") % data.__class__.__name__ if isinstance(data, TimeSeries): self.is_time_series = True data = data.to_frame() self.setWindowTitle(title) self.resize(600, 500) self.dataModel = DataFrameModel(data, parent=self) self.dataTable = DataFrameView(self, self.dataModel) self.layout.addWidget(self.dataTable) self.setLayout(self.layout) self.setMinimumSize(400, 300) # Make the dialog act as a window self.setWindowFlags(Qt.Window) btn_layout = QHBoxLayout() btn = QPushButton(_("Format")) # disable format button for int type btn_layout.addWidget(btn) self.connect(btn, SIGNAL("clicked()"), self.change_format) btn = QPushButton(_('Resize')) btn_layout.addWidget(btn) self.connect(btn, SIGNAL("clicked()"), self.dataTable.resizeColumnsToContents) bgcolor = QCheckBox(_('Background color')) bgcolor.setChecked(self.dataModel.bgcolor_enabled) bgcolor.setEnabled(self.dataModel.bgcolor_enabled) self.connect(bgcolor, SIGNAL("stateChanged(int)"), self.change_bgcolor_enable) btn_layout.addWidget(bgcolor) self.bgcolor_global = QCheckBox(_('Column min/max')) self.bgcolor_global.setChecked(self.dataModel.colum_avg_enabled) self.bgcolor_global.setEnabled(not self.is_time_series and self.dataModel.bgcolor_enabled) self.connect(self.bgcolor_global, SIGNAL("stateChanged(int)"), self.dataModel.colum_avg) btn_layout.addWidget(self.bgcolor_global) btn_layout.addStretch() bbox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.connect(bbox, SIGNAL("accepted()"), SLOT("accept()")) self.connect(bbox, SIGNAL("rejected()"), SLOT("reject()")) btn_layout.addWidget(bbox) self.layout.addLayout(btn_layout, 2, 0) return True
def transcode(self, qba): if os.name == 'nt': return to_text_string(CP850_CODEC.toUnicode(qba.data())) else: return ExternalShellBase.transcode(self, qba)
def eol_changed(self, os_name): os_name = to_text_string(os_name) self.eol.setText({"nt": "CRLF", "posix": "LF"}.get(os_name, "CR"))
def url_to_text(self, url): """Convert QUrl object to displayed text in combo box""" return osp.splitext(to_text_string(url.path()))[0][1:]
def get_block_indentation(self, block_nb): """Return line indentation (character number)""" text = to_text_string( self.document().findBlockByNumber(block_nb).text()) return len(text) - len(text.lstrip())
def has_selected_text(self): """Returns True if some text is selected""" return bool(to_text_string(self.textCursor().selectedText()))
def import_data(self, filenames=None): """Import data from text file""" title = _("Import data") if filenames is None: if self.filename is None: basedir = getcwd() else: basedir = osp.dirname(self.filename) filenames, _selfilter = getopenfilenames(self, title, basedir, iofunctions.load_filters) if not filenames: return elif is_text_string(filenames): filenames = [filenames] for filename in filenames: self.filename = to_text_string(filename) ext = osp.splitext(self.filename)[1].lower() if ext not in iofunctions.load_funcs: buttons = QMessageBox.Yes | QMessageBox.Cancel answer = QMessageBox.question(self, title, _("<b>Unsupported file extension '%s'</b><br><br>" "Would you like to import it anyway " "(by selecting a known file format)?" ) % ext, buttons) if answer == QMessageBox.Cancel: return formats = list(iofunctions.load_extensions.keys()) item, ok = QInputDialog.getItem(self, title, _('Open file as:'), formats, 0, False) if ok: ext = iofunctions.load_extensions[to_text_string(item)] else: return load_func = iofunctions.load_funcs[ext] # 'import_wizard' (self.setup_io) if is_text_string(load_func): # Import data with import wizard error_message = None try: text, _encoding = encoding.read(self.filename) if self.is_internal_shell: self.editor.import_from_string(text) else: base_name = osp.basename(self.filename) editor = ImportWizard(self, text, title=base_name, varname=fix_reference_name(base_name)) if editor.exec_(): var_name, clip_data = editor.get_data() monitor_set_global(self._get_sock(), var_name, clip_data) except Exception as error: error_message = str(error) else: QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) QApplication.processEvents() if self.is_internal_shell: namespace, error_message = load_func(self.filename) interpreter = self.shellwidget.interpreter for key in list(namespace.keys()): new_key = fix_reference_name(key, blacklist=list(interpreter.namespace.keys())) if new_key != key: namespace[new_key] = namespace.pop(key) if error_message is None: interpreter.namespace.update(namespace) else: error_message = monitor_load_globals(self._get_sock(), self.filename, ext) QApplication.restoreOverrideCursor() QApplication.processEvents() if error_message is not None: QMessageBox.critical(self, title, _("<b>Unable to load '%s'</b>" "<br><br>Error message:<br>%s" ) % (self.filename, error_message)) self.refresh_table()